@columnus/shared 0.1.55 → 0.1.58

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 (76) hide show
  1. package/dist/apiProfile.d.ts +41 -0
  2. package/dist/apiProfile.js +20 -2
  3. package/dist/apiProfile.js.map +1 -1
  4. package/dist/assetFamily.d.ts +36 -0
  5. package/dist/assetFamily.js +73 -0
  6. package/dist/assetFamily.js.map +1 -0
  7. package/dist/assetFieldValues.d.ts +21 -0
  8. package/dist/{storageFieldValues.js → assetFieldValues.js} +159 -60
  9. package/dist/assetFieldValues.js.map +1 -0
  10. package/dist/assetGraph.d.ts +221 -0
  11. package/dist/assetGraph.js +241 -0
  12. package/dist/assetGraph.js.map +1 -0
  13. package/dist/assetJobs.d.ts +99 -0
  14. package/dist/assetJobs.js +41 -0
  15. package/dist/assetJobs.js.map +1 -0
  16. package/dist/assetSettings.d.ts +129 -0
  17. package/dist/assetSettings.js +87 -0
  18. package/dist/assetSettings.js.map +1 -0
  19. package/dist/assetValidators.d.ts +475 -0
  20. package/dist/assetValidators.js +83 -0
  21. package/dist/assetValidators.js.map +1 -0
  22. package/dist/bffProtocol.d.ts +29 -24
  23. package/dist/bffProtocol.js +5 -1
  24. package/dist/bffProtocol.js.map +1 -1
  25. package/dist/ciPreviewEnv.js +1 -1
  26. package/dist/ciPreviewEnv.js.map +1 -1
  27. package/dist/clipboardTransfer.js +112 -12
  28. package/dist/clipboardTransfer.js.map +1 -1
  29. package/dist/csv.js +118 -18
  30. package/dist/csv.js.map +1 -1
  31. package/dist/displayLabel.js +1 -1
  32. package/dist/displayLabel.js.map +1 -1
  33. package/dist/dotenv.js +5 -1
  34. package/dist/dotenv.js.map +1 -1
  35. package/dist/importMatch.js +118 -18
  36. package/dist/importMatch.js.map +1 -1
  37. package/dist/index.d.ts +7 -1
  38. package/dist/index.js +750 -80
  39. package/dist/index.js.map +1 -1
  40. package/dist/postLoginPath.d.ts +21 -0
  41. package/dist/postLoginPath.js +24 -0
  42. package/dist/postLoginPath.js.map +1 -0
  43. package/dist/previewDeployName.js +2 -2
  44. package/dist/previewDeployName.js.map +1 -1
  45. package/dist/recordTableColumns.js +112 -12
  46. package/dist/recordTableColumns.js.map +1 -1
  47. package/dist/recordTablePreload.js.map +1 -1
  48. package/dist/refDisplayRequests.js +112 -12
  49. package/dist/refDisplayRequests.js.map +1 -1
  50. package/dist/richDoc.d.ts +2 -2
  51. package/dist/richDoc.js +5 -5
  52. package/dist/richDoc.js.map +1 -1
  53. package/dist/schemaGenerator.d.ts +25 -1
  54. package/dist/schemaGenerator.js +4569 -18
  55. package/dist/schemaGenerator.js.map +1 -1
  56. package/dist/schemaShrink.d.ts +3 -1
  57. package/dist/schemaShrink.js +4451 -1
  58. package/dist/schemaShrink.js.map +1 -1
  59. package/dist/schemaShrinkValidators.d.ts +2 -2
  60. package/dist/schemaTypes.d.ts +123 -0
  61. package/dist/schemaTypes.js +107 -13
  62. package/dist/schemaTypes.js.map +1 -1
  63. package/dist/share.js +6 -1
  64. package/dist/share.js.map +1 -1
  65. package/dist/shareApiBridge.js +6 -1
  66. package/dist/shareApiBridge.js.map +1 -1
  67. package/dist/shareProposal.js +112 -12
  68. package/dist/shareProposal.js.map +1 -1
  69. package/dist/spaceBundle.js +112 -12
  70. package/dist/spaceBundle.js.map +1 -1
  71. package/dist/syncChannel.d.ts +15 -0
  72. package/dist/syncChannel.js +4642 -0
  73. package/dist/syncChannel.js.map +1 -0
  74. package/package.json +1 -1
  75. package/dist/storageFieldValues.d.ts +0 -10
  76. package/dist/storageFieldValues.js.map +0 -1
package/dist/index.js CHANGED
@@ -5620,19 +5620,19 @@ function isBlockNoteContent(value) {
5620
5620
  function isHttpUrl(value) {
5621
5621
  return /^https?:\/\//i.test(value);
5622
5622
  }
5623
- function collectImageStorageIdsFromBlocks(blocks, out) {
5623
+ function collectImageAssetIdsFromBlocks(blocks, out) {
5624
5624
  for (const block of blocks) {
5625
5625
  if (block.type === "image") {
5626
5626
  const url = block.props?.url;
5627
5627
  if (typeof url === "string" && url.trim() !== "" && !isHttpUrl(url)) out.add(url);
5628
5628
  }
5629
- if (block.children?.length) collectImageStorageIdsFromBlocks(block.children, out);
5629
+ if (block.children?.length) collectImageAssetIdsFromBlocks(block.children, out);
5630
5630
  }
5631
5631
  }
5632
- function collectRichDocStorageIds(value) {
5632
+ function collectRichDocAssetIds(value) {
5633
5633
  if (!isBlockNoteContent(value)) return [];
5634
5634
  const ids = /* @__PURE__ */ new Set();
5635
- collectImageStorageIdsFromBlocks(parseRichDocBlocks(value), ids);
5635
+ collectImageAssetIdsFromBlocks(parseRichDocBlocks(value), ids);
5636
5636
  return [...ids];
5637
5637
  }
5638
5638
  function plainMarkdownText(value) {
@@ -5662,7 +5662,13 @@ var RESERVED_TABLE_NAMES = /* @__PURE__ */ new Set([
5662
5662
  "columnus_api_output_secrets",
5663
5663
  "columnus_api_sync_routes",
5664
5664
  "columnus_api_outbox",
5665
- "columnus_api_delivery"
5665
+ "columnus_api_delivery",
5666
+ "columnus_assets",
5667
+ "columnus_asset_versions",
5668
+ "columnus_asset_refs",
5669
+ "columnus_asset_profiles",
5670
+ "columnus_asset_settings",
5671
+ "columnus_asset_jobs"
5666
5672
  ]);
5667
5673
  var displayTemplatesSchema = external_exports.object({
5668
5674
  id: external_exports.string().optional(),
@@ -5695,6 +5701,12 @@ var TABLE_COLORS = [
5695
5701
  "lavender"
5696
5702
  ];
5697
5703
  var tableColorSchema = external_exports.enum(TABLE_COLORS);
5704
+ var TABLE_KINDS = ["record", "asset"];
5705
+ var tableKindSchema = external_exports.enum(TABLE_KINDS);
5706
+ var assetBindingSchema = external_exports.object({
5707
+ profile: external_exports.string().min(1),
5708
+ enforced: external_exports.boolean().optional()
5709
+ });
5698
5710
  var fieldTypeSchema = external_exports.lazy(
5699
5711
  () => external_exports.discriminatedUnion("kind", [
5700
5712
  external_exports.object({ kind: external_exports.literal("string") }),
@@ -5722,7 +5734,9 @@ var fieldTypeSchema = external_exports.lazy(
5722
5734
  name: external_exports.string().regex(IDENT),
5723
5735
  label: external_exports.string().optional(),
5724
5736
  type: fieldTypeSchema,
5725
- optional: external_exports.boolean()
5737
+ optional: external_exports.boolean(),
5738
+ /** Nested image/file placements bind a Media profile like top-level ones. */
5739
+ asset: assetBindingSchema.optional()
5726
5740
  })
5727
5741
  )
5728
5742
  }),
@@ -5736,7 +5750,9 @@ var fieldSchema = external_exports.object({
5736
5750
  name: external_exports.string().regex(IDENT, "must be a valid identifier"),
5737
5751
  label: external_exports.string().optional(),
5738
5752
  type: fieldTypeSchema,
5739
- optional: external_exports.boolean()
5753
+ optional: external_exports.boolean(),
5754
+ /** Image/file fields may pin a Media profile; existence is enforced at upload/pick. */
5755
+ asset: assetBindingSchema.optional()
5740
5756
  });
5741
5757
  var indexSchema = external_exports.object({
5742
5758
  name: external_exports.string().regex(IDENT),
@@ -5753,6 +5769,8 @@ var tableSchema = external_exports.object({
5753
5769
  }),
5754
5770
  label: external_exports.string().optional(),
5755
5771
  color: tableColorSchema.optional(),
5772
+ /** Asset metadata tables are typed root tables but never ordinary user records. */
5773
+ kind: tableKindSchema.optional().default("record"),
5756
5774
  fields: external_exports.array(fieldSchema),
5757
5775
  indexes: external_exports.array(indexSchema).default([]),
5758
5776
  searchIndexes: external_exports.array(searchIndexSchema).default([]),
@@ -5762,6 +5780,7 @@ var manifestSchema = external_exports.object({
5762
5780
  tables: external_exports.array(tableSchema)
5763
5781
  }).superRefine((manifest, ctx) => {
5764
5782
  const tableNames = /* @__PURE__ */ new Set();
5783
+ const tablesByName = /* @__PURE__ */ new Map();
5765
5784
  for (const t of manifest.tables) {
5766
5785
  if (tableNames.has(t.name)) {
5767
5786
  ctx.addIssue({
@@ -5771,6 +5790,37 @@ var manifestSchema = external_exports.object({
5771
5790
  });
5772
5791
  }
5773
5792
  tableNames.add(t.name);
5793
+ tablesByName.set(t.name, t);
5794
+ if (tableKind(t) === "asset") {
5795
+ if (t.indexes.length > 0) {
5796
+ ctx.addIssue({
5797
+ code: external_exports.ZodIssueCode.custom,
5798
+ message: `${t.name} is an asset metadata table and cannot define indexes`,
5799
+ path: ["tables"]
5800
+ });
5801
+ }
5802
+ if (t.searchIndexes.length > 0) {
5803
+ ctx.addIssue({
5804
+ code: external_exports.ZodIssueCode.custom,
5805
+ message: `${t.name} is an asset metadata table and cannot define search indexes`,
5806
+ path: ["tables"]
5807
+ });
5808
+ }
5809
+ if (t.displayTemplates !== void 0) {
5810
+ ctx.addIssue({
5811
+ code: external_exports.ZodIssueCode.custom,
5812
+ message: `${t.name} is an asset metadata table and cannot define display templates`,
5813
+ path: ["tables"]
5814
+ });
5815
+ }
5816
+ if (t.color !== void 0) {
5817
+ ctx.addIssue({
5818
+ code: external_exports.ZodIssueCode.custom,
5819
+ message: `${t.name} is an asset metadata table and cannot define a color`,
5820
+ path: ["tables"]
5821
+ });
5822
+ }
5823
+ }
5774
5824
  const fieldNames = /* @__PURE__ */ new Set();
5775
5825
  for (const f of t.fields) {
5776
5826
  if (fieldNames.has(f.name)) {
@@ -5781,36 +5831,43 @@ var manifestSchema = external_exports.object({
5781
5831
  });
5782
5832
  }
5783
5833
  fieldNames.add(f.name);
5834
+ assertAssetBindingAllowed(ctx, t, f);
5784
5835
  }
5785
5836
  }
5786
5837
  for (const t of manifest.tables) {
5787
5838
  for (const f of t.fields) {
5788
- const danglingRef = findDanglingRef(f.type, tableNames);
5789
- if (danglingRef) {
5839
+ const invalidRef = findInvalidReference(f.type, tablesByName);
5840
+ if (invalidRef) {
5790
5841
  ctx.addIssue({
5791
5842
  code: external_exports.ZodIssueCode.custom,
5792
- message: `${t.name}.${f.name} references unknown table: ${danglingRef}`,
5843
+ message: `${t.name}.${f.name} ${invalidRef}`,
5793
5844
  path: ["tables"]
5794
5845
  });
5795
5846
  }
5796
5847
  }
5797
5848
  }
5798
5849
  });
5799
- function findDanglingRef(t, known) {
5850
+ function findInvalidReference(t, tablesByName) {
5800
5851
  switch (t.kind) {
5801
- case "id":
5802
- return known.has(t.table) ? null : t.table;
5852
+ case "id": {
5853
+ const target = tablesByName.get(t.table);
5854
+ if (!target) return `references unknown table: ${t.table}`;
5855
+ if (tableKind(target) === "asset") {
5856
+ return `cannot reference asset metadata table: ${t.table}`;
5857
+ }
5858
+ return null;
5859
+ }
5803
5860
  case "array":
5804
- return findDanglingRef(t.element, known);
5861
+ return findInvalidReference(t.element, tablesByName);
5805
5862
  case "object":
5806
5863
  for (const f of t.fields) {
5807
- const r = findDanglingRef(f.type, known);
5864
+ const r = findInvalidReference(f.type, tablesByName);
5808
5865
  if (r) return r;
5809
5866
  }
5810
5867
  return null;
5811
5868
  case "union":
5812
5869
  for (const o of t.options) {
5813
- const r = findDanglingRef(o, known);
5870
+ const r = findInvalidReference(o, tablesByName);
5814
5871
  if (r) return r;
5815
5872
  }
5816
5873
  return null;
@@ -5819,6 +5876,12 @@ function findDanglingRef(t, known) {
5819
5876
  }
5820
5877
  }
5821
5878
  var EMPTY_MANIFEST = { tables: [] };
5879
+ function tableKind(table) {
5880
+ return table.kind ?? "record";
5881
+ }
5882
+ function isAssetTable(table) {
5883
+ return tableKind(table) === "asset";
5884
+ }
5822
5885
  function trimmedLabel(label) {
5823
5886
  const t = label?.trim();
5824
5887
  return t ? t : void 0;
@@ -5887,6 +5950,37 @@ function isImageFieldType(t) {
5887
5950
  function isStorageFieldType(t) {
5888
5951
  return isFileFieldType(t) || isFileArrayFieldType(t);
5889
5952
  }
5953
+ function assertAssetBindingAllowed(ctx, table, field) {
5954
+ if (field.asset && tableKind(table) === "asset") {
5955
+ ctx.addIssue({
5956
+ code: external_exports.ZodIssueCode.custom,
5957
+ message: `${table.name}.${field.name} asset metadata fields cannot define a Media profile`,
5958
+ path: ["tables"]
5959
+ });
5960
+ } else if (field.asset && !isStorageFieldType(field.type)) {
5961
+ ctx.addIssue({
5962
+ code: external_exports.ZodIssueCode.custom,
5963
+ message: `${table.name}.${field.name} asset profile can only be set on image/file fields`,
5964
+ path: ["tables"]
5965
+ });
5966
+ }
5967
+ assertAssetBindingsInType(ctx, table, field.type);
5968
+ }
5969
+ function assertAssetBindingsInType(ctx, table, type) {
5970
+ switch (type.kind) {
5971
+ case "array":
5972
+ assertAssetBindingsInType(ctx, table, type.element);
5973
+ return;
5974
+ case "object":
5975
+ for (const field of type.fields) assertAssetBindingAllowed(ctx, table, field);
5976
+ return;
5977
+ case "union":
5978
+ for (const option of type.options) assertAssetBindingsInType(ctx, table, option);
5979
+ return;
5980
+ default:
5981
+ return;
5982
+ }
5983
+ }
5890
5984
  function isTextScalarKind(t) {
5891
5985
  return t.kind === "string" || t.kind === "number" || t.kind === "bigint" || t.kind === "id";
5892
5986
  }
@@ -6142,6 +6236,289 @@ function isManifestDeployStatus(value) {
6142
6236
  return MANIFEST_DEPLOY_STATUSES.some((status) => status === value);
6143
6237
  }
6144
6238
 
6239
+ // packages/@columnus/shared/src/assetFamily.ts
6240
+ var ASSET_FAMILIES = ["image", "document", "audio", "video", "vector", "other"];
6241
+ var ASSET_FAMILY_SET = new Set(ASSET_FAMILIES);
6242
+ function isAssetFamily(value) {
6243
+ return typeof value === "string" && ASSET_FAMILY_SET.has(value);
6244
+ }
6245
+ var VECTOR_CONTENT_TYPES = /* @__PURE__ */ new Set([
6246
+ "image/svg+xml",
6247
+ "application/postscript",
6248
+ "application/eps",
6249
+ "application/x-eps",
6250
+ "image/eps",
6251
+ "image/x-eps",
6252
+ "application/illustrator",
6253
+ "application/vnd.adobe.illustrator"
6254
+ ]);
6255
+ var DISPLAYABLE_VECTOR_CONTENT_TYPES = ["image/svg+xml"];
6256
+ var DISPLAYABLE_VECTOR_CONTENT_TYPE_SET = new Set(
6257
+ DISPLAYABLE_VECTOR_CONTENT_TYPES
6258
+ );
6259
+ var RASTER_RENDITION_CONTENT_TYPES = /* @__PURE__ */ new Set([
6260
+ "image/jpeg",
6261
+ "image/pjpeg",
6262
+ "image/png",
6263
+ "image/webp",
6264
+ "image/avif",
6265
+ "image/tiff",
6266
+ "image/heic",
6267
+ "image/heif",
6268
+ "image/gif"
6269
+ ]);
6270
+ function isRasterRenditionSource(contentType) {
6271
+ return RASTER_RENDITION_CONTENT_TYPES.has(normalizeContentType(contentType));
6272
+ }
6273
+ var VECTOR_FILE_ACCEPT = ".svg,.eps,.ai,image/svg+xml,application/postscript,application/illustrator";
6274
+ function normalizeContentType(contentType) {
6275
+ return contentType?.split(";")[0]?.trim().toLowerCase() ?? "";
6276
+ }
6277
+ function hasVectorExtension(filename) {
6278
+ return filename?.trim().toLowerCase().endsWith(".svg") ?? false;
6279
+ }
6280
+ function isVectorContentType(contentType, filename) {
6281
+ const value = normalizeContentType(contentType);
6282
+ if (!value) return hasVectorExtension(filename);
6283
+ return VECTOR_CONTENT_TYPES.has(value);
6284
+ }
6285
+ function isDisplayableVectorContentType(contentType, filename) {
6286
+ const value = normalizeContentType(contentType);
6287
+ if (!value) return hasVectorExtension(filename);
6288
+ return DISPLAYABLE_VECTOR_CONTENT_TYPE_SET.has(value);
6289
+ }
6290
+ function assetFamilyForContentType(contentType, filename) {
6291
+ const value = normalizeContentType(contentType);
6292
+ if (isVectorContentType(contentType, filename)) return "vector";
6293
+ if (value.startsWith("image/")) return "image";
6294
+ if (value.startsWith("audio/")) return "audio";
6295
+ if (value.startsWith("video/")) return "video";
6296
+ if (value === "application/pdf" || value.startsWith("text/") || value.startsWith("application/msword") || value.startsWith("application/vnd.openxmlformats-officedocument") || value.startsWith("application/vnd.oasis.opendocument")) {
6297
+ return "document";
6298
+ }
6299
+ return "other";
6300
+ }
6301
+ function isExtractableFamily(family) {
6302
+ return family === "image" || family === "vector";
6303
+ }
6304
+ function isImageFieldPickable(asset) {
6305
+ if (asset.family === "image") return true;
6306
+ return isDisplayableVectorContentType(asset.contentType, asset.filename);
6307
+ }
6308
+
6309
+ // packages/@columnus/shared/src/assetGraph.ts
6310
+ var MAX_RENDER_MEGAPIXELS = 500;
6311
+ var MAX_RENDER_PIXELS = MAX_RENDER_MEGAPIXELS * 1e6;
6312
+ var RENDITION_TIMEOUT_MS = 6e5;
6313
+ function resolveAssetGraph(familyGraph, profileExtraNodes = []) {
6314
+ const byId = /* @__PURE__ */ new Map();
6315
+ for (const nodes of profileExtraNodes) {
6316
+ for (const node of nodes) byId.set(node.id, node);
6317
+ }
6318
+ for (const node of familyGraph ?? []) byId.set(node.id, node);
6319
+ return [...byId.values()];
6320
+ }
6321
+ function rootRenditionNodes(graph) {
6322
+ const ids = new Set(graph.map((node) => node.id));
6323
+ return graph.filter((node) => node.parentId === void 0 || !ids.has(node.parentId));
6324
+ }
6325
+ function childRenditionNodes(graph, nodeId) {
6326
+ return graph.filter((node) => node.parentId === nodeId);
6327
+ }
6328
+ var MAX_RENDITION_NODES = 100;
6329
+ function assetBuildsRenditions(family, contentType) {
6330
+ return family === "image" && isRasterRenditionSource(contentType);
6331
+ }
6332
+ function validateRenditionNodes(nodes, label) {
6333
+ if (nodes.length > MAX_RENDITION_NODES) {
6334
+ throw new Error(`${label} may have at most ${MAX_RENDITION_NODES} nodes`);
6335
+ }
6336
+ const byId = /* @__PURE__ */ new Map();
6337
+ for (const node of nodes) {
6338
+ const id = node.id.trim();
6339
+ if (!id) throw new Error(`${label} nodes need an id`);
6340
+ if (byId.has(id)) throw new Error(`${label} nodes must have unique ids`);
6341
+ if (!Number.isSafeInteger(node.maxWidth) || node.maxWidth < 1) {
6342
+ throw new Error(`${label} node widths must be positive whole numbers`);
6343
+ }
6344
+ if (!Number.isSafeInteger(node.maxHeight) || node.maxHeight < 1) {
6345
+ throw new Error(`${label} node heights must be positive whole numbers`);
6346
+ }
6347
+ if (!node.format.trim()) throw new Error(`${label} nodes need an output format`);
6348
+ const quality = node.quality;
6349
+ if (quality !== void 0 && (!Number.isSafeInteger(quality) || quality < 1 || quality > 100)) {
6350
+ throw new Error(`${label} node quality must be between 1 and 100`);
6351
+ }
6352
+ byId.set(id, node);
6353
+ }
6354
+ const visiting = /* @__PURE__ */ new Set();
6355
+ const visited = /* @__PURE__ */ new Set();
6356
+ const visit = (id) => {
6357
+ if (visited.has(id)) return;
6358
+ if (visiting.has(id)) throw new Error(`${label} nodes cannot contain a cycle`);
6359
+ visiting.add(id);
6360
+ const parentId = byId.get(id)?.parentId;
6361
+ if (parentId) {
6362
+ if (!byId.has(parentId)) throw new Error(`${label} node \u201C${id}\u201D has an unknown parent`);
6363
+ visit(parentId);
6364
+ }
6365
+ visiting.delete(id);
6366
+ visited.add(id);
6367
+ };
6368
+ for (const id of byId.keys()) visit(id);
6369
+ }
6370
+ var ASSET_PROCESSING_STATUSES = ["ready", "pending", "failed", "dead_letter"];
6371
+ function rollupProcessingStatus(graph, builtNodeIds, failure) {
6372
+ if (failure) return failure;
6373
+ const built = new Set(builtNodeIds);
6374
+ return graph.every((node) => built.has(node.id)) ? "ready" : "pending";
6375
+ }
6376
+ function renditionPlan(node, source, focal = { x: 0.5, y: 0.5 }) {
6377
+ const empty = { width: 0, height: 0 };
6378
+ if (source.width <= 0 || source.height <= 0) return { resize: empty, output: empty };
6379
+ const scaleX = node.maxWidth / source.width;
6380
+ const scaleY = node.maxHeight / source.height;
6381
+ const scale = Math.min(
6382
+ node.op === "cover" ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY),
6383
+ 1
6384
+ );
6385
+ const resize = {
6386
+ width: Math.max(1, Math.round(source.width * scale)),
6387
+ height: Math.max(1, Math.round(source.height * scale))
6388
+ };
6389
+ if (node.op !== "cover") return { resize, output: resize };
6390
+ const output = {
6391
+ width: Math.min(node.maxWidth, resize.width),
6392
+ height: Math.min(node.maxHeight, resize.height)
6393
+ };
6394
+ const clamp = (value, max) => Math.max(0, Math.min(Math.round(value), max));
6395
+ const crop = {
6396
+ ...output,
6397
+ left: clamp(resize.width * focal.x - output.width / 2, resize.width - output.width),
6398
+ top: clamp(resize.height * focal.y - output.height / 2, resize.height - output.height)
6399
+ };
6400
+ return { resize, crop, output };
6401
+ }
6402
+ function renditionNodeFingerprint(node) {
6403
+ return [
6404
+ node.parentId ?? "",
6405
+ node.op,
6406
+ node.maxWidth,
6407
+ node.maxHeight,
6408
+ node.format,
6409
+ node.quality ?? ""
6410
+ ].join("|");
6411
+ }
6412
+ function planGraphDelta(previous, next) {
6413
+ const before = new Map(previous.map((node) => [node.id, node]));
6414
+ const stillPresent = new Set(next.map((node) => node.id));
6415
+ const dirty = /* @__PURE__ */ new Set();
6416
+ for (const node of next) {
6417
+ const old = before.get(node.id);
6418
+ if (!old || renditionNodeFingerprint(old) !== renditionNodeFingerprint(node)) {
6419
+ dirty.add(node.id);
6420
+ }
6421
+ }
6422
+ let changed = true;
6423
+ while (changed) {
6424
+ changed = false;
6425
+ for (const node of next) {
6426
+ if (dirty.has(node.id)) continue;
6427
+ if (node.parentId !== void 0 && dirty.has(node.parentId)) {
6428
+ dirty.add(node.id);
6429
+ changed = true;
6430
+ }
6431
+ }
6432
+ }
6433
+ return {
6434
+ rebuild: next.filter((node) => dirty.has(node.id)).map((node) => node.id),
6435
+ removed: previous.filter((node) => !stillPresent.has(node.id)).map((node) => node.id)
6436
+ };
6437
+ }
6438
+ function pendingRebuildsForSave(previous, next) {
6439
+ const families = /* @__PURE__ */ new Set([...Object.keys(previous ?? {}), ...Object.keys(next ?? {})]);
6440
+ const pending = [];
6441
+ for (const family of families) {
6442
+ const delta = planGraphDelta(
6443
+ previous?.[family] ?? [],
6444
+ next?.[family] ?? []
6445
+ );
6446
+ if (delta.rebuild.length === 0 && delta.removed.length === 0) continue;
6447
+ pending.push({ family, ...delta });
6448
+ }
6449
+ return pending;
6450
+ }
6451
+ function assertAssetSlotsResolve(familyGraphs, slots) {
6452
+ for (const [family, mapping] of Object.entries(slots ?? {})) {
6453
+ const ids = new Set((familyGraphs?.[family] ?? []).map((node) => node.id));
6454
+ for (const [slot, nodeId] of Object.entries(mapping ?? {})) {
6455
+ if (nodeId === void 0 || nodeId === "") continue;
6456
+ if (!ids.has(nodeId)) {
6457
+ throw new Error(
6458
+ `Media ${family} ${slot} slot points at \u201C${nodeId}\u201D, which is not a node in that graph`
6459
+ );
6460
+ }
6461
+ }
6462
+ }
6463
+ }
6464
+ function resolveAssetSlotDisplay(input) {
6465
+ if (!assetBuildsRenditions(input.family, input.contentType)) return { kind: "original" };
6466
+ if (!input.slotNodeId) return { kind: "original" };
6467
+ const storageId = input.renditions?.[input.slotNodeId];
6468
+ if (storageId) return { kind: "rendition", storageId };
6469
+ if (input.processingStatus === "failed" || input.processingStatus === "dead_letter") {
6470
+ return { kind: "failed" };
6471
+ }
6472
+ return { kind: "pending" };
6473
+ }
6474
+ function normalizeDisplayFocal(focal) {
6475
+ return { x: focal?.x ?? 0.5, y: focal?.y ?? 0.5 };
6476
+ }
6477
+ function focalObjectPosition(focal) {
6478
+ const { x, y } = normalizeDisplayFocal(focal);
6479
+ return `${x * 100}% ${y * 100}%`;
6480
+ }
6481
+ function mapsFromAssetDisplayRows(rows, slot = "compact") {
6482
+ const urls = /* @__PURE__ */ new Map();
6483
+ const slots = /* @__PURE__ */ new Map();
6484
+ const focals = /* @__PURE__ */ new Map();
6485
+ const metadata = /* @__PURE__ */ new Map();
6486
+ for (const row of rows) {
6487
+ const id = String(row.assetId);
6488
+ const view = assetSlotView(row, slot);
6489
+ urls.set(id, view.url);
6490
+ slots.set(id, view);
6491
+ focals.set(id, normalizeDisplayFocal(row.focalPoint));
6492
+ if (row.size !== void 0) {
6493
+ metadata.set(id, {
6494
+ contentType: row.contentType,
6495
+ size: row.size
6496
+ });
6497
+ }
6498
+ }
6499
+ return { urls, slots, focals, metadata };
6500
+ }
6501
+ function assetSlotView(row, slot) {
6502
+ const decision = row[slot];
6503
+ if (!decision || decision.kind === "original") {
6504
+ return { url: row.originalUrl, pending: false, failed: false };
6505
+ }
6506
+ return {
6507
+ url: decision.url,
6508
+ pending: decision.kind === "pending",
6509
+ failed: decision.kind === "failed"
6510
+ };
6511
+ }
6512
+ function publicRenditionUrlKeys(graph, renditions) {
6513
+ const built = renditions ?? {};
6514
+ return graph.filter((node) => built[node.id] !== void 0).map((node) => node.id);
6515
+ }
6516
+ function renderPixelCapError(label, size) {
6517
+ const pixels = size.width * size.height;
6518
+ if (pixels <= MAX_RENDER_PIXELS) return null;
6519
+ return `${label} is ${(pixels / 1e6).toFixed(1)}MP, above the ${MAX_RENDER_MEGAPIXELS}MP render limit`;
6520
+ }
6521
+
6145
6522
  // packages/@columnus/shared/src/schemaGenerator.ts
6146
6523
  var BANNER = `// AUTO-GENERATED by Columnus. Do not edit by hand \u2014
6147
6524
  // changes here will be overwritten when Columnus next saves the schema.
@@ -6164,6 +6541,45 @@ var API_SYNC_ROUTES_TABLE_NAME = "columnus_api_sync_routes";
6164
6541
  var API_OUTBOX_TABLE_NAME = "columnus_api_outbox";
6165
6542
  var API_DELIVERY_TABLE_NAME = "columnus_api_delivery";
6166
6543
  var INCOMING_REFS_TABLE_NAME = "columnus_incoming_refs";
6544
+ var ASSETS_TABLE_NAME = "columnus_assets";
6545
+ var ASSET_VERSIONS_TABLE_NAME = "columnus_asset_versions";
6546
+ var ASSET_REFS_TABLE_NAME = "columnus_asset_refs";
6547
+ var ASSET_PROFILES_TABLE_NAME = "columnus_asset_profiles";
6548
+ var ASSET_SETTINGS_TABLE_NAME = "columnus_asset_settings";
6549
+ var ASSET_FAMILY_LITERALS = ASSET_FAMILIES.map(
6550
+ (family) => ` v.literal(${JSON.stringify(family)}),`
6551
+ ).join("\n");
6552
+ var ASSET_PROCESSING_STATUS_LITERALS = ASSET_PROCESSING_STATUSES.map(
6553
+ (status) => ` v.literal(${JSON.stringify(status)}),`
6554
+ ).join("\n");
6555
+ var ASSETS_TABLE_SOURCE = ` ${ASSETS_TABLE_NAME}: defineTable({
6556
+ currentVersionId: v.optional(v.string()),
6557
+ currentOriginalStorageId: v.optional(v.id("_storage")),
6558
+ currentRenditionStorageIds: v.optional(v.record(v.string(), v.id("_storage"))),
6559
+ family: v.optional(
6560
+ v.union(
6561
+ ${ASSET_FAMILY_LITERALS}
6562
+ ),
6563
+ ),
6564
+ profileSlugs: v.array(v.string()),
6565
+ focalPoint: v.optional(v.object({ x: v.number(), y: v.number() })),
6566
+ processingStatus: v.union(
6567
+ ${ASSET_PROCESSING_STATUS_LITERALS}
6568
+ ),
6569
+ contentType: v.optional(v.string()),
6570
+ filename: v.string(),
6571
+ size: v.optional(v.number()),
6572
+ isDeleted: v.boolean(),
6573
+ deletedAt: v.optional(v.number()),
6574
+ wipedAt: v.optional(v.number()),
6575
+ })
6576
+ .index("by_isDeleted_and_deletedAt", ["isDeleted", "deletedAt"])
6577
+ .index("by_isDeleted_and_family_and_wipedAt", ["isDeleted", "family", "wipedAt"])
6578
+ .index("by_isDeleted_and_wipedAt_and_deletedAt", ["isDeleted", "wipedAt", "deletedAt"])
6579
+ .searchIndex("search_filename", {
6580
+ searchField: "filename",
6581
+ filterFields: ["isDeleted", "family", "wipedAt"],
6582
+ }),`;
6167
6583
  var AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({
6168
6584
  timestamp: v.number(),
6169
6585
  kind: v.union(v.literal("data"), v.literal("schema")),
@@ -6174,6 +6590,7 @@ var AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({
6174
6590
  after: v.optional(v.any()),
6175
6591
  })
6176
6592
  .index("by_timestamp", ["timestamp"])
6593
+ .index("by_kind_and_timestamp", ["kind", "timestamp"])
6177
6594
  .index("by_table", ["table", "timestamp"])
6178
6595
  .index("by_document", ["documentId", "timestamp"]),`;
6179
6596
  var SPACES_TABLE_SOURCE = ` ${SPACES_TABLE_NAME}: defineTable({
@@ -6234,8 +6651,9 @@ function generateSchemaTs(manifest, opts) {
6234
6651
  const includeManifestTable = opts?.includeManifestTable ?? true;
6235
6652
  const includeAuditTable = opts?.includeAuditTable ?? true;
6236
6653
  const includeDisplayValuesTable = opts?.includeDisplayValuesTable ?? true;
6654
+ const assetFieldIds = opts?.assetFieldIds ?? "assets";
6237
6655
  const userTables = [...manifest.tables].sort((a, b) => a.name.localeCompare(b.name));
6238
- const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t)},`).join("\n");
6656
+ const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t, assetFieldIds)},`).join("\n");
6239
6657
  let body;
6240
6658
  if (includeColumnusTables) {
6241
6659
  const columnusSource = columnusTablesSource({
@@ -6244,37 +6662,47 @@ function generateSchemaTs(manifest, opts) {
6244
6662
  includeAuditTable,
6245
6663
  includeDisplayValuesTable
6246
6664
  });
6247
- body = userBody ? `${userBody}
6248
- ${columnusSource}` : columnusSource;
6665
+ body = [userBody, ASSETS_TABLE_SOURCE, columnusSource].filter(Boolean).join("\n");
6249
6666
  } else {
6250
- body = userBody || "";
6667
+ body = [userBody, ASSETS_TABLE_SOURCE].filter(Boolean).join("\n");
6251
6668
  }
6252
6669
  const banner = includeColumnusTables ? BANNER : CONSUMER_BANNER;
6253
6670
  const schemaBody = body ? `${body}
6254
6671
  ` : "";
6672
+ const schemaOpts = opts?.schemaValidation === false ? ", { schemaValidation: false }" : "";
6255
6673
  return `${banner}import { defineSchema, defineTable } from "convex/server";
6256
6674
  import { v } from "convex/values";
6257
6675
 
6258
6676
  export default defineSchema({
6259
- ${schemaBody}});
6677
+ ${schemaBody}}${schemaOpts});
6260
6678
  `;
6261
6679
  }
6262
- function renderTable(t) {
6263
- const fieldsBlock = t.fields.length ? `{
6264
- ${t.fields.map((f) => {
6265
- const inner = renderType(f.type);
6680
+ function renderTable(t, assetFieldIds) {
6681
+ const fields = isAssetTable(t) ? [
6682
+ ...t.fields,
6683
+ {
6684
+ name: "assetId",
6685
+ type: { kind: "id", table: ASSETS_TABLE_NAME },
6686
+ optional: false
6687
+ }
6688
+ ] : t.fields;
6689
+ const fieldsBlock = fields.length ? `{
6690
+ ${fields.map((f) => {
6691
+ const inner = renderType(f.type, assetFieldIds);
6266
6692
  const value = f.optional ? `v.optional(${inner})` : inner;
6267
6693
  return ` ${f.name}: ${value},`;
6268
6694
  }).join("\n")}
6269
6695
  }` : `{}`;
6270
6696
  let out = `defineTable(${fieldsBlock})`;
6271
- const inlineSingleIndex = t.indexes.length === 1 && t.searchIndexes.length === 0;
6272
- for (const idx of t.indexes) {
6697
+ const indexes = isAssetTable(t) ? [{ name: "by_assetId", fields: ["assetId"] }] : t.indexes;
6698
+ const searchIndexes = isAssetTable(t) ? [] : t.searchIndexes;
6699
+ const inlineSingleIndex = indexes.length === 1 && searchIndexes.length === 0;
6700
+ for (const idx of indexes) {
6273
6701
  const cols = idx.fields.map((c) => JSON.stringify(c)).join(", ");
6274
6702
  const sep = inlineSingleIndex ? "" : "\n ";
6275
6703
  out += `${sep}.index(${JSON.stringify(idx.name)}, [${cols}])`;
6276
6704
  }
6277
- for (const sx of t.searchIndexes) {
6705
+ for (const sx of searchIndexes) {
6278
6706
  const cfg = [`searchField: ${JSON.stringify(sx.searchField)}`];
6279
6707
  if (sx.filterFields && sx.filterFields.length > 0) {
6280
6708
  cfg.push(`filterFields: [${sx.filterFields.map((c) => JSON.stringify(c)).join(", ")}]`);
@@ -6284,7 +6712,20 @@ ${t.fields.map((f) => {
6284
6712
  }
6285
6713
  return out;
6286
6714
  }
6287
- function renderType(t) {
6715
+ function renderAssetIdType(assetFieldIds) {
6716
+ const assetId = `v.id(${JSON.stringify(ASSETS_TABLE_NAME)})`;
6717
+ switch (assetFieldIds) {
6718
+ case "storage-or-assets":
6719
+ return `v.union(v.id("_storage"), ${assetId})`;
6720
+ case "assets":
6721
+ return assetId;
6722
+ default: {
6723
+ const _exhaustive = assetFieldIds;
6724
+ return _exhaustive;
6725
+ }
6726
+ }
6727
+ }
6728
+ function renderType(t, assetFieldIds) {
6288
6729
  switch (t.kind) {
6289
6730
  case "string":
6290
6731
  case "markdown":
@@ -6306,26 +6747,62 @@ function renderType(t) {
6306
6747
  return "v.bytes()";
6307
6748
  case "file":
6308
6749
  case "image":
6309
- return 'v.id("_storage")';
6750
+ return renderAssetIdType(assetFieldIds);
6310
6751
  case "id":
6311
6752
  return `v.id(${JSON.stringify(t.table)})`;
6312
6753
  case "literal":
6313
6754
  return `v.literal(${JSON.stringify(t.value)})`;
6314
6755
  case "array":
6315
- return `v.array(${renderType(t.element)})`;
6756
+ return `v.array(${renderType(t.element, assetFieldIds)})`;
6316
6757
  case "object": {
6317
6758
  if (t.fields.length === 0) return `v.object({})`;
6318
6759
  const inner = t.fields.map((f) => {
6319
- const value = f.optional ? `v.optional(${renderType(f.type)})` : renderType(f.type);
6760
+ const inner2 = renderType(f.type, assetFieldIds);
6761
+ const value = f.optional ? `v.optional(${inner2})` : inner2;
6320
6762
  return `${f.name}: ${value}`;
6321
6763
  }).join(", ");
6322
6764
  return `v.object({ ${inner} })`;
6323
6765
  }
6324
6766
  case "union":
6325
- return `v.union(${t.options.map(renderType).join(", ")})`;
6767
+ return `v.union(${t.options.map((option) => renderType(option, assetFieldIds)).join(", ")})`;
6326
6768
  }
6327
6769
  throw new Error(`unknown field kind: ${t.kind}`);
6328
6770
  }
6771
+ function fieldTypeContainsFileOrImage(t) {
6772
+ switch (t.kind) {
6773
+ case "file":
6774
+ case "image":
6775
+ return true;
6776
+ case "array":
6777
+ return fieldTypeContainsFileOrImage(t.element);
6778
+ case "object":
6779
+ return t.fields.some((field) => fieldTypeContainsFileOrImage(field.type));
6780
+ case "union":
6781
+ return t.options.some(fieldTypeContainsFileOrImage);
6782
+ case "string":
6783
+ case "markdown":
6784
+ case "number":
6785
+ case "boolean":
6786
+ case "bigint":
6787
+ case "null":
6788
+ case "any":
6789
+ case "bytes":
6790
+ case "date":
6791
+ case "datetime":
6792
+ case "id":
6793
+ case "literal":
6794
+ return false;
6795
+ default: {
6796
+ const _exhaustive = t;
6797
+ return _exhaustive;
6798
+ }
6799
+ }
6800
+ }
6801
+ function manifestHasFileOrImageFields(manifest) {
6802
+ return manifest.tables.some(
6803
+ (table) => table.fields.some((field) => fieldTypeContainsFileOrImage(field.type))
6804
+ );
6805
+ }
6329
6806
 
6330
6807
  // packages/@columnus/shared/src/schemaShrink.ts
6331
6808
  var SHRINK_IMPACT_CAP = 500;
@@ -6351,6 +6828,16 @@ function computeShrinkPlan(saved, draft) {
6351
6828
  }
6352
6829
  return { removedTables, removedFields };
6353
6830
  }
6831
+ function assertTableKindsImmutable(saved, draft) {
6832
+ const draftByName = new Map(draft.tables.map((table) => [table.name, table]));
6833
+ for (const previous of saved.tables) {
6834
+ const next = draftByName.get(previous.name);
6835
+ if (!next || tableKind(previous) === tableKind(next)) continue;
6836
+ throw new Error(
6837
+ `Table "${previous.name}" cannot change kind from ${tableKind(previous)} to ${tableKind(next)}`
6838
+ );
6839
+ }
6840
+ }
6354
6841
  function shrinkPlanIsEmpty(plan) {
6355
6842
  return plan.removedTables.length === 0 && plan.removedFields.size === 0;
6356
6843
  }
@@ -6449,6 +6936,7 @@ function createCleanupState(targetManifestJson, beforeManifestJson, saved, plan)
6449
6936
  };
6450
6937
  }
6451
6938
  function prepareShrinkSave(saved, draft, beforeManifestJson = JSON.stringify(saved)) {
6939
+ assertTableKindsImmutable(saved, draft);
6452
6940
  const plan = computeShrinkPlan(saved, draft);
6453
6941
  const normalized = normalizeManifestForShrink(draft, plan);
6454
6942
  const normalizedJson = JSON.stringify(normalized);
@@ -6653,7 +7141,7 @@ function fallbackIdLabel(documentId) {
6653
7141
  function formatIdShort(id, n = 6) {
6654
7142
  return `${id.slice(0, n)}\u2026`;
6655
7143
  }
6656
- var CONVEX_DOCUMENT_ID = /^[a-z0-9]{32}$/;
7144
+ var CONVEX_DOCUMENT_ID = /^[a-z0-9]{26,64}$/;
6657
7145
  function looksLikeId(s) {
6658
7146
  return CONVEX_DOCUMENT_ID.test(s);
6659
7147
  }
@@ -7101,68 +7589,161 @@ function formatRecordTableCellText(value, type, locale) {
7101
7589
  }
7102
7590
  }
7103
7591
 
7104
- // packages/@columnus/shared/src/storageFieldValues.ts
7105
- var STORAGE_ID = /^[a-z0-9]+$/i;
7106
- function isValidStorageId(value) {
7107
- return STORAGE_ID.test(value) && value.length >= 10;
7592
+ // packages/@columnus/shared/src/assetFieldValues.ts
7593
+ var ASSET_ID = /^[a-z0-9]+$/i;
7594
+ function isValidAssetId(value) {
7595
+ return ASSET_ID.test(value) && value.length >= 10;
7108
7596
  }
7109
- function collectStorageIds(value, type, out = /* @__PURE__ */ new Set()) {
7597
+ function collectAssetIds(value, type, out = /* @__PURE__ */ new Set()) {
7110
7598
  if (isFileFieldType(type)) {
7111
7599
  const id = toDocumentId(value);
7112
7600
  if (id) out.add(id);
7113
7601
  return out;
7114
7602
  }
7115
- if (isFileArrayFieldType(type) && Array.isArray(value)) {
7116
- for (const item of value) {
7117
- const id = toDocumentId(item);
7118
- if (id) out.add(id);
7603
+ if (type.kind === "array" && Array.isArray(value)) {
7604
+ for (const item of value) collectAssetIds(item, type.element, out);
7605
+ return out;
7606
+ }
7607
+ if (type.kind === "object" && value !== null && typeof value === "object" && !Array.isArray(value)) {
7608
+ const record = value;
7609
+ for (const field of type.fields) {
7610
+ collectAssetIds(record[field.name], field.type, out);
7119
7611
  }
7612
+ return out;
7613
+ }
7614
+ if (type.kind === "union") {
7615
+ for (const option of type.options) collectAssetIds(value, option, out);
7120
7616
  }
7121
7617
  return out;
7122
7618
  }
7123
- function collectStorageIdsFromRow(row, fields, out = /* @__PURE__ */ new Set()) {
7619
+ function collectAssetIdsFromRow(row, fields, out = /* @__PURE__ */ new Set()) {
7124
7620
  if (!row) return out;
7125
7621
  for (const field of fields) {
7126
- if (!isStorageFieldType(field.type)) continue;
7127
- collectStorageIds(row[field.name], field.type, out);
7622
+ collectAssetIds(row[field.name], field.type, out);
7128
7623
  }
7129
7624
  return out;
7130
7625
  }
7131
- function storageIdsRemovedByPatches(serverRowById, patches, fields) {
7132
- const removed = [];
7133
- for (const { id, patch } of patches) {
7134
- const before = serverRowById.get(id);
7135
- if (!before) continue;
7136
- const after = { ...before, ...patch };
7137
- for (const field of fields) {
7138
- if (!(field.name in patch)) continue;
7139
- if (!isStorageFieldType(field.type)) continue;
7140
- const beforeIds = collectStorageIds(before[field.name], field.type);
7141
- const afterIds = collectStorageIds(after[field.name], field.type);
7142
- for (const storageId of beforeIds) {
7143
- if (!afterIds.has(storageId)) removed.push(storageId);
7144
- }
7145
- }
7626
+
7627
+ // packages/@columnus/shared/src/assetJobs.ts
7628
+ var ASSET_JOB_KINDS = ["extract", "rendition"];
7629
+ var ASSET_JOB_STATUSES = ["pending", "claimed", "done", "failed", "dead_letter"];
7630
+ var ASSET_JOB_MAX_ATTEMPTS = 5;
7631
+ var ASSET_JOB_TIMEOUT_MS = 6e5;
7632
+ var ASSET_JOB_LEASE_MS = 15 * 6e4;
7633
+ var ASSET_JOB_MAX_RECLAIMS = 5;
7634
+ var ASSET_JOB_BACKOFF_MS = [15e3, 6e4, 5 * 6e4, 60 * 6e4];
7635
+ function assetJobRetryDelayMs(attempts) {
7636
+ if (attempts >= ASSET_JOB_MAX_ATTEMPTS) return null;
7637
+ const index = Math.max(0, Math.min(attempts - 1, ASSET_JOB_BACKOFF_MS.length - 1));
7638
+ return ASSET_JOB_BACKOFF_MS[index] ?? null;
7639
+ }
7640
+ function assetJobFailureOutcome(attempts, now) {
7641
+ const delay = assetJobRetryDelayMs(attempts);
7642
+ if (delay === null) return { status: "dead_letter" };
7643
+ return { status: "pending", runAfter: now + delay };
7644
+ }
7645
+ function assetJobReclaimOutcome(reclaims) {
7646
+ return reclaims + 1 >= ASSET_JOB_MAX_RECLAIMS ? { status: "dead_letter" } : { status: "pending" };
7647
+ }
7648
+ function assetJobLeaseExpired(leaseUntil, now) {
7649
+ return leaseUntil === void 0 || leaseUntil <= now;
7650
+ }
7651
+ function nextAssetJobWakeAt(jobs, now) {
7652
+ let earliest = null;
7653
+ for (const job of jobs) {
7654
+ if (job.status !== "pending" || job.runAfter <= now) continue;
7655
+ if (earliest === null || job.runAfter < earliest) earliest = job.runAfter;
7656
+ }
7657
+ return earliest;
7658
+ }
7659
+ function assetJobKey(input) {
7660
+ if (input.kind !== "rendition") return `${input.versionId}:extract`;
7661
+ const node = input.nodeId ?? "";
7662
+ return input.fingerprint ? `${input.versionId}:rendition:${node}:${input.fingerprint}` : `${input.versionId}:rendition:${node}`;
7663
+ }
7664
+
7665
+ // packages/@columnus/shared/src/assetSettings.ts
7666
+ var DEFAULT_MEDIA_WARN_BYTES = 10 * 1024 * 1024 * 1024;
7667
+ var DEFAULT_MEDIA_REJECT_BYTES = 100 * 1024 * 1024 * 1024;
7668
+ var DEFAULT_MEDIA_UPLOAD_CAPS = {
7669
+ warnBytes: DEFAULT_MEDIA_WARN_BYTES,
7670
+ rejectBytes: DEFAULT_MEDIA_REJECT_BYTES
7671
+ };
7672
+ function formatMediaBytes(bytes) {
7673
+ if (bytes < 1024) return `${bytes} B`;
7674
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
7675
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
7676
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
7677
+ }
7678
+ function mediaUploadCapsError(caps) {
7679
+ if (!Number.isSafeInteger(caps.warnBytes) || caps.warnBytes < 0) {
7680
+ return "Media warning limit must be a non-negative whole number of bytes";
7681
+ }
7682
+ if (!Number.isSafeInteger(caps.rejectBytes) || caps.rejectBytes <= 0) {
7683
+ return "Media reject limit must be a positive whole number of bytes";
7146
7684
  }
7147
- return removed;
7685
+ if (caps.warnBytes > caps.rejectBytes) {
7686
+ return "Media warning limit cannot exceed the reject limit";
7687
+ }
7688
+ return null;
7148
7689
  }
7149
- function collectReferencedStorageIds(serverRowById, pendingEdits, draftRowIds, fields) {
7150
- const referenced = /* @__PURE__ */ new Set();
7151
- for (const row of serverRowById.values()) {
7152
- collectStorageIdsFromRow(row, fields, referenced);
7690
+ function mediaUploadLimit(size, caps) {
7691
+ if (!Number.isSafeInteger(size) || size < 0) {
7692
+ return { level: "reject", message: "Media upload size is invalid" };
7693
+ }
7694
+ if (size > caps.rejectBytes) {
7695
+ return {
7696
+ level: "reject",
7697
+ message: `This file is ${formatMediaBytes(size)}. Media uploads are limited to ${formatMediaBytes(caps.rejectBytes)}.`
7698
+ };
7153
7699
  }
7154
- for (const [rowId, patch] of pendingEdits) {
7155
- const baseline = isDraftRowId(rowId) ? patch : { ...serverRowById.get(rowId), ...patch };
7156
- collectStorageIdsFromRow(baseline, fields, referenced);
7700
+ if (size > caps.warnBytes) {
7701
+ return {
7702
+ level: "warn",
7703
+ message: `This file is ${formatMediaBytes(size)}, above the ${formatMediaBytes(caps.warnBytes)} Media warning limit. Continue uploading?`
7704
+ };
7157
7705
  }
7158
- for (const rowId of draftRowIds) {
7159
- const patch = pendingEdits.get(rowId);
7160
- if (patch) collectStorageIdsFromRow(patch, fields, referenced);
7706
+ return null;
7707
+ }
7708
+ var DEFAULT_IMAGE_GRAPH = [
7709
+ { id: "preview", op: "contain", maxWidth: 2e3, maxHeight: 2e3, format: "webp", quality: 80 },
7710
+ {
7711
+ id: "thumb",
7712
+ parentId: "preview",
7713
+ op: "contain",
7714
+ maxWidth: 400,
7715
+ maxHeight: 400,
7716
+ format: "webp",
7717
+ quality: 80
7718
+ },
7719
+ {
7720
+ id: "thumbSm",
7721
+ parentId: "preview",
7722
+ op: "contain",
7723
+ maxWidth: 200,
7724
+ maxHeight: 200,
7725
+ format: "webp",
7726
+ quality: 80
7161
7727
  }
7162
- return referenced;
7728
+ ];
7729
+ var DEFAULT_ASSET_SLOTS = {
7730
+ image: { compact: "thumbSm", preview: "preview" }
7731
+ };
7732
+ function defaultAssetSettings() {
7733
+ return {
7734
+ ...DEFAULT_MEDIA_UPLOAD_CAPS,
7735
+ familyGraphs: { image: DEFAULT_IMAGE_GRAPH },
7736
+ familySchemas: {},
7737
+ slots: DEFAULT_ASSET_SLOTS
7738
+ };
7163
7739
  }
7164
- function isDraftRowId(rowId) {
7165
- return rowId.startsWith("__draft__");
7740
+ function unsavedAssetSettings() {
7741
+ return { ...defaultAssetSettings(), updatedAt: 0 };
7742
+ }
7743
+ function resolveFamilySlotMapping(settings, family) {
7744
+ if (family === void 0) return void 0;
7745
+ const resolved = settings ?? unsavedAssetSettings();
7746
+ return resolved.slots?.[family] ?? DEFAULT_ASSET_SLOTS[family];
7166
7747
  }
7167
7748
 
7168
7749
  // packages/@columnus/shared/src/fieldValueEqual.ts
@@ -7469,7 +8050,7 @@ function coerceCsvValue(raw, type, optional) {
7469
8050
  return ok(raw);
7470
8051
  case "file":
7471
8052
  case "image":
7472
- if (!isValidStorageId(raw)) return fail("Invalid storage file id");
8053
+ if (!isValidAssetId(raw)) return fail("Invalid asset id");
7473
8054
  return ok(raw);
7474
8055
  case "number": {
7475
8056
  const n = Number(raw);
@@ -8206,6 +8787,27 @@ function isRadixOverlayOpen() {
8206
8787
  if (ae?.getAttribute("aria-expanded") === "true") return true;
8207
8788
  return Boolean(ae?.closest("[data-radix-popper-content-wrapper]"));
8208
8789
  }
8790
+
8791
+ // packages/@columnus/shared/src/postLoginPath.ts
8792
+ var RESOLVE_BASE = "https://post-login.invalid";
8793
+ function safePostLoginPath(raw, fallback = "/") {
8794
+ if (raw == null) return fallback;
8795
+ const trimmed = raw.trim();
8796
+ if (!trimmed.startsWith("/") || trimmed.startsWith("//") || trimmed.includes("\\")) {
8797
+ return fallback;
8798
+ }
8799
+ try {
8800
+ const url = new URL(trimmed, RESOLVE_BASE);
8801
+ if (url.origin !== RESOLVE_BASE) return fallback;
8802
+ const path = `${url.pathname}${url.search}${url.hash}`;
8803
+ return path.startsWith("/") ? path : fallback;
8804
+ } catch {
8805
+ return fallback;
8806
+ }
8807
+ }
8808
+ function postLoginRedirectPath(search, fallback = "/") {
8809
+ return safePostLoginPath(new URLSearchParams(search).get("next"), fallback);
8810
+ }
8209
8811
  function useDebouncedValue(value, ms) {
8210
8812
  const [debounced, setDebounced] = useState(value);
8211
8813
  useEffect(() => {
@@ -8323,10 +8925,10 @@ function isCiPreviewBuild(env = process.env) {
8323
8925
  return true;
8324
8926
  }
8325
8927
  const host = coolifyHostnameFromEnv(env);
8326
- return Boolean(host && /^(?:manage-|deploy-)?preview-\d+\./.test(host));
8928
+ return Boolean(host && /^(?:manage-|deploy-|renderer-)?preview-\d+\./.test(host));
8327
8929
  }
8328
8930
  var PULL_HEAD_BRANCH_RE = /^pull\/(\d+)\/head$/i;
8329
- var PREVIEW_HOST_PR_RE = /^(?:manage-|deploy-)?preview-(\d+)\./;
8931
+ var PREVIEW_HOST_PR_RE = /^(?:manage-|deploy-|renderer-)?preview-(\d+)\./;
8330
8932
  function resolvePreviewPrId(env = process.env) {
8331
8933
  const host = coolifyHostnameFromEnv(env);
8332
8934
  if (host) {
@@ -9147,7 +9749,12 @@ var apiTableAccessSchema = external_exports.object({
9147
9749
  */
9148
9750
  rowQuery: clampQuerySchema.optional(),
9149
9751
  /** Scan ceiling for Read/guest list plans; callers may only lower. Not applied to Sync/Resync. */
9150
- maxScanLimit: external_exports.number().int().positive().optional()
9752
+ maxScanLimit: external_exports.number().int().positive().optional(),
9753
+ /**
9754
+ * Media source scope for the fixed `columnus_assets` source. Omit for all
9755
+ * live Media; an empty list intentionally grants no Media assets.
9756
+ */
9757
+ assetProfiles: external_exports.array(external_exports.string().min(1)).max(100).optional()
9151
9758
  });
9152
9759
  var apiProfileSnapshotSchema = external_exports.object({
9153
9760
  id: external_exports.string(),
@@ -9166,6 +9773,9 @@ function editorAccessEnabled(access) {
9166
9773
  function findTableAccess(tableAccess, table) {
9167
9774
  return tableAccess?.find((entry) => entry.table === table);
9168
9775
  }
9776
+ function profileTableAccesses(profile) {
9777
+ return profile.tableAccess ?? profile.tables.map((table) => ({ table, read: true }));
9778
+ }
9169
9779
  function assertPatchesHaveEditorAccess(profile, patches) {
9170
9780
  const byTable = new Map((profile.tableAccess ?? []).map((access) => [access.table, access]));
9171
9781
  for (const patch of patches) {
@@ -9184,6 +9794,16 @@ function syncEnabledTables(profile) {
9184
9794
  }
9185
9795
  return [...tables];
9186
9796
  }
9797
+ var MEDIA_LIBRARY_JOURNAL_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
9798
+ function assetMatchesProfileScope(asset, assetProfiles) {
9799
+ if (!asset || asset.isDeleted === true || asset.wipedAt !== void 0) return false;
9800
+ if (assetProfiles === void 0) return true;
9801
+ if (assetProfiles.length === 0) return false;
9802
+ const profileSet = new Set(assetProfiles);
9803
+ return Array.isArray(asset.profileSlugs) && asset.profileSlugs.some(
9804
+ (profile) => typeof profile === "string" && profileSet.has(profile)
9805
+ );
9806
+ }
9187
9807
 
9188
9808
  // packages/@columnus/shared/src/shareApiBridge.ts
9189
9809
  function shareScopeAccessMode(scope) {
@@ -9427,6 +10047,52 @@ function resolveSyncMembershipOp(args) {
9427
10047
  return null;
9428
10048
  }
9429
10049
 
10050
+ // packages/@columnus/shared/src/syncChannel.ts
10051
+ function syncChannelForTable(table) {
10052
+ return table === ASSETS_TABLE_NAME ? "asset" : "record";
10053
+ }
10054
+ function resolveAssetSyncMembershipOp(change, assetProfiles) {
10055
+ const beforeMatches = assetMatchesProfileScope(change.before, assetProfiles);
10056
+ const afterMatches = assetMatchesProfileScope(change.after, assetProfiles);
10057
+ if (change.op === "delete") return beforeMatches ? "delete" : null;
10058
+ if (afterMatches) return "upsert";
10059
+ return beforeMatches ? "delete" : null;
10060
+ }
10061
+ function resolveChannelMembershipOp(args) {
10062
+ const channel = syncChannelForTable(args.table);
10063
+ switch (channel) {
10064
+ case "asset":
10065
+ return resolveAssetSyncMembershipOp(
10066
+ { op: args.requestedOp, before: args.before, after: args.after },
10067
+ findTableAccess(args.tableAccess, args.table)?.assetProfiles
10068
+ );
10069
+ case "record":
10070
+ return resolveSyncMembershipOp({
10071
+ predicates: syncClampPredicates(args.tableAccess, args.table),
10072
+ before: args.before,
10073
+ after: args.after,
10074
+ requestedOp: args.requestedOp
10075
+ });
10076
+ default: {
10077
+ const _exhaustive = channel;
10078
+ return _exhaustive;
10079
+ }
10080
+ }
10081
+ }
10082
+ function documentMatchesSyncChannel(doc, table, tableAccess) {
10083
+ const channel = syncChannelForTable(table);
10084
+ switch (channel) {
10085
+ case "asset":
10086
+ return assetMatchesProfileScope(doc, findTableAccess(tableAccess, table)?.assetProfiles);
10087
+ case "record":
10088
+ return documentMatchesSyncClamp(doc, syncClampPredicates(tableAccess, table));
10089
+ default: {
10090
+ const _exhaustive = channel;
10091
+ return _exhaustive;
10092
+ }
10093
+ }
10094
+ }
10095
+
9430
10096
  // packages/@columnus/shared/src/readApiQuery.ts
9431
10097
  function readApiQueryExportName(kind, tableName) {
9432
10098
  return `${kind}${tableName}`;
@@ -10252,6 +10918,10 @@ function isSchemaDeployPhaseActive(phase) {
10252
10918
  function hasSchemaDeployOperationLeaseExpired(startedAt, now) {
10253
10919
  return startedAt !== void 0 && now - startedAt >= SCHEMA_DEPLOY_OPERATION_LEASE_MS;
10254
10920
  }
10921
+ function isSchemaDeployOperationBlocking(phase, startedAt, now = Date.now()) {
10922
+ if (!isSchemaDeployPhaseActive(phase)) return false;
10923
+ return !hasSchemaDeployOperationLeaseExpired(startedAt, now);
10924
+ }
10255
10925
  function base64UrlFromBytes(bytes) {
10256
10926
  let binary = "";
10257
10927
  for (const byte of bytes) binary += String.fromCharCode(byte);
@@ -10874,6 +11544,6 @@ papaparse/papaparse.min.js:
10874
11544
  *)
10875
11545
  */
10876
11546
 
10877
- export { API_DELIVERY_TABLE_NAME, API_OUTBOX_TABLE_NAME, API_OUTPUTS_TABLE_NAME, API_OUTPUT_SECRETS_TABLE_NAME, API_PROFILES_TABLE_NAME, API_PROFILE_SLUG_RE, API_SYNC_ROUTES_TABLE_NAME, API_TOKENS_TABLE_NAME, API_TOKEN_PREFIX, AUDIT_TABLE_NAME, BFF_JSON_BODY_LIMIT_BYTES, MAX_TRANSFER_BYTES as BFF_TRANSFER_MAX_BYTES, COLUMNUS_BFF_API_PREFIX, COLUMNUS_BFF_MANAGEMENT_PREFIX, COLUMNUS_BFF_MANAGEMENT_SECRET_HEADER, COLUMNUS_BFF_PROTOCOL_VERSION, COLUMNUS_BUNDLE_VERSION, COLUMNUS_CLIPBOARD_MARKER, COLUMNUS_CLIPBOARD_VERSION, COLUMNUS_DATA_TRANSFER_VERSION, COLUMNUS_DEPLOY_INTERNAL_PREFIX, COLUMNUS_DEPLOY_OPS_PREFIX, COLUMNUS_DOC_LINK_MARKER, COLUMNUS_PREVIEW_REGISTRATION_SECRET_HEADER, DEFAULT_MAX_SCAN_LIMIT, DISPLAY_VALUES_TABLE_NAME, EMPTY_BLOCK_ID, EMPTY_MANIFEST, EMPTY_MARKDOWN_DOC, EMPTY_RICH_DOC, FIELD_TYPE_KIND_ICONS, FIELD_TYPE_KIND_LABELS, FIELD_TYPE_SELECT_KINDS, HOST_SCHEMA_PROFILE, INCOMING_REFS_TABLE_NAME, MANIFEST_DEPLOY_STATUSES, MANIFEST_HASH_RE, MANIFEST_TABLE_NAME, MATCH_ERROR_KEY, MAX_TRANSFER_BYTES, OPERATION_ID_RE, OVERLAP_MESSAGE, PREDICATE_OPS, PREDICATE_VARIANTS, PREVIEW_TENANT_SLUG_RE, RECORD_TABLE_DEFAULT_FIELD_COUNT, REDACTED, REFS_RECOMPUTE_STALE_MS, RESERVED_TABLE_NAMES, RESERVED_TENANT_SLUGS, RICH_DOC_FORMAT, RICH_DOC_VERSION, SCHEMA_DEPLOY_OPERATION_LEASE_MS, SHARE_TOKEN_ENCRYPTION_KEY_ENV, SHARE_TOKEN_PREFIX, SHRINK_CLEANUP_PAGE_SIZE, SHRINK_IMPACT_CAP, SPACES_TABLE_NAME, STALE_ENDPOINT_DEPLOY_ERROR, STUDIO_DOC_LINK_MARKER, TABLE_COLORS, TABLE_NAME_RE2 as TABLE_NAME_RE, TENANT_SECRETS_KEK_ENV, TENANT_SECRET_CRYPTO_VERSION, TENANT_SLUG_RE, TRANSFER_ID_RE, addRef, anyTenantSlugFromHost, apiProfileSlugToConvexModuleSegment, apiProfileSnapshotSchema, apiProfileToShareScopes, apiProfilesSchema, apiTableAccessSchema, apiTokenPrefix, applyDisplayIdResolution, applyImportRowIdResolution, assertApiProfileSlug, assertPatchesHaveEditorAccess, assertProfileSlugUnchanged, assertProposalAccess, assertShareLinkTypeConsistency, assertShareOperation, attachBffCleanupIdentity, authConfigIssuerFromProcessEnv, betterAuthTrustedOrigins, betweenToIndexBound, bffActiveOperationMetaSchema, bffErrorCodeSchema, bffErrorResponseSchema, bffHealthResponseSchema, bffPrepareOperationSchema, bffPrepareOperationTypeSchema, bffPrepareRequestSchema, bffPreparedBodyEnvelopeSchema, bffPreparedTenantSchema, bffPreviewRegisterRequestSchema, bffPreviewRemoveRequestSchema, bffSchemaDeployRequestSchema, bffSchemaDeployResponseSchema, bffTransferCommitRequestSchema, bffTransferCommitResponseSchema, bffTransferCreateResponseSchema, bffTransferScopeRequestSchema, bffTransferUploadResponseSchema, blocksForBlockNoteDisplay, briefFieldTypeLabel, buildCleanupTasks, buildCsvRows, buildCsvRowsForColumns, buildImportCommitRows, buildRecordTablePreload, buildRefRequestsFromFieldValues, buildRefRequestsFromTableRows, buildShareWizardInput, buildShrinkImpactPreview, buildSpaceExport, canCreateFormReferences, canProposeInsert, canProposeOperation, canSearchFormReferences, canonicalManifestTablesJson, canonicalRichFieldJson, ciPreviewDeployName, clampQuerySchema, clampQueryValidator, classifyPhase, cleanupStateValidator, coerceCsvValue, collectExportDisplayIdRefs, collectFilterRefIds, collectIdReferenceClosure, collectIdsFromField, collectIdsFromValues, collectImportDisplayIds, collectImportRowDisplayIds, collectMatchDisplayIdRefs, collectQueryRefIds, collectRecordLinkIds, collectRecordLinkIdsFromBlocks, collectReferencedIds, collectReferencedStorageIds, collectRichDocStorageIds, collectStorageIds, collectStorageIdsFromRow, compareOrdered, computeManifestAccessHash, computeManifestHash, computeProposalFieldDiff, computeProposalRecordDiff, computeRefGraphFingerprint, computeShrinkPlan, convexCloudToSiteUrl, convexDeploymentSlugFromUrl, convexSiteToCloudUrl, convexSiteUrlFromProcessEnv, coolifyHostnameFromEnv, createCleanupState, createOperationId, createRandomId, createTransferId, csvHasIdColumn, cycleQueryOrder, dataTransferManifestSchema, dateInputValue, dateTimeInputValue, decryptShareToken, decryptTenantSecret, defaultMatchColumn, defaultProdDeployUrl, defaultRecordTableFieldNames, defaultValueForType, deployHealthResponseSchema, deployInternalSchemaDeployPayloadSchema, deployInternalSchemaDeployResponseSchema, deployInternalTransferCommitPayloadSchema, deployInternalTransferCreateResponseSchema, deployInternalTransferExportPayloadSchema, deployInternalTransferImportPreparePayloadSchema, deriveConvexDeploymentFromCloudUrl, deriveListMeta, derivePreviewDeployBuildUrl, derivePreviewStudioDeployUrl, describeFieldType, discretionaryRecordTableFieldNames, displayTemplatesSchema, docsSeedSyncEmailFromEnv, documentMatchesPredicate, documentMatchesPredicates, documentMatchesSyncClamp, editorAccessEnabled, editorAccessToShareScopes, effectiveQueryFieldType, eligibleReferencedParents, emptyCleanupStats, emptyParagraphBlock, emptyToUndefined, encryptShareToken, encryptTenantSecret, extractError, extractPlainText, extractTrustedHostname, fallbackIdLabel, fallbackPreviewLabel, fieldByName, fieldDisplayName, fieldOpSupport, fieldSchema, fieldSupportsSort, fieldTypeHasOutgoingRefs, fieldTypeKindIconName, fieldTypeKindLabel, fieldTypeSchema, fieldValuesEqual, filterChangedPatchFields, findDuplicateIdentifier, findOverlappingProposalIds, findProposalIdsOverlappingTarget, findSearchIndex, findShareScopeConflicts, findTableAccess, findTemplateRefsToRemovedFields, findUnsatisfiablePredicates, formatCanonicalFieldType, formatDateCell, formatDateTimeCell, formatDisplayPreviewText, formatEditorSummaryFieldType, formatErdCompactFieldType, formatEscapeShortcut, formatFilterEqDisplayValue, formatIdShort, formatMatchLabelFieldType, formatModEnterShortcut, formatModShortcut, formatNumericDate, formatPrimitivePreview, formatRecordTableCellText, formatRecordTableQuerySummary, formatShrinkImpactLine, generateApiToken, generateDisplayValuesTs, generateSchemaTs, generateShareToken, generateTenantSecretsKekBase64, guestSearchableScopes, guestVisibleScopes, hasIdentifierCollision, hasSchemaDeployOperationLeaseExpired, hashApiToken, hashShareToken, hostFromForwardedHeader, hostnameFromHostHeader, idListMeta, importStagingId, indexSchema, inferDefaultGuestView, inferIdentifier, inferUniqueIdentifier, isApiProfileSlug, isApiTokenFormat, isBlockNoteContent, isBlockNoteEnvelope, isCiPreviewBuild, isClassifiedKey, isCompleteBetween, isConvexJwt, isEditableKind, isEmptyQuery, isFileArrayFieldType, isFileFieldType, isFormSubmissionScope, isHttpUrl, isImageFieldType, isInlinePrimitive, isJwtExpired, isLoopbackDeployServiceUrl, isManifestDeployStatus, isManifestHash, isMarkdownField, isOperationId, isPlaceholderManagementSiteUrl, isPreviewStudioHost, isPrimaryShareScope, isPrimitiveKind, isProdDeployServiceUrl, isProtectedTransferTable, isRadixOverlayOpen, isRangeOp, isRecoverableDeployError, isReferenceFieldType, isReferenceOnlyScope, isRefsRecomputeInFlight, isReservedTenantSlug, isSchemaDeployPhaseActive, isStaleEndpointDeployError, isStorageFieldType, isSystemField, isTextScalarKind, isTransferId, isTypingInEditor, isValidIdentifier, isValidMarkdownDocJson, isValidPreviewTenantSlug, isValidRichFieldJson, isValidStorageId, isValidTenantSlug, listAccessKindSchema, listMetaOrderSchema, listMetaSchema, listPageKindSchema, listTablesWithRefGraphChanges, looksLikeId, makePredicate, manifestHashSchema, manifestSchema, manifestTablesUseFileStorage, matchColumnsForTable, matchEscape, matchKeyFromColumn, matchModEnter, matchModShiftShortcut, matchModShortcut, matchSave, matchToggleEditMode, matchUndoRedo, matchesBetween, matchesDeployCompletion, maxScanLimitValidator, mergeDraftErdLayoutIntoCanonical, mergeErdLayouts, mergeProposedRecord, mergeQuery, mergeReferenceScopes, mergeStagingPendingEdits, modKeyLabel, newProvisionalRowId, normalizeConvexUrl, normalizeDisplayTemplateBody, normalizeManifestDisplayTemplates, normalizeManifestForShrink, normalizeMarkdownField, normalizeMatchKeyFromCsvRow, normalizeMatchKeyFromValue, normalizePreviewDeployName, normalizeRichField, normalizeShareScopes, opAllowedForType, operationIdSchema, parseClampQuery, parseColumnusClipboard, parseCsvText, parseDateCsv, parseDateInput, parseDateTimeInput, parseDocLinkHref, parseErdLayoutOrEmpty, parseErdLayoutOrThrow, parseGitSha, parseImportPaste, parseQuery, parseQueryJson, parseRecordTableFieldsJson, parseRecordTableQueryJson, parseRichDocBlocks, parseShareTokenEncryptionKey, parseTenantSecretsKek, parseTrustedSiteUrls, patchIsStale, patchMergeImportRow, pickProposalFields, planMergedQuery, planProposalPatches, planQuery, planStudioBoot, postprocessDocLinksInBlocks, predicateOpLabel, predicateOpSchema, predicateSchema, predicateValidator, predicatesEqual, prepareProposalPatchesForAccept, prepareShrinkSave, preprocessDocLinksInBlocks, preprocessDocLinksInMarkdown, previewImportMerge, previewSlugFromHost, primaryTrustedSiteUrl, profileSlugChangeError, promoteErdLayoutOnSave, proposalDiffFieldNames, proposalOverlapsAny, proposeApiExportName, provisionalRowKey, pruneErdLayout, queriesEqual, queryArgValidator, queryErrorCodeSchema, queryHasActiveConstraints, queryOrderSchema, queryPredicateFieldNames, querySchema, querySearchSchema, queryValidator, readApiAnyApiPath, readApiQueryExportName, readApiQueryModuleSegment, readConvexSiteUrlEnv, readTenantSecretsKekFromEnv, reconcileStagingMatchState, redactForLogs, redactString, refFieldsForTable, referencedTargetIds, refsMapToRequests, replaceProvisionalReferences, residualClampPredicates, resolveAuthConfigIssuerFromEnv, resolveBffManagementSiteUrl, resolveConvexSiteUrl, resolveConvexSiteUrlFromEnv, resolveGuestCapabilities, resolveGuestLinkCapabilities, resolveGuestScopeCapabilities, resolveImportMatches, resolvePreloadedLabel, resolvePreviewBranch, resolvePreviewPrId, resolveQueryFieldType, resolveRecordTableVisibleFields, resolveRuntimeDeployServiceUrl, resolveRuntimeManagementSiteUrl, resolveSyncDeployUrl, resolveSyncMembershipOp, resolveTrustedAuthOrigin, revalidateStagingRow, richContentPlainText, runAcceptProposalBatch, safeStringify, sanitizePreviewDeployName, savedTableByName, schemaDeployPhaseSchema, scopesToWizardInput, searchIndexSchema, secretsEqual, serializeColumnusClipboard, serializeCsvValue, serializeDateCsv, serializeDateTimeCsv, serializeErdLayout, setQueryOrder, setQueryOrderDirection, setQueryOrderField, shareScopeAccessMode, shareScopeToTableAccess, shareTokenPrefix, shareTypeDefaultScopes, shouldExpectConvexAuth, shrinkPlanIsEmpty, signInViaEmailOtp, singleHeaderHostValue, slugifyApiProfileName, snapshotBaseFields, sortDocuments, sortableQueryFields, stagingRowToImportRow, stagingRowsToGridRows, storageIdsRemovedByPatches, stringifyQuery, stringifyRecordTableFields, stringifyRecordTableQuery, stringifyRichDoc, stripAnsi, stripSystemFields, suggestIndexFields, summarizePreparedEnvelope, syncClampPredicates, syncEnabledTables, tableAccessToShareScope, tableColorSchema, tableDisplayName, tableSchema, tablesWithOutgoingRefs, takeRangeBound, tenantPublicHost, tenantSlugFromHost, toDocumentId, transferIdSchema, transferOperationSchema, transferSessionRecordSchema, transferSessionStateSchema, truncateDisplay, unionTableNames, uniqueIdentifier, unparseCsv, useDebouncedCommit, useDebouncedValue, useModifierHeld, validateClipboardColumns, validateDataTransferManifest, validateDisplayTemplates, validateFieldValue, validateImportRow, validatePatch, validatePreviewSourceCommit, validateQueryForTable, wrapPlainTextAsRichDoc };
11547
+ export { API_DELIVERY_TABLE_NAME, API_OUTBOX_TABLE_NAME, API_OUTPUTS_TABLE_NAME, API_OUTPUT_SECRETS_TABLE_NAME, API_PROFILES_TABLE_NAME, API_PROFILE_SLUG_RE, API_SYNC_ROUTES_TABLE_NAME, API_TOKENS_TABLE_NAME, API_TOKEN_PREFIX, ASSETS_TABLE_NAME, ASSET_FAMILIES, ASSET_JOB_KINDS, ASSET_JOB_LEASE_MS, ASSET_JOB_MAX_ATTEMPTS, ASSET_JOB_MAX_RECLAIMS, ASSET_JOB_STATUSES, ASSET_JOB_TIMEOUT_MS, ASSET_PROCESSING_STATUSES, ASSET_PROFILES_TABLE_NAME, ASSET_REFS_TABLE_NAME, ASSET_SETTINGS_TABLE_NAME, ASSET_VERSIONS_TABLE_NAME, AUDIT_TABLE_NAME, BFF_JSON_BODY_LIMIT_BYTES, MAX_TRANSFER_BYTES as BFF_TRANSFER_MAX_BYTES, COLUMNUS_BFF_API_PREFIX, COLUMNUS_BFF_MANAGEMENT_PREFIX, COLUMNUS_BFF_MANAGEMENT_SECRET_HEADER, COLUMNUS_BFF_PROTOCOL_VERSION, COLUMNUS_BUNDLE_VERSION, COLUMNUS_CLIPBOARD_MARKER, COLUMNUS_CLIPBOARD_VERSION, COLUMNUS_DATA_TRANSFER_VERSION, COLUMNUS_DEPLOY_INTERNAL_PREFIX, COLUMNUS_DEPLOY_OPS_PREFIX, COLUMNUS_DOC_LINK_MARKER, COLUMNUS_PREVIEW_REGISTRATION_SECRET_HEADER, DEFAULT_ASSET_SLOTS, DEFAULT_IMAGE_GRAPH, DEFAULT_MAX_SCAN_LIMIT, DEFAULT_MEDIA_REJECT_BYTES, DEFAULT_MEDIA_UPLOAD_CAPS, DEFAULT_MEDIA_WARN_BYTES, DISPLAYABLE_VECTOR_CONTENT_TYPES, DISPLAY_VALUES_TABLE_NAME, EMPTY_BLOCK_ID, EMPTY_MANIFEST, EMPTY_MARKDOWN_DOC, EMPTY_RICH_DOC, FIELD_TYPE_KIND_ICONS, FIELD_TYPE_KIND_LABELS, FIELD_TYPE_SELECT_KINDS, HOST_SCHEMA_PROFILE, INCOMING_REFS_TABLE_NAME, MANIFEST_DEPLOY_STATUSES, MANIFEST_HASH_RE, MANIFEST_TABLE_NAME, MATCH_ERROR_KEY, MAX_RENDER_MEGAPIXELS, MAX_RENDER_PIXELS, MAX_TRANSFER_BYTES, MEDIA_LIBRARY_JOURNAL_TTL_MS, OPERATION_ID_RE, OVERLAP_MESSAGE, PREDICATE_OPS, PREDICATE_VARIANTS, PREVIEW_TENANT_SLUG_RE, RECORD_TABLE_DEFAULT_FIELD_COUNT, REDACTED, REFS_RECOMPUTE_STALE_MS, RENDITION_TIMEOUT_MS, RESERVED_TABLE_NAMES, RESERVED_TENANT_SLUGS, RICH_DOC_FORMAT, RICH_DOC_VERSION, SCHEMA_DEPLOY_OPERATION_LEASE_MS, SHARE_TOKEN_ENCRYPTION_KEY_ENV, SHARE_TOKEN_PREFIX, SHRINK_CLEANUP_PAGE_SIZE, SHRINK_IMPACT_CAP, SPACES_TABLE_NAME, STALE_ENDPOINT_DEPLOY_ERROR, STUDIO_DOC_LINK_MARKER, TABLE_COLORS, TABLE_KINDS, TABLE_NAME_RE2 as TABLE_NAME_RE, TENANT_SECRETS_KEK_ENV, TENANT_SECRET_CRYPTO_VERSION, TENANT_SLUG_RE, TRANSFER_ID_RE, VECTOR_FILE_ACCEPT, addRef, anyTenantSlugFromHost, apiProfileSlugToConvexModuleSegment, apiProfileSnapshotSchema, apiProfileToShareScopes, apiProfilesSchema, apiTableAccessSchema, apiTokenPrefix, applyDisplayIdResolution, applyImportRowIdResolution, assertApiProfileSlug, assertAssetSlotsResolve, assertPatchesHaveEditorAccess, assertProfileSlugUnchanged, assertProposalAccess, assertShareLinkTypeConsistency, assertShareOperation, assertTableKindsImmutable, assetBindingSchema, assetBuildsRenditions, assetFamilyForContentType, assetJobFailureOutcome, assetJobKey, assetJobLeaseExpired, assetJobReclaimOutcome, assetJobRetryDelayMs, assetMatchesProfileScope, assetSlotView, attachBffCleanupIdentity, authConfigIssuerFromProcessEnv, betterAuthTrustedOrigins, betweenToIndexBound, bffActiveOperationMetaSchema, bffErrorCodeSchema, bffErrorResponseSchema, bffHealthResponseSchema, bffPrepareOperationSchema, bffPrepareOperationTypeSchema, bffPrepareRequestSchema, bffPreparedBodyEnvelopeSchema, bffPreparedTenantSchema, bffPreviewRegisterRequestSchema, bffPreviewRemoveRequestSchema, bffSchemaDeployRequestSchema, bffSchemaDeployResponseSchema, bffTransferCommitRequestSchema, bffTransferCommitResponseSchema, bffTransferCreateResponseSchema, bffTransferScopeRequestSchema, bffTransferUploadResponseSchema, blocksForBlockNoteDisplay, briefFieldTypeLabel, buildCleanupTasks, buildCsvRows, buildCsvRowsForColumns, buildImportCommitRows, buildRecordTablePreload, buildRefRequestsFromFieldValues, buildRefRequestsFromTableRows, buildShareWizardInput, buildShrinkImpactPreview, buildSpaceExport, canCreateFormReferences, canProposeInsert, canProposeOperation, canSearchFormReferences, canonicalManifestTablesJson, canonicalRichFieldJson, childRenditionNodes, ciPreviewDeployName, clampQuerySchema, clampQueryValidator, classifyPhase, cleanupStateValidator, coerceCsvValue, collectAssetIds, collectAssetIdsFromRow, collectExportDisplayIdRefs, collectFilterRefIds, collectIdReferenceClosure, collectIdsFromField, collectIdsFromValues, collectImportDisplayIds, collectImportRowDisplayIds, collectMatchDisplayIdRefs, collectQueryRefIds, collectRecordLinkIds, collectRecordLinkIdsFromBlocks, collectReferencedIds, collectRichDocAssetIds, compareOrdered, computeManifestAccessHash, computeManifestHash, computeProposalFieldDiff, computeProposalRecordDiff, computeRefGraphFingerprint, computeShrinkPlan, convexCloudToSiteUrl, convexDeploymentSlugFromUrl, convexSiteToCloudUrl, convexSiteUrlFromProcessEnv, coolifyHostnameFromEnv, createCleanupState, createOperationId, createRandomId, createTransferId, csvHasIdColumn, cycleQueryOrder, dataTransferManifestSchema, dateInputValue, dateTimeInputValue, decryptShareToken, decryptTenantSecret, defaultAssetSettings, defaultMatchColumn, defaultProdDeployUrl, defaultRecordTableFieldNames, defaultValueForType, deployHealthResponseSchema, deployInternalSchemaDeployPayloadSchema, deployInternalSchemaDeployResponseSchema, deployInternalTransferCommitPayloadSchema, deployInternalTransferCreateResponseSchema, deployInternalTransferExportPayloadSchema, deployInternalTransferImportPreparePayloadSchema, deriveConvexDeploymentFromCloudUrl, deriveListMeta, derivePreviewDeployBuildUrl, derivePreviewStudioDeployUrl, describeFieldType, discretionaryRecordTableFieldNames, displayTemplatesSchema, docsSeedSyncEmailFromEnv, documentMatchesPredicate, documentMatchesPredicates, documentMatchesSyncChannel, documentMatchesSyncClamp, editorAccessEnabled, editorAccessToShareScopes, effectiveQueryFieldType, eligibleReferencedParents, emptyCleanupStats, emptyParagraphBlock, emptyToUndefined, encryptShareToken, encryptTenantSecret, extractError, extractPlainText, extractTrustedHostname, fallbackIdLabel, fallbackPreviewLabel, fieldByName, fieldDisplayName, fieldOpSupport, fieldSchema, fieldSupportsSort, fieldTypeHasOutgoingRefs, fieldTypeKindIconName, fieldTypeKindLabel, fieldTypeSchema, fieldValuesEqual, filterChangedPatchFields, findDuplicateIdentifier, findOverlappingProposalIds, findProposalIdsOverlappingTarget, findSearchIndex, findShareScopeConflicts, findTableAccess, findTemplateRefsToRemovedFields, findUnsatisfiablePredicates, focalObjectPosition, formatCanonicalFieldType, formatDateCell, formatDateTimeCell, formatDisplayPreviewText, formatEditorSummaryFieldType, formatErdCompactFieldType, formatEscapeShortcut, formatFilterEqDisplayValue, formatIdShort, formatMatchLabelFieldType, formatMediaBytes, formatModEnterShortcut, formatModShortcut, formatNumericDate, formatPrimitivePreview, formatRecordTableCellText, formatRecordTableQuerySummary, formatShrinkImpactLine, generateApiToken, generateDisplayValuesTs, generateSchemaTs, generateShareToken, generateTenantSecretsKekBase64, guestSearchableScopes, guestVisibleScopes, hasIdentifierCollision, hasSchemaDeployOperationLeaseExpired, hashApiToken, hashShareToken, hostFromForwardedHeader, hostnameFromHostHeader, idListMeta, importStagingId, indexSchema, inferDefaultGuestView, inferIdentifier, inferUniqueIdentifier, isApiProfileSlug, isApiTokenFormat, isAssetFamily, isAssetTable, isBlockNoteContent, isBlockNoteEnvelope, isCiPreviewBuild, isClassifiedKey, isCompleteBetween, isConvexJwt, isDisplayableVectorContentType, isEditableKind, isEmptyQuery, isExtractableFamily, isFileArrayFieldType, isFileFieldType, isFormSubmissionScope, isHttpUrl, isImageFieldPickable, isImageFieldType, isInlinePrimitive, isJwtExpired, isLoopbackDeployServiceUrl, isManifestDeployStatus, isManifestHash, isMarkdownField, isOperationId, isPlaceholderManagementSiteUrl, isPreviewStudioHost, isPrimaryShareScope, isPrimitiveKind, isProdDeployServiceUrl, isProtectedTransferTable, isRadixOverlayOpen, isRangeOp, isRasterRenditionSource, isRecoverableDeployError, isReferenceFieldType, isReferenceOnlyScope, isRefsRecomputeInFlight, isReservedTenantSlug, isSchemaDeployOperationBlocking, isSchemaDeployPhaseActive, isStaleEndpointDeployError, isStorageFieldType, isSystemField, isTextScalarKind, isTransferId, isTypingInEditor, isValidAssetId, isValidIdentifier, isValidMarkdownDocJson, isValidPreviewTenantSlug, isValidRichFieldJson, isValidTenantSlug, isVectorContentType, listAccessKindSchema, listMetaOrderSchema, listMetaSchema, listPageKindSchema, listTablesWithRefGraphChanges, looksLikeId, makePredicate, manifestHasFileOrImageFields, manifestHashSchema, manifestSchema, manifestTablesUseFileStorage, mapsFromAssetDisplayRows, matchColumnsForTable, matchEscape, matchKeyFromColumn, matchModEnter, matchModShiftShortcut, matchModShortcut, matchSave, matchToggleEditMode, matchUndoRedo, matchesBetween, matchesDeployCompletion, maxScanLimitValidator, mediaUploadCapsError, mediaUploadLimit, mergeDraftErdLayoutIntoCanonical, mergeErdLayouts, mergeProposedRecord, mergeQuery, mergeReferenceScopes, mergeStagingPendingEdits, modKeyLabel, newProvisionalRowId, nextAssetJobWakeAt, normalizeConvexUrl, normalizeDisplayFocal, normalizeDisplayTemplateBody, normalizeManifestDisplayTemplates, normalizeManifestForShrink, normalizeMarkdownField, normalizeMatchKeyFromCsvRow, normalizeMatchKeyFromValue, normalizePreviewDeployName, normalizeRichField, normalizeShareScopes, opAllowedForType, operationIdSchema, parseClampQuery, parseColumnusClipboard, parseCsvText, parseDateCsv, parseDateInput, parseDateTimeInput, parseDocLinkHref, parseErdLayoutOrEmpty, parseErdLayoutOrThrow, parseGitSha, parseImportPaste, parseQuery, parseQueryJson, parseRecordTableFieldsJson, parseRecordTableQueryJson, parseRichDocBlocks, parseShareTokenEncryptionKey, parseTenantSecretsKek, parseTrustedSiteUrls, patchIsStale, patchMergeImportRow, pendingRebuildsForSave, pickProposalFields, planGraphDelta, planMergedQuery, planProposalPatches, planQuery, planStudioBoot, postLoginRedirectPath, postprocessDocLinksInBlocks, predicateOpLabel, predicateOpSchema, predicateSchema, predicateValidator, predicatesEqual, prepareProposalPatchesForAccept, prepareShrinkSave, preprocessDocLinksInBlocks, preprocessDocLinksInMarkdown, previewImportMerge, previewSlugFromHost, primaryTrustedSiteUrl, profileSlugChangeError, profileTableAccesses, promoteErdLayoutOnSave, proposalDiffFieldNames, proposalOverlapsAny, proposeApiExportName, provisionalRowKey, pruneErdLayout, publicRenditionUrlKeys, queriesEqual, queryArgValidator, queryErrorCodeSchema, queryHasActiveConstraints, queryOrderSchema, queryPredicateFieldNames, querySchema, querySearchSchema, queryValidator, readApiAnyApiPath, readApiQueryExportName, readApiQueryModuleSegment, readConvexSiteUrlEnv, readTenantSecretsKekFromEnv, reconcileStagingMatchState, redactForLogs, redactString, refFieldsForTable, referencedTargetIds, refsMapToRequests, renderPixelCapError, renditionNodeFingerprint, renditionPlan, replaceProvisionalReferences, residualClampPredicates, resolveAssetGraph, resolveAssetSlotDisplay, resolveAuthConfigIssuerFromEnv, resolveBffManagementSiteUrl, resolveChannelMembershipOp, resolveConvexSiteUrl, resolveConvexSiteUrlFromEnv, resolveFamilySlotMapping, resolveGuestCapabilities, resolveGuestLinkCapabilities, resolveGuestScopeCapabilities, resolveImportMatches, resolvePreloadedLabel, resolvePreviewBranch, resolvePreviewPrId, resolveQueryFieldType, resolveRecordTableVisibleFields, resolveRuntimeDeployServiceUrl, resolveRuntimeManagementSiteUrl, resolveSyncDeployUrl, resolveSyncMembershipOp, resolveTrustedAuthOrigin, revalidateStagingRow, richContentPlainText, rollupProcessingStatus, rootRenditionNodes, runAcceptProposalBatch, safePostLoginPath, safeStringify, sanitizePreviewDeployName, savedTableByName, schemaDeployPhaseSchema, scopesToWizardInput, searchIndexSchema, secretsEqual, serializeColumnusClipboard, serializeCsvValue, serializeDateCsv, serializeDateTimeCsv, serializeErdLayout, setQueryOrder, setQueryOrderDirection, setQueryOrderField, shareScopeAccessMode, shareScopeToTableAccess, shareTokenPrefix, shareTypeDefaultScopes, shouldExpectConvexAuth, shrinkPlanIsEmpty, signInViaEmailOtp, singleHeaderHostValue, slugifyApiProfileName, snapshotBaseFields, sortDocuments, sortableQueryFields, stagingRowToImportRow, stagingRowsToGridRows, stringifyQuery, stringifyRecordTableFields, stringifyRecordTableQuery, stringifyRichDoc, stripAnsi, stripSystemFields, suggestIndexFields, summarizePreparedEnvelope, syncChannelForTable, syncClampPredicates, syncEnabledTables, tableAccessToShareScope, tableColorSchema, tableDisplayName, tableKind, tableKindSchema, tableSchema, tablesWithOutgoingRefs, takeRangeBound, tenantPublicHost, tenantSlugFromHost, toDocumentId, transferIdSchema, transferOperationSchema, transferSessionRecordSchema, transferSessionStateSchema, truncateDisplay, unionTableNames, uniqueIdentifier, unparseCsv, unsavedAssetSettings, useDebouncedCommit, useDebouncedValue, useModifierHeld, validateClipboardColumns, validateDataTransferManifest, validateDisplayTemplates, validateFieldValue, validateImportRow, validatePatch, validatePreviewSourceCommit, validateQueryForTable, validateRenditionNodes, wrapPlainTextAsRichDoc };
10878
11548
  //# sourceMappingURL=index.js.map
10879
11549
  //# sourceMappingURL=index.js.map