@columnus/shared 0.1.47

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 (206) hide show
  1. package/LICENSE +21 -0
  2. package/dist/apiProfile.d.ts +1072 -0
  3. package/dist/apiProfile.js +4210 -0
  4. package/dist/apiProfile.js.map +1 -0
  5. package/dist/apiProfileSlug.d.ts +11 -0
  6. package/dist/apiProfileSlug.js +39 -0
  7. package/dist/apiProfileSlug.js.map +1 -0
  8. package/dist/apiToken.d.ts +6 -0
  9. package/dist/apiToken.js +35 -0
  10. package/dist/apiToken.js.map +1 -0
  11. package/dist/betterAuthSession.d.ts +8 -0
  12. package/dist/betterAuthSession.js +57 -0
  13. package/dist/betterAuthSession.js.map +1 -0
  14. package/dist/bffHost.d.ts +36 -0
  15. package/dist/bffHost.js +74 -0
  16. package/dist/bffHost.js.map +1 -0
  17. package/dist/bffProtocol.d.ts +1357 -0
  18. package/dist/bffProtocol.js +4362 -0
  19. package/dist/bffProtocol.js.map +1 -0
  20. package/dist/bffRedact.d.ts +30 -0
  21. package/dist/bffRedact.js +55 -0
  22. package/dist/bffRedact.js.map +1 -0
  23. package/dist/ciPreviewEnv.d.ts +49 -0
  24. package/dist/ciPreviewEnv.js +143 -0
  25. package/dist/ciPreviewEnv.js.map +1 -0
  26. package/dist/clipboardTransfer.d.ts +25 -0
  27. package/dist/clipboardTransfer.js +4862 -0
  28. package/dist/clipboardTransfer.js.map +1 -0
  29. package/dist/convexSiteUrl.d.ts +73 -0
  30. package/dist/convexSiteUrl.js +137 -0
  31. package/dist/convexSiteUrl.js.map +1 -0
  32. package/dist/csv.d.ts +54 -0
  33. package/dist/csv.js +5499 -0
  34. package/dist/csv.js.map +1 -0
  35. package/dist/dataTransfer.d.ts +21 -0
  36. package/dist/dataTransfer.js +74 -0
  37. package/dist/dataTransfer.js.map +1 -0
  38. package/dist/dateValues.d.ts +18 -0
  39. package/dist/dateValues.js +73 -0
  40. package/dist/dateValues.js.map +1 -0
  41. package/dist/deployOutput.d.ts +3 -0
  42. package/dist/deployOutput.js +23 -0
  43. package/dist/deployOutput.js.map +1 -0
  44. package/dist/displayLabel.d.ts +13 -0
  45. package/dist/displayLabel.js +4342 -0
  46. package/dist/displayLabel.js.map +1 -0
  47. package/dist/displayTemplateGenerator.d.ts +11 -0
  48. package/dist/displayTemplateGenerator.js +98 -0
  49. package/dist/displayTemplateGenerator.js.map +1 -0
  50. package/dist/displayTypes.d.ts +10 -0
  51. package/dist/displayTypes.js +3 -0
  52. package/dist/displayTypes.js.map +1 -0
  53. package/dist/dotenv.d.ts +8 -0
  54. package/dist/dotenv.js +61 -0
  55. package/dist/dotenv.js.map +1 -0
  56. package/dist/erdLayout.d.ts +27 -0
  57. package/dist/erdLayout.js +78 -0
  58. package/dist/erdLayout.js.map +1 -0
  59. package/dist/fieldTypeFormat.d.ts +5 -0
  60. package/dist/fieldTypeFormat.js +63 -0
  61. package/dist/fieldTypeFormat.js.map +1 -0
  62. package/dist/fieldTypeMeta.d.ts +50 -0
  63. package/dist/fieldTypeMeta.js +84 -0
  64. package/dist/fieldTypeMeta.js.map +1 -0
  65. package/dist/fieldValueEqual.d.ts +4 -0
  66. package/dist/fieldValueEqual.js +58 -0
  67. package/dist/fieldValueEqual.js.map +1 -0
  68. package/dist/importMatch.d.ts +80 -0
  69. package/dist/importMatch.js +5643 -0
  70. package/dist/importMatch.js.map +1 -0
  71. package/dist/index.d.ts +58 -0
  72. package/dist/index.js +10647 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/inferIdentifier.d.ts +18 -0
  75. package/dist/inferIdentifier.js +49 -0
  76. package/dist/inferIdentifier.js.map +1 -0
  77. package/dist/keyboard.d.ts +16 -0
  78. package/dist/keyboard.js +71 -0
  79. package/dist/keyboard.js.map +1 -0
  80. package/dist/manifestDeploy.d.ts +27 -0
  81. package/dist/manifestDeploy.js +16 -0
  82. package/dist/manifestDeploy.js.map +1 -0
  83. package/dist/manifestHash.d.ts +11 -0
  84. package/dist/manifestHash.js +35 -0
  85. package/dist/manifestHash.js.map +1 -0
  86. package/dist/previewDeployName.d.ts +26 -0
  87. package/dist/previewDeployName.js +77 -0
  88. package/dist/previewDeployName.js.map +1 -0
  89. package/dist/proposePolicy.d.ts +17 -0
  90. package/dist/proposePolicy.js +33 -0
  91. package/dist/proposePolicy.js.map +1 -0
  92. package/dist/queryBetween.d.ts +20 -0
  93. package/dist/queryBetween.js +28 -0
  94. package/dist/queryBetween.js.map +1 -0
  95. package/dist/queryExecution.d.ts +5 -0
  96. package/dist/queryExecution.js +58 -0
  97. package/dist/queryExecution.js.map +1 -0
  98. package/dist/queryFieldOps.d.ts +66 -0
  99. package/dist/queryFieldOps.js +138 -0
  100. package/dist/queryFieldOps.js.map +1 -0
  101. package/dist/queryMerge.d.ts +29 -0
  102. package/dist/queryMerge.js +4277 -0
  103. package/dist/queryMerge.js.map +1 -0
  104. package/dist/queryPlan.d.ts +97 -0
  105. package/dist/queryPlan.js +4564 -0
  106. package/dist/queryPlan.js.map +1 -0
  107. package/dist/queryStudio.d.ts +25 -0
  108. package/dist/queryStudio.js +4658 -0
  109. package/dist/queryStudio.js.map +1 -0
  110. package/dist/queryTypes.d.ts +402 -0
  111. package/dist/queryTypes.js +4239 -0
  112. package/dist/queryTypes.js.map +1 -0
  113. package/dist/queryValidators.d.ts +99 -0
  114. package/dist/queryValidators.js +76 -0
  115. package/dist/queryValidators.js.map +1 -0
  116. package/dist/readApiQuery.d.ts +10 -0
  117. package/dist/readApiQuery.js +24 -0
  118. package/dist/readApiQuery.js.map +1 -0
  119. package/dist/recordTableColumns.d.ts +21 -0
  120. package/dist/recordTableColumns.js +4469 -0
  121. package/dist/recordTableColumns.js.map +1 -0
  122. package/dist/refDisplayRequests.d.ts +17 -0
  123. package/dist/refDisplayRequests.js +4877 -0
  124. package/dist/refDisplayRequests.js.map +1 -0
  125. package/dist/refGraph.d.ts +23 -0
  126. package/dist/refGraph.js +102 -0
  127. package/dist/refGraph.js.map +1 -0
  128. package/dist/refsRecompute.d.ts +8 -0
  129. package/dist/refsRecompute.js +12 -0
  130. package/dist/refsRecompute.js.map +1 -0
  131. package/dist/richDoc.d.ts +67 -0
  132. package/dist/richDoc.js +4408 -0
  133. package/dist/richDoc.js.map +1 -0
  134. package/dist/schemaGenerator.d.ts +31 -0
  135. package/dist/schemaGenerator.js +198 -0
  136. package/dist/schemaGenerator.js.map +1 -0
  137. package/dist/schemaShrink.d.ts +74 -0
  138. package/dist/schemaShrink.js +132 -0
  139. package/dist/schemaShrink.js.map +1 -0
  140. package/dist/schemaShrinkValidators.d.ts +72 -0
  141. package/dist/schemaShrinkValidators.js +31 -0
  142. package/dist/schemaShrinkValidators.js.map +1 -0
  143. package/dist/schemaTypes.d.ts +454 -0
  144. package/dist/schemaTypes.js +4557 -0
  145. package/dist/schemaTypes.js.map +1 -0
  146. package/dist/share.d.ts +8 -0
  147. package/dist/share.js +4755 -0
  148. package/dist/share.js.map +1 -0
  149. package/dist/shareApiBridge.d.ts +18 -0
  150. package/dist/shareApiBridge.js +4283 -0
  151. package/dist/shareApiBridge.js.map +1 -0
  152. package/dist/shareGuestPolicy.d.ts +14 -0
  153. package/dist/shareGuestPolicy.js +90 -0
  154. package/dist/shareGuestPolicy.js.map +1 -0
  155. package/dist/shareProposal.d.ts +113 -0
  156. package/dist/shareProposal.js +4810 -0
  157. package/dist/shareProposal.js.map +1 -0
  158. package/dist/shareProposalDiff.d.ts +13 -0
  159. package/dist/shareProposalDiff.js +91 -0
  160. package/dist/shareProposalDiff.js.map +1 -0
  161. package/dist/shareScopes.d.ts +14 -0
  162. package/dist/shareScopes.js +223 -0
  163. package/dist/shareScopes.js.map +1 -0
  164. package/dist/shareTokenCrypto.d.ts +9 -0
  165. package/dist/shareTokenCrypto.js +87 -0
  166. package/dist/shareTokenCrypto.js.map +1 -0
  167. package/dist/shareTokens.d.ts +6 -0
  168. package/dist/shareTokens.js +26 -0
  169. package/dist/shareTokens.js.map +1 -0
  170. package/dist/shareTypes.d.ts +107 -0
  171. package/dist/shareTypes.js +3 -0
  172. package/dist/shareTypes.js.map +1 -0
  173. package/dist/shareValidators.d.ts +168 -0
  174. package/dist/shareValidators.js +124 -0
  175. package/dist/shareValidators.js.map +1 -0
  176. package/dist/shareWizard.d.ts +14 -0
  177. package/dist/shareWizard.js +200 -0
  178. package/dist/shareWizard.js.map +1 -0
  179. package/dist/spaceBundle.d.ts +67 -0
  180. package/dist/spaceBundle.js +4664 -0
  181. package/dist/spaceBundle.js.map +1 -0
  182. package/dist/storageFieldValues.d.ts +10 -0
  183. package/dist/storageFieldValues.js +4421 -0
  184. package/dist/storageFieldValues.js.map +1 -0
  185. package/dist/studioBoot.d.ts +49 -0
  186. package/dist/studioBoot.js +167 -0
  187. package/dist/studioBoot.js.map +1 -0
  188. package/dist/syncClampMembership.d.ts +22 -0
  189. package/dist/syncClampMembership.js +74 -0
  190. package/dist/syncClampMembership.js.map +1 -0
  191. package/dist/tenantHosts.d.ts +30 -0
  192. package/dist/tenantHosts.js +60 -0
  193. package/dist/tenantHosts.js.map +1 -0
  194. package/dist/tenantSecretsCrypto.d.ts +31 -0
  195. package/dist/tenantSecretsCrypto.js +145 -0
  196. package/dist/tenantSecretsCrypto.js.map +1 -0
  197. package/dist/useDebouncedCommit.d.ts +11 -0
  198. package/dist/useDebouncedCommit.js +34 -0
  199. package/dist/useDebouncedCommit.js.map +1 -0
  200. package/dist/useDebouncedValue.d.ts +1 -0
  201. package/dist/useDebouncedValue.js +15 -0
  202. package/dist/useDebouncedValue.js.map +1 -0
  203. package/dist/useModifierHeld.d.ts +2 -0
  204. package/dist/useModifierHeld.js +28 -0
  205. package/dist/useModifierHeld.js.map +1 -0
  206. package/package.json +36 -0
@@ -0,0 +1,31 @@
1
+ import type { Manifest } from "./schemaTypes.ts";
2
+ export type GenerateSchemaOptions = {
3
+ includeColumnusTables?: boolean;
4
+ /** @deprecated Use includeColumnusTables */
5
+ includeStudioTables?: boolean;
6
+ /** When includeColumnusTables, omit columnus_spaces (owned by @columnus/component). Default true. */
7
+ includeSpacesTable?: boolean;
8
+ /** When includeColumnusTables, omit columnus_manifest (owned by @columnus/component). Default true. */
9
+ includeManifestTable?: boolean;
10
+ /** When includeColumnusTables, omit columnus_audit_log (owned by @columnus/component). Default true. */
11
+ includeAuditTable?: boolean;
12
+ /** When includeColumnusTables, omit columnus_display_values (owned by @columnus/component). Default true. */
13
+ includeDisplayValuesTable?: boolean;
14
+ };
15
+ /** User tables only — component tables live in @columnus/component. */
16
+ export declare const HOST_SCHEMA_PROFILE: {
17
+ readonly includeColumnusTables: false;
18
+ };
19
+ export declare const AUDIT_TABLE_NAME = "columnus_audit_log";
20
+ export declare const SPACES_TABLE_NAME = "columnus_spaces";
21
+ export declare const MANIFEST_TABLE_NAME = "columnus_manifest";
22
+ export declare const DISPLAY_VALUES_TABLE_NAME = "columnus_display_values";
23
+ export declare const API_PROFILES_TABLE_NAME = "columnus_api_profiles";
24
+ export declare const API_TOKENS_TABLE_NAME = "columnus_api_tokens";
25
+ export declare const API_OUTPUTS_TABLE_NAME = "columnus_api_outputs";
26
+ export declare const API_OUTPUT_SECRETS_TABLE_NAME = "columnus_api_output_secrets";
27
+ export declare const API_SYNC_ROUTES_TABLE_NAME = "columnus_api_sync_routes";
28
+ export declare const API_OUTBOX_TABLE_NAME = "columnus_api_outbox";
29
+ export declare const API_DELIVERY_TABLE_NAME = "columnus_api_delivery";
30
+ export declare const INCOMING_REFS_TABLE_NAME = "columnus_incoming_refs";
31
+ export declare function generateSchemaTs(manifest: Manifest, opts?: GenerateSchemaOptions): string;
@@ -0,0 +1,198 @@
1
+ // packages/@columnus/shared/src/manifestDeploy.ts
2
+ var MANIFEST_DEPLOY_STATUSES = [
3
+ "idle",
4
+ "cleaning",
5
+ "ready",
6
+ "deploying",
7
+ "deployed",
8
+ "failed"
9
+ ];
10
+
11
+ // packages/@columnus/shared/src/schemaGenerator.ts
12
+ var BANNER = `// AUTO-GENERATED by Columnus. Do not edit by hand \u2014
13
+ // changes here will be overwritten when Columnus next saves the schema.
14
+ `;
15
+ var CONSUMER_BANNER = `// AUTO-GENERATED by columnus-schema-sync. Do not edit by hand \u2014
16
+ // changes here will be overwritten when the schema sync CLI next runs.
17
+ `;
18
+ var HOST_SCHEMA_PROFILE = {
19
+ includeColumnusTables: false
20
+ };
21
+ var AUDIT_TABLE_NAME = "columnus_audit_log";
22
+ var SPACES_TABLE_NAME = "columnus_spaces";
23
+ var MANIFEST_TABLE_NAME = "columnus_manifest";
24
+ var DISPLAY_VALUES_TABLE_NAME = "columnus_display_values";
25
+ var API_PROFILES_TABLE_NAME = "columnus_api_profiles";
26
+ var API_TOKENS_TABLE_NAME = "columnus_api_tokens";
27
+ var API_OUTPUTS_TABLE_NAME = "columnus_api_outputs";
28
+ var API_OUTPUT_SECRETS_TABLE_NAME = "columnus_api_output_secrets";
29
+ var API_SYNC_ROUTES_TABLE_NAME = "columnus_api_sync_routes";
30
+ var API_OUTBOX_TABLE_NAME = "columnus_api_outbox";
31
+ var API_DELIVERY_TABLE_NAME = "columnus_api_delivery";
32
+ var INCOMING_REFS_TABLE_NAME = "columnus_incoming_refs";
33
+ var AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({
34
+ timestamp: v.number(),
35
+ kind: v.union(v.literal("data"), v.literal("schema")),
36
+ operation: v.string(),
37
+ table: v.optional(v.string()),
38
+ documentId: v.optional(v.string()),
39
+ before: v.optional(v.any()),
40
+ after: v.optional(v.any()),
41
+ })
42
+ .index("by_timestamp", ["timestamp"])
43
+ .index("by_table", ["table", "timestamp"])
44
+ .index("by_document", ["documentId", "timestamp"]),`;
45
+ var SPACES_TABLE_SOURCE = ` ${SPACES_TABLE_NAME}: defineTable({
46
+ name: v.string(),
47
+ slug: v.string(),
48
+ description: v.optional(v.string()),
49
+ icon: v.optional(v.string()),
50
+ order: v.number(),
51
+ tables: v.array(v.string()),
52
+ erdLayoutJson: v.optional(v.string()),
53
+ createdAt: v.number(),
54
+ updatedAt: v.number(),
55
+ })
56
+ .index("by_order", ["order"])
57
+ .index("by_slug", ["slug"]),`;
58
+ var MANIFEST_DEPLOY_STATUS_SOURCE = MANIFEST_DEPLOY_STATUSES.map(
59
+ (status) => ` v.literal(${JSON.stringify(status)}),`
60
+ ).join("\n");
61
+ var MANIFEST_TABLE_SOURCE = ` ${MANIFEST_TABLE_NAME}: defineTable({
62
+ manifestJson: v.string(),
63
+ draftManifestJson: v.optional(v.string()),
64
+ draftUpdatedAt: v.optional(v.number()),
65
+ erdLayoutJson: v.optional(v.string()),
66
+ draftErdLayoutJson: v.optional(v.string()),
67
+ deployStatus: v.union(
68
+ ${MANIFEST_DEPLOY_STATUS_SOURCE}
69
+ ),
70
+ deployError: v.optional(v.string()),
71
+ deployLogTail: v.optional(v.string()),
72
+ deployedAt: v.optional(v.number()),
73
+ lastSaveAt: v.number(),
74
+ }),`;
75
+ var DISPLAY_VALUES_TABLE_SOURCE = ` ${DISPLAY_VALUES_TABLE_NAME}: defineTable({
76
+ table: v.string(),
77
+ documentId: v.string(),
78
+ type: v.union(v.literal("id"), v.literal("preview")),
79
+ value: v.string(),
80
+ updatedAt: v.number(),
81
+ })
82
+ .index("by_document", ["table", "documentId"])
83
+ .index("by_table_type", ["table", "type"])
84
+ .index("by_table_type_value", ["table", "type", "value"])
85
+ .searchIndex("search_value", {
86
+ searchField: "value",
87
+ filterFields: ["table", "type"],
88
+ }),`;
89
+ function columnusTablesSource(opts) {
90
+ const parts = [];
91
+ if (opts.includeAuditTable) parts.push(AUDIT_TABLE_SOURCE);
92
+ if (opts.includeSpacesTable) parts.push(SPACES_TABLE_SOURCE);
93
+ if (opts.includeManifestTable) parts.push(MANIFEST_TABLE_SOURCE);
94
+ if (opts.includeDisplayValuesTable) parts.push(DISPLAY_VALUES_TABLE_SOURCE);
95
+ return parts.join("\n");
96
+ }
97
+ function generateSchemaTs(manifest, opts) {
98
+ const includeColumnusTables = opts?.includeColumnusTables ?? opts?.includeStudioTables ?? false;
99
+ const includeSpacesTable = opts?.includeSpacesTable ?? true;
100
+ const includeManifestTable = opts?.includeManifestTable ?? true;
101
+ const includeAuditTable = opts?.includeAuditTable ?? true;
102
+ const includeDisplayValuesTable = opts?.includeDisplayValuesTable ?? true;
103
+ const userTables = [...manifest.tables].sort((a, b) => a.name.localeCompare(b.name));
104
+ const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t)},`).join("\n");
105
+ let body;
106
+ if (includeColumnusTables) {
107
+ const columnusSource = columnusTablesSource({
108
+ includeSpacesTable,
109
+ includeManifestTable,
110
+ includeAuditTable,
111
+ includeDisplayValuesTable
112
+ });
113
+ body = userBody ? `${userBody}
114
+ ${columnusSource}` : columnusSource;
115
+ } else {
116
+ body = userBody || "";
117
+ }
118
+ const banner = includeColumnusTables ? BANNER : CONSUMER_BANNER;
119
+ const schemaBody = body ? `${body}
120
+ ` : "";
121
+ return `${banner}import { defineSchema, defineTable } from "convex/server";
122
+ import { v } from "convex/values";
123
+
124
+ export default defineSchema({
125
+ ${schemaBody}});
126
+ `;
127
+ }
128
+ function renderTable(t) {
129
+ const fieldsBlock = t.fields.length ? `{
130
+ ${t.fields.map((f) => {
131
+ const inner = renderType(f.type);
132
+ const value = f.optional ? `v.optional(${inner})` : inner;
133
+ return ` ${f.name}: ${value},`;
134
+ }).join("\n")}
135
+ }` : `{}`;
136
+ let out = `defineTable(${fieldsBlock})`;
137
+ const inlineSingleIndex = t.indexes.length === 1 && t.searchIndexes.length === 0;
138
+ for (const idx of t.indexes) {
139
+ const cols = idx.fields.map((c) => JSON.stringify(c)).join(", ");
140
+ const sep = inlineSingleIndex ? "" : "\n ";
141
+ out += `${sep}.index(${JSON.stringify(idx.name)}, [${cols}])`;
142
+ }
143
+ for (const sx of t.searchIndexes) {
144
+ const cfg = [`searchField: ${JSON.stringify(sx.searchField)}`];
145
+ if (sx.filterFields && sx.filterFields.length > 0) {
146
+ cfg.push(`filterFields: [${sx.filterFields.map((c) => JSON.stringify(c)).join(", ")}]`);
147
+ }
148
+ out += `
149
+ .searchIndex(${JSON.stringify(sx.name)}, { ${cfg.join(", ")} })`;
150
+ }
151
+ return out;
152
+ }
153
+ function renderType(t) {
154
+ switch (t.kind) {
155
+ case "string":
156
+ case "markdown":
157
+ return "v.string()";
158
+ case "number":
159
+ return "v.number()";
160
+ case "date":
161
+ case "datetime":
162
+ return "v.number()";
163
+ case "boolean":
164
+ return "v.boolean()";
165
+ case "bigint":
166
+ return "v.int64()";
167
+ case "null":
168
+ return "v.null()";
169
+ case "any":
170
+ return "v.any()";
171
+ case "bytes":
172
+ return "v.bytes()";
173
+ case "file":
174
+ case "image":
175
+ return 'v.id("_storage")';
176
+ case "id":
177
+ return `v.id(${JSON.stringify(t.table)})`;
178
+ case "literal":
179
+ return `v.literal(${JSON.stringify(t.value)})`;
180
+ case "array":
181
+ return `v.array(${renderType(t.element)})`;
182
+ case "object": {
183
+ if (t.fields.length === 0) return `v.object({})`;
184
+ const inner = t.fields.map((f) => {
185
+ const value = f.optional ? `v.optional(${renderType(f.type)})` : renderType(f.type);
186
+ return `${f.name}: ${value}`;
187
+ }).join(", ");
188
+ return `v.object({ ${inner} })`;
189
+ }
190
+ case "union":
191
+ return `v.union(${t.options.map(renderType).join(", ")})`;
192
+ }
193
+ throw new Error(`unknown field kind: ${t.kind}`);
194
+ }
195
+
196
+ export { API_DELIVERY_TABLE_NAME, API_OUTBOX_TABLE_NAME, API_OUTPUTS_TABLE_NAME, API_OUTPUT_SECRETS_TABLE_NAME, API_PROFILES_TABLE_NAME, API_SYNC_ROUTES_TABLE_NAME, API_TOKENS_TABLE_NAME, AUDIT_TABLE_NAME, DISPLAY_VALUES_TABLE_NAME, HOST_SCHEMA_PROFILE, INCOMING_REFS_TABLE_NAME, MANIFEST_TABLE_NAME, SPACES_TABLE_NAME, generateSchemaTs };
197
+ //# sourceMappingURL=schemaGenerator.js.map
198
+ //# sourceMappingURL=schemaGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/manifestDeploy.ts","../src/schemaGenerator.ts"],"names":[],"mappings":"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","file":"schemaGenerator.js","sourcesContent":["export const MANIFEST_DEPLOY_STATUSES = [\n \"idle\",\n \"cleaning\",\n \"ready\",\n \"deploying\",\n \"deployed\",\n \"failed\",\n] as const;\n\n/** Status persisted in the singleton Columnus manifest row. */\nexport type ManifestDeployStatus = (typeof MANIFEST_DEPLOY_STATUSES)[number];\n\nexport function isManifestDeployStatus(value: unknown): value is ManifestDeployStatus {\n return MANIFEST_DEPLOY_STATUSES.some((status) => status === value);\n}\n\n/** Manifest row fields shared by the component, host, read API, CLI, and UI boundaries. */\nexport type ManifestDeploySnapshot = {\n manifestJson: string;\n draftManifestJson?: string;\n draftUpdatedAt?: number;\n erdLayoutJson?: string;\n draftErdLayoutJson?: string;\n lastSaveAt: number;\n deployStatus: ManifestDeployStatus;\n deployError?: string;\n deployLogTail?: string;\n deployedAt?: number;\n deployOperationId?: string;\n desiredManifestHash?: string;\n deployedManifestHash?: string;\n deployStartedAt?: number;\n deployCompletedAt?: number;\n refsSchemaHash?: string;\n refsIndexedAt?: number;\n refsRecomputeTargetHash?: string;\n refsRecomputeHeartbeatAt?: number;\n pendingRefsRecomputeBeforeJson?: string;\n};\n","import type { Field, FieldType, Manifest, Table } from \"./schemaTypes.ts\";\nimport { MANIFEST_DEPLOY_STATUSES } from \"./manifestDeploy.ts\";\n\nconst BANNER = `// AUTO-GENERATED by Columnus. Do not edit by hand —\n// changes here will be overwritten when Columnus next saves the schema.\n`;\n\nconst CONSUMER_BANNER = `// AUTO-GENERATED by columnus-schema-sync. Do not edit by hand —\n// changes here will be overwritten when the schema sync CLI next runs.\n`;\n\nexport type GenerateSchemaOptions = {\n includeColumnusTables?: boolean;\n /** @deprecated Use includeColumnusTables */\n includeStudioTables?: boolean;\n /** When includeColumnusTables, omit columnus_spaces (owned by @columnus/component). Default true. */\n includeSpacesTable?: boolean;\n /** When includeColumnusTables, omit columnus_manifest (owned by @columnus/component). Default true. */\n includeManifestTable?: boolean;\n /** When includeColumnusTables, omit columnus_audit_log (owned by @columnus/component). Default true. */\n includeAuditTable?: boolean;\n /** When includeColumnusTables, omit columnus_display_values (owned by @columnus/component). Default true. */\n includeDisplayValuesTable?: boolean;\n};\n\n/** User tables only — component tables live in @columnus/component. */\nexport const HOST_SCHEMA_PROFILE = {\n includeColumnusTables: false,\n} as const satisfies GenerateSchemaOptions;\n\nexport const AUDIT_TABLE_NAME = \"columnus_audit_log\";\nexport const SPACES_TABLE_NAME = \"columnus_spaces\";\nexport const MANIFEST_TABLE_NAME = \"columnus_manifest\";\nexport const DISPLAY_VALUES_TABLE_NAME = \"columnus_display_values\";\nexport const API_PROFILES_TABLE_NAME = \"columnus_api_profiles\";\nexport const API_TOKENS_TABLE_NAME = \"columnus_api_tokens\";\nexport const API_OUTPUTS_TABLE_NAME = \"columnus_api_outputs\";\nexport const API_OUTPUT_SECRETS_TABLE_NAME = \"columnus_api_output_secrets\";\nexport const API_SYNC_ROUTES_TABLE_NAME = \"columnus_api_sync_routes\";\nexport const API_OUTBOX_TABLE_NAME = \"columnus_api_outbox\";\nexport const API_DELIVERY_TABLE_NAME = \"columnus_api_delivery\";\nexport const INCOMING_REFS_TABLE_NAME = \"columnus_incoming_refs\";\n\n// Studio-managed table written by every mutation wrapper in convex/_studio.ts.\n// Always emitted so audit logging never silently breaks after a manifest change.\nconst AUDIT_TABLE_SOURCE = ` ${AUDIT_TABLE_NAME}: defineTable({\n timestamp: v.number(),\n kind: v.union(v.literal(\"data\"), v.literal(\"schema\")),\n operation: v.string(),\n table: v.optional(v.string()),\n documentId: v.optional(v.string()),\n before: v.optional(v.any()),\n after: v.optional(v.any()),\n })\n .index(\"by_timestamp\", [\"timestamp\"])\n .index(\"by_table\", [\"table\", \"timestamp\"])\n .index(\"by_document\", [\"documentId\", \"timestamp\"]),`;\n\n// Studio-managed table that backs the Spaces feature — a UI grouping of\n// tables. Membership is an ordered array of table names (tables are\n// identified by name, not Convex id). `icon` stores a lucide-react icon\n// identifier (e.g. \"Folder\") looked up at render time via the icon registry.\n// Always emitted.\nconst SPACES_TABLE_SOURCE = ` ${SPACES_TABLE_NAME}: defineTable({\n name: v.string(),\n slug: v.string(),\n description: v.optional(v.string()),\n icon: v.optional(v.string()),\n order: v.number(),\n tables: v.array(v.string()),\n erdLayoutJson: v.optional(v.string()),\n createdAt: v.number(),\n updatedAt: v.number(),\n })\n .index(\"by_order\", [\"order\"])\n .index(\"by_slug\", [\"slug\"]),`;\n\n// Studio-managed singleton table holding the live manifest + last-deploy\n// status. Backs the prod schema editor path: the studio reads/writes via\n// Convex (live across tabs), and api/deploy-schema.ts patches deployStatus\n// from the Vercel deploy job. Always emitted — dropping it mid-deploy\n// would race against the in-flight save.\nconst MANIFEST_DEPLOY_STATUS_SOURCE = MANIFEST_DEPLOY_STATUSES.map(\n (status) => ` v.literal(${JSON.stringify(status)}),`,\n).join(\"\\n\");\n\nconst MANIFEST_TABLE_SOURCE = ` ${MANIFEST_TABLE_NAME}: defineTable({\n manifestJson: v.string(),\n draftManifestJson: v.optional(v.string()),\n draftUpdatedAt: v.optional(v.number()),\n erdLayoutJson: v.optional(v.string()),\n draftErdLayoutJson: v.optional(v.string()),\n deployStatus: v.union(\n${MANIFEST_DEPLOY_STATUS_SOURCE}\n ),\n deployError: v.optional(v.string()),\n deployLogTail: v.optional(v.string()),\n deployedAt: v.optional(v.number()),\n lastSaveAt: v.number(),\n }),`;\n\n// Cached display strings (Id + Preview) computed from per-table templates.\n// One row per (table, documentId, type); upserted on record create/update.\nconst DISPLAY_VALUES_TABLE_SOURCE = ` ${DISPLAY_VALUES_TABLE_NAME}: defineTable({\n table: v.string(),\n documentId: v.string(),\n type: v.union(v.literal(\"id\"), v.literal(\"preview\")),\n value: v.string(),\n updatedAt: v.number(),\n })\n .index(\"by_document\", [\"table\", \"documentId\"])\n .index(\"by_table_type\", [\"table\", \"type\"])\n .index(\"by_table_type_value\", [\"table\", \"type\", \"value\"])\n .searchIndex(\"search_value\", {\n searchField: \"value\",\n filterFields: [\"table\", \"type\"],\n }),`;\n\nfunction columnusTablesSource(opts: {\n includeSpacesTable: boolean;\n includeManifestTable: boolean;\n includeAuditTable: boolean;\n includeDisplayValuesTable: boolean;\n}): string {\n const parts: string[] = [];\n if (opts.includeAuditTable) parts.push(AUDIT_TABLE_SOURCE);\n if (opts.includeSpacesTable) parts.push(SPACES_TABLE_SOURCE);\n if (opts.includeManifestTable) parts.push(MANIFEST_TABLE_SOURCE);\n if (opts.includeDisplayValuesTable) parts.push(DISPLAY_VALUES_TABLE_SOURCE);\n return parts.join(\"\\n\");\n}\n\nexport function generateSchemaTs(manifest: Manifest, opts?: GenerateSchemaOptions): string {\n const includeColumnusTables = opts?.includeColumnusTables ?? opts?.includeStudioTables ?? false;\n const includeSpacesTable = opts?.includeSpacesTable ?? true;\n const includeManifestTable = opts?.includeManifestTable ?? true;\n const includeAuditTable = opts?.includeAuditTable ?? true;\n const includeDisplayValuesTable = opts?.includeDisplayValuesTable ?? true;\n const userTables = [...manifest.tables].sort((a, b) => a.name.localeCompare(b.name));\n const userBody = userTables.map((t) => ` ${t.name}: ${renderTable(t)},`).join(\"\\n\");\n let body: string;\n if (includeColumnusTables) {\n const columnusSource = columnusTablesSource({\n includeSpacesTable,\n includeManifestTable,\n includeAuditTable,\n includeDisplayValuesTable,\n });\n body = userBody ? `${userBody}\\n${columnusSource}` : columnusSource;\n } else {\n body = userBody || \"\";\n }\n\n const banner = includeColumnusTables ? BANNER : CONSUMER_BANNER;\n const schemaBody = body ? `${body}\\n` : \"\";\n\n return `${banner}import { defineSchema, defineTable } from \"convex/server\";\nimport { v } from \"convex/values\";\n\nexport default defineSchema({\n${schemaBody}});\n`;\n}\n\nfunction renderTable(t: Table): string {\n const fieldsBlock = t.fields.length\n ? `{\\n${t.fields\n .map((f) => {\n const inner = renderType(f.type);\n const value = f.optional ? `v.optional(${inner})` : inner;\n return ` ${f.name}: ${value},`;\n })\n .join(\"\\n\")}\\n }`\n : `{}`;\n\n let out = `defineTable(${fieldsBlock})`;\n // When a table has exactly one index (and no search indexes), emit it on\n // the same line as defineTable(...) — that matches what biome's formatter\n // produces, so `schema.ts` doesn't fail pre-commit format checks after\n // every regeneration.\n const inlineSingleIndex = t.indexes.length === 1 && t.searchIndexes.length === 0;\n for (const idx of t.indexes) {\n const cols = idx.fields.map((c) => JSON.stringify(c)).join(\", \");\n const sep = inlineSingleIndex ? \"\" : \"\\n \";\n out += `${sep}.index(${JSON.stringify(idx.name)}, [${cols}])`;\n }\n for (const sx of t.searchIndexes) {\n const cfg: string[] = [`searchField: ${JSON.stringify(sx.searchField)}`];\n if (sx.filterFields && sx.filterFields.length > 0) {\n cfg.push(`filterFields: [${sx.filterFields.map((c) => JSON.stringify(c)).join(\", \")}]`);\n }\n out += `\\n .searchIndex(${JSON.stringify(sx.name)}, { ${cfg.join(\", \")} })`;\n }\n return out;\n}\n\nfunction renderType(t: FieldType): string {\n switch (t.kind) {\n case \"string\":\n case \"markdown\":\n return \"v.string()\";\n case \"number\":\n return \"v.number()\";\n case \"date\":\n case \"datetime\":\n return \"v.number()\";\n case \"boolean\":\n return \"v.boolean()\";\n case \"bigint\":\n return \"v.int64()\";\n case \"null\":\n return \"v.null()\";\n case \"any\":\n return \"v.any()\";\n case \"bytes\":\n return \"v.bytes()\";\n case \"file\":\n case \"image\":\n return 'v.id(\"_storage\")';\n case \"id\":\n return `v.id(${JSON.stringify(t.table)})`;\n case \"literal\":\n return `v.literal(${JSON.stringify(t.value)})`;\n case \"array\":\n return `v.array(${renderType(t.element)})`;\n case \"object\": {\n if (t.fields.length === 0) return `v.object({})`;\n const inner = t.fields\n .map((f: Field) => {\n const value = f.optional ? `v.optional(${renderType(f.type)})` : renderType(f.type);\n return `${f.name}: ${value}`;\n })\n .join(\", \");\n return `v.object({ ${inner} })`;\n }\n case \"union\":\n return `v.union(${t.options.map(renderType).join(\", \")})`;\n }\n // Convex's typecheck doesn't prove the switch is exhaustive (the discriminant\n // is recursive via Field[]), so add an explicit guard.\n throw new Error(`unknown field kind: ${(t as { kind: string }).kind}`);\n}\n"]}
@@ -0,0 +1,74 @@
1
+ import type { Field, FieldType, Manifest, Table } from "./schemaTypes.ts";
2
+ export declare const SHRINK_IMPACT_CAP = 500;
3
+ export declare const SHRINK_CLEANUP_PAGE_SIZE = 100;
4
+ export type ShrinkImpactItem = {
5
+ kind: "table" | "field";
6
+ table: string;
7
+ field?: string;
8
+ count: number;
9
+ capped: boolean;
10
+ };
11
+ export type ShrinkImpactPreview = {
12
+ items: ShrinkImpactItem[];
13
+ requiresConfirmation: boolean;
14
+ };
15
+ export type TemplateRefWarning = {
16
+ table: string;
17
+ kind: "id" | "preview";
18
+ fields: string[];
19
+ };
20
+ export type SchemaShrinkPlan = {
21
+ removedTables: string[];
22
+ removedFields: Map<string, string[]>;
23
+ };
24
+ export type CleanupStats = {
25
+ rowsDeleted: number;
26
+ fieldsStripped: number;
27
+ storageDeleted: number;
28
+ };
29
+ export type CleanupTask = {
30
+ kind: "delete_table";
31
+ table: string;
32
+ } | {
33
+ kind: "strip_field";
34
+ table: string;
35
+ field: string;
36
+ fieldType: FieldType;
37
+ };
38
+ /** Shrink cleanup progress before a BFF operation identity is attached. */
39
+ export type CleanupProgress = {
40
+ targetManifestJson: string;
41
+ beforeManifestJson: string;
42
+ tasks: CleanupTask[];
43
+ taskIndex: number;
44
+ cursor: string | null;
45
+ stats: CleanupStats;
46
+ };
47
+ /** Cleanup scheduled under a BFF deploy lease — identity is always present. */
48
+ export type CleanupState = CleanupProgress & {
49
+ bffOperationId: string;
50
+ desiredManifestHash: string;
51
+ };
52
+ export declare function attachBffCleanupIdentity(state: CleanupProgress, identity: {
53
+ bffOperationId: string;
54
+ desiredManifestHash: string;
55
+ }): CleanupState;
56
+ export declare function computeShrinkPlan(saved: Manifest, draft: Manifest): SchemaShrinkPlan;
57
+ export declare function shrinkPlanIsEmpty(plan: SchemaShrinkPlan): boolean;
58
+ export declare function normalizeManifestForShrink(manifest: Manifest, plan: SchemaShrinkPlan): Manifest;
59
+ export declare function findTemplateRefsToRemovedFields(saved: Manifest, plan: SchemaShrinkPlan): TemplateRefWarning[];
60
+ export declare function buildShrinkImpactPreview(counts: ShrinkImpactItem[]): ShrinkImpactPreview;
61
+ export declare function formatShrinkImpactLine(item: ShrinkImpactItem): string;
62
+ export declare function buildCleanupTasks(saved: Manifest, plan: SchemaShrinkPlan): CleanupTask[];
63
+ export declare function savedTableByName(saved: Manifest, tableName: string): Table | undefined;
64
+ export declare function fieldByName(table: Table, fieldName: string): Field | undefined;
65
+ export declare function emptyCleanupStats(): CleanupStats;
66
+ export declare function createCleanupState(targetManifestJson: string, beforeManifestJson: string, saved: Manifest, plan: SchemaShrinkPlan): CleanupProgress;
67
+ export type PreparedShrinkSave = {
68
+ plan: SchemaShrinkPlan;
69
+ normalized: Manifest;
70
+ normalizedJson: string;
71
+ cleanupState: CleanupProgress | null;
72
+ };
73
+ /** Plan shrink, normalize indexes, and build cleanup state when rows must be cleaned. */
74
+ export declare function prepareShrinkSave(saved: Manifest, draft: Manifest, beforeManifestJson?: string): PreparedShrinkSave;
@@ -0,0 +1,132 @@
1
+ // packages/@columnus/shared/src/schemaShrink.ts
2
+ var SHRINK_IMPACT_CAP = 500;
3
+ var SHRINK_CLEANUP_PAGE_SIZE = 100;
4
+ function attachBffCleanupIdentity(state, identity) {
5
+ return { ...state, ...identity };
6
+ }
7
+ var ROW_FIELD_REF = /\brow\.([A-Za-z_][A-Za-z0-9_]*)\b/g;
8
+ function computeShrinkPlan(saved, draft) {
9
+ const savedTables = new Map(saved.tables.map((t) => [t.name, t]));
10
+ const draftTables = new Map(draft.tables.map((t) => [t.name, t]));
11
+ const removedTables = [];
12
+ for (const name of savedTables.keys()) {
13
+ if (!draftTables.has(name)) removedTables.push(name);
14
+ }
15
+ const removedFields = /* @__PURE__ */ new Map();
16
+ for (const [tableName, savedTable] of savedTables) {
17
+ const draftTable = draftTables.get(tableName);
18
+ if (!draftTable) continue;
19
+ const draftFieldNames = new Set(draftTable.fields.map((f) => f.name));
20
+ const removed = savedTable.fields.map((f) => f.name).filter((n) => !draftFieldNames.has(n));
21
+ if (removed.length > 0) removedFields.set(tableName, removed);
22
+ }
23
+ return { removedTables, removedFields };
24
+ }
25
+ function shrinkPlanIsEmpty(plan) {
26
+ return plan.removedTables.length === 0 && plan.removedFields.size === 0;
27
+ }
28
+ function normalizeManifestForShrink(manifest, plan) {
29
+ if (shrinkPlanIsEmpty(plan)) return manifest;
30
+ const removedByTable = plan.removedFields;
31
+ return {
32
+ ...manifest,
33
+ tables: manifest.tables.map((table) => {
34
+ const removed = new Set(removedByTable.get(table.name) ?? []);
35
+ if (removed.size === 0) return table;
36
+ return {
37
+ ...table,
38
+ indexes: table.indexes.filter((idx) => idx.fields.every((f) => !removed.has(f))),
39
+ searchIndexes: table.searchIndexes.filter(
40
+ (si) => !removed.has(si.searchField) && (si.filterFields ?? []).every((f) => !removed.has(f))
41
+ )
42
+ };
43
+ })
44
+ };
45
+ }
46
+ function findTemplateRefsToRemovedFields(saved, plan) {
47
+ const warnings = [];
48
+ const savedTables = new Map(saved.tables.map((t) => [t.name, t]));
49
+ for (const [tableName, removedFieldNames] of plan.removedFields) {
50
+ const table = savedTables.get(tableName);
51
+ if (!table?.displayTemplates) continue;
52
+ const removed = new Set(removedFieldNames);
53
+ for (const kind of ["id", "preview"]) {
54
+ const source = table.displayTemplates[kind];
55
+ if (!source) continue;
56
+ const refs = extractRowFieldRefs(source).filter((f) => removed.has(f));
57
+ if (refs.length > 0) warnings.push({ table: tableName, kind, fields: refs });
58
+ }
59
+ }
60
+ return warnings;
61
+ }
62
+ function extractRowFieldRefs(source) {
63
+ const found = /* @__PURE__ */ new Set();
64
+ for (const match of source.matchAll(ROW_FIELD_REF)) {
65
+ const name = match[1];
66
+ if (name) found.add(name);
67
+ }
68
+ return [...found];
69
+ }
70
+ function buildShrinkImpactPreview(counts) {
71
+ const requiresConfirmation = counts.some((item) => item.count >= 1);
72
+ return { items: counts, requiresConfirmation };
73
+ }
74
+ function formatShrinkImpactLine(item) {
75
+ const countLabel = item.capped ? `${SHRINK_IMPACT_CAP}+` : String(item.count);
76
+ if (item.kind === "table") {
77
+ return `${item.table}: ${countLabel} row${item.count === 1 && !item.capped ? "" : "s"} will be deleted`;
78
+ }
79
+ return `${item.table}.${item.field}: ${countLabel} row${item.count === 1 && !item.capped ? "" : "s"} will lose this field`;
80
+ }
81
+ function buildCleanupTasks(saved, plan) {
82
+ const savedTables = new Map(saved.tables.map((t) => [t.name, t]));
83
+ const tasks = [];
84
+ for (const table of plan.removedTables) {
85
+ tasks.push({ kind: "delete_table", table });
86
+ }
87
+ for (const [tableName, fieldNames] of plan.removedFields) {
88
+ const savedTable = savedTables.get(tableName);
89
+ if (!savedTable) continue;
90
+ for (const fieldName of fieldNames) {
91
+ const field = savedTable.fields.find((f) => f.name === fieldName);
92
+ if (!field) continue;
93
+ tasks.push({
94
+ kind: "strip_field",
95
+ table: tableName,
96
+ field: fieldName,
97
+ fieldType: field.type
98
+ });
99
+ }
100
+ }
101
+ return tasks;
102
+ }
103
+ function savedTableByName(saved, tableName) {
104
+ return saved.tables.find((t) => t.name === tableName);
105
+ }
106
+ function fieldByName(table, fieldName) {
107
+ return table.fields.find((f) => f.name === fieldName);
108
+ }
109
+ function emptyCleanupStats() {
110
+ return { rowsDeleted: 0, fieldsStripped: 0, storageDeleted: 0 };
111
+ }
112
+ function createCleanupState(targetManifestJson, beforeManifestJson, saved, plan) {
113
+ return {
114
+ targetManifestJson,
115
+ beforeManifestJson,
116
+ tasks: buildCleanupTasks(saved, plan),
117
+ taskIndex: 0,
118
+ cursor: null,
119
+ stats: emptyCleanupStats()
120
+ };
121
+ }
122
+ function prepareShrinkSave(saved, draft, beforeManifestJson = JSON.stringify(saved)) {
123
+ const plan = computeShrinkPlan(saved, draft);
124
+ const normalized = normalizeManifestForShrink(draft, plan);
125
+ const normalizedJson = JSON.stringify(normalized);
126
+ const cleanupState = shrinkPlanIsEmpty(plan) ? null : createCleanupState(normalizedJson, beforeManifestJson, saved, plan);
127
+ return { plan, normalized, normalizedJson, cleanupState };
128
+ }
129
+
130
+ export { SHRINK_CLEANUP_PAGE_SIZE, SHRINK_IMPACT_CAP, attachBffCleanupIdentity, buildCleanupTasks, buildShrinkImpactPreview, computeShrinkPlan, createCleanupState, emptyCleanupStats, fieldByName, findTemplateRefsToRemovedFields, formatShrinkImpactLine, normalizeManifestForShrink, prepareShrinkSave, savedTableByName, shrinkPlanIsEmpty };
131
+ //# sourceMappingURL=schemaShrink.js.map
132
+ //# sourceMappingURL=schemaShrink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemaShrink.ts"],"names":[],"mappings":"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","file":"schemaShrink.js","sourcesContent":["import type { Field, FieldType, Manifest, Table } from \"./schemaTypes.ts\";\n\nexport const SHRINK_IMPACT_CAP = 500;\nexport const SHRINK_CLEANUP_PAGE_SIZE = 100;\n\nexport type ShrinkImpactItem = {\n kind: \"table\" | \"field\";\n table: string;\n field?: string;\n count: number;\n capped: boolean;\n};\n\nexport type ShrinkImpactPreview = {\n items: ShrinkImpactItem[];\n requiresConfirmation: boolean;\n};\n\nexport type TemplateRefWarning = {\n table: string;\n kind: \"id\" | \"preview\";\n fields: string[];\n};\n\nexport type SchemaShrinkPlan = {\n removedTables: string[];\n removedFields: Map<string, string[]>;\n};\n\nexport type CleanupStats = {\n rowsDeleted: number;\n fieldsStripped: number;\n storageDeleted: number;\n};\n\nexport type CleanupTask =\n | { kind: \"delete_table\"; table: string }\n | { kind: \"strip_field\"; table: string; field: string; fieldType: FieldType };\n\n/** Shrink cleanup progress before a BFF operation identity is attached. */\nexport type CleanupProgress = {\n targetManifestJson: string;\n beforeManifestJson: string;\n tasks: CleanupTask[];\n taskIndex: number;\n cursor: string | null;\n stats: CleanupStats;\n};\n\n/** Cleanup scheduled under a BFF deploy lease — identity is always present. */\nexport type CleanupState = CleanupProgress & {\n bffOperationId: string;\n desiredManifestHash: string;\n};\n\nexport function attachBffCleanupIdentity(\n state: CleanupProgress,\n identity: { bffOperationId: string; desiredManifestHash: string },\n): CleanupState {\n return { ...state, ...identity };\n}\n\nconst ROW_FIELD_REF = /\\brow\\.([A-Za-z_][A-Za-z0-9_]*)\\b/g;\n\nexport function computeShrinkPlan(saved: Manifest, draft: Manifest): SchemaShrinkPlan {\n const savedTables = new Map(saved.tables.map((t) => [t.name, t]));\n const draftTables = new Map(draft.tables.map((t) => [t.name, t]));\n\n const removedTables: string[] = [];\n for (const name of savedTables.keys()) {\n if (!draftTables.has(name)) removedTables.push(name);\n }\n\n const removedFields = new Map<string, string[]>();\n for (const [tableName, savedTable] of savedTables) {\n const draftTable = draftTables.get(tableName);\n if (!draftTable) continue;\n const draftFieldNames = new Set(draftTable.fields.map((f) => f.name));\n const removed = savedTable.fields.map((f) => f.name).filter((n) => !draftFieldNames.has(n));\n if (removed.length > 0) removedFields.set(tableName, removed);\n }\n\n return { removedTables, removedFields };\n}\n\nexport function shrinkPlanIsEmpty(plan: SchemaShrinkPlan): boolean {\n return plan.removedTables.length === 0 && plan.removedFields.size === 0;\n}\n\nexport function normalizeManifestForShrink(manifest: Manifest, plan: SchemaShrinkPlan): Manifest {\n if (shrinkPlanIsEmpty(plan)) return manifest;\n\n const removedByTable = plan.removedFields;\n return {\n ...manifest,\n tables: manifest.tables.map((table) => {\n const removed = new Set(removedByTable.get(table.name) ?? []);\n if (removed.size === 0) return table;\n return {\n ...table,\n indexes: table.indexes.filter((idx) => idx.fields.every((f) => !removed.has(f))),\n searchIndexes: table.searchIndexes.filter(\n (si) =>\n !removed.has(si.searchField) && (si.filterFields ?? []).every((f) => !removed.has(f)),\n ),\n };\n }),\n };\n}\n\nexport function findTemplateRefsToRemovedFields(\n saved: Manifest,\n plan: SchemaShrinkPlan,\n): TemplateRefWarning[] {\n const warnings: TemplateRefWarning[] = [];\n const savedTables = new Map(saved.tables.map((t) => [t.name, t]));\n\n for (const [tableName, removedFieldNames] of plan.removedFields) {\n const table = savedTables.get(tableName);\n if (!table?.displayTemplates) continue;\n const removed = new Set(removedFieldNames);\n for (const kind of [\"id\", \"preview\"] as const) {\n const source = table.displayTemplates[kind];\n if (!source) continue;\n const refs = extractRowFieldRefs(source).filter((f) => removed.has(f));\n if (refs.length > 0) warnings.push({ table: tableName, kind, fields: refs });\n }\n }\n\n return warnings;\n}\n\nfunction extractRowFieldRefs(source: string): string[] {\n const found = new Set<string>();\n for (const match of source.matchAll(ROW_FIELD_REF)) {\n const name = match[1];\n if (name) found.add(name);\n }\n return [...found];\n}\n\nexport function buildShrinkImpactPreview(counts: ShrinkImpactItem[]): ShrinkImpactPreview {\n const requiresConfirmation = counts.some((item) => item.count >= 1);\n return { items: counts, requiresConfirmation };\n}\n\nexport function formatShrinkImpactLine(item: ShrinkImpactItem): string {\n const countLabel = item.capped ? `${SHRINK_IMPACT_CAP}+` : String(item.count);\n if (item.kind === \"table\") {\n return `${item.table}: ${countLabel} row${item.count === 1 && !item.capped ? \"\" : \"s\"} will be deleted`;\n }\n return `${item.table}.${item.field}: ${countLabel} row${item.count === 1 && !item.capped ? \"\" : \"s\"} will lose this field`;\n}\n\nexport function buildCleanupTasks(saved: Manifest, plan: SchemaShrinkPlan): CleanupTask[] {\n const savedTables = new Map(saved.tables.map((t) => [t.name, t]));\n const tasks: CleanupTask[] = [];\n\n for (const table of plan.removedTables) {\n tasks.push({ kind: \"delete_table\", table });\n }\n\n for (const [tableName, fieldNames] of plan.removedFields) {\n const savedTable = savedTables.get(tableName);\n if (!savedTable) continue;\n for (const fieldName of fieldNames) {\n const field = savedTable.fields.find((f) => f.name === fieldName);\n if (!field) continue;\n tasks.push({\n kind: \"strip_field\",\n table: tableName,\n field: fieldName,\n fieldType: field.type,\n });\n }\n }\n\n return tasks;\n}\n\nexport function savedTableByName(saved: Manifest, tableName: string): Table | undefined {\n return saved.tables.find((t) => t.name === tableName);\n}\n\nexport function fieldByName(table: Table, fieldName: string): Field | undefined {\n return table.fields.find((f) => f.name === fieldName);\n}\n\nexport function emptyCleanupStats(): CleanupStats {\n return { rowsDeleted: 0, fieldsStripped: 0, storageDeleted: 0 };\n}\n\nexport function createCleanupState(\n targetManifestJson: string,\n beforeManifestJson: string,\n saved: Manifest,\n plan: SchemaShrinkPlan,\n): CleanupProgress {\n return {\n targetManifestJson,\n beforeManifestJson,\n tasks: buildCleanupTasks(saved, plan),\n taskIndex: 0,\n cursor: null,\n stats: emptyCleanupStats(),\n };\n}\n\nexport type PreparedShrinkSave = {\n plan: SchemaShrinkPlan;\n normalized: Manifest;\n normalizedJson: string;\n cleanupState: CleanupProgress | null;\n};\n\n/** Plan shrink, normalize indexes, and build cleanup state when rows must be cleaned. */\nexport function prepareShrinkSave(\n saved: Manifest,\n draft: Manifest,\n beforeManifestJson: string = JSON.stringify(saved),\n): PreparedShrinkSave {\n const plan = computeShrinkPlan(saved, draft);\n const normalized = normalizeManifestForShrink(draft, plan);\n const normalizedJson = JSON.stringify(normalized);\n const cleanupState = shrinkPlanIsEmpty(plan)\n ? null\n : createCleanupState(normalizedJson, beforeManifestJson, saved, plan);\n return { plan, normalized, normalizedJson, cleanupState };\n}\n"]}
@@ -0,0 +1,72 @@
1
+ /** Shared Convex validator for paginated schema-shrink cleanup state. */
2
+ export declare const cleanupStateValidator: import("convex/values").VObject<{
3
+ desiredManifestHash: string;
4
+ targetManifestJson: string;
5
+ beforeManifestJson: string;
6
+ tasks: ({
7
+ table: string;
8
+ kind: "delete_table";
9
+ } | {
10
+ field: string;
11
+ table: string;
12
+ kind: "strip_field";
13
+ fieldType: any;
14
+ })[];
15
+ taskIndex: number;
16
+ cursor: string | null;
17
+ stats: {
18
+ rowsDeleted: number;
19
+ fieldsStripped: number;
20
+ storageDeleted: number;
21
+ };
22
+ bffOperationId: string;
23
+ }, {
24
+ targetManifestJson: import("convex/values").VString<string, "required">;
25
+ beforeManifestJson: import("convex/values").VString<string, "required">;
26
+ tasks: import("convex/values").VArray<({
27
+ table: string;
28
+ kind: "delete_table";
29
+ } | {
30
+ field: string;
31
+ table: string;
32
+ kind: "strip_field";
33
+ fieldType: any;
34
+ })[], import("convex/values").VUnion<{
35
+ table: string;
36
+ kind: "delete_table";
37
+ } | {
38
+ field: string;
39
+ table: string;
40
+ kind: "strip_field";
41
+ fieldType: any;
42
+ }, [import("convex/values").VObject<{
43
+ table: string;
44
+ kind: "delete_table";
45
+ }, {
46
+ kind: import("convex/values").VLiteral<"delete_table", "required">;
47
+ table: import("convex/values").VString<string, "required">;
48
+ }, "required", "table" | "kind">, import("convex/values").VObject<{
49
+ field: string;
50
+ table: string;
51
+ kind: "strip_field";
52
+ fieldType: any;
53
+ }, {
54
+ kind: import("convex/values").VLiteral<"strip_field", "required">;
55
+ table: import("convex/values").VString<string, "required">;
56
+ field: import("convex/values").VString<string, "required">;
57
+ fieldType: import("convex/values").VAny<any, "required", string>;
58
+ }, "required", "field" | "table" | "kind" | "fieldType" | `fieldType.${string}`>], "required", "field" | "table" | "kind" | "fieldType" | `fieldType.${string}`>, "required">;
59
+ taskIndex: import("convex/values").VFloat64<number, "required">;
60
+ cursor: import("convex/values").VUnion<string | null, [import("convex/values").VString<string, "required">, import("convex/values").VNull<null, "required">], "required", never>;
61
+ stats: import("convex/values").VObject<{
62
+ rowsDeleted: number;
63
+ fieldsStripped: number;
64
+ storageDeleted: number;
65
+ }, {
66
+ rowsDeleted: import("convex/values").VFloat64<number, "required">;
67
+ fieldsStripped: import("convex/values").VFloat64<number, "required">;
68
+ storageDeleted: import("convex/values").VFloat64<number, "required">;
69
+ }, "required", "rowsDeleted" | "fieldsStripped" | "storageDeleted">;
70
+ bffOperationId: import("convex/values").VString<string, "required">;
71
+ desiredManifestHash: import("convex/values").VString<string, "required">;
72
+ }, "required", "desiredManifestHash" | "targetManifestJson" | "beforeManifestJson" | "tasks" | "taskIndex" | "cursor" | "stats" | "bffOperationId" | "stats.rowsDeleted" | "stats.fieldsStripped" | "stats.storageDeleted">;
@@ -0,0 +1,31 @@
1
+ import { v } from 'convex/values';
2
+
3
+ // packages/@columnus/shared/src/schemaShrinkValidators.ts
4
+ var cleanupStateValidator = v.object({
5
+ targetManifestJson: v.string(),
6
+ beforeManifestJson: v.string(),
7
+ tasks: v.array(
8
+ v.union(
9
+ v.object({ kind: v.literal("delete_table"), table: v.string() }),
10
+ v.object({
11
+ kind: v.literal("strip_field"),
12
+ table: v.string(),
13
+ field: v.string(),
14
+ fieldType: v.any()
15
+ })
16
+ )
17
+ ),
18
+ taskIndex: v.number(),
19
+ cursor: v.union(v.string(), v.null()),
20
+ stats: v.object({
21
+ rowsDeleted: v.number(),
22
+ fieldsStripped: v.number(),
23
+ storageDeleted: v.number()
24
+ }),
25
+ bffOperationId: v.string(),
26
+ desiredManifestHash: v.string()
27
+ });
28
+
29
+ export { cleanupStateValidator };
30
+ //# sourceMappingURL=schemaShrinkValidators.js.map
31
+ //# sourceMappingURL=schemaShrinkValidators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemaShrinkValidators.ts"],"names":[],"mappings":";;;AAGO,IAAM,qBAAA,GAAwB,EAAE,MAAA,CAAO;AAAA,EAC5C,kBAAA,EAAoB,EAAE,MAAA,EAAO;AAAA,EAC7B,kBAAA,EAAoB,EAAE,MAAA,EAAO;AAAA,EAC7B,OAAO,CAAA,CAAE,KAAA;AAAA,IACP,CAAA,CAAE,KAAA;AAAA,MACA,CAAA,CAAE,MAAA,CAAO,EAAE,IAAA,EAAM,CAAA,CAAE,OAAA,CAAQ,cAAc,CAAA,EAAG,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,EAAG,CAAA;AAAA,MAC/D,EAAE,MAAA,CAAO;AAAA,QACP,IAAA,EAAM,CAAA,CAAE,OAAA,CAAQ,aAAa,CAAA;AAAA,QAC7B,KAAA,EAAO,EAAE,MAAA,EAAO;AAAA,QAChB,KAAA,EAAO,EAAE,MAAA,EAAO;AAAA,QAChB,SAAA,EAAW,EAAE,GAAA;AAAI,OAClB;AAAA;AACH,GACF;AAAA,EACA,SAAA,EAAW,EAAE,MAAA,EAAO;AAAA,EACpB,MAAA,EAAQ,EAAE,KAAA,CAAM,CAAA,CAAE,QAAO,EAAG,CAAA,CAAE,MAAM,CAAA;AAAA,EACpC,KAAA,EAAO,EAAE,MAAA,CAAO;AAAA,IACd,WAAA,EAAa,EAAE,MAAA,EAAO;AAAA,IACtB,cAAA,EAAgB,EAAE,MAAA,EAAO;AAAA,IACzB,cAAA,EAAgB,EAAE,MAAA;AAAO,GAC1B,CAAA;AAAA,EACD,cAAA,EAAgB,EAAE,MAAA,EAAO;AAAA,EACzB,mBAAA,EAAqB,EAAE,MAAA;AACzB,CAAC","file":"schemaShrinkValidators.js","sourcesContent":["import { v } from \"convex/values\";\n\n/** Shared Convex validator for paginated schema-shrink cleanup state. */\nexport const cleanupStateValidator = v.object({\n targetManifestJson: v.string(),\n beforeManifestJson: v.string(),\n tasks: v.array(\n v.union(\n v.object({ kind: v.literal(\"delete_table\"), table: v.string() }),\n v.object({\n kind: v.literal(\"strip_field\"),\n table: v.string(),\n field: v.string(),\n fieldType: v.any(),\n }),\n ),\n ),\n taskIndex: v.number(),\n cursor: v.union(v.string(), v.null()),\n stats: v.object({\n rowsDeleted: v.number(),\n fieldsStripped: v.number(),\n storageDeleted: v.number(),\n }),\n bffOperationId: v.string(),\n desiredManifestHash: v.string(),\n});\n"]}