@nonext/husk 0.2.3

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 (89) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/LICENSE +166 -0
  3. package/README.md +140 -0
  4. package/api/public-api.md +1070 -0
  5. package/dist/adapter-C_0mhENy.d.ts +320 -0
  6. package/dist/admin/admin.css +5 -0
  7. package/dist/admin/index.d.ts +265 -0
  8. package/dist/admin/index.js +393 -0
  9. package/dist/admin/index.js.map +1 -0
  10. package/dist/admin/tokens.css +597 -0
  11. package/dist/admin/ui.d.ts +3013 -0
  12. package/dist/admin/ui.js +9783 -0
  13. package/dist/admin/ui.js.map +1 -0
  14. package/dist/auth/index.d.ts +4 -0
  15. package/dist/auth/index.js +9 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/auth-B2gBtHl5.d.ts +28 -0
  18. package/dist/can-Chy7zmx7.d.ts +69 -0
  19. package/dist/chunk-3I6337WJ.js +83 -0
  20. package/dist/chunk-3I6337WJ.js.map +1 -0
  21. package/dist/chunk-4Z6P3XCE.js +62 -0
  22. package/dist/chunk-4Z6P3XCE.js.map +1 -0
  23. package/dist/chunk-6E3ZS5Z5.js +1007 -0
  24. package/dist/chunk-6E3ZS5Z5.js.map +1 -0
  25. package/dist/chunk-77JDRXXU.js +3 -0
  26. package/dist/chunk-77JDRXXU.js.map +1 -0
  27. package/dist/chunk-FHYWJCG6.js +171 -0
  28. package/dist/chunk-FHYWJCG6.js.map +1 -0
  29. package/dist/chunk-JAE7HHMM.js +506 -0
  30. package/dist/chunk-JAE7HHMM.js.map +1 -0
  31. package/dist/chunk-NPDBQBLW.js +68 -0
  32. package/dist/chunk-NPDBQBLW.js.map +1 -0
  33. package/dist/chunk-ORMYARXD.js +6 -0
  34. package/dist/chunk-ORMYARXD.js.map +1 -0
  35. package/dist/chunk-R4O7APIX.js +51 -0
  36. package/dist/chunk-R4O7APIX.js.map +1 -0
  37. package/dist/chunk-ROLKRJWI.js +187 -0
  38. package/dist/chunk-ROLKRJWI.js.map +1 -0
  39. package/dist/chunk-SOTQ3WP5.js +31 -0
  40. package/dist/chunk-SOTQ3WP5.js.map +1 -0
  41. package/dist/chunk-TCFFHTY3.js +97 -0
  42. package/dist/chunk-TCFFHTY3.js.map +1 -0
  43. package/dist/chunk-TS7Y7GEZ.js +7 -0
  44. package/dist/chunk-TS7Y7GEZ.js.map +1 -0
  45. package/dist/chunk-VLGR5PZX.js +3 -0
  46. package/dist/chunk-VLGR5PZX.js.map +1 -0
  47. package/dist/chunk-ZW2PUSVS.js +40 -0
  48. package/dist/chunk-ZW2PUSVS.js.map +1 -0
  49. package/dist/chunk-ZYNBMYJ6.js +392 -0
  50. package/dist/chunk-ZYNBMYJ6.js.map +1 -0
  51. package/dist/cli/nonext-husk.js +3360 -0
  52. package/dist/cli/nonext-husk.js.map +1 -0
  53. package/dist/cli/templates/firestore.rules +393 -0
  54. package/dist/cli/templates/storage.rules +165 -0
  55. package/dist/client/index.d.ts +27 -0
  56. package/dist/client/index.js +15 -0
  57. package/dist/client/index.js.map +1 -0
  58. package/dist/cms-9fSA3uQV.d.ts +158 -0
  59. package/dist/core/index.d.ts +1267 -0
  60. package/dist/core/index.js +12 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/entry-D3kiE8T1.d.ts +163 -0
  63. package/dist/field-Diyf5siF.d.ts +158 -0
  64. package/dist/field-type-D25Vojb0.d.ts +157 -0
  65. package/dist/firebase/index.d.ts +251 -0
  66. package/dist/firebase/index.js +991 -0
  67. package/dist/firebase/index.js.map +1 -0
  68. package/dist/index-5ylaMBUH.d.ts +155 -0
  69. package/dist/index.d.ts +14 -0
  70. package/dist/index.js +17 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/permissions/index.d.ts +101 -0
  73. package/dist/permissions/index.js +7 -0
  74. package/dist/permissions/index.js.map +1 -0
  75. package/dist/registry-CUC25qay.d.ts +59 -0
  76. package/dist/richtext/index.d.ts +85 -0
  77. package/dist/richtext/index.js +127 -0
  78. package/dist/richtext/index.js.map +1 -0
  79. package/dist/schema/index.d.ts +50 -0
  80. package/dist/schema/index.js +5 -0
  81. package/dist/schema/index.js.map +1 -0
  82. package/dist/server/index.d.ts +39 -0
  83. package/dist/server/index.js +25 -0
  84. package/dist/server/index.js.map +1 -0
  85. package/dist/types/index.d.ts +36 -0
  86. package/dist/types/index.js +6 -0
  87. package/dist/types/index.js.map +1 -0
  88. package/dist/write-limits-Djmm6L3R.d.ts +215 -0
  89. package/package.json +136 -0
@@ -0,0 +1,506 @@
1
+ import { assertValidContentType } from './chunk-ROLKRJWI.js';
2
+ import { SchemaError, LockedTypeError } from './chunk-4Z6P3XCE.js';
3
+
4
+ // src/core/adapter.ts
5
+ var MEDIA_USAGE_LIMIT = 25;
6
+ var MAX_FIELD_PURGE = 250;
7
+ var DEFAULT_PAGE_SIZE = 25;
8
+ var MAX_PAGE_SIZE = 100;
9
+ function normalizeLimit(limit) {
10
+ if (limit === void 0 || !Number.isFinite(limit)) return DEFAULT_PAGE_SIZE;
11
+ return Math.min(Math.max(Math.trunc(limit), 1), MAX_PAGE_SIZE);
12
+ }
13
+
14
+ // src/core/schema-fields.ts
15
+ function fieldKeyState(type, key) {
16
+ if (key in type.fields) return "live";
17
+ if (type.removedFields !== void 0 && key in type.removedFields) return "removed";
18
+ return "free";
19
+ }
20
+ function removedFieldEntries(type) {
21
+ return Object.entries(type.removedFields ?? {}).map(([key, removed]) => ({ key, ...removed })).sort((left, right) => left.key.localeCompare(right.key));
22
+ }
23
+ function withoutKey(map, key) {
24
+ const next = {};
25
+ for (const [existing, value] of Object.entries(map)) {
26
+ if (existing !== key) next[existing] = value;
27
+ }
28
+ return next;
29
+ }
30
+ function rebuild(type, fields, removedFields) {
31
+ const { removedFields: _dropped, ...rest } = type;
32
+ const next = {
33
+ ...rest,
34
+ fields,
35
+ ...Object.keys(removedFields).length > 0 ? { removedFields } : {}
36
+ };
37
+ assertValidContentType(next);
38
+ return next;
39
+ }
40
+ function removeField(type, key, context) {
41
+ const field = type.fields[key];
42
+ if (!field) {
43
+ throw new SchemaError(
44
+ fieldKeyState(type, key) === "removed" ? `Field "${key}" of content type "${type.slug}" is already removed.` : `Content type "${type.slug}" has no field "${key}".`
45
+ );
46
+ }
47
+ if (Object.keys(type.fields).length === 1) {
48
+ throw new SchemaError(
49
+ `Field "${key}" is the only field of content type "${type.slug}". A content type must keep at least one field; delete the type instead.`
50
+ );
51
+ }
52
+ if (type.titleField === key) {
53
+ throw new SchemaError(
54
+ `Field "${key}" is the title field of content type "${type.slug}". Choose another title field before removing it.`
55
+ );
56
+ }
57
+ if (type.defaultSort?.field === key) {
58
+ throw new SchemaError(
59
+ `Field "${key}" is the default sort of content type "${type.slug}". Choose another sort before removing it.`
60
+ );
61
+ }
62
+ const removed = {
63
+ field,
64
+ removedAt: context.removedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
65
+ removedBy: context.removedBy
66
+ };
67
+ return rebuild(type, withoutKey(type.fields, key), {
68
+ ...type.removedFields ?? {},
69
+ [key]: removed
70
+ });
71
+ }
72
+ function addField(type, key, field) {
73
+ const state = fieldKeyState(type, key);
74
+ if (state === "live") {
75
+ throw new SchemaError(`Content type "${type.slug}" already has a field "${key}".`);
76
+ }
77
+ if (state === "removed") {
78
+ throw new SchemaError(
79
+ `Field "${key}" of content type "${type.slug}" was removed and its values are still stored. Restore it to get those values back, or purge them first.`
80
+ );
81
+ }
82
+ return rebuild(type, { ...type.fields, [key]: field }, type.removedFields ?? {});
83
+ }
84
+ function restoreField(type, key, options = {}) {
85
+ const removed = type.removedFields?.[key];
86
+ if (!removed) {
87
+ throw new SchemaError(`Content type "${type.slug}" has no removed field "${key}".`);
88
+ }
89
+ const field = options.field ?? removed.field;
90
+ if (!storesTheSameWay(removed.field, field)) {
91
+ throw new SchemaError(
92
+ `Field "${key}" of content type "${type.slug}" was removed as "${removed.field.type}" and cannot be restored as "${field.type}": the preserved values are stored in the old shape. Purge the values first, then add the field fresh.`
93
+ );
94
+ }
95
+ return rebuild(
96
+ type,
97
+ { ...type.fields, [key]: field },
98
+ withoutKey(type.removedFields ?? {}, key)
99
+ );
100
+ }
101
+ function forgetRemovedField(type, key) {
102
+ if (type.removedFields?.[key] === void 0) {
103
+ throw new SchemaError(`Content type "${type.slug}" has no removed field "${key}".`);
104
+ }
105
+ return rebuild(type, type.fields, withoutKey(type.removedFields, key));
106
+ }
107
+ function storesTheSameWay(left, right) {
108
+ return storageSignatureOf(left) === storageSignatureOf(right);
109
+ }
110
+ function storageSignatureOf(field) {
111
+ switch (field.type) {
112
+ case "select":
113
+ return `select:${field.multiple === true ? "many" : "one"}:${field.options.map((option) => option.value).sort().join("|")}`;
114
+ case "relation":
115
+ return `relation:${field.to}:${field.many === true ? "many" : "one"}`;
116
+ case "date":
117
+ return `date:${field.precision ?? "date"}`;
118
+ case "repeater":
119
+ return `repeater:{${fieldMapSignature(field.fields)}}`;
120
+ default:
121
+ return field.type;
122
+ }
123
+ }
124
+ function fieldMapSignature(fields) {
125
+ return Object.entries(fields).map(([key, field]) => `${key}=${storageSignatureOf(field)}`).sort().join(",");
126
+ }
127
+
128
+ // src/core/slug-field.ts
129
+ function slugFieldKey(type) {
130
+ for (const [key, field] of Object.entries(type.fields)) {
131
+ if (field.type === "slug") return key;
132
+ }
133
+ return "slug" in type.fields ? "slug" : null;
134
+ }
135
+
136
+ // src/core/media-constraints.ts
137
+ var MB = 1024 * 1024;
138
+ var MAX_MEDIA_BYTES = 25 * MB;
139
+ var MAX_IMAGE_BYTES = 10 * MB;
140
+ var ALLOWED_MEDIA_TYPES = [
141
+ {
142
+ type: "image/jpeg",
143
+ category: "image",
144
+ maxBytes: MAX_IMAGE_BYTES,
145
+ extensions: [".jpg", ".jpeg"]
146
+ },
147
+ {
148
+ type: "image/png",
149
+ category: "image",
150
+ maxBytes: MAX_IMAGE_BYTES,
151
+ extensions: [".png"]
152
+ },
153
+ {
154
+ type: "image/webp",
155
+ category: "image",
156
+ maxBytes: MAX_IMAGE_BYTES,
157
+ extensions: [".webp"]
158
+ },
159
+ {
160
+ type: "image/avif",
161
+ category: "image",
162
+ maxBytes: MAX_IMAGE_BYTES,
163
+ extensions: [".avif"]
164
+ },
165
+ {
166
+ type: "image/gif",
167
+ category: "image",
168
+ maxBytes: MAX_IMAGE_BYTES,
169
+ extensions: [".gif"]
170
+ },
171
+ {
172
+ type: "application/pdf",
173
+ category: "document",
174
+ maxBytes: MAX_MEDIA_BYTES,
175
+ extensions: [".pdf"]
176
+ },
177
+ {
178
+ type: "video/mp4",
179
+ category: "video",
180
+ maxBytes: MAX_MEDIA_BYTES,
181
+ extensions: [".mp4"]
182
+ },
183
+ {
184
+ type: "video/webm",
185
+ category: "video",
186
+ maxBytes: MAX_MEDIA_BYTES,
187
+ extensions: [".webm"]
188
+ },
189
+ {
190
+ type: "audio/mpeg",
191
+ category: "audio",
192
+ maxBytes: MAX_MEDIA_BYTES,
193
+ extensions: [".mp3"]
194
+ },
195
+ {
196
+ type: "audio/ogg",
197
+ category: "audio",
198
+ maxBytes: MAX_MEDIA_BYTES,
199
+ extensions: [".ogg"]
200
+ },
201
+ {
202
+ type: "audio/wav",
203
+ category: "audio",
204
+ maxBytes: MAX_MEDIA_BYTES,
205
+ extensions: [".wav"]
206
+ }
207
+ ];
208
+ var MEDIA_ACCEPT_ATTRIBUTE = ALLOWED_MEDIA_TYPES.map((rule) => rule.type).join(
209
+ ","
210
+ );
211
+ function mediaTypeRule(type) {
212
+ const normalized = normalizeMediaType(type);
213
+ return ALLOWED_MEDIA_TYPES.find((rule) => rule.type === normalized) ?? null;
214
+ }
215
+ function normalizeMediaType(type) {
216
+ const [base] = type.split(";");
217
+ return (base ?? "").trim().toLowerCase();
218
+ }
219
+ function fileExtension(name) {
220
+ const index = name.lastIndexOf(".");
221
+ return index <= 0 ? "" : name.slice(index).toLowerCase();
222
+ }
223
+ function checkMediaFile(file) {
224
+ const rule = mediaTypeRule(file.type);
225
+ if (rule === null) {
226
+ return {
227
+ code: "type-not-allowed",
228
+ message: `Files of type ${file.type || "unknown"} cannot be uploaded.`
229
+ };
230
+ }
231
+ if (file.size <= 0) {
232
+ return { code: "empty", message: "The file is empty." };
233
+ }
234
+ if (file.size > rule.maxBytes) {
235
+ return {
236
+ code: "too-large",
237
+ message: `${describeBytes(file.size)} is over the ${describeBytes(rule.maxBytes)} limit for ${rule.type} files.`
238
+ };
239
+ }
240
+ if (!rule.extensions.includes(fileExtension(file.name))) {
241
+ return {
242
+ code: "extension-mismatch",
243
+ message: `A ${rule.type} file must be named ${rule.extensions.join(" or ")}.`
244
+ };
245
+ }
246
+ return null;
247
+ }
248
+ function safeFileName(name, type) {
249
+ const extension = mediaTypeRule(type)?.extensions[0] ?? fileExtension(name);
250
+ const base = (extension !== "" && name.toLowerCase().endsWith(extension) ? name.slice(0, -extension.length) : name).toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
251
+ return `${base === "" ? "file" : base}${extension}`;
252
+ }
253
+ function describeBytes(bytes) {
254
+ if (bytes >= MB) return `${Math.round(bytes / MB * 10) / 10} MB`;
255
+ if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
256
+ return `${bytes} bytes`;
257
+ }
258
+
259
+ // src/core/registry.ts
260
+ function buildRegistry(code, database) {
261
+ const bySlug = /* @__PURE__ */ new Map();
262
+ const invalid = [];
263
+ for (const type of code) {
264
+ assertValidContentType(type);
265
+ if (bySlug.has(type.slug)) {
266
+ throw new SchemaError(
267
+ `Content type "${type.slug}" is defined twice in code. A slug identifies exactly one content type.`
268
+ );
269
+ }
270
+ bySlug.set(type.slug, {
271
+ type,
272
+ source: "code",
273
+ locked: type.locked ?? false
274
+ });
275
+ }
276
+ for (const type of database) {
277
+ try {
278
+ assertValidContentType(type);
279
+ } catch (thrown) {
280
+ invalid.push({
281
+ slug: typeof type?.slug === "string" ? type.slug : "(unknown)",
282
+ reason: thrown instanceof Error ? thrown.message : String(thrown),
283
+ definition: type
284
+ });
285
+ continue;
286
+ }
287
+ const existing = bySlug.get(type.slug);
288
+ if (!existing) {
289
+ bySlug.set(type.slug, { type, source: "database", locked: false });
290
+ continue;
291
+ }
292
+ if (existing.source === "database") {
293
+ invalid.push({
294
+ slug: type.slug,
295
+ reason: `Content type "${type.slug}" appears twice in the database. Only the first was loaded.`,
296
+ definition: type
297
+ });
298
+ continue;
299
+ }
300
+ bySlug.set(type.slug, { ...existing, conflict: { source: "database", type } });
301
+ }
302
+ const types = [...bySlug.values()];
303
+ return {
304
+ types,
305
+ conflicts: types.filter((entry) => entry.conflict !== void 0),
306
+ invalid,
307
+ get: (slug) => bySlug.get(slug),
308
+ has: (slug) => bySlug.has(slug),
309
+ require(slug) {
310
+ const entry = bySlug.get(slug);
311
+ if (!entry) {
312
+ throw new SchemaError(
313
+ `Unknown content type "${slug}". Known types: ${types.map((known) => known.type.slug).join(", ") || "none"}.`
314
+ );
315
+ }
316
+ return entry;
317
+ },
318
+ bySource: (source) => types.filter((entry) => entry.source === source)
319
+ };
320
+ }
321
+ function assertSchemaWritable(registry, slug) {
322
+ const entry = registry.require(slug);
323
+ if (entry.locked) {
324
+ throw new LockedTypeError(slug);
325
+ }
326
+ if (entry.source === "code") {
327
+ throw new LockedTypeError(
328
+ slug,
329
+ `Content type "${slug}" is defined in code. The Schema Builder writes database-defined types only; change the TypeScript definition and deploy.`
330
+ );
331
+ }
332
+ return entry;
333
+ }
334
+ function isSchemaReadOnly(entry) {
335
+ return entry.locked || entry.source === "code";
336
+ }
337
+
338
+ // src/core/schema-version.ts
339
+ function storageSignature(type) {
340
+ return `${type.kind}|${fieldMapSignature(type.fields)}`;
341
+ }
342
+ var INITIAL_SCHEMA_VERSION = 1;
343
+ function schemaVersionOf(type) {
344
+ const version = type.schemaVersion;
345
+ return typeof version === "number" && Number.isInteger(version) && version >= 1 ? version : INITIAL_SCHEMA_VERSION;
346
+ }
347
+ function nextSchemaVersion(previous, next) {
348
+ if (previous === null) return INITIAL_SCHEMA_VERSION;
349
+ const current = schemaVersionOf(previous);
350
+ return storageSignature(previous) === storageSignature(next) ? current : current + 1;
351
+ }
352
+ function storageShapeChanged(previous, next) {
353
+ return storageSignature(previous) !== storageSignature(next);
354
+ }
355
+
356
+ // src/core/write-limits.ts
357
+ var FIRESTORE_DOCUMENT_BYTES = 1048576;
358
+ var MAX_WRITE_BYTES = 9e5;
359
+ var MAX_ENTRY_FIELDS = 200;
360
+ var MAX_CONTENT_TYPE_FIELDS = 100;
361
+ var MAX_SETTINGS_FIELDS = 100;
362
+ var MAX_NESTING_DEPTH = 20;
363
+ var MAX_ARRAY_ITEMS = 1e3;
364
+ var MIN_WRITE_INTERVAL_MS = 200;
365
+ var WRITE_BURST_LIMIT = 200;
366
+ var WRITE_BURST_WINDOW_MS = 1e4;
367
+ function approximateBytes(value) {
368
+ if (value === null || value === void 0) return 1;
369
+ if (typeof value === "boolean") return 1;
370
+ if (typeof value === "number") return 8;
371
+ if (typeof value === "string") return utf8Length(value) + 1;
372
+ if (value instanceof Date) return 8;
373
+ if (Array.isArray(value)) {
374
+ return value.reduce((total, item) => total + approximateBytes(item), 2);
375
+ }
376
+ if (typeof value === "object") {
377
+ return Object.entries(value).reduce(
378
+ (total, [key, item]) => total + utf8Length(key) + 1 + approximateBytes(item),
379
+ 2
380
+ );
381
+ }
382
+ return 8;
383
+ }
384
+ function utf8Length(value) {
385
+ return new TextEncoder().encode(value).length;
386
+ }
387
+ function checkWritePayload(values, limits = {}) {
388
+ const maxFields = limits.maxFields ?? MAX_ENTRY_FIELDS;
389
+ const maxBytes = limits.maxBytes ?? MAX_WRITE_BYTES;
390
+ const keys = Object.keys(values);
391
+ if (keys.length > maxFields) {
392
+ return {
393
+ code: "too-many-fields",
394
+ path: "",
395
+ message: `This write has ${keys.length} top-level fields and the limit is ${maxFields}.`
396
+ };
397
+ }
398
+ const structural = checkStructure(values, "", 1);
399
+ if (structural !== null) return structural;
400
+ const bytes = approximateBytes(values);
401
+ if (bytes > maxBytes) {
402
+ return {
403
+ code: "too-large",
404
+ path: "",
405
+ message: `This write is about ${Math.round(bytes / 1024)} KB and the limit is ${Math.round(maxBytes / 1024)} KB. Move large content into a media file and reference it.`
406
+ };
407
+ }
408
+ return null;
409
+ }
410
+ function checkStructure(value, path, depth) {
411
+ if (depth > MAX_NESTING_DEPTH) {
412
+ return {
413
+ code: "too-deep",
414
+ path,
415
+ message: `This value nests more than ${MAX_NESTING_DEPTH} levels deep, which Firestore refuses to store.`
416
+ };
417
+ }
418
+ if (Array.isArray(value)) {
419
+ if (value.length > MAX_ARRAY_ITEMS) {
420
+ return {
421
+ code: "too-many-items",
422
+ path,
423
+ message: `"${path}" holds ${value.length} items and the limit is ${MAX_ARRAY_ITEMS}.`
424
+ };
425
+ }
426
+ for (const [index, item] of value.entries()) {
427
+ const found = checkStructure(item, `${path}.${index}`, depth + 1);
428
+ if (found !== null) return found;
429
+ }
430
+ return null;
431
+ }
432
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) {
433
+ for (const [key, item] of Object.entries(value)) {
434
+ const found = checkStructure(item, path === "" ? key : `${path}.${key}`, depth + 1);
435
+ if (found !== null) return found;
436
+ }
437
+ }
438
+ return null;
439
+ }
440
+ function createWriteRateLimiter(clock = Date.now) {
441
+ let window = [];
442
+ return {
443
+ check() {
444
+ const now = clock();
445
+ window = window.filter((at) => now - at < WRITE_BURST_WINDOW_MS);
446
+ if (window.length >= WRITE_BURST_LIMIT) {
447
+ return {
448
+ code: "too-fast",
449
+ path: "",
450
+ message: `More than ${WRITE_BURST_LIMIT} writes in ${WRITE_BURST_WINDOW_MS / 1e3} seconds. Something is looping; nothing was written.`
451
+ };
452
+ }
453
+ window.push(now);
454
+ return null;
455
+ }
456
+ };
457
+ }
458
+
459
+ // src/core/media-references.ts
460
+ var MEDIA_REFS_KEY = "mediaRefs";
461
+ var MAX_MEDIA_REFS = 100;
462
+ function collectMediaIds(data) {
463
+ const found = /* @__PURE__ */ new Set();
464
+ function walk(value) {
465
+ if (Array.isArray(value)) {
466
+ for (const item of value) walk(item);
467
+ return;
468
+ }
469
+ if (!isPlainObject(value)) return;
470
+ const mediaId = value["mediaId"];
471
+ if (typeof mediaId === "string") {
472
+ if (mediaId !== "") found.add(mediaId);
473
+ return;
474
+ }
475
+ for (const nested of Object.values(value)) walk(nested);
476
+ }
477
+ walk(data);
478
+ return [...found].sort().slice(0, MAX_MEDIA_REFS);
479
+ }
480
+ function retargetMediaUrls(data, mediaId, url) {
481
+ let changed = false;
482
+ function walk(value) {
483
+ if (Array.isArray(value)) return value.map(walk);
484
+ if (!isPlainObject(value)) return value;
485
+ const record = value;
486
+ if (record["mediaId"] === mediaId) {
487
+ if (record["url"] === url) return record;
488
+ changed = true;
489
+ return { ...record, url };
490
+ }
491
+ const next = {};
492
+ for (const [key, nested] of Object.entries(record)) next[key] = walk(nested);
493
+ return next;
494
+ }
495
+ const result = walk(data);
496
+ return changed ? result : null;
497
+ }
498
+ function isPlainObject(value) {
499
+ if (typeof value !== "object" || value === null) return false;
500
+ const proto = Object.getPrototypeOf(value);
501
+ return proto === Object.prototype || proto === null;
502
+ }
503
+
504
+ export { ALLOWED_MEDIA_TYPES, DEFAULT_PAGE_SIZE, FIRESTORE_DOCUMENT_BYTES, INITIAL_SCHEMA_VERSION, MAX_ARRAY_ITEMS, MAX_CONTENT_TYPE_FIELDS, MAX_ENTRY_FIELDS, MAX_FIELD_PURGE, MAX_IMAGE_BYTES, MAX_MEDIA_BYTES, MAX_MEDIA_REFS, MAX_NESTING_DEPTH, MAX_PAGE_SIZE, MAX_SETTINGS_FIELDS, MAX_WRITE_BYTES, MEDIA_ACCEPT_ATTRIBUTE, MEDIA_REFS_KEY, MEDIA_USAGE_LIMIT, MIN_WRITE_INTERVAL_MS, WRITE_BURST_LIMIT, WRITE_BURST_WINDOW_MS, addField, approximateBytes, assertSchemaWritable, buildRegistry, checkMediaFile, checkWritePayload, collectMediaIds, createWriteRateLimiter, fieldKeyState, fieldMapSignature, fileExtension, forgetRemovedField, isSchemaReadOnly, mediaTypeRule, nextSchemaVersion, normalizeLimit, normalizeMediaType, removeField, removedFieldEntries, restoreField, retargetMediaUrls, safeFileName, schemaVersionOf, slugFieldKey, storageShapeChanged, storageSignature, storageSignatureOf, storesTheSameWay };
505
+ //# sourceMappingURL=chunk-JAE7HHMM.js.map
506
+ //# sourceMappingURL=chunk-JAE7HHMM.js.map