litsquare-storage-core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ import type { DocumentExtension, DocumentLibrary, DocumentRecord, LegacyDocument, RemoteDocumentRef, StorageProfile } from './types.js';
2
+ export declare function contentFingerprint(content: string): string;
3
+ export interface BrowserDocumentStore<Extension extends DocumentExtension> {
4
+ initialize(legacy: LegacyDocument | null, fallback: {
5
+ title: string;
6
+ markdown: string;
7
+ }): Promise<DocumentLibrary<Extension>>;
8
+ list(): Promise<DocumentRecord<Extension>[]>;
9
+ create(input?: {
10
+ title?: string;
11
+ markdown?: string;
12
+ extension?: Extension;
13
+ cloud?: RemoteDocumentRef<Extension>;
14
+ }): DocumentRecord<Extension>;
15
+ add(document: DocumentRecord<Extension>): Promise<DocumentRecord<Extension>>;
16
+ save(id: string, input: Pick<DocumentRecord<Extension>, 'title' | 'markdown'> & Partial<Pick<DocumentRecord<Extension>, 'extension' | 'cloud'>>): Promise<DocumentRecord<Extension>>;
17
+ activate(id: string, previousId: string | null): Promise<DocumentRecord<Extension>>;
18
+ duplicate(source: DocumentRecord<Extension>): Promise<DocumentRecord<Extension>>;
19
+ delete(id: string): Promise<void>;
20
+ clearForTests(): Promise<void>;
21
+ fingerprint(content: string): string;
22
+ isRemoteDirty(document: DocumentRecord<Extension>, markdown?: string): boolean;
23
+ }
24
+ export declare function createBrowserDocumentStore<Extension extends DocumentExtension>(profile: StorageProfile<Extension>): BrowserDocumentStore<Extension>;
25
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAA;AAwBnB,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,MAAM,WAAW,oBAAoB,CAAC,SAAS,SAAS,iBAAiB;IACvE,UAAU,CACR,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAC5C,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAA;IACtC,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IAC5C,MAAM,CAAC,KAAK,CAAC,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,SAAS,CAAA;QACrB,KAAK,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAA;KACrC,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IAC7B,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IAC5E,IAAI,CACF,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,GAChE,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IACrC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IACnF,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IAChF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACpC,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/E;AAED,wBAAgB,0BAA0B,CAAC,SAAS,SAAS,iBAAiB,EAC5E,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,GACjC,oBAAoB,CAAC,SAAS,CAAC,CA+KjC"}
@@ -0,0 +1,201 @@
1
+ const databaseVersion = 1;
2
+ const documentsStore = 'documents';
3
+ const settingsStore = 'settings';
4
+ const activeDocumentKey = 'active-document-id';
5
+ const previousDocumentKey = 'previous-document-id';
6
+ const legacyMigrationKey = 'legacy-local-storage-migrated';
7
+ function requestResult(request) {
8
+ return new Promise((resolve, reject) => {
9
+ request.onsuccess = () => resolve(request.result);
10
+ request.onerror = () => reject(request.error ?? new Error('Browser storage request failed.'));
11
+ });
12
+ }
13
+ function transactionDone(transaction) {
14
+ return new Promise((resolve, reject) => {
15
+ transaction.oncomplete = () => resolve();
16
+ transaction.onabort = () => reject(transaction.error ?? new Error('Browser storage transaction was aborted.'));
17
+ transaction.onerror = () => reject(transaction.error ?? new Error('Browser storage transaction failed.'));
18
+ });
19
+ }
20
+ export function contentFingerprint(content) {
21
+ let hash = 0x811c9dc5;
22
+ for (let index = 0; index < content.length; index += 1) {
23
+ hash ^= content.charCodeAt(index);
24
+ hash = Math.imul(hash, 0x01000193);
25
+ }
26
+ return (hash >>> 0).toString(16).padStart(8, '0');
27
+ }
28
+ export function createBrowserDocumentStore(profile) {
29
+ const openDatabase = () => new Promise((resolve, reject) => {
30
+ const request = indexedDB.open(profile.databaseName, databaseVersion);
31
+ request.onupgradeneeded = () => {
32
+ const database = request.result;
33
+ if (!database.objectStoreNames.contains(documentsStore)) {
34
+ const documents = database.createObjectStore(documentsStore, { keyPath: 'id' });
35
+ documents.createIndex('updatedAt', 'updatedAt');
36
+ documents.createIndex('title', 'title');
37
+ }
38
+ if (!database.objectStoreNames.contains(settingsStore))
39
+ database.createObjectStore(settingsStore);
40
+ };
41
+ request.onsuccess = () => resolve(request.result);
42
+ request.onerror = () => reject(request.error ?? new Error('Browser storage is unavailable.'));
43
+ });
44
+ const getSetting = async (database, key) => {
45
+ const transaction = database.transaction(settingsStore, 'readonly');
46
+ const value = await requestResult(transaction.objectStore(settingsStore).get(key));
47
+ return value ?? null;
48
+ };
49
+ const setSetting = async (database, key, value) => {
50
+ const transaction = database.transaction(settingsStore, 'readwrite');
51
+ transaction.objectStore(settingsStore).put(value, key);
52
+ await transactionDone(transaction);
53
+ };
54
+ const allDocuments = async (database) => {
55
+ const transaction = database.transaction(documentsStore, 'readonly');
56
+ const documents = await requestResult(transaction.objectStore(documentsStore).getAll());
57
+ return documents.sort((left, right) => right.openedAt.localeCompare(left.openedAt));
58
+ };
59
+ const putDocument = async (database, document) => {
60
+ const transaction = database.transaction(documentsStore, 'readwrite');
61
+ transaction.objectStore(documentsStore).put(document);
62
+ await transactionDone(transaction);
63
+ };
64
+ const create = (input = {}) => {
65
+ const timestamp = new Date().toISOString();
66
+ return {
67
+ id: crypto.randomUUID(),
68
+ title: input.title?.trim() || 'Untitled document',
69
+ markdown: input.markdown ?? '',
70
+ extension: input.extension ?? profile.defaultExtension,
71
+ createdAt: timestamp,
72
+ updatedAt: timestamp,
73
+ openedAt: timestamp,
74
+ cloud: input.cloud,
75
+ };
76
+ };
77
+ const add = async (document) => {
78
+ const database = await openDatabase();
79
+ try {
80
+ await putDocument(database, document);
81
+ return document;
82
+ }
83
+ finally {
84
+ database.close();
85
+ }
86
+ };
87
+ const store = {
88
+ async initialize(legacy, fallback) {
89
+ const database = await openDatabase();
90
+ try {
91
+ let documents = await allDocuments(database);
92
+ const migrated = await getSetting(database, legacyMigrationKey);
93
+ if (!migrated) {
94
+ if (legacy && documents.length === 0) {
95
+ const document = create({ title: legacy.title, markdown: legacy.markdown });
96
+ document.createdAt = legacy.savedAt;
97
+ document.updatedAt = legacy.savedAt;
98
+ document.openedAt = legacy.savedAt;
99
+ await putDocument(database, document);
100
+ documents = [document];
101
+ }
102
+ await setSetting(database, legacyMigrationKey, true);
103
+ }
104
+ if (documents.length === 0) {
105
+ const document = create(fallback);
106
+ await putDocument(database, document);
107
+ documents = [document];
108
+ }
109
+ const activeId = await getSetting(database, activeDocumentKey);
110
+ const activeDocument = documents.find((document) => document.id === activeId) ?? documents[0];
111
+ await setSetting(database, activeDocumentKey, activeDocument.id);
112
+ return {
113
+ documents,
114
+ activeDocument,
115
+ previousDocumentId: await getSetting(database, previousDocumentKey),
116
+ };
117
+ }
118
+ finally {
119
+ database.close();
120
+ }
121
+ },
122
+ async list() {
123
+ const database = await openDatabase();
124
+ try {
125
+ return await allDocuments(database);
126
+ }
127
+ finally {
128
+ database.close();
129
+ }
130
+ },
131
+ create,
132
+ add,
133
+ async save(id, input) {
134
+ const database = await openDatabase();
135
+ try {
136
+ const transaction = database.transaction(documentsStore, 'readonly');
137
+ const existing = await requestResult(transaction.objectStore(documentsStore).get(id));
138
+ if (!existing)
139
+ throw new Error('This browser document no longer exists.');
140
+ const document = {
141
+ ...existing,
142
+ title: input.title.trim() || 'Untitled document',
143
+ markdown: input.markdown,
144
+ extension: input.extension ?? existing.extension,
145
+ cloud: input.cloud === undefined ? existing.cloud : input.cloud,
146
+ updatedAt: new Date().toISOString(),
147
+ };
148
+ await putDocument(database, document);
149
+ return document;
150
+ }
151
+ finally {
152
+ database.close();
153
+ }
154
+ },
155
+ async activate(id, previousId) {
156
+ const database = await openDatabase();
157
+ try {
158
+ const transaction = database.transaction(documentsStore, 'readonly');
159
+ const existing = await requestResult(transaction.objectStore(documentsStore).get(id));
160
+ if (!existing)
161
+ throw new Error('This browser document no longer exists.');
162
+ const document = { ...existing, openedAt: new Date().toISOString() };
163
+ await putDocument(database, document);
164
+ await setSetting(database, activeDocumentKey, id);
165
+ await setSetting(database, previousDocumentKey, previousId);
166
+ return document;
167
+ }
168
+ finally {
169
+ database.close();
170
+ }
171
+ },
172
+ async duplicate(source) {
173
+ return add(create({ title: `${source.title} copy`, markdown: source.markdown, extension: source.extension }));
174
+ },
175
+ async delete(id) {
176
+ const database = await openDatabase();
177
+ try {
178
+ const transaction = database.transaction(documentsStore, 'readwrite');
179
+ transaction.objectStore(documentsStore).delete(id);
180
+ await transactionDone(transaction);
181
+ }
182
+ finally {
183
+ database.close();
184
+ }
185
+ },
186
+ async clearForTests() {
187
+ await new Promise((resolve, reject) => {
188
+ const request = indexedDB.deleteDatabase(profile.databaseName);
189
+ request.onsuccess = () => resolve();
190
+ request.onerror = () => reject(request.error);
191
+ request.onblocked = () => reject(new Error('Browser storage is still open.'));
192
+ });
193
+ },
194
+ fingerprint: contentFingerprint,
195
+ isRemoteDirty(document, markdown = document.markdown) {
196
+ return Boolean(document.cloud && document.cloud.lastSavedFingerprint !== contentFingerprint(markdown));
197
+ },
198
+ };
199
+ return store;
200
+ }
201
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export * from './types.js';
2
+ export interface GistShareTarget {
3
+ gistUrl: string;
4
+ fileName: string;
5
+ view?: 'edit' | 'preview';
6
+ }
7
+ export interface SessionStorageAdapter {
8
+ getItem(key: string): string | null;
9
+ setItem(key: string, value: string): void;
10
+ removeItem(key: string): void;
11
+ }
12
+ export interface SupabaseAuthSession {
13
+ access_token: string;
14
+ provider_token?: string | null;
15
+ }
16
+ export interface SupabaseAuthAdapter {
17
+ getSession(): Promise<{
18
+ data: {
19
+ session: SupabaseAuthSession | null;
20
+ };
21
+ error: Error | null;
22
+ }>;
23
+ onAuthStateChange?(callback: (event: string, session: SupabaseAuthSession | null) => void): unknown;
24
+ signInWithOAuth(input: {
25
+ provider: 'github';
26
+ options: {
27
+ scopes: 'gist';
28
+ redirectTo: string;
29
+ };
30
+ }): Promise<{
31
+ error: Error | null;
32
+ }>;
33
+ signOut(options?: {
34
+ scope?: 'local';
35
+ }): Promise<{
36
+ error: Error | null;
37
+ }>;
38
+ }
39
+ export interface SupabaseGistStatus {
40
+ authenticated: boolean;
41
+ invited: boolean;
42
+ connected: boolean;
43
+ revoked?: boolean;
44
+ githubLogin?: string;
45
+ memberCount?: number;
46
+ }
47
+ export interface SupabaseGistClientOptions {
48
+ projectUrl: string;
49
+ publishableKey: string;
50
+ productId: string;
51
+ auth: SupabaseAuthAdapter;
52
+ location: {
53
+ href: string;
54
+ };
55
+ consumeProviderToken?: () => string | null;
56
+ fetchImpl?: typeof fetch;
57
+ }
58
+ export interface SupabaseGistClient {
59
+ connect(): Promise<void>;
60
+ disconnect(): Promise<SupabaseGistStatus>;
61
+ status(): Promise<SupabaseGistStatus>;
62
+ redeemInvite(code: string): Promise<SupabaseGistStatus>;
63
+ list<T>(page?: number): Promise<T>;
64
+ read<T>(id: string, path?: string): Promise<T>;
65
+ write<T>(input: unknown): Promise<T>;
66
+ readShared<T>(url: string, name: string): Promise<T>;
67
+ }
68
+ export declare class SupabaseGistError extends Error {
69
+ status: number;
70
+ code: string;
71
+ constructor(status: number, code: string, message: string);
72
+ }
73
+ export declare function createSanitizedSessionStorage(storage: SessionStorageAdapter, onProviderToken?: (token: string) => void): SessionStorageAdapter;
74
+ export declare function createSupabaseGistClient(options: SupabaseGistClientOptions): SupabaseGistClient;
75
+ export declare function createGistShareUrl(origin: string, target: GistShareTarget): string;
76
+ export declare function parseGistShareHash(hash: string): GistShareTarget | null;
77
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,204 @@
1
+ export * from './types.js';
2
+ export class SupabaseGistError extends Error {
3
+ status;
4
+ code;
5
+ constructor(status, code, message) {
6
+ super(message);
7
+ this.name = 'SupabaseGistError';
8
+ this.status = status;
9
+ this.code = code;
10
+ }
11
+ }
12
+ function removeProviderTokens(value) {
13
+ if (Array.isArray(value))
14
+ return value.map(removeProviderTokens);
15
+ if (!value || typeof value !== 'object')
16
+ return value;
17
+ return Object.fromEntries(Object.entries(value).flatMap(([key, child]) => {
18
+ if (key === 'provider_token' || key === 'provider_refresh_token')
19
+ return [];
20
+ return [[key, removeProviderTokens(child)]];
21
+ }));
22
+ }
23
+ function providerToken(value) {
24
+ if (Array.isArray(value)) {
25
+ for (const child of value) {
26
+ const token = providerToken(child);
27
+ if (token)
28
+ return token;
29
+ }
30
+ return null;
31
+ }
32
+ if (!value || typeof value !== 'object')
33
+ return null;
34
+ for (const [key, child] of Object.entries(value)) {
35
+ if (key === 'provider_token' && typeof child === 'string' && child)
36
+ return child;
37
+ const token = providerToken(child);
38
+ if (token)
39
+ return token;
40
+ }
41
+ return null;
42
+ }
43
+ export function createSanitizedSessionStorage(storage, onProviderToken) {
44
+ return {
45
+ getItem: (key) => storage.getItem(key),
46
+ removeItem: (key) => storage.removeItem(key),
47
+ setItem(key, value) {
48
+ try {
49
+ const parsed = JSON.parse(value);
50
+ const token = providerToken(parsed);
51
+ if (token)
52
+ onProviderToken?.(token);
53
+ storage.setItem(key, JSON.stringify(removeProviderTokens(parsed)));
54
+ }
55
+ catch {
56
+ storage.setItem(key, value);
57
+ }
58
+ },
59
+ };
60
+ }
61
+ export function createSupabaseGistClient(options) {
62
+ const request = options.fetchImpl ?? fetch;
63
+ const projectUrl = options.projectUrl.replace(/\/$/, '');
64
+ let capturedProviderToken = null;
65
+ let pendingProviderToken = null;
66
+ const initialAuthState = options.auth.onAuthStateChange
67
+ ? new Promise((resolve) => {
68
+ let initialized = false;
69
+ options.auth.onAuthStateChange?.((_event, nextSession) => {
70
+ if (nextSession?.provider_token)
71
+ pendingProviderToken = nextSession.provider_token;
72
+ if (!initialized) {
73
+ initialized = true;
74
+ resolve();
75
+ }
76
+ });
77
+ })
78
+ : Promise.resolve();
79
+ async function session() {
80
+ const result = await options.auth.getSession();
81
+ if (result.error)
82
+ throw result.error;
83
+ return result.data.session;
84
+ }
85
+ async function invoke(action, payload = {}) {
86
+ const current = await session();
87
+ if (!current) {
88
+ throw new SupabaseGistError(401, 'not_connected', 'Connect GitHub Gist first.');
89
+ }
90
+ const response = await request(`${projectUrl}/functions/v1/ink-gist`, {
91
+ method: 'POST',
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ apikey: options.publishableKey,
95
+ Authorization: `Bearer ${current.access_token}`,
96
+ },
97
+ body: JSON.stringify({ action, product: options.productId, ...payload }),
98
+ });
99
+ if (!response.ok) {
100
+ const detail = await response.json().catch(() => ({}));
101
+ throw new SupabaseGistError(response.status, detail.code ?? 'cloud_error', detail.error ?? 'GitHub Gist storage is unavailable.');
102
+ }
103
+ return response.json();
104
+ }
105
+ return {
106
+ async connect() {
107
+ const result = await options.auth.signInWithOAuth({
108
+ provider: 'github',
109
+ options: { scopes: 'gist', redirectTo: options.location.href },
110
+ });
111
+ if (result.error)
112
+ throw result.error;
113
+ },
114
+ async disconnect() {
115
+ const status = await invoke('disconnect');
116
+ const result = await options.auth.signOut({ scope: 'local' });
117
+ if (result.error)
118
+ throw result.error;
119
+ capturedProviderToken = null;
120
+ pendingProviderToken = null;
121
+ return { ...status, authenticated: false, invited: false };
122
+ },
123
+ async status() {
124
+ await initialAuthState;
125
+ const current = await session();
126
+ if (!current)
127
+ return { authenticated: false, invited: false, connected: false };
128
+ let access = await invoke('access-status');
129
+ if (!access.invited)
130
+ return access;
131
+ const nextProviderToken = current.provider_token ?? pendingProviderToken ?? options.consumeProviderToken?.();
132
+ if (nextProviderToken && nextProviderToken !== capturedProviderToken) {
133
+ pendingProviderToken = nextProviderToken;
134
+ await invoke('connect', { providerToken: nextProviderToken });
135
+ capturedProviderToken = nextProviderToken;
136
+ pendingProviderToken = null;
137
+ access = await invoke('access-status');
138
+ }
139
+ return access;
140
+ },
141
+ async redeemInvite(code) {
142
+ const normalized = code.trim();
143
+ const bytes = new TextEncoder().encode(normalized);
144
+ const digest = await crypto.subtle.digest('SHA-256', bytes);
145
+ const codeHash = Array.from(new Uint8Array(digest), (value) => value.toString(16).padStart(2, '0')).join('');
146
+ await invoke('redeem-invite', { codeHash });
147
+ return this.status();
148
+ },
149
+ list(page = 1) {
150
+ return invoke('list', { page });
151
+ },
152
+ read(id, path) {
153
+ return invoke('read', { id, path });
154
+ },
155
+ write(input) {
156
+ return invoke('write', { input });
157
+ },
158
+ readShared(url, name) {
159
+ return invoke('shared-read', { url, name });
160
+ },
161
+ };
162
+ }
163
+ function canonicalGistUrl(value) {
164
+ try {
165
+ const url = new URL(value);
166
+ const parts = url.pathname.split('/').filter(Boolean);
167
+ if (url.protocol !== 'https:' || url.hostname !== 'gist.github.com' || parts.length !== 2)
168
+ return null;
169
+ if (!/^[A-Za-z0-9-]+$/.test(parts[0]) || !/^[a-fA-F0-9]+$/.test(parts[1]))
170
+ return null;
171
+ return `https://gist.github.com/${parts[0]}/${parts[1]}`;
172
+ }
173
+ catch {
174
+ return null;
175
+ }
176
+ }
177
+ export function createGistShareUrl(origin, target) {
178
+ const gistUrl = canonicalGistUrl(target.gistUrl);
179
+ if (!gistUrl || !target.fileName || target.fileName.includes('/') || target.fileName.includes('\\')) {
180
+ throw new Error('Invalid Gist share target.');
181
+ }
182
+ const url = new URL('/', origin);
183
+ const parameters = new URLSearchParams({
184
+ gist: gistUrl,
185
+ file: target.fileName,
186
+ view: target.view ?? 'edit',
187
+ });
188
+ url.hash = parameters.toString();
189
+ return url.toString();
190
+ }
191
+ export function parseGistShareHash(hash) {
192
+ const source = hash.startsWith('#') ? hash.slice(1) : hash;
193
+ const parameters = new URLSearchParams(source);
194
+ const gistUrl = parameters.get('gist');
195
+ const fileName = parameters.get('file');
196
+ const view = parameters.get('view') ?? 'edit';
197
+ const canonical = gistUrl ? canonicalGistUrl(gistUrl) : null;
198
+ if (!canonical || !fileName || fileName.includes('/') || fileName.includes('\\'))
199
+ return null;
200
+ if (view !== 'edit' && view !== 'preview')
201
+ return null;
202
+ return { gistUrl: canonical, fileName, view };
203
+ }
204
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './browser.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './browser.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { type DocumentExtension, type RemoteDocumentRef, type RemoteVisibility, type StorageProfile } from './types.js';
2
+ export interface AccessToken {
3
+ accessToken: string;
4
+ }
5
+ export interface GitHubGistWriteInput<Extension extends DocumentExtension> {
6
+ name: string;
7
+ content: string;
8
+ extension: Extension;
9
+ visibility?: RemoteVisibility;
10
+ saveCopy?: boolean;
11
+ remote?: RemoteDocumentRef<Extension>;
12
+ }
13
+ export interface GitHubGistProvider<Extension extends DocumentExtension> {
14
+ parseSharedUrl(value: unknown): {
15
+ id: string;
16
+ url: string;
17
+ } | null;
18
+ list(page: number, tokens: AccessToken): Promise<Response>;
19
+ read(id: string, requestedName: string | undefined, tokens: AccessToken | undefined, canEdit: boolean): Promise<Response>;
20
+ write(input: GitHubGistWriteInput<Extension>, tokens: AccessToken): Promise<Response>;
21
+ }
22
+ interface GitHubGistProviderOptions<Extension extends DocumentExtension> {
23
+ profile: StorageProfile<Extension>;
24
+ maximumFileSize?: number;
25
+ fetchImpl?: typeof fetch;
26
+ }
27
+ export declare function createGitHubGistProvider<Extension extends DocumentExtension>(options: GitHubGistProviderOptions<Extension>): GitHubGistProvider<Extension>;
28
+ export {};
29
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,oBAAoB,CAAC,SAAS,SAAS,iBAAiB;IACvE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,SAAS,CAAA;IACpB,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,kBAAkB,CAAC,SAAS,SAAS,iBAAiB;IACrE,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAClE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACzH,KAAK,CAAC,KAAK,EAAE,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtF;AAED,UAAU,yBAAyB,CAAC,SAAS,SAAS,iBAAiB;IACrE,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAA;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AA2CD,wBAAgB,wBAAwB,CAAC,SAAS,SAAS,iBAAiB,EAC1E,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,kBAAkB,CAAC,SAAS,CAAC,CAgH/B"}
package/dist/server.js ADDED
@@ -0,0 +1,165 @@
1
+ import { extensionFromFileName, mimeTypeForExtension, } from './types.js';
2
+ function json(status, payload) {
3
+ return Response.json(payload, { status, headers: { 'Cache-Control': 'no-store' } });
4
+ }
5
+ function error(status, code, message) {
6
+ return json(status, { code, error: message });
7
+ }
8
+ function headers(tokens) {
9
+ return {
10
+ Accept: 'application/vnd.github+json',
11
+ 'X-GitHub-Api-Version': '2022-11-28',
12
+ ...(tokens ? { Authorization: `Bearer ${tokens.accessToken}` } : {}),
13
+ };
14
+ }
15
+ function revision(gist) {
16
+ const history = Array.isArray(gist.history) ? gist.history : [];
17
+ return String(history[0]?.version ?? gist.updated_at ?? '');
18
+ }
19
+ function visibility(gist) {
20
+ return gist.public === true ? 'public' : 'secret';
21
+ }
22
+ function files(gist) {
23
+ return gist.files && typeof gist.files === 'object' ? gist.files : {};
24
+ }
25
+ function nextPage(header) {
26
+ if (!header)
27
+ return null;
28
+ for (const part of header.split(',')) {
29
+ if (!/rel="next"/.test(part))
30
+ continue;
31
+ const match = part.match(/<([^>]+)>/);
32
+ if (!match)
33
+ continue;
34
+ const page = Number(new URL(match[1]).searchParams.get('page'));
35
+ return Number.isSafeInteger(page) && page > 0 ? page : null;
36
+ }
37
+ return null;
38
+ }
39
+ export function createGitHubGistProvider(options) {
40
+ const { profile } = options;
41
+ const maximumFileSize = options.maximumFileSize ?? 5 * 1024 * 1024;
42
+ const request = (...args) => (options.fetchImpl ?? fetch)(...args);
43
+ const gist = async (id, tokens) => {
44
+ const response = await request(`https://api.github.com/gists/${encodeURIComponent(id)}`, { headers: headers(tokens) });
45
+ if (response.status === 404)
46
+ throw Object.assign(new Error('This Gist no longer exists.'), { status: 404, code: 'not_found' });
47
+ if (response.status === 403 || response.status === 429)
48
+ throw Object.assign(new Error('GitHub rate limited this request. Try again later.'), { status: 429, code: 'rate_limited' });
49
+ if (!response.ok)
50
+ throw Object.assign(new Error('GitHub could not open this Gist.'), { status: response.status, code: 'provider_error' });
51
+ return response.json();
52
+ };
53
+ const fileRef = (payload, name, canEdit) => {
54
+ const fileExtension = extensionFromFileName(name, profile);
55
+ if (!fileExtension)
56
+ throw Object.assign(new Error('Choose a supported Gist file.'), { status: 415, code: 'unsupported_file' });
57
+ return {
58
+ provider: 'github-gist', id: String(payload.id ?? ''), path: name, name, extension: fileExtension,
59
+ mimeType: mimeTypeForExtension(fileExtension), revision: revision(payload),
60
+ modifiedAt: typeof payload.updated_at === 'string' ? payload.updated_at : undefined,
61
+ url: typeof payload.html_url === 'string' ? payload.html_url : undefined,
62
+ visibility: visibility(payload), canEdit, lastSavedFingerprint: '',
63
+ };
64
+ };
65
+ const fileContent = async (payload, requestedName) => {
66
+ const gistFiles = files(payload);
67
+ const name = requestedName && gistFiles[requestedName]
68
+ ? requestedName
69
+ : Object.keys(gistFiles).find((candidate) => extensionFromFileName(candidate, profile) !== null);
70
+ if (!name || !extensionFromFileName(name, profile)) {
71
+ throw Object.assign(new Error('Choose a supported Gist file.'), { status: 415, code: 'unsupported_file' });
72
+ }
73
+ const file = gistFiles[name];
74
+ if (file.truncated === true) {
75
+ const rawUrl = new URL(String(file.raw_url ?? ''));
76
+ if (rawUrl.protocol !== 'https:' || rawUrl.hostname !== 'gist.githubusercontent.com') {
77
+ throw Object.assign(new Error('GitHub returned an invalid Gist file URL.'), { status: 502, code: 'provider_error' });
78
+ }
79
+ const response = await request(rawUrl, { headers: { Accept: 'text/plain' }, redirect: 'error' });
80
+ if (!response.ok)
81
+ throw Object.assign(new Error('GitHub could not download this Gist file.'), { status: response.status, code: 'provider_error' });
82
+ const content = await response.text();
83
+ if (new TextEncoder().encode(content).byteLength > maximumFileSize) {
84
+ throw Object.assign(new Error('Choose a text file smaller than 5 MiB.'), { status: 413, code: 'file_too_large' });
85
+ }
86
+ return { content, name };
87
+ }
88
+ const content = String(file.content ?? '');
89
+ if (new TextEncoder().encode(content).byteLength > maximumFileSize) {
90
+ throw Object.assign(new Error('Choose a text file smaller than 5 MiB.'), { status: 413, code: 'file_too_large' });
91
+ }
92
+ return { content, name };
93
+ };
94
+ return {
95
+ parseSharedUrl(value) {
96
+ if (typeof value !== 'string')
97
+ return null;
98
+ try {
99
+ const url = new URL(value);
100
+ if (url.protocol !== 'https:' || url.hostname !== 'gist.github.com' || url.username || url.password)
101
+ return null;
102
+ const parts = url.pathname.split('/').filter(Boolean);
103
+ const id = parts.at(-1)?.replace(/\.git$/i, '') ?? '';
104
+ if (parts.length !== 2 || !/^[a-zA-Z0-9]+$/.test(id))
105
+ return null;
106
+ return { id, url: `https://gist.github.com/${parts[0]}/${id}` };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ },
112
+ async list(page, tokens) {
113
+ const response = await request(`https://api.github.com/gists?per_page=30&page=${page}`, { headers: headers(tokens) });
114
+ if (response.status === 403 || response.status === 429)
115
+ return error(429, 'rate_limited', 'GitHub rate limited this request. Try again later.');
116
+ if (!response.ok)
117
+ return error(response.status, 'provider_error', 'GitHub could not list your Gists.');
118
+ const payload = await response.json();
119
+ const entries = payload.flatMap((item) => Object.values(files(item)).flatMap((file) => {
120
+ const name = String(file.filename ?? '');
121
+ const fileExtension = extensionFromFileName(name, profile);
122
+ if (!fileExtension)
123
+ return [];
124
+ return [{
125
+ id: String(item.id ?? ''), name, path: name, kind: 'file', extension: fileExtension,
126
+ revision: revision(item), url: typeof item.html_url === 'string' ? item.html_url : undefined,
127
+ visibility: visibility(item), modifiedAt: typeof item.updated_at === 'string' ? item.updated_at : undefined,
128
+ }];
129
+ }));
130
+ return json(200, { entries, nextPage: nextPage(response.headers.get('link')) });
131
+ },
132
+ async read(id, requestedName, tokens, canEdit) {
133
+ const payload = await gist(id, tokens);
134
+ const { content, name } = await fileContent(payload, requestedName);
135
+ return json(200, { content, file: fileRef(payload, name, canEdit) });
136
+ },
137
+ async write(input, tokens) {
138
+ const updating = Boolean(input.remote?.id && !input.saveCopy);
139
+ if (updating) {
140
+ const current = await gist(input.remote.id, tokens);
141
+ if (revision(current) !== input.remote?.revision)
142
+ return error(409, 'revision_conflict', 'This Gist changed since it was opened.');
143
+ }
144
+ const endpoint = updating ? `https://api.github.com/gists/${encodeURIComponent(input.remote.id)}` : 'https://api.github.com/gists';
145
+ const gistFiles = { [input.name]: { content: input.content } };
146
+ if (updating && input.remote?.name && input.remote.name !== input.name)
147
+ gistFiles[input.remote.name] = null;
148
+ const body = { description: `${input.name} · ${profile.productName}`, files: gistFiles };
149
+ if (!updating)
150
+ body.public = input.visibility === 'public';
151
+ const response = await request(endpoint, {
152
+ method: updating ? 'PATCH' : 'POST',
153
+ headers: { ...headers(tokens), 'Content-Type': 'application/json' },
154
+ body: JSON.stringify(body),
155
+ });
156
+ if (response.status === 403 || response.status === 429)
157
+ return error(429, 'rate_limited', 'GitHub rate limited this request. Try again later.');
158
+ if (!response.ok)
159
+ return error(response.status, 'provider_error', 'GitHub could not save this Gist.');
160
+ const payload = await response.json();
161
+ return json(200, { file: fileRef(payload, input.name, true) });
162
+ },
163
+ };
164
+ }
165
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ export type DocumentExtension = 'md' | 'mdx' | 'txt';
2
+ export type RemoteProvider = 'github-gist' | 'google-drive' | 'dropbox';
3
+ export type RemoteVisibility = 'secret' | 'public';
4
+ export interface StorageProfile<Extension extends DocumentExtension = DocumentExtension> {
5
+ productId: string;
6
+ productName: string;
7
+ databaseName: string;
8
+ sessionCookie: string;
9
+ blobStoreName: string;
10
+ requestHeader: string;
11
+ allowedExtensions: readonly Extension[];
12
+ defaultExtension: Extension;
13
+ acceptsExtension(value: string): value is Extension;
14
+ }
15
+ type StorageProfileInput<Extensions extends readonly DocumentExtension[]> = Omit<StorageProfile<Extensions[number]>, 'allowedExtensions' | 'acceptsExtension'> & {
16
+ allowedExtensions: Extensions;
17
+ };
18
+ export declare function createStorageProfile<const Extensions extends readonly DocumentExtension[]>(input: StorageProfileInput<Extensions>): StorageProfile<Extensions[number]>;
19
+ export interface RemoteDocumentRef<Extension extends DocumentExtension = DocumentExtension> {
20
+ provider: RemoteProvider;
21
+ id: string;
22
+ path?: string;
23
+ name: string;
24
+ extension: Extension;
25
+ mimeType: 'text/markdown' | 'text/plain';
26
+ revision: string;
27
+ modifiedAt?: string;
28
+ url?: string;
29
+ visibility?: RemoteVisibility;
30
+ canEdit: boolean;
31
+ lastSavedFingerprint: string;
32
+ }
33
+ export interface DocumentRecord<Extension extends DocumentExtension = DocumentExtension> {
34
+ id: string;
35
+ title: string;
36
+ markdown: string;
37
+ extension: Extension;
38
+ createdAt: string;
39
+ updatedAt: string;
40
+ openedAt: string;
41
+ cloud?: RemoteDocumentRef<Extension>;
42
+ }
43
+ export interface DocumentLibrary<Extension extends DocumentExtension = DocumentExtension> {
44
+ documents: DocumentRecord<Extension>[];
45
+ activeDocument: DocumentRecord<Extension>;
46
+ previousDocumentId: string | null;
47
+ }
48
+ export interface LegacyDocument {
49
+ version: 1;
50
+ title: string;
51
+ markdown: string;
52
+ savedAt: string;
53
+ }
54
+ export declare function extensionFromFileName<Extension extends DocumentExtension>(name: string, profile: StorageProfile<Extension>): Extension | null;
55
+ export declare function mimeTypeForExtension(extension: DocumentExtension): 'text/markdown' | 'text/plain';
56
+ export {};
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,22 @@
1
+ export function createStorageProfile(input) {
2
+ const allowed = new Set(input.allowedExtensions);
3
+ if (!allowed.has(input.defaultExtension)) {
4
+ throw new Error('The default extension must be included in the storage profile.');
5
+ }
6
+ return Object.freeze({
7
+ ...input,
8
+ allowedExtensions: Object.freeze([...input.allowedExtensions]),
9
+ acceptsExtension(value) {
10
+ return allowed.has(value.toLowerCase());
11
+ },
12
+ });
13
+ }
14
+ export function extensionFromFileName(name, profile) {
15
+ const match = name.toLowerCase().match(/\.([a-z0-9]+)$/);
16
+ const value = match?.[1] ?? '';
17
+ return profile.acceptsExtension(value) ? value : null;
18
+ }
19
+ export function mimeTypeForExtension(extension) {
20
+ return extension === 'txt' ? 'text/plain' : 'text/markdown';
21
+ }
22
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,oBAAoB,CAClC,KAAsC;IAEtC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;IACnF,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,KAAK;QACR,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC9D,gBAAgB,CAAC,KAAa;YAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;QACzC,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAyCD,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,OAAkC;IAElC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACxD,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9B,OAAO,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACvD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,SAA4B;IAC/D,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAA;AAC7D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "litsquare-storage-core",
3
+ "version": "0.3.0",
4
+ "description": "Offline-first browser and remote document storage for LitSquare Ink applications.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "files": ["dist"],
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./browser": {
15
+ "types": "./dist/browser.d.ts",
16
+ "import": "./dist/browser.js"
17
+ },
18
+ "./client": {
19
+ "types": "./dist/client.d.ts",
20
+ "import": "./dist/client.js"
21
+ },
22
+ "./server": {
23
+ "types": "./dist/server.d.ts",
24
+ "import": "./dist/server.js"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "tsc -p tsconfig.json",
29
+ "prepack": "npm run build"
30
+ },
31
+ "dependencies": {
32
+ "@netlify/blobs": "^11.0.1"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^26.2.0",
36
+ "typescript": "^6.0.3"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }