@columnus/shared 0.1.54 → 0.1.56

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 (77) hide show
  1. package/dist/apiProfile.d.ts +39 -0
  2. package/dist/apiProfile.js +19 -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 +199 -0
  11. package/dist/assetGraph.js +214 -0
  12. package/dist/assetGraph.js.map +1 -0
  13. package/dist/assetJobs.d.ts +95 -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 +20 -3
  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 +741 -82
  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.d.ts +0 -7
  44. package/dist/previewDeployName.js +21 -4
  45. package/dist/previewDeployName.js.map +1 -1
  46. package/dist/recordTableColumns.js +112 -12
  47. package/dist/recordTableColumns.js.map +1 -1
  48. package/dist/recordTablePreload.js.map +1 -1
  49. package/dist/refDisplayRequests.js +112 -12
  50. package/dist/refDisplayRequests.js.map +1 -1
  51. package/dist/richDoc.d.ts +2 -2
  52. package/dist/richDoc.js +5 -5
  53. package/dist/richDoc.js.map +1 -1
  54. package/dist/schemaGenerator.d.ts +25 -1
  55. package/dist/schemaGenerator.js +4569 -18
  56. package/dist/schemaGenerator.js.map +1 -1
  57. package/dist/schemaShrink.d.ts +3 -1
  58. package/dist/schemaShrink.js +4451 -1
  59. package/dist/schemaShrink.js.map +1 -1
  60. package/dist/schemaShrinkValidators.d.ts +2 -2
  61. package/dist/schemaTypes.d.ts +123 -0
  62. package/dist/schemaTypes.js +107 -13
  63. package/dist/schemaTypes.js.map +1 -1
  64. package/dist/share.js +6 -1
  65. package/dist/share.js.map +1 -1
  66. package/dist/shareApiBridge.js +6 -1
  67. package/dist/shareApiBridge.js.map +1 -1
  68. package/dist/shareProposal.js +112 -12
  69. package/dist/shareProposal.js.map +1 -1
  70. package/dist/spaceBundle.js +112 -12
  71. package/dist/spaceBundle.js.map +1 -1
  72. package/dist/syncChannel.d.ts +15 -0
  73. package/dist/syncChannel.js +4642 -0
  74. package/dist/syncChannel.js.map +1 -0
  75. package/package.json +1 -1
  76. package/dist/storageFieldValues.d.ts +0 -10
  77. 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,262 @@ 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 = 50;
6311
+ var MAX_RENDER_PIXELS = MAX_RENDER_MEGAPIXELS * 1e6;
6312
+ var RENDITION_TIMEOUT_MS = 6e4;
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 assetSlotView(row, slot) {
6475
+ const decision = row[slot];
6476
+ if (!decision || decision.kind === "original") {
6477
+ return { url: row.originalUrl, pending: false, failed: false };
6478
+ }
6479
+ return {
6480
+ url: decision.url,
6481
+ pending: decision.kind === "pending",
6482
+ failed: decision.kind === "failed"
6483
+ };
6484
+ }
6485
+ function publicRenditionUrlKeys(graph, renditions) {
6486
+ const built = renditions ?? {};
6487
+ return graph.filter((node) => built[node.id] !== void 0).map((node) => node.id);
6488
+ }
6489
+ function renderPixelCapError(label, size) {
6490
+ const pixels = size.width * size.height;
6491
+ if (pixels <= MAX_RENDER_PIXELS) return null;
6492
+ return `${label} is ${(pixels / 1e6).toFixed(1)}MP, above the ${MAX_RENDER_MEGAPIXELS}MP render limit`;
6493
+ }
6494
+
6145
6495
  // packages/@columnus/shared/src/schemaGenerator.ts
6146
6496
  var BANNER = `// AUTO-GENERATED by Columnus. Do not edit by hand \u2014
6147
6497
  // changes here will be overwritten when Columnus next saves the schema.
@@ -6164,6 +6514,45 @@ var API_SYNC_ROUTES_TABLE_NAME = "columnus_api_sync_routes";
6164
6514
  var API_OUTBOX_TABLE_NAME = "columnus_api_outbox";
6165
6515
  var API_DELIVERY_TABLE_NAME = "columnus_api_delivery";
6166
6516
  var INCOMING_REFS_TABLE_NAME = "columnus_incoming_refs";
6517
+ var ASSETS_TABLE_NAME = "columnus_assets";
6518
+ var ASSET_VERSIONS_TABLE_NAME = "columnus_asset_versions";
6519
+ var ASSET_REFS_TABLE_NAME = "columnus_asset_refs";
6520
+ var ASSET_PROFILES_TABLE_NAME = "columnus_asset_profiles";
6521
+ var ASSET_SETTINGS_TABLE_NAME = "columnus_asset_settings";
6522
+ var ASSET_FAMILY_LITERALS = ASSET_FAMILIES.map(
6523
+ (family) => ` v.literal(${JSON.stringify(family)}),`
6524
+ ).join("\n");
6525
+ var ASSET_PROCESSING_STATUS_LITERALS = ASSET_PROCESSING_STATUSES.map(
6526
+ (status) => ` v.literal(${JSON.stringify(status)}),`
6527
+ ).join("\n");
6528
+ var ASSETS_TABLE_SOURCE = ` ${ASSETS_TABLE_NAME}: defineTable({
6529
+ currentVersionId: v.optional(v.string()),
6530
+ currentOriginalStorageId: v.optional(v.id("_storage")),
6531
+ currentRenditionStorageIds: v.optional(v.record(v.string(), v.id("_storage"))),
6532
+ family: v.optional(
6533
+ v.union(
6534
+ ${ASSET_FAMILY_LITERALS}
6535
+ ),
6536
+ ),
6537
+ profileSlugs: v.array(v.string()),
6538
+ focalPoint: v.optional(v.object({ x: v.number(), y: v.number() })),
6539
+ processingStatus: v.union(
6540
+ ${ASSET_PROCESSING_STATUS_LITERALS}
6541
+ ),
6542
+ contentType: v.optional(v.string()),
6543
+ filename: v.string(),
6544
+ size: v.optional(v.number()),
6545
+ isDeleted: v.boolean(),
6546
+ deletedAt: v.optional(v.number()),
6547
+ wipedAt: v.optional(v.number()),
6548
+ })
6549
+ .index("by_isDeleted_and_deletedAt", ["isDeleted", "deletedAt"])
6550
+ .index("by_isDeleted_and_family_and_wipedAt", ["isDeleted", "family", "wipedAt"])
6551
+ .index("by_isDeleted_and_wipedAt_and_deletedAt", ["isDeleted", "wipedAt", "deletedAt"])
6552
+ .searchIndex("search_filename", {
6553
+ searchField: "filename",
6554
+ filterFields: ["isDeleted", "family", "wipedAt"],
6555
+ }),`;
6167
6556
  var AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({
6168
6557
  timestamp: v.number(),
6169
6558
  kind: v.union(v.literal("data"), v.literal("schema")),
@@ -6174,6 +6563,7 @@ var AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({
6174
6563
  after: v.optional(v.any()),
6175
6564
  })
6176
6565
  .index("by_timestamp", ["timestamp"])
6566
+ .index("by_kind_and_timestamp", ["kind", "timestamp"])
6177
6567
  .index("by_table", ["table", "timestamp"])
6178
6568
  .index("by_document", ["documentId", "timestamp"]),`;
6179
6569
  var SPACES_TABLE_SOURCE = ` ${SPACES_TABLE_NAME}: defineTable({
@@ -6234,8 +6624,9 @@ function generateSchemaTs(manifest, opts) {
6234
6624
  const includeManifestTable = opts?.includeManifestTable ?? true;
6235
6625
  const includeAuditTable = opts?.includeAuditTable ?? true;
6236
6626
  const includeDisplayValuesTable = opts?.includeDisplayValuesTable ?? true;
6627
+ const assetFieldIds = opts?.assetFieldIds ?? "assets";
6237
6628
  const userTables = [...manifest.tables].sort((a, b) => a.name.localeCompare(b.name));
6238
- const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t)},`).join("\n");
6629
+ const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t, assetFieldIds)},`).join("\n");
6239
6630
  let body;
6240
6631
  if (includeColumnusTables) {
6241
6632
  const columnusSource = columnusTablesSource({
@@ -6244,37 +6635,47 @@ function generateSchemaTs(manifest, opts) {
6244
6635
  includeAuditTable,
6245
6636
  includeDisplayValuesTable
6246
6637
  });
6247
- body = userBody ? `${userBody}
6248
- ${columnusSource}` : columnusSource;
6638
+ body = [userBody, ASSETS_TABLE_SOURCE, columnusSource].filter(Boolean).join("\n");
6249
6639
  } else {
6250
- body = userBody || "";
6640
+ body = [userBody, ASSETS_TABLE_SOURCE].filter(Boolean).join("\n");
6251
6641
  }
6252
6642
  const banner = includeColumnusTables ? BANNER : CONSUMER_BANNER;
6253
6643
  const schemaBody = body ? `${body}
6254
6644
  ` : "";
6645
+ const schemaOpts = opts?.schemaValidation === false ? ", { schemaValidation: false }" : "";
6255
6646
  return `${banner}import { defineSchema, defineTable } from "convex/server";
6256
6647
  import { v } from "convex/values";
6257
6648
 
6258
6649
  export default defineSchema({
6259
- ${schemaBody}});
6650
+ ${schemaBody}}${schemaOpts});
6260
6651
  `;
6261
6652
  }
6262
- function renderTable(t) {
6263
- const fieldsBlock = t.fields.length ? `{
6264
- ${t.fields.map((f) => {
6265
- const inner = renderType(f.type);
6653
+ function renderTable(t, assetFieldIds) {
6654
+ const fields = isAssetTable(t) ? [
6655
+ ...t.fields,
6656
+ {
6657
+ name: "assetId",
6658
+ type: { kind: "id", table: ASSETS_TABLE_NAME },
6659
+ optional: false
6660
+ }
6661
+ ] : t.fields;
6662
+ const fieldsBlock = fields.length ? `{
6663
+ ${fields.map((f) => {
6664
+ const inner = renderType(f.type, assetFieldIds);
6266
6665
  const value = f.optional ? `v.optional(${inner})` : inner;
6267
6666
  return ` ${f.name}: ${value},`;
6268
6667
  }).join("\n")}
6269
6668
  }` : `{}`;
6270
6669
  let out = `defineTable(${fieldsBlock})`;
6271
- const inlineSingleIndex = t.indexes.length === 1 && t.searchIndexes.length === 0;
6272
- for (const idx of t.indexes) {
6670
+ const indexes = isAssetTable(t) ? [{ name: "by_assetId", fields: ["assetId"] }] : t.indexes;
6671
+ const searchIndexes = isAssetTable(t) ? [] : t.searchIndexes;
6672
+ const inlineSingleIndex = indexes.length === 1 && searchIndexes.length === 0;
6673
+ for (const idx of indexes) {
6273
6674
  const cols = idx.fields.map((c) => JSON.stringify(c)).join(", ");
6274
6675
  const sep = inlineSingleIndex ? "" : "\n ";
6275
6676
  out += `${sep}.index(${JSON.stringify(idx.name)}, [${cols}])`;
6276
6677
  }
6277
- for (const sx of t.searchIndexes) {
6678
+ for (const sx of searchIndexes) {
6278
6679
  const cfg = [`searchField: ${JSON.stringify(sx.searchField)}`];
6279
6680
  if (sx.filterFields && sx.filterFields.length > 0) {
6280
6681
  cfg.push(`filterFields: [${sx.filterFields.map((c) => JSON.stringify(c)).join(", ")}]`);
@@ -6284,7 +6685,20 @@ ${t.fields.map((f) => {
6284
6685
  }
6285
6686
  return out;
6286
6687
  }
6287
- function renderType(t) {
6688
+ function renderAssetIdType(assetFieldIds) {
6689
+ const assetId = `v.id(${JSON.stringify(ASSETS_TABLE_NAME)})`;
6690
+ switch (assetFieldIds) {
6691
+ case "storage-or-assets":
6692
+ return `v.union(v.id("_storage"), ${assetId})`;
6693
+ case "assets":
6694
+ return assetId;
6695
+ default: {
6696
+ const _exhaustive = assetFieldIds;
6697
+ return _exhaustive;
6698
+ }
6699
+ }
6700
+ }
6701
+ function renderType(t, assetFieldIds) {
6288
6702
  switch (t.kind) {
6289
6703
  case "string":
6290
6704
  case "markdown":
@@ -6306,26 +6720,62 @@ function renderType(t) {
6306
6720
  return "v.bytes()";
6307
6721
  case "file":
6308
6722
  case "image":
6309
- return 'v.id("_storage")';
6723
+ return renderAssetIdType(assetFieldIds);
6310
6724
  case "id":
6311
6725
  return `v.id(${JSON.stringify(t.table)})`;
6312
6726
  case "literal":
6313
6727
  return `v.literal(${JSON.stringify(t.value)})`;
6314
6728
  case "array":
6315
- return `v.array(${renderType(t.element)})`;
6729
+ return `v.array(${renderType(t.element, assetFieldIds)})`;
6316
6730
  case "object": {
6317
6731
  if (t.fields.length === 0) return `v.object({})`;
6318
6732
  const inner = t.fields.map((f) => {
6319
- const value = f.optional ? `v.optional(${renderType(f.type)})` : renderType(f.type);
6733
+ const inner2 = renderType(f.type, assetFieldIds);
6734
+ const value = f.optional ? `v.optional(${inner2})` : inner2;
6320
6735
  return `${f.name}: ${value}`;
6321
6736
  }).join(", ");
6322
6737
  return `v.object({ ${inner} })`;
6323
6738
  }
6324
6739
  case "union":
6325
- return `v.union(${t.options.map(renderType).join(", ")})`;
6740
+ return `v.union(${t.options.map((option) => renderType(option, assetFieldIds)).join(", ")})`;
6326
6741
  }
6327
6742
  throw new Error(`unknown field kind: ${t.kind}`);
6328
6743
  }
6744
+ function fieldTypeContainsFileOrImage(t) {
6745
+ switch (t.kind) {
6746
+ case "file":
6747
+ case "image":
6748
+ return true;
6749
+ case "array":
6750
+ return fieldTypeContainsFileOrImage(t.element);
6751
+ case "object":
6752
+ return t.fields.some((field) => fieldTypeContainsFileOrImage(field.type));
6753
+ case "union":
6754
+ return t.options.some(fieldTypeContainsFileOrImage);
6755
+ case "string":
6756
+ case "markdown":
6757
+ case "number":
6758
+ case "boolean":
6759
+ case "bigint":
6760
+ case "null":
6761
+ case "any":
6762
+ case "bytes":
6763
+ case "date":
6764
+ case "datetime":
6765
+ case "id":
6766
+ case "literal":
6767
+ return false;
6768
+ default: {
6769
+ const _exhaustive = t;
6770
+ return _exhaustive;
6771
+ }
6772
+ }
6773
+ }
6774
+ function manifestHasFileOrImageFields(manifest) {
6775
+ return manifest.tables.some(
6776
+ (table) => table.fields.some((field) => fieldTypeContainsFileOrImage(field.type))
6777
+ );
6778
+ }
6329
6779
 
6330
6780
  // packages/@columnus/shared/src/schemaShrink.ts
6331
6781
  var SHRINK_IMPACT_CAP = 500;
@@ -6351,6 +6801,16 @@ function computeShrinkPlan(saved, draft) {
6351
6801
  }
6352
6802
  return { removedTables, removedFields };
6353
6803
  }
6804
+ function assertTableKindsImmutable(saved, draft) {
6805
+ const draftByName = new Map(draft.tables.map((table) => [table.name, table]));
6806
+ for (const previous of saved.tables) {
6807
+ const next = draftByName.get(previous.name);
6808
+ if (!next || tableKind(previous) === tableKind(next)) continue;
6809
+ throw new Error(
6810
+ `Table "${previous.name}" cannot change kind from ${tableKind(previous)} to ${tableKind(next)}`
6811
+ );
6812
+ }
6813
+ }
6354
6814
  function shrinkPlanIsEmpty(plan) {
6355
6815
  return plan.removedTables.length === 0 && plan.removedFields.size === 0;
6356
6816
  }
@@ -6449,6 +6909,7 @@ function createCleanupState(targetManifestJson, beforeManifestJson, saved, plan)
6449
6909
  };
6450
6910
  }
6451
6911
  function prepareShrinkSave(saved, draft, beforeManifestJson = JSON.stringify(saved)) {
6912
+ assertTableKindsImmutable(saved, draft);
6452
6913
  const plan = computeShrinkPlan(saved, draft);
6453
6914
  const normalized = normalizeManifestForShrink(draft, plan);
6454
6915
  const normalizedJson = JSON.stringify(normalized);
@@ -6653,7 +7114,7 @@ function fallbackIdLabel(documentId) {
6653
7114
  function formatIdShort(id, n = 6) {
6654
7115
  return `${id.slice(0, n)}\u2026`;
6655
7116
  }
6656
- var CONVEX_DOCUMENT_ID = /^[a-z0-9]{32}$/;
7117
+ var CONVEX_DOCUMENT_ID = /^[a-z0-9]{26,64}$/;
6657
7118
  function looksLikeId(s) {
6658
7119
  return CONVEX_DOCUMENT_ID.test(s);
6659
7120
  }
@@ -7101,68 +7562,161 @@ function formatRecordTableCellText(value, type, locale) {
7101
7562
  }
7102
7563
  }
7103
7564
 
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;
7565
+ // packages/@columnus/shared/src/assetFieldValues.ts
7566
+ var ASSET_ID = /^[a-z0-9]+$/i;
7567
+ function isValidAssetId(value) {
7568
+ return ASSET_ID.test(value) && value.length >= 10;
7108
7569
  }
7109
- function collectStorageIds(value, type, out = /* @__PURE__ */ new Set()) {
7570
+ function collectAssetIds(value, type, out = /* @__PURE__ */ new Set()) {
7110
7571
  if (isFileFieldType(type)) {
7111
7572
  const id = toDocumentId(value);
7112
7573
  if (id) out.add(id);
7113
7574
  return out;
7114
7575
  }
7115
- if (isFileArrayFieldType(type) && Array.isArray(value)) {
7116
- for (const item of value) {
7117
- const id = toDocumentId(item);
7118
- if (id) out.add(id);
7576
+ if (type.kind === "array" && Array.isArray(value)) {
7577
+ for (const item of value) collectAssetIds(item, type.element, out);
7578
+ return out;
7579
+ }
7580
+ if (type.kind === "object" && value !== null && typeof value === "object" && !Array.isArray(value)) {
7581
+ const record = value;
7582
+ for (const field of type.fields) {
7583
+ collectAssetIds(record[field.name], field.type, out);
7119
7584
  }
7585
+ return out;
7586
+ }
7587
+ if (type.kind === "union") {
7588
+ for (const option of type.options) collectAssetIds(value, option, out);
7120
7589
  }
7121
7590
  return out;
7122
7591
  }
7123
- function collectStorageIdsFromRow(row, fields, out = /* @__PURE__ */ new Set()) {
7592
+ function collectAssetIdsFromRow(row, fields, out = /* @__PURE__ */ new Set()) {
7124
7593
  if (!row) return out;
7125
7594
  for (const field of fields) {
7126
- if (!isStorageFieldType(field.type)) continue;
7127
- collectStorageIds(row[field.name], field.type, out);
7595
+ collectAssetIds(row[field.name], field.type, out);
7128
7596
  }
7129
7597
  return out;
7130
7598
  }
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
- }
7599
+
7600
+ // packages/@columnus/shared/src/assetJobs.ts
7601
+ var ASSET_JOB_KINDS = ["extract", "rendition"];
7602
+ var ASSET_JOB_STATUSES = ["pending", "claimed", "done", "failed", "dead_letter"];
7603
+ var ASSET_JOB_MAX_ATTEMPTS = 5;
7604
+ var ASSET_JOB_TIMEOUT_MS = 6e4;
7605
+ var ASSET_JOB_LEASE_MS = 3 * 6e4;
7606
+ var ASSET_JOB_MAX_RECLAIMS = 5;
7607
+ var ASSET_JOB_BACKOFF_MS = [15e3, 6e4, 5 * 6e4, 60 * 6e4];
7608
+ function assetJobRetryDelayMs(attempts) {
7609
+ if (attempts >= ASSET_JOB_MAX_ATTEMPTS) return null;
7610
+ const index = Math.max(0, Math.min(attempts - 1, ASSET_JOB_BACKOFF_MS.length - 1));
7611
+ return ASSET_JOB_BACKOFF_MS[index] ?? null;
7612
+ }
7613
+ function assetJobFailureOutcome(attempts, now) {
7614
+ const delay = assetJobRetryDelayMs(attempts);
7615
+ if (delay === null) return { status: "dead_letter" };
7616
+ return { status: "pending", runAfter: now + delay };
7617
+ }
7618
+ function assetJobReclaimOutcome(reclaims) {
7619
+ return reclaims + 1 >= ASSET_JOB_MAX_RECLAIMS ? { status: "dead_letter" } : { status: "pending" };
7620
+ }
7621
+ function assetJobLeaseExpired(leaseUntil, now) {
7622
+ return leaseUntil === void 0 || leaseUntil <= now;
7623
+ }
7624
+ function nextAssetJobWakeAt(jobs, now) {
7625
+ let earliest = null;
7626
+ for (const job of jobs) {
7627
+ if (job.status !== "pending" || job.runAfter <= now) continue;
7628
+ if (earliest === null || job.runAfter < earliest) earliest = job.runAfter;
7629
+ }
7630
+ return earliest;
7631
+ }
7632
+ function assetJobKey(input) {
7633
+ if (input.kind !== "rendition") return `${input.versionId}:extract`;
7634
+ const node = input.nodeId ?? "";
7635
+ return input.fingerprint ? `${input.versionId}:rendition:${node}:${input.fingerprint}` : `${input.versionId}:rendition:${node}`;
7636
+ }
7637
+
7638
+ // packages/@columnus/shared/src/assetSettings.ts
7639
+ var DEFAULT_MEDIA_WARN_BYTES = 10 * 1024 * 1024 * 1024;
7640
+ var DEFAULT_MEDIA_REJECT_BYTES = 100 * 1024 * 1024 * 1024;
7641
+ var DEFAULT_MEDIA_UPLOAD_CAPS = {
7642
+ warnBytes: DEFAULT_MEDIA_WARN_BYTES,
7643
+ rejectBytes: DEFAULT_MEDIA_REJECT_BYTES
7644
+ };
7645
+ function formatMediaBytes(bytes) {
7646
+ if (bytes < 1024) return `${bytes} B`;
7647
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
7648
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
7649
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
7650
+ }
7651
+ function mediaUploadCapsError(caps) {
7652
+ if (!Number.isSafeInteger(caps.warnBytes) || caps.warnBytes < 0) {
7653
+ return "Media warning limit must be a non-negative whole number of bytes";
7654
+ }
7655
+ if (!Number.isSafeInteger(caps.rejectBytes) || caps.rejectBytes <= 0) {
7656
+ return "Media reject limit must be a positive whole number of bytes";
7657
+ }
7658
+ if (caps.warnBytes > caps.rejectBytes) {
7659
+ return "Media warning limit cannot exceed the reject limit";
7146
7660
  }
7147
- return removed;
7661
+ return null;
7148
7662
  }
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);
7663
+ function mediaUploadLimit(size, caps) {
7664
+ if (!Number.isSafeInteger(size) || size < 0) {
7665
+ return { level: "reject", message: "Media upload size is invalid" };
7153
7666
  }
7154
- for (const [rowId, patch] of pendingEdits) {
7155
- const baseline = isDraftRowId(rowId) ? patch : { ...serverRowById.get(rowId), ...patch };
7156
- collectStorageIdsFromRow(baseline, fields, referenced);
7667
+ if (size > caps.rejectBytes) {
7668
+ return {
7669
+ level: "reject",
7670
+ message: `This file is ${formatMediaBytes(size)}. Media uploads are limited to ${formatMediaBytes(caps.rejectBytes)}.`
7671
+ };
7157
7672
  }
7158
- for (const rowId of draftRowIds) {
7159
- const patch = pendingEdits.get(rowId);
7160
- if (patch) collectStorageIdsFromRow(patch, fields, referenced);
7673
+ if (size > caps.warnBytes) {
7674
+ return {
7675
+ level: "warn",
7676
+ message: `This file is ${formatMediaBytes(size)}, above the ${formatMediaBytes(caps.warnBytes)} Media warning limit. Continue uploading?`
7677
+ };
7161
7678
  }
7162
- return referenced;
7679
+ return null;
7680
+ }
7681
+ var DEFAULT_IMAGE_GRAPH = [
7682
+ { id: "preview", op: "contain", maxWidth: 2e3, maxHeight: 2e3, format: "webp", quality: 80 },
7683
+ {
7684
+ id: "thumb",
7685
+ parentId: "preview",
7686
+ op: "contain",
7687
+ maxWidth: 400,
7688
+ maxHeight: 400,
7689
+ format: "webp",
7690
+ quality: 80
7691
+ },
7692
+ {
7693
+ id: "thumbSm",
7694
+ parentId: "preview",
7695
+ op: "contain",
7696
+ maxWidth: 200,
7697
+ maxHeight: 200,
7698
+ format: "webp",
7699
+ quality: 80
7700
+ }
7701
+ ];
7702
+ var DEFAULT_ASSET_SLOTS = {
7703
+ image: { compact: "thumbSm", preview: "preview" }
7704
+ };
7705
+ function defaultAssetSettings() {
7706
+ return {
7707
+ ...DEFAULT_MEDIA_UPLOAD_CAPS,
7708
+ familyGraphs: { image: DEFAULT_IMAGE_GRAPH },
7709
+ familySchemas: {},
7710
+ slots: DEFAULT_ASSET_SLOTS
7711
+ };
7163
7712
  }
7164
- function isDraftRowId(rowId) {
7165
- return rowId.startsWith("__draft__");
7713
+ function unsavedAssetSettings() {
7714
+ return { ...defaultAssetSettings(), updatedAt: 0 };
7715
+ }
7716
+ function resolveFamilySlotMapping(settings, family) {
7717
+ if (family === void 0) return void 0;
7718
+ const resolved = settings ?? unsavedAssetSettings();
7719
+ return resolved.slots?.[family] ?? DEFAULT_ASSET_SLOTS[family];
7166
7720
  }
7167
7721
 
7168
7722
  // packages/@columnus/shared/src/fieldValueEqual.ts
@@ -7469,7 +8023,7 @@ function coerceCsvValue(raw, type, optional) {
7469
8023
  return ok(raw);
7470
8024
  case "file":
7471
8025
  case "image":
7472
- if (!isValidStorageId(raw)) return fail("Invalid storage file id");
8026
+ if (!isValidAssetId(raw)) return fail("Invalid asset id");
7473
8027
  return ok(raw);
7474
8028
  case "number": {
7475
8029
  const n = Number(raw);
@@ -8206,6 +8760,27 @@ function isRadixOverlayOpen() {
8206
8760
  if (ae?.getAttribute("aria-expanded") === "true") return true;
8207
8761
  return Boolean(ae?.closest("[data-radix-popper-content-wrapper]"));
8208
8762
  }
8763
+
8764
+ // packages/@columnus/shared/src/postLoginPath.ts
8765
+ var RESOLVE_BASE = "https://post-login.invalid";
8766
+ function safePostLoginPath(raw, fallback = "/") {
8767
+ if (raw == null) return fallback;
8768
+ const trimmed = raw.trim();
8769
+ if (!trimmed.startsWith("/") || trimmed.startsWith("//") || trimmed.includes("\\")) {
8770
+ return fallback;
8771
+ }
8772
+ try {
8773
+ const url = new URL(trimmed, RESOLVE_BASE);
8774
+ if (url.origin !== RESOLVE_BASE) return fallback;
8775
+ const path = `${url.pathname}${url.search}${url.hash}`;
8776
+ return path.startsWith("/") ? path : fallback;
8777
+ } catch {
8778
+ return fallback;
8779
+ }
8780
+ }
8781
+ function postLoginRedirectPath(search, fallback = "/") {
8782
+ return safePostLoginPath(new URLSearchParams(search).get("next"), fallback);
8783
+ }
8209
8784
  function useDebouncedValue(value, ms) {
8210
8785
  const [debounced, setDebounced] = useState(value);
8211
8786
  useEffect(() => {
@@ -8284,11 +8859,28 @@ function classifyPhase(out) {
8284
8859
  }
8285
8860
 
8286
8861
  // packages/@columnus/shared/src/previewDeployName.ts
8862
+ function hostnameFromCoolifyToken(raw) {
8863
+ const token = raw.trim();
8864
+ if (!token || /^https?:?$/i.test(token)) return null;
8865
+ try {
8866
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(token)) {
8867
+ return new URL(token).hostname || null;
8868
+ }
8869
+ } catch {
8870
+ return null;
8871
+ }
8872
+ const host = token.split("/")[0]?.split(":")[0] ?? "";
8873
+ if (!host || !host.includes(".") && host !== "localhost") return null;
8874
+ return host;
8875
+ }
8287
8876
  function coolifyHostnameFromEnv(env = process.env) {
8288
8877
  const raw = env.COOLIFY_FQDN ?? env.COOLIFY_URL;
8289
8878
  if (!raw) return null;
8290
- const host = raw.replace(/^https?:\/\//, "").split("/")[0] ?? "";
8291
- return host || null;
8879
+ for (const part of raw.split(",")) {
8880
+ const host = hostnameFromCoolifyToken(part);
8881
+ if (host) return host;
8882
+ }
8883
+ return null;
8292
8884
  }
8293
8885
  function resolveTrustedAuthOrigin(env = process.env) {
8294
8886
  const explicit = env.COLUMNUS_AUTH_ORIGIN?.trim();
@@ -8306,10 +8898,10 @@ function isCiPreviewBuild(env = process.env) {
8306
8898
  return true;
8307
8899
  }
8308
8900
  const host = coolifyHostnameFromEnv(env);
8309
- return Boolean(host && /^(?:manage-|deploy-)?preview-\d+\./.test(host));
8901
+ return Boolean(host && /^(?:manage-|deploy-|renderer-)?preview-\d+\./.test(host));
8310
8902
  }
8311
8903
  var PULL_HEAD_BRANCH_RE = /^pull\/(\d+)\/head$/i;
8312
- var PREVIEW_HOST_PR_RE = /^(?:manage-|deploy-)?preview-(\d+)\./;
8904
+ var PREVIEW_HOST_PR_RE = /^(?:manage-|deploy-|renderer-)?preview-(\d+)\./;
8313
8905
  function resolvePreviewPrId(env = process.env) {
8314
8906
  const host = coolifyHostnameFromEnv(env);
8315
8907
  if (host) {
@@ -9130,7 +9722,12 @@ var apiTableAccessSchema = external_exports.object({
9130
9722
  */
9131
9723
  rowQuery: clampQuerySchema.optional(),
9132
9724
  /** Scan ceiling for Read/guest list plans; callers may only lower. Not applied to Sync/Resync. */
9133
- maxScanLimit: external_exports.number().int().positive().optional()
9725
+ maxScanLimit: external_exports.number().int().positive().optional(),
9726
+ /**
9727
+ * Media source scope for the fixed `columnus_assets` source. Omit for all
9728
+ * live Media; an empty list intentionally grants no Media assets.
9729
+ */
9730
+ assetProfiles: external_exports.array(external_exports.string().min(1)).max(100).optional()
9134
9731
  });
9135
9732
  var apiProfileSnapshotSchema = external_exports.object({
9136
9733
  id: external_exports.string(),
@@ -9149,6 +9746,9 @@ function editorAccessEnabled(access) {
9149
9746
  function findTableAccess(tableAccess, table) {
9150
9747
  return tableAccess?.find((entry) => entry.table === table);
9151
9748
  }
9749
+ function profileTableAccesses(profile) {
9750
+ return profile.tableAccess ?? profile.tables.map((table) => ({ table, read: true }));
9751
+ }
9152
9752
  function assertPatchesHaveEditorAccess(profile, patches) {
9153
9753
  const byTable = new Map((profile.tableAccess ?? []).map((access) => [access.table, access]));
9154
9754
  for (const patch of patches) {
@@ -9167,6 +9767,15 @@ function syncEnabledTables(profile) {
9167
9767
  }
9168
9768
  return [...tables];
9169
9769
  }
9770
+ function assetMatchesProfileScope(asset, assetProfiles) {
9771
+ if (!asset || asset.isDeleted === true || asset.wipedAt !== void 0) return false;
9772
+ if (assetProfiles === void 0) return true;
9773
+ if (assetProfiles.length === 0) return false;
9774
+ const profileSet = new Set(assetProfiles);
9775
+ return Array.isArray(asset.profileSlugs) && asset.profileSlugs.some(
9776
+ (profile) => typeof profile === "string" && profileSet.has(profile)
9777
+ );
9778
+ }
9170
9779
 
9171
9780
  // packages/@columnus/shared/src/shareApiBridge.ts
9172
9781
  function shareScopeAccessMode(scope) {
@@ -9410,6 +10019,52 @@ function resolveSyncMembershipOp(args) {
9410
10019
  return null;
9411
10020
  }
9412
10021
 
10022
+ // packages/@columnus/shared/src/syncChannel.ts
10023
+ function syncChannelForTable(table) {
10024
+ return table === ASSETS_TABLE_NAME ? "asset" : "record";
10025
+ }
10026
+ function resolveAssetSyncMembershipOp(change, assetProfiles) {
10027
+ const beforeMatches = assetMatchesProfileScope(change.before, assetProfiles);
10028
+ const afterMatches = assetMatchesProfileScope(change.after, assetProfiles);
10029
+ if (change.op === "delete") return beforeMatches ? "delete" : null;
10030
+ if (afterMatches) return "upsert";
10031
+ return beforeMatches ? "delete" : null;
10032
+ }
10033
+ function resolveChannelMembershipOp(args) {
10034
+ const channel = syncChannelForTable(args.table);
10035
+ switch (channel) {
10036
+ case "asset":
10037
+ return resolveAssetSyncMembershipOp(
10038
+ { op: args.requestedOp, before: args.before, after: args.after },
10039
+ findTableAccess(args.tableAccess, args.table)?.assetProfiles
10040
+ );
10041
+ case "record":
10042
+ return resolveSyncMembershipOp({
10043
+ predicates: syncClampPredicates(args.tableAccess, args.table),
10044
+ before: args.before,
10045
+ after: args.after,
10046
+ requestedOp: args.requestedOp
10047
+ });
10048
+ default: {
10049
+ const _exhaustive = channel;
10050
+ return _exhaustive;
10051
+ }
10052
+ }
10053
+ }
10054
+ function documentMatchesSyncChannel(doc, table, tableAccess) {
10055
+ const channel = syncChannelForTable(table);
10056
+ switch (channel) {
10057
+ case "asset":
10058
+ return assetMatchesProfileScope(doc, findTableAccess(tableAccess, table)?.assetProfiles);
10059
+ case "record":
10060
+ return documentMatchesSyncClamp(doc, syncClampPredicates(tableAccess, table));
10061
+ default: {
10062
+ const _exhaustive = channel;
10063
+ return _exhaustive;
10064
+ }
10065
+ }
10066
+ }
10067
+
9413
10068
  // packages/@columnus/shared/src/readApiQuery.ts
9414
10069
  function readApiQueryExportName(kind, tableName) {
9415
10070
  return `${kind}${tableName}`;
@@ -10235,6 +10890,10 @@ function isSchemaDeployPhaseActive(phase) {
10235
10890
  function hasSchemaDeployOperationLeaseExpired(startedAt, now) {
10236
10891
  return startedAt !== void 0 && now - startedAt >= SCHEMA_DEPLOY_OPERATION_LEASE_MS;
10237
10892
  }
10893
+ function isSchemaDeployOperationBlocking(phase, startedAt, now = Date.now()) {
10894
+ if (!isSchemaDeployPhaseActive(phase)) return false;
10895
+ return !hasSchemaDeployOperationLeaseExpired(startedAt, now);
10896
+ }
10238
10897
  function base64UrlFromBytes(bytes) {
10239
10898
  let binary = "";
10240
10899
  for (const byte of bytes) binary += String.fromCharCode(byte);
@@ -10857,6 +11516,6 @@ papaparse/papaparse.min.js:
10857
11516
  *)
10858
11517
  */
10859
11518
 
10860
- 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 };
11519
+ 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, 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, 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, matchColumnsForTable, matchEscape, matchKeyFromColumn, matchModEnter, matchModShiftShortcut, matchModShortcut, matchSave, matchToggleEditMode, matchUndoRedo, matchesBetween, matchesDeployCompletion, maxScanLimitValidator, mediaUploadCapsError, mediaUploadLimit, mergeDraftErdLayoutIntoCanonical, mergeErdLayouts, mergeProposedRecord, mergeQuery, mergeReferenceScopes, mergeStagingPendingEdits, modKeyLabel, newProvisionalRowId, nextAssetJobWakeAt, 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, 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 };
10861
11520
  //# sourceMappingURL=index.js.map
10862
11521
  //# sourceMappingURL=index.js.map