Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/toolbox-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
"files": [
"dist/*"
],
"exports": {
".": "./dist/index.js"
},
"imports": {
"#blobInternals": {
"node": "./dist/usernotes/blobInternals.node.js",
"default": "./dist/usernotes/blobInternals.default.js"
}
},
"scripts": {
"fmt": "dprint fmt",
"fmt:check": "dprint check",
Expand All @@ -25,13 +34,15 @@
"url": "https://github.com/toolbox-team/storage/issues"
},
"homepage": "https://github.com/toolbox-team/storage/tree/main/packages/toolbox-storage#readme",
"dependencies": {
"optionalDependencies": {
"core-js": "^3.40.0",
"pako": "^1.0.11"
},
"devDependencies": {
"@ava/typescript": "^5.0.0",
"@tsconfig/node-lts": "^22.0.1",
"@types/node": "^13.7.4",
"@types/node": "^22.13.5",
"@types/pako": "^2.0.3",
"ava": "^6.2.0",
"dprint": "^0.40.2",
"nyc": "^15.0.0"
Expand Down
34 changes: 29 additions & 5 deletions packages/toolbox-storage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
export * from './config/RawSubredditConfig.js';
export * from './config/SubredditConfig.js';
export {
DEFAULT_CONFIG,
DEFAULT_USERNOTE_TYPES,
EARLIEST_KNOWN_CONFIG_SCHEMA,
LATEST_KNOWN_CONFIG_SCHEMA,
migrateConfigToLatestSchema,
RawDomainTag,
RawModMacro,
RawRemovalReason,
RawSubredditConfig,
RawUsernoteType,
} from './config/RawSubredditConfig.js';
export {SubredditConfig} from './config/SubredditConfig.js';

export * from './usernotes/RawUsernotes.js';
export * from './usernotes/Usernote.js';
export * from './usernotes/Usernotes.js';
export {
compressBlob,
decompressBlob,
EARLIEST_KNOWN_USERNOTES_SCHEMA,
expandPermalink,
LATEST_KNOWN_USERNOTES_SCHEMA,
migrateUsernotesToLatestSchema,
RawUsernotes,
RawUsernotesBlob,
RawUsernotesConstants,
RawUsernotesNote,
RawUsernotesUsers,
squashPermalink,
} from './usernotes/RawUsernotes.js';
export {Usernote, UsernoteInit} from './usernotes/Usernote.js';
export {Usernotes} from './usernotes/Usernotes.js';
4 changes: 0 additions & 4 deletions packages/toolbox-storage/src/usernotes/RawUsernotes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,4 @@ test('expandPermalink', t => {
}
});

test.todo('compressBlob');

test.todo('decompressBlob');

test.todo('migrateUsernotesSchema');
16 changes: 6 additions & 10 deletions packages/toolbox-storage/src/usernotes/RawUsernotes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// type imports for doc links
import pako from 'pako';

import {_compressBlob, _decompressBlob} from '#blobInternals';

/**
* The latest usernotes schema version that this library can handle. If a
* usernotes page reports a schema version higher than this number, it can't be
Expand Down Expand Up @@ -131,9 +133,8 @@ export function expandPermalink (shortenedLink: string): string {
* @param value The object or value to compress
* @returns The generated blob.
*/
export function compressBlob<T> (value: T): RawUsernotesBlob<T> {
return Buffer.from(pako.deflate(JSON.stringify(value))).toString('base64');
}
export const compressBlob = <T>(value: T): RawUsernotesBlob<T> =>
_compressBlob(value);

/**
* Decompresses a {@linkcode RawUsernotesBlob} string into the JSON value it
Expand All @@ -142,13 +143,8 @@ export function compressBlob<T> (value: T): RawUsernotesBlob<T> {
* @param blob The blob to decompress
* @returns The original JSON value.
*/
export function decompressBlob<T> (blob: RawUsernotesBlob<T>): T {
return JSON.parse(
pako.inflate(Buffer.from(blob, 'base64').toString('binary'), {
to: 'string',
}),
);
}
export const decompressBlob = <T>(blob: RawUsernotesBlob<T>): T =>
_decompressBlob(blob);

/**
* Checks the schema version of raw usernotes data and attempts to update it to
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import test from 'ava';

test.todo('_compressBlob');

test.todo('_decompressBlob');
32 changes: 32 additions & 0 deletions packages/toolbox-storage/src/usernotes/blobInternals.default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Generic implementation of RawUsernotesBlob compression/decompression

import 'core-js/actual/typed-array/from-base64';
declare global {
interface Uint8ArrayConstructor {
fromBase64(
string: string,
options?: {
alphabet?: 'base64' | 'base64url';
lastChunkHandling?: 'loose' | 'strict' | 'stop-before-partial';
},
): Uint8Array;
}
}

import 'core-js/actual/typed-array/to-base64';
declare global {
interface Uint8Array {
toBase64(
options?: {alphabet?: 'base64' | 'base64url'; omitPadding?: boolean},
): string;
}
}

import {deflate, inflate} from 'pako';
import {type RawUsernotesBlob} from './RawUsernotes.js';

export const _compressBlob = <T>(value: T): RawUsernotesBlob<T> =>
deflate(JSON.stringify(value)).toBase64();

export const _decompressBlob = <T>(blob: RawUsernotesBlob<T>): T =>
JSON.parse(inflate(Uint8Array.fromBase64(blob), {to: 'string'}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import test from 'ava';

test.todo('_compressBlob');

test.todo('_decompressBlob');
15 changes: 15 additions & 0 deletions packages/toolbox-storage/src/usernotes/blobInternals.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Node-specific implementation of RawUsernotesBlob compression/decompression,
// which doesn't use any dependencies

import {deflateSync, inflateSync} from 'node:zlib';
import {type RawUsernotesBlob} from './RawUsernotes.js';

export const _compressBlob = <T>(value: T): RawUsernotesBlob<T> => {
const input = Buffer.from(JSON.stringify(value), 'utf-8');
return deflateSync(input).toString('base64');
};

export const _decompressBlob = <T>(blob: RawUsernotesBlob<T>): T => {
const input = Buffer.from(blob, 'base64');
return JSON.parse(inflateSync(input).toString('utf-8'));
};
Loading