@instantdb/platform 1.0.60 → 1.0.61

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.
Files changed (42) hide show
  1. package/.turbo/turbo-build.log +9 -9
  2. package/__tests__/src/backupDownload.test.ts +193 -0
  3. package/__tests__/src/backups.test.ts +168 -0
  4. package/dist/commonjs/api.d.ts +7 -0
  5. package/dist/commonjs/api.d.ts.map +1 -1
  6. package/dist/commonjs/api.js +10 -0
  7. package/dist/commonjs/api.js.map +1 -1
  8. package/dist/commonjs/backupDownload.d.ts +74 -0
  9. package/dist/commonjs/backupDownload.d.ts.map +1 -0
  10. package/dist/commonjs/backupDownload.js +255 -0
  11. package/dist/commonjs/backupDownload.js.map +1 -0
  12. package/dist/commonjs/backups.d.ts +146 -0
  13. package/dist/commonjs/backups.d.ts.map +1 -0
  14. package/dist/commonjs/backups.js +248 -0
  15. package/dist/commonjs/backups.js.map +1 -0
  16. package/dist/commonjs/index.d.ts +2 -0
  17. package/dist/commonjs/index.d.ts.map +1 -1
  18. package/dist/commonjs/index.js +7 -1
  19. package/dist/commonjs/index.js.map +1 -1
  20. package/dist/esm/api.d.ts +7 -0
  21. package/dist/esm/api.d.ts.map +1 -1
  22. package/dist/esm/api.js +10 -0
  23. package/dist/esm/api.js.map +1 -1
  24. package/dist/esm/backupDownload.d.ts +74 -0
  25. package/dist/esm/backupDownload.d.ts.map +1 -0
  26. package/dist/esm/backupDownload.js +252 -0
  27. package/dist/esm/backupDownload.js.map +1 -0
  28. package/dist/esm/backups.d.ts +146 -0
  29. package/dist/esm/backups.d.ts.map +1 -0
  30. package/dist/esm/backups.js +237 -0
  31. package/dist/esm/backups.js.map +1 -0
  32. package/dist/esm/index.d.ts +2 -0
  33. package/dist/esm/index.d.ts.map +1 -1
  34. package/dist/esm/index.js +1 -0
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/standalone/index.js +1929 -1610
  37. package/dist/standalone/index.umd.cjs +24 -22
  38. package/package.json +4 -4
  39. package/src/api.ts +15 -0
  40. package/src/backupDownload.ts +364 -0
  41. package/src/backups.ts +342 -0
  42. package/src/index.ts +18 -0
@@ -0,0 +1,237 @@
1
+ import { InstantAPIError, version as coreVersion } from '@instantdb/core';
2
+ import version from "./version.js";
3
+ import { downloadBackupArchive, } from "./backupDownload.js";
4
+ /** Converts a backup row as the server sends it into an {@link AppBackup}. */
5
+ export function toAppBackup(row) {
6
+ return {
7
+ id: row.id,
8
+ isn: row.isn,
9
+ backupAt: new Date(row.backup_at),
10
+ filesSize: row.files_size,
11
+ dbSize: row.db_size,
12
+ uncompressedSize: row.uncompressed_size,
13
+ description: row.description,
14
+ expiresAt: row.expires_at ? new Date(row.expires_at) : null,
15
+ };
16
+ }
17
+ /** Suggested filename for a backup archive. */
18
+ export function backupZipName(backup) {
19
+ const safe = backup.backupAt.toISOString().replace(/[:.]/g, '-');
20
+ return `instant-backup-${safe}.zip`;
21
+ }
22
+ /**
23
+ * Formats a byte count the way macOS/Finder reports file sizes: decimal
24
+ * (1000-based) units with SI labels, so the number lines up with what lands
25
+ * on disk.
26
+ */
27
+ export function formatFileSize(n) {
28
+ if (n < 1000)
29
+ return `${n} B`;
30
+ const units = ['KB', 'MB', 'GB', 'TB'];
31
+ let i = -1;
32
+ let v = n;
33
+ do {
34
+ v /= 1000;
35
+ i++;
36
+ } while (v >= 1000 && i < units.length - 1);
37
+ let digits = v < 10 ? 2 : v < 100 ? 1 : 0;
38
+ // Rounding can cross a unit boundary (999,500 would read "1000 KB");
39
+ // promote to the next unit instead.
40
+ if (Number(v.toFixed(digits)) >= 1000 && i < units.length - 1) {
41
+ v /= 1000;
42
+ i++;
43
+ digits = 2;
44
+ }
45
+ return `${v.toFixed(digits)} ${units[i]}`;
46
+ }
47
+ /**
48
+ * Estimated size range for a backup's zip archive, or null when the backup
49
+ * row carries no sizes. Upper bound: everything stored uncompressed (STORE
50
+ * mode and/or files that don't compress). Lower bound: everything compressed
51
+ * at a ~4x DEFLATE ratio, best case for text/JSON, but storage files vary
52
+ * wildly (raw text compresses well, already-compressed images/videos don't).
53
+ * The same divisor applies to both since the file types aren't visible from
54
+ * here; the actual zip lands somewhere inside the range.
55
+ */
56
+ export function estimateZipSize(backup) {
57
+ const backupBytes = backup.uncompressedSize ?? backup.dbSize;
58
+ if (backupBytes == null || backup.filesSize == null)
59
+ return null;
60
+ const max = backupBytes + backup.filesSize;
61
+ return { min: Math.round(max / 4), max };
62
+ }
63
+ function authHeaders(token) {
64
+ return {
65
+ authorization: `Bearer ${token}`,
66
+ 'Instant-Platform-Version': version,
67
+ 'Instant-Core-Version': coreVersion,
68
+ 'X-Instant-Source': 'platform-sdk',
69
+ 'X-Instant-Version': version,
70
+ };
71
+ }
72
+ async function apiError(res) {
73
+ const body = await res.text();
74
+ try {
75
+ return new InstantAPIError({ status: res.status, body: JSON.parse(body) });
76
+ }
77
+ catch (_e) {
78
+ return new InstantAPIError({
79
+ status: res.status,
80
+ body: { type: undefined, message: body },
81
+ });
82
+ }
83
+ }
84
+ async function* ndjsonLines(body) {
85
+ const reader = body.getReader();
86
+ try {
87
+ const decoder = new TextDecoder();
88
+ let buf = '';
89
+ while (true) {
90
+ const { done, value } = await reader.read();
91
+ if (done)
92
+ break;
93
+ buf += decoder.decode(value, { stream: true });
94
+ let nl = buf.indexOf('\n');
95
+ while (nl !== -1) {
96
+ const line = buf.slice(0, nl).trim();
97
+ buf = buf.slice(nl + 1);
98
+ if (line.length > 0) {
99
+ yield JSON.parse(line);
100
+ }
101
+ nl = buf.indexOf('\n');
102
+ }
103
+ }
104
+ const line = buf.trim();
105
+ if (line.length > 0) {
106
+ yield JSON.parse(line);
107
+ }
108
+ }
109
+ finally {
110
+ // Also releases the connection when the consumer stops iterating early.
111
+ await reader.cancel().catch(() => { });
112
+ }
113
+ }
114
+ /**
115
+ * Read-only API for an app's backups.
116
+ *
117
+ * A backup archive has a canonical entry order that restore relies on:
118
+ * `config.json` first, then every `entities/<etype>.jsonl` shard, then the
119
+ * `files/<locationId>` storage blobs. In particular ALL entity files must
120
+ * come before ANY storage file, so a restore can process the archive in a
121
+ * single streaming pass: `config.json` sets up the schema, the `$files`
122
+ * entities register file metadata, and only then can each blob be matched
123
+ * to its entity. {@link downloadArchive} implements that order end to end;
124
+ * {@link listFiles} (which returns the entity files already in write order)
125
+ * and {@link streamStorageFiles} are the pieces for building a custom
126
+ * pipeline.
127
+ */
128
+ export class BackupsManager {
129
+ #appId;
130
+ #apiURI;
131
+ #withAuth;
132
+ constructor(opts) {
133
+ this.#appId = opts.appId;
134
+ this.#apiURI = opts.apiURI;
135
+ this.#withAuth = opts.withAuth;
136
+ }
137
+ #getJson(path, signal) {
138
+ return this.#withAuth(async (token) => {
139
+ const res = await fetch(`${this.#apiURI}${path}`, {
140
+ headers: authHeaders(token),
141
+ signal,
142
+ });
143
+ if (res.status !== 200) {
144
+ throw await apiError(res);
145
+ }
146
+ return res.json();
147
+ });
148
+ }
149
+ /**
150
+ * Returns the app's downloadable (non-expired) backups, newest first.
151
+ */
152
+ async list(opts) {
153
+ const res = await this.#getJson(`/dash/apps/${this.#appId}/backups`, opts?.signal);
154
+ return (res.backups || []).map(toAppBackup);
155
+ }
156
+ /**
157
+ * Returns the backup's entity files (`config.json` and the
158
+ * `entities/<etype>.jsonl` shards) in archive write order. Storage blobs
159
+ * are not included; discover those with {@link streamStorageFiles}.
160
+ */
161
+ async listFiles(backupId, opts) {
162
+ const res = await this.#getJson(`/dash/apps/${this.#appId}/backups/${backupId}/files`, opts?.signal);
163
+ return (res.files || []);
164
+ }
165
+ /**
166
+ * Returns a presigned download URL for one of the backup's entity files.
167
+ * The URL expires after 1 hour, so fetch it right before downloading.
168
+ *
169
+ * The entity files are stored zstd-compressed (the response carries
170
+ * `Content-Encoding: zstd`); decompress to get the raw JSON/JSONL.
171
+ */
172
+ async getFileUrl(backupId, name, opts) {
173
+ const res = await this.#getJson(`/dash/apps/${this.#appId}/backups/${backupId}/file-url?name=${encodeURIComponent(name)}`, opts?.signal);
174
+ return res.url;
175
+ }
176
+ /**
177
+ * Streams every storage file captured in the backup, each with a presigned
178
+ * download URL. Completes without yielding anything when the app has no
179
+ * storage files.
180
+ *
181
+ * The server ends a healthy stream with a terminal sentinel; if the stream
182
+ * closes without it (a server-side failure truncated the listing), this
183
+ * throws instead of silently under-reporting files.
184
+ */
185
+ async *streamStorageFiles(backupId, opts) {
186
+ const res = await this.#withAuth(async (token) => {
187
+ const res = await fetch(`${this.#apiURI}/dash/apps/${this.#appId}/backups/${backupId}/storage-files`, { headers: authHeaders(token), signal: opts?.signal });
188
+ if (res.status !== 200) {
189
+ throw await apiError(res);
190
+ }
191
+ return res;
192
+ });
193
+ if (!res.body) {
194
+ throw new Error('Storage file listing returned no body.');
195
+ }
196
+ let complete = false;
197
+ for await (const line of ndjsonLines(res.body)) {
198
+ if (line.done === true) {
199
+ complete = true;
200
+ break;
201
+ }
202
+ // A file record always carries a locationId and url; anything else is
203
+ // corruption, and skipping it would silently omit a file from the
204
+ // archive.
205
+ if (typeof line.locationId !== 'string' ||
206
+ line.locationId.length === 0 ||
207
+ // The locationId becomes the archive entry path `files/<locationId>`;
208
+ // reject separators and control characters that could escape it.
209
+ /[/\\\u0000-\u001f\u007f]/.test(line.locationId) ||
210
+ line.locationId === '.' ||
211
+ line.locationId === '..' ||
212
+ typeof line.url !== 'string' ||
213
+ line.url.length === 0) {
214
+ throw new Error('Storage file listing returned a malformed record. Please retry the download.');
215
+ }
216
+ yield {
217
+ locationId: line.locationId,
218
+ path: line.path ?? null,
219
+ url: line.url,
220
+ };
221
+ }
222
+ if (!complete) {
223
+ throw new Error('Storage file listing ended before it finished. Please retry the download.');
224
+ }
225
+ }
226
+ /**
227
+ * Downloads the backup into a single zip archive written to `opts.sink`,
228
+ * entries in the canonical restore order described above. The caller
229
+ * supplies the runtime-specific pieces — how to fetch a presigned URL,
230
+ * where the bytes go, and the archive encoder (e.g. zip.js's `ZipWriter`);
231
+ * see {@link DownloadBackupArchiveOpts}.
232
+ */
233
+ downloadArchive(opts) {
234
+ return downloadBackupArchive({ manager: this, ...opts });
235
+ }
236
+ }
237
+ //# sourceMappingURL=backups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backups.js","sourceRoot":"","sources":["../../src/backups.ts"],"names":[],"mappings":"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","sourcesContent":["import { InstantAPIError, version as coreVersion } from '@instantdb/core';\nimport type { WithAuth } from '@instantdb/webhooks';\nimport version from './version.ts';\nimport {\n downloadBackupArchive,\n type BackupDownloadResult,\n type DownloadBackupArchiveOpts,\n} from './backupDownload.ts';\n\n/** A point-in-time snapshot of an app. */\nexport type AppBackup = {\n /** Unique identifier for the backup. */\n id: string;\n /** Instant sequence number the snapshot was taken at. */\n isn: string;\n /** When the snapshot was taken. */\n backupAt: Date;\n /** Total size in bytes of the app's storage files at backup time, if known. */\n filesSize: number | null;\n /** Size in bytes of the app's database at backup time, if known. */\n dbSize: number | null;\n /**\n * Total uncompressed size in bytes of the backup's entity files (what they\n * take up unpacked on disk), if known.\n */\n uncompressedSize: number | null;\n /** Human-readable label, e.g. \"Automated Daily Snapshot\". */\n description: string | null;\n /** When the backup stops being available for download. */\n expiresAt: Date | null;\n};\n\n/**\n * A file that makes up the backup payload: `config.json` or an\n * `entities/<etype>.jsonl` shard.\n */\nexport type AppBackupFile = {\n name: string;\n /** Size in bytes as stored (the entity shards are stored compressed). */\n size: number;\n};\n\n/** A storage file captured in a backup, with a presigned download URL. */\nexport type AppBackupStorageFile = {\n /**\n * Stable id of the file's blob. A backup archive stores the blob at\n * `files/<locationId>`.\n */\n locationId: string;\n /** The path the user uploaded the file to. */\n path: string | null;\n /** Presigned URL for the file's contents. Expires after 12 hours. */\n url: string;\n};\n\ntype AppBackupResponse = {\n id: string;\n isn: string;\n backup_at: string;\n files_size: number | null;\n db_size: number | null;\n uncompressed_size: number | null;\n description: string | null;\n expires_at: string | null;\n};\n\n/** Converts a backup row as the server sends it into an {@link AppBackup}. */\nexport function toAppBackup(row: AppBackupResponse): AppBackup {\n return {\n id: row.id,\n isn: row.isn,\n backupAt: new Date(row.backup_at),\n filesSize: row.files_size,\n dbSize: row.db_size,\n uncompressedSize: row.uncompressed_size,\n description: row.description,\n expiresAt: row.expires_at ? new Date(row.expires_at) : null,\n };\n}\n\n/** Suggested filename for a backup archive. */\nexport function backupZipName(backup: AppBackup): string {\n const safe = backup.backupAt.toISOString().replace(/[:.]/g, '-');\n return `instant-backup-${safe}.zip`;\n}\n\n/**\n * Formats a byte count the way macOS/Finder reports file sizes: decimal\n * (1000-based) units with SI labels, so the number lines up with what lands\n * on disk.\n */\nexport function formatFileSize(n: number): string {\n if (n < 1000) return `${n} B`;\n const units = ['KB', 'MB', 'GB', 'TB'];\n let i = -1;\n let v = n;\n do {\n v /= 1000;\n i++;\n } while (v >= 1000 && i < units.length - 1);\n let digits = v < 10 ? 2 : v < 100 ? 1 : 0;\n // Rounding can cross a unit boundary (999,500 would read \"1000 KB\");\n // promote to the next unit instead.\n if (Number(v.toFixed(digits)) >= 1000 && i < units.length - 1) {\n v /= 1000;\n i++;\n digits = 2;\n }\n return `${v.toFixed(digits)} ${units[i]}`;\n}\n\n/**\n * Estimated size range for a backup's zip archive, or null when the backup\n * row carries no sizes. Upper bound: everything stored uncompressed (STORE\n * mode and/or files that don't compress). Lower bound: everything compressed\n * at a ~4x DEFLATE ratio, best case for text/JSON, but storage files vary\n * wildly (raw text compresses well, already-compressed images/videos don't).\n * The same divisor applies to both since the file types aren't visible from\n * here; the actual zip lands somewhere inside the range.\n */\nexport function estimateZipSize(\n backup: AppBackup,\n): { min: number; max: number } | null {\n const backupBytes = backup.uncompressedSize ?? backup.dbSize;\n if (backupBytes == null || backup.filesSize == null) return null;\n const max = backupBytes + backup.filesSize;\n return { min: Math.round(max / 4), max };\n}\n\nfunction authHeaders(token: string): Record<string, string> {\n return {\n authorization: `Bearer ${token}`,\n 'Instant-Platform-Version': version,\n 'Instant-Core-Version': coreVersion,\n 'X-Instant-Source': 'platform-sdk',\n 'X-Instant-Version': version,\n };\n}\n\nasync function apiError(res: Response): Promise<InstantAPIError> {\n const body = await res.text();\n try {\n return new InstantAPIError({ status: res.status, body: JSON.parse(body) });\n } catch (_e) {\n return new InstantAPIError({\n status: res.status,\n body: { type: undefined, message: body },\n });\n }\n}\n\nasync function* ndjsonLines(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<any, void, void> {\n const reader = body.getReader();\n try {\n const decoder = new TextDecoder();\n let buf = '';\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n let nl = buf.indexOf('\\n');\n while (nl !== -1) {\n const line = buf.slice(0, nl).trim();\n buf = buf.slice(nl + 1);\n if (line.length > 0) {\n yield JSON.parse(line);\n }\n nl = buf.indexOf('\\n');\n }\n }\n const line = buf.trim();\n if (line.length > 0) {\n yield JSON.parse(line);\n }\n } finally {\n // Also releases the connection when the consumer stops iterating early.\n await reader.cancel().catch(() => {});\n }\n}\n\n/**\n * Read-only API for an app's backups.\n *\n * A backup archive has a canonical entry order that restore relies on:\n * `config.json` first, then every `entities/<etype>.jsonl` shard, then the\n * `files/<locationId>` storage blobs. In particular ALL entity files must\n * come before ANY storage file, so a restore can process the archive in a\n * single streaming pass: `config.json` sets up the schema, the `$files`\n * entities register file metadata, and only then can each blob be matched\n * to its entity. {@link downloadArchive} implements that order end to end;\n * {@link listFiles} (which returns the entity files already in write order)\n * and {@link streamStorageFiles} are the pieces for building a custom\n * pipeline.\n */\nexport class BackupsManager {\n #appId: string;\n #apiURI: string;\n #withAuth: WithAuth;\n\n constructor(opts: { appId: string; apiURI: string; withAuth: WithAuth }) {\n this.#appId = opts.appId;\n this.#apiURI = opts.apiURI;\n this.#withAuth = opts.withAuth;\n }\n\n #getJson(path: string, signal?: AbortSignal): Promise<any> {\n return this.#withAuth(async (token) => {\n const res = await fetch(`${this.#apiURI}${path}`, {\n headers: authHeaders(token),\n signal,\n });\n if (res.status !== 200) {\n throw await apiError(res);\n }\n return res.json();\n });\n }\n\n /**\n * Returns the app's downloadable (non-expired) backups, newest first.\n */\n async list(opts?: { signal?: AbortSignal }): Promise<AppBackup[]> {\n const res = await this.#getJson(\n `/dash/apps/${this.#appId}/backups`,\n opts?.signal,\n );\n return ((res.backups || []) as AppBackupResponse[]).map(toAppBackup);\n }\n\n /**\n * Returns the backup's entity files (`config.json` and the\n * `entities/<etype>.jsonl` shards) in archive write order. Storage blobs\n * are not included; discover those with {@link streamStorageFiles}.\n */\n async listFiles(\n backupId: string,\n opts?: { signal?: AbortSignal },\n ): Promise<AppBackupFile[]> {\n const res = await this.#getJson(\n `/dash/apps/${this.#appId}/backups/${backupId}/files`,\n opts?.signal,\n );\n return (res.files || []) as AppBackupFile[];\n }\n\n /**\n * Returns a presigned download URL for one of the backup's entity files.\n * The URL expires after 1 hour, so fetch it right before downloading.\n *\n * The entity files are stored zstd-compressed (the response carries\n * `Content-Encoding: zstd`); decompress to get the raw JSON/JSONL.\n */\n async getFileUrl(\n backupId: string,\n name: string,\n opts?: { signal?: AbortSignal },\n ): Promise<string> {\n const res = await this.#getJson(\n `/dash/apps/${this.#appId}/backups/${backupId}/file-url?name=${encodeURIComponent(name)}`,\n opts?.signal,\n );\n return res.url as string;\n }\n\n /**\n * Streams every storage file captured in the backup, each with a presigned\n * download URL. Completes without yielding anything when the app has no\n * storage files.\n *\n * The server ends a healthy stream with a terminal sentinel; if the stream\n * closes without it (a server-side failure truncated the listing), this\n * throws instead of silently under-reporting files.\n */\n async *streamStorageFiles(\n backupId: string,\n opts?: { signal?: AbortSignal },\n ): AsyncGenerator<AppBackupStorageFile, void, void> {\n const res = await this.#withAuth(async (token) => {\n const res = await fetch(\n `${this.#apiURI}/dash/apps/${this.#appId}/backups/${backupId}/storage-files`,\n { headers: authHeaders(token), signal: opts?.signal },\n );\n if (res.status !== 200) {\n throw await apiError(res);\n }\n return res;\n });\n if (!res.body) {\n throw new Error('Storage file listing returned no body.');\n }\n let complete = false;\n for await (const line of ndjsonLines(res.body)) {\n if (line.done === true) {\n complete = true;\n break;\n }\n // A file record always carries a locationId and url; anything else is\n // corruption, and skipping it would silently omit a file from the\n // archive.\n if (\n typeof line.locationId !== 'string' ||\n line.locationId.length === 0 ||\n // The locationId becomes the archive entry path `files/<locationId>`;\n // reject separators and control characters that could escape it.\n /[/\\\\\\u0000-\\u001f\\u007f]/.test(line.locationId) ||\n line.locationId === '.' ||\n line.locationId === '..' ||\n typeof line.url !== 'string' ||\n line.url.length === 0\n ) {\n throw new Error(\n 'Storage file listing returned a malformed record. Please retry the download.',\n );\n }\n yield {\n locationId: line.locationId,\n path: line.path ?? null,\n url: line.url,\n };\n }\n if (!complete) {\n throw new Error(\n 'Storage file listing ended before it finished. Please retry the download.',\n );\n }\n }\n\n /**\n * Downloads the backup into a single zip archive written to `opts.sink`,\n * entries in the canonical restore order described above. The caller\n * supplies the runtime-specific pieces — how to fetch a presigned URL,\n * where the bytes go, and the archive encoder (e.g. zip.js's `ZipWriter`);\n * see {@link DownloadBackupArchiveOpts}.\n */\n downloadArchive(\n opts: DownloadBackupArchiveOpts,\n ): Promise<BackupDownloadResult> {\n return downloadBackupArchive({ manager: this, ...opts });\n }\n}\n"]}
@@ -12,5 +12,7 @@ import { clerkDomainFromPublishableKey } from './clerk.ts';
12
12
  import { Webhooks, type WebhookAction, type WebhookStatus, type WebhookEventStatus, type WebhookInfo, type WebhookAttempt, type WebhookEventInfo, type WebhookEventsPage, type WebhookBody, type WebhookEntity, type WebhookPayload, type WebhookPayloadRecord, type WebhookPayloadRecordFor, type WebhookHandlerFn, type WebhookHandlers, type WebhookHelpers, type CreateWebhookParams, type UpdateWebhookParams, WebhooksManager } from '@instantdb/webhooks';
13
13
  export { type InstantAPIPlatformSchema, type InstantDBOAuthAccessToken, type OAuthHandlerConfig, type OAuthScope, type InstantRules, type InstantRouteHandlerPayloadByType, type InstantRouteHandlerType, type InstantRouteHandlerBody, OAuthHandler, InstantOAuthError, generateSchemaTypescriptFile, collectSystemCatalogIdentNames, validateSchema, SchemaValidationError, generatePermsTypescriptFile, permsTypescriptFileToCode, apiSchemaToInstantSchemaDef, schemaTypescriptFileToInstantSchema, version, translatePlanSteps, PlatformApi, ProgressPromise, exchangeCodeForToken, exchangeRefreshToken, clerkDomainFromPublishableKey, i, Webhooks, WebhooksManager, type WebhookAction, type WebhookStatus, type WebhookEventStatus, type WebhookInfo, type WebhookAttempt, type WebhookEventInfo, type WebhookEventsPage, type WebhookBody, type WebhookEntity, type WebhookPayload, type WebhookPayloadRecord, type WebhookPayloadRecordFor, type WebhookHandlerFn, type WebhookHandlers, type WebhookHelpers, type CreateWebhookParams, type UpdateWebhookParams, };
14
14
  export { diffSchemas, convertTxSteps, isRenamePromptItem, buildAutoRenameSelector, type RenameResolveFn, type MigrationTx, type MigrationTxSpecific, type MigrationTxTypes, type Identifier, } from './migrations.ts';
15
+ export { BackupsManager, backupZipName, estimateZipSize, formatFileSize, toAppBackup, type AppBackup, type AppBackupFile, type AppBackupStorageFile, } from './backups.ts';
16
+ export { type DownloadBackupArchiveOpts, type BackupArchiveWriter, type BackupDownloadProgress, type BackupDownloadResult, } from './backupDownload.ts';
15
17
  export { DEFAULT_OAUTH_CALLBACK_URL, oauthCallbackURL, GOOGLE_AUTHORIZATION_ENDPOINT, GOOGLE_DISCOVERY_ENDPOINT, GOOGLE_TOKEN_ENDPOINT, APPLE_AUTHORIZATION_ENDPOINT, APPLE_DISCOVERY_ENDPOINT, APPLE_TOKEN_ENDPOINT, LINKEDIN_AUTHORIZATION_ENDPOINT, LINKEDIN_DISCOVERY_ENDPOINT, LINKEDIN_TOKEN_ENDPOINT, } from './consts.ts';
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -12,5 +12,6 @@ import { clerkDomainFromPublishableKey } from "./clerk.js";
12
12
  import { Webhooks, WebhooksManager, } from '@instantdb/webhooks';
13
13
  export { OAuthHandler, InstantOAuthError, generateSchemaTypescriptFile, collectSystemCatalogIdentNames, validateSchema, SchemaValidationError, generatePermsTypescriptFile, permsTypescriptFileToCode, apiSchemaToInstantSchemaDef, schemaTypescriptFileToInstantSchema, version, translatePlanSteps, PlatformApi, ProgressPromise, exchangeCodeForToken, exchangeRefreshToken, clerkDomainFromPublishableKey, i, Webhooks, WebhooksManager, };
14
14
  export { diffSchemas, convertTxSteps, isRenamePromptItem, buildAutoRenameSelector, } from "./migrations.js";
15
+ export { BackupsManager, backupZipName, estimateZipSize, formatFileSize, toAppBackup, } from "./backups.js";
15
16
  export { DEFAULT_OAUTH_CALLBACK_URL, oauthCallbackURL, GOOGLE_AUTHORIZATION_ENDPOINT, GOOGLE_DISCOVERY_ENDPOINT, GOOGLE_TOKEN_ENDPOINT, APPLE_AUTHORIZATION_ENDPOINT, APPLE_DISCOVERY_ENDPOINT, APPLE_TOKEN_ENDPOINT, LINKEDIN_AUTHORIZATION_ENDPOINT, LINKEDIN_DISCOVERY_ENDPOINT, LINKEDIN_TOKEN_ENDPOINT, } from "./consts.js";
16
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAmB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAGL,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,4BAA4B,EAC5B,8BAA8B,EAC9B,cAAc,EACd,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,WAAW,EACX,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mCAAmC,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,CAAC,GAKF,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EACL,QAAQ,EAkBR,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EASL,YAAY,EACZ,iBAAiB,EACjB,4BAA4B,EAC5B,8BAA8B,EAC9B,cAAc,EACd,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC3B,mCAAmC,EACnC,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,CAAC,EACD,QAAQ,EACR,eAAe,GAkBhB,CAAC;AAEF,OAAO,EACL,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GAMxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,6BAA6B,EAC7B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,EACxB,oBAAoB,EACpB,+BAA+B,EAC/B,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,aAAa,CAAC","sourcesContent":["import { InstantOAuthError, type OAuthScope } from './oauthCommon.ts';\nimport {\n type InstantDBOAuthAccessToken,\n type OAuthHandlerConfig,\n OAuthHandler,\n} from './oauth.ts';\nimport {\n generatePermsTypescriptFile,\n permsTypescriptFileToCode,\n} from './perms.ts';\nimport {\n type InstantAPIPlatformSchema,\n generateSchemaTypescriptFile,\n collectSystemCatalogIdentNames,\n validateSchema,\n SchemaValidationError,\n} from './schema.ts';\nimport {\n apiSchemaToInstantSchemaDef,\n PlatformApi,\n translatePlanSteps,\n} from './api.ts';\nimport { schemaTypescriptFileToInstantSchema } from './typescript-schema.ts';\n\nimport version from './version.ts';\nimport { ProgressPromise } from './ProgressPromise.ts';\nimport {\n i,\n type InstantRules,\n type InstantRouteHandlerPayloadByType,\n type InstantRouteHandlerType,\n type InstantRouteHandlerBody,\n} from '@instantdb/core';\nimport { exchangeCodeForToken, exchangeRefreshToken } from './serverOAuth.ts';\nimport { clerkDomainFromPublishableKey } from './clerk.ts';\nimport {\n Webhooks,\n type WebhookAction,\n type WebhookStatus,\n type WebhookEventStatus,\n type WebhookInfo,\n type WebhookAttempt,\n type WebhookEventInfo,\n type WebhookEventsPage,\n type WebhookBody,\n type WebhookEntity,\n type WebhookPayload,\n type WebhookPayloadRecord,\n type WebhookPayloadRecordFor,\n type WebhookHandlerFn,\n type WebhookHandlers,\n type WebhookHelpers,\n type CreateWebhookParams,\n type UpdateWebhookParams,\n WebhooksManager,\n} from '@instantdb/webhooks';\n\nexport {\n type InstantAPIPlatformSchema,\n type InstantDBOAuthAccessToken,\n type OAuthHandlerConfig,\n type OAuthScope,\n type InstantRules,\n type InstantRouteHandlerPayloadByType,\n type InstantRouteHandlerType,\n type InstantRouteHandlerBody,\n OAuthHandler,\n InstantOAuthError,\n generateSchemaTypescriptFile,\n collectSystemCatalogIdentNames,\n validateSchema,\n SchemaValidationError,\n generatePermsTypescriptFile,\n permsTypescriptFileToCode,\n apiSchemaToInstantSchemaDef,\n schemaTypescriptFileToInstantSchema,\n version,\n translatePlanSteps,\n PlatformApi,\n ProgressPromise,\n exchangeCodeForToken,\n exchangeRefreshToken,\n clerkDomainFromPublishableKey,\n i,\n Webhooks,\n WebhooksManager,\n type WebhookAction,\n type WebhookStatus,\n type WebhookEventStatus,\n type WebhookInfo,\n type WebhookAttempt,\n type WebhookEventInfo,\n type WebhookEventsPage,\n type WebhookBody,\n type WebhookEntity,\n type WebhookPayload,\n type WebhookPayloadRecord,\n type WebhookPayloadRecordFor,\n type WebhookHandlerFn,\n type WebhookHandlers,\n type WebhookHelpers,\n type CreateWebhookParams,\n type UpdateWebhookParams,\n};\n\nexport {\n diffSchemas,\n convertTxSteps,\n isRenamePromptItem,\n buildAutoRenameSelector,\n type RenameResolveFn,\n type MigrationTx,\n type MigrationTxSpecific,\n type MigrationTxTypes,\n type Identifier,\n} from './migrations.ts';\n\nexport {\n DEFAULT_OAUTH_CALLBACK_URL,\n oauthCallbackURL,\n GOOGLE_AUTHORIZATION_ENDPOINT,\n GOOGLE_DISCOVERY_ENDPOINT,\n GOOGLE_TOKEN_ENDPOINT,\n APPLE_AUTHORIZATION_ENDPOINT,\n APPLE_DISCOVERY_ENDPOINT,\n APPLE_TOKEN_ENDPOINT,\n LINKEDIN_AUTHORIZATION_ENDPOINT,\n LINKEDIN_DISCOVERY_ENDPOINT,\n LINKEDIN_TOKEN_ENDPOINT,\n} from './consts.ts';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAmB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAGL,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,4BAA4B,EAC5B,8BAA8B,EAC9B,cAAc,EACd,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,WAAW,EACX,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mCAAmC,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,CAAC,GAKF,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EACL,QAAQ,EAkBR,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EASL,YAAY,EACZ,iBAAiB,EACjB,4BAA4B,EAC5B,8BAA8B,EAC9B,cAAc,EACd,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC3B,mCAAmC,EACnC,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,CAAC,EACD,QAAQ,EACR,eAAe,GAkBhB,CAAC;AAEF,OAAO,EACL,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GAMxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,GAIZ,MAAM,cAAc,CAAC;AAStB,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,6BAA6B,EAC7B,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,EACxB,oBAAoB,EACpB,+BAA+B,EAC/B,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,aAAa,CAAC","sourcesContent":["import { InstantOAuthError, type OAuthScope } from './oauthCommon.ts';\nimport {\n type InstantDBOAuthAccessToken,\n type OAuthHandlerConfig,\n OAuthHandler,\n} from './oauth.ts';\nimport {\n generatePermsTypescriptFile,\n permsTypescriptFileToCode,\n} from './perms.ts';\nimport {\n type InstantAPIPlatformSchema,\n generateSchemaTypescriptFile,\n collectSystemCatalogIdentNames,\n validateSchema,\n SchemaValidationError,\n} from './schema.ts';\nimport {\n apiSchemaToInstantSchemaDef,\n PlatformApi,\n translatePlanSteps,\n} from './api.ts';\nimport { schemaTypescriptFileToInstantSchema } from './typescript-schema.ts';\n\nimport version from './version.ts';\nimport { ProgressPromise } from './ProgressPromise.ts';\nimport {\n i,\n type InstantRules,\n type InstantRouteHandlerPayloadByType,\n type InstantRouteHandlerType,\n type InstantRouteHandlerBody,\n} from '@instantdb/core';\nimport { exchangeCodeForToken, exchangeRefreshToken } from './serverOAuth.ts';\nimport { clerkDomainFromPublishableKey } from './clerk.ts';\nimport {\n Webhooks,\n type WebhookAction,\n type WebhookStatus,\n type WebhookEventStatus,\n type WebhookInfo,\n type WebhookAttempt,\n type WebhookEventInfo,\n type WebhookEventsPage,\n type WebhookBody,\n type WebhookEntity,\n type WebhookPayload,\n type WebhookPayloadRecord,\n type WebhookPayloadRecordFor,\n type WebhookHandlerFn,\n type WebhookHandlers,\n type WebhookHelpers,\n type CreateWebhookParams,\n type UpdateWebhookParams,\n WebhooksManager,\n} from '@instantdb/webhooks';\n\nexport {\n type InstantAPIPlatformSchema,\n type InstantDBOAuthAccessToken,\n type OAuthHandlerConfig,\n type OAuthScope,\n type InstantRules,\n type InstantRouteHandlerPayloadByType,\n type InstantRouteHandlerType,\n type InstantRouteHandlerBody,\n OAuthHandler,\n InstantOAuthError,\n generateSchemaTypescriptFile,\n collectSystemCatalogIdentNames,\n validateSchema,\n SchemaValidationError,\n generatePermsTypescriptFile,\n permsTypescriptFileToCode,\n apiSchemaToInstantSchemaDef,\n schemaTypescriptFileToInstantSchema,\n version,\n translatePlanSteps,\n PlatformApi,\n ProgressPromise,\n exchangeCodeForToken,\n exchangeRefreshToken,\n clerkDomainFromPublishableKey,\n i,\n Webhooks,\n WebhooksManager,\n type WebhookAction,\n type WebhookStatus,\n type WebhookEventStatus,\n type WebhookInfo,\n type WebhookAttempt,\n type WebhookEventInfo,\n type WebhookEventsPage,\n type WebhookBody,\n type WebhookEntity,\n type WebhookPayload,\n type WebhookPayloadRecord,\n type WebhookPayloadRecordFor,\n type WebhookHandlerFn,\n type WebhookHandlers,\n type WebhookHelpers,\n type CreateWebhookParams,\n type UpdateWebhookParams,\n};\n\nexport {\n diffSchemas,\n convertTxSteps,\n isRenamePromptItem,\n buildAutoRenameSelector,\n type RenameResolveFn,\n type MigrationTx,\n type MigrationTxSpecific,\n type MigrationTxTypes,\n type Identifier,\n} from './migrations.ts';\n\nexport {\n BackupsManager,\n backupZipName,\n estimateZipSize,\n formatFileSize,\n toAppBackup,\n type AppBackup,\n type AppBackupFile,\n type AppBackupStorageFile,\n} from './backups.ts';\n\nexport {\n type DownloadBackupArchiveOpts,\n type BackupArchiveWriter,\n type BackupDownloadProgress,\n type BackupDownloadResult,\n} from './backupDownload.ts';\n\nexport {\n DEFAULT_OAUTH_CALLBACK_URL,\n oauthCallbackURL,\n GOOGLE_AUTHORIZATION_ENDPOINT,\n GOOGLE_DISCOVERY_ENDPOINT,\n GOOGLE_TOKEN_ENDPOINT,\n APPLE_AUTHORIZATION_ENDPOINT,\n APPLE_DISCOVERY_ENDPOINT,\n APPLE_TOKEN_ENDPOINT,\n LINKEDIN_AUTHORIZATION_ENDPOINT,\n LINKEDIN_DISCOVERY_ENDPOINT,\n LINKEDIN_TOKEN_ENDPOINT,\n} from './consts.ts';\n"]}