zitejs 0.9.105 → 0.9.106

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.
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const lib_js_1 = require("./lib.js");
5
+ const sdkNames_js_1 = require("./sdkNames.js");
6
+ // `generateSchema` warns on every rename; silence it so the suite stays
7
+ // readable, and assert on the emitted names instead.
8
+ (0, vitest_1.beforeEach)(() => {
9
+ vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
10
+ });
11
+ (0, vitest_1.afterEach)(() => {
12
+ vitest_1.vi.restoreAllMocks();
13
+ });
14
+ const field = (id, name) => ({ id, name, type: "single_line_text", order: 0 });
15
+ const database = (tables) => ({
16
+ id: "base_1",
17
+ name: "Base",
18
+ tables,
19
+ createdAt: "",
20
+ updatedAt: "",
21
+ url: "",
22
+ });
23
+ /** Every key in the emitted `export const zite = { … }` literal. */
24
+ const ziteKeys = (source) => {
25
+ const body = source.slice(source.indexOf("export const zite = {"));
26
+ return [...body.matchAll(/^ {2}([A-Za-z_$][\w$]*):/gm)].map((m) => m[1]);
27
+ };
28
+ /** Every property key on one emitted record type. */
29
+ const recordTypeKeys = (source, typeName) => {
30
+ const start = source.indexOf(`export type ${typeName} = {`);
31
+ const body = source.slice(start, source.indexOf("};", start));
32
+ return [...body.matchAll(/^ {2}([A-Za-z_$][\w$]*)\??:/gm)].map((m) => m[1]);
33
+ };
34
+ (0, vitest_1.describe)("reserved platform accessors", () => {
35
+ // Sudzy Dashboard: a table named "Notifications" emitted a second
36
+ // `notifications:` key, and the platform client — written last — won. The
37
+ // table lost findAll and typed as `{ create(NotificationsCreateParams) }`.
38
+ (0, vitest_1.it)("moves a table off the notifications accessor", () => {
39
+ const schema = (0, lib_js_1.generateSchema)(database([{ id: "tbl_1", name: "Notifications", fields: [] }]));
40
+ (0, vitest_1.expect)(schema.tables[0].sdkName).toBe("notifications2");
41
+ const keys = ziteKeys((0, lib_js_1.generateDbTs)(schema));
42
+ (0, vitest_1.expect)(keys).toContain("notifications2");
43
+ (0, vitest_1.expect)(keys.filter((k) => k === "notifications")).toHaveLength(1);
44
+ (0, vitest_1.expect)(new Set(keys).size).toBe(keys.length);
45
+ });
46
+ vitest_1.it.each(["sql", "auth", "notifications"])("keeps the platform %s accessor for the platform", (reserved) => {
47
+ const schema = (0, lib_js_1.generateSchema)(database([{ id: "tbl_1", name: reserved, fields: [] }]));
48
+ (0, vitest_1.expect)(schema.tables[0].sdkName).toBe(`${reserved}2`);
49
+ const keys = ziteKeys((0, lib_js_1.generateDbTs)(schema));
50
+ (0, vitest_1.expect)(new Set(keys).size).toBe(keys.length);
51
+ });
52
+ vitest_1.it.each(["__proto__", "constructor", "prototype"])("refuses %s as a table accessor", (hazard) => {
53
+ const schema = (0, lib_js_1.generateSchema)(database([{ id: "tbl_1", name: hazard, fields: [] }]));
54
+ (0, vitest_1.expect)(schema.tables[0].sdkName).not.toBe(hazard);
55
+ });
56
+ });
57
+ (0, vitest_1.describe)("collision de-duplication", () => {
58
+ // Nevada Car Coalition: 1.0's generator suffixed colliding names, so the app
59
+ // was written against `category1` / `sponsor1`. 2.0 had no accumulator at
60
+ // all, so the second field silently overwrote the first.
61
+ (0, vitest_1.it)("keeps both fields when two display names normalize alike", () => {
62
+ const schema = (0, lib_js_1.generateSchema)(database([
63
+ {
64
+ id: "tbl_1",
65
+ name: "K9 Winners",
66
+ fields: [field("fld_1", "Category"), field("fld_2", "category")],
67
+ },
68
+ ]));
69
+ const names = schema.tables[0].fields.map((f) => f.sdkName);
70
+ (0, vitest_1.expect)(names).toEqual(["category", "category2"]);
71
+ const keys = recordTypeKeys((0, lib_js_1.generateDbTs)(schema), "K9WinnersRecordType");
72
+ (0, vitest_1.expect)(keys).toEqual(["id", "category", "category2"]);
73
+ });
74
+ (0, vitest_1.it)("de-duplicates two tables that normalize alike", () => {
75
+ const schema = (0, lib_js_1.generateSchema)(database([
76
+ { id: "tbl_1", name: "Orders", fields: [] },
77
+ { id: "tbl_2", name: "orders", fields: [] },
78
+ ]));
79
+ (0, vitest_1.expect)(schema.tables.map((t) => t.sdkName)).toEqual(["orders", "orders2"]);
80
+ });
81
+ // Two sdkNames sharing a PascalCase form emit `FooRecordType` twice, which is
82
+ // a duplicate identifier even though the accessors differ.
83
+ (0, vitest_1.it)("separates tables whose class names would collide", () => {
84
+ const source = (0, lib_js_1.generateDbTs)({
85
+ tables: [
86
+ { id: "tbl_1", sdkName: "orders", fields: [] },
87
+ { id: "tbl_2", sdkName: "Orders", fields: [] },
88
+ ],
89
+ });
90
+ const declared = [...source.matchAll(/export type (\w+RecordType)/g)].map((m) => m[1]);
91
+ (0, vitest_1.expect)(new Set(declared).size).toBe(declared.length);
92
+ });
93
+ (0, vitest_1.it)("reserves id so a field named ID stays readable", () => {
94
+ const schema = (0, lib_js_1.generateSchema)(database([{ id: "tbl_1", name: "Rows", fields: [field("fld_1", "ID")] }]));
95
+ (0, vitest_1.expect)(schema.tables[0].fields[0].sdkName).toBe("id2");
96
+ (0, vitest_1.expect)(recordTypeKeys((0, lib_js_1.generateDbTs)(schema), "RowsRecordType")).toEqual([
97
+ "id",
98
+ "id2",
99
+ ]);
100
+ });
101
+ });
102
+ (0, vitest_1.describe)("name stability", () => {
103
+ const existing = {
104
+ tables: [
105
+ {
106
+ id: "tbl_1",
107
+ sdkName: "priceList",
108
+ fields: [
109
+ { id: "fld_1", sdkName: "srp", definition: { type: "number" } },
110
+ ],
111
+ },
112
+ ],
113
+ };
114
+ // Kelly: the app was written against `srp`, and the field's display name has
115
+ // drifted since. A locked name is what the app compiles against.
116
+ (0, vitest_1.it)("preserves a locked name over the one the display name would produce", () => {
117
+ const schema = (0, lib_js_1.generateSchema)(database([
118
+ {
119
+ id: "tbl_1",
120
+ name: "Price List",
121
+ fields: [field("fld_1", "SRP (Suggested Retail Price)")],
122
+ },
123
+ ]), existing);
124
+ (0, vitest_1.expect)(schema.tables[0].fields[0].sdkName).toBe("srp");
125
+ });
126
+ (0, vitest_1.it)("does not let a new field displace a locked one", () => {
127
+ const schema = (0, lib_js_1.generateSchema)(database([
128
+ {
129
+ id: "tbl_1",
130
+ name: "Price List",
131
+ // The new field's fresh name is exactly what fld_1 holds.
132
+ fields: [field("fld_2", "SRP"), field("fld_1", "Anything")],
133
+ },
134
+ ]), existing);
135
+ const byId = Object.fromEntries(schema.tables[0].fields.map((f) => [f.id, f.sdkName]));
136
+ (0, vitest_1.expect)(byId.fld_1).toBe("srp");
137
+ (0, vitest_1.expect)(byId.fld_2).toBe("srp2");
138
+ });
139
+ (0, vitest_1.it)("is stable across repeated generation", () => {
140
+ const db = database([
141
+ {
142
+ id: "tbl_1",
143
+ name: "Notifications",
144
+ fields: [field("fld_1", "Category"), field("fld_2", "category")],
145
+ },
146
+ ]);
147
+ const first = (0, lib_js_1.generateSchema)(db);
148
+ const second = (0, lib_js_1.generateSchema)(db, first);
149
+ const third = (0, lib_js_1.generateSchema)(db, second);
150
+ (0, vitest_1.expect)(second).toEqual(first);
151
+ (0, vitest_1.expect)(third).toEqual(first);
152
+ });
153
+ (0, vitest_1.it)("recomputes a name that is not a valid identifier", () => {
154
+ const schema = (0, lib_js_1.generateSchema)(database([
155
+ { id: "tbl_1", name: "Rows", fields: [field("fld_1", "Time")] },
156
+ ]), {
157
+ tables: [
158
+ {
159
+ id: "tbl_1",
160
+ sdkName: "rows",
161
+ fields: [
162
+ {
163
+ id: "fld_1",
164
+ sdkName: "timeSeconds)",
165
+ definition: { type: "number" },
166
+ },
167
+ ],
168
+ },
169
+ ],
170
+ });
171
+ (0, vitest_1.expect)(schema.tables[0].fields[0].sdkName).toBe("time");
172
+ });
173
+ });
174
+ (0, vitest_1.describe)("normalizeSchemaNames", () => {
175
+ (0, vitest_1.it)("is a no-op on a well-formed schema", () => {
176
+ const schema = {
177
+ tables: [
178
+ {
179
+ id: "tbl_1",
180
+ sdkName: "orders",
181
+ fields: [
182
+ { id: "fld_1", sdkName: "total", definition: { type: "number" } },
183
+ ],
184
+ },
185
+ ],
186
+ };
187
+ const result = (0, sdkNames_js_1.normalizeSchemaNames)(schema);
188
+ (0, vitest_1.expect)(result.renames).toEqual([]);
189
+ (0, vitest_1.expect)(result.schema).toEqual(schema);
190
+ });
191
+ // A schema committed before allocation existed. The sandbox's boot-time
192
+ // `zitejs generate` reads it with no generateSchema pass in front, so this is
193
+ // the only thing standing between it and a TS1117 it cannot build past.
194
+ (0, vitest_1.it)("repairs a committed schema that already holds the collision", () => {
195
+ const source = (0, lib_js_1.generateDbTs)({
196
+ tables: [
197
+ { id: "tbl_1", sdkName: "notifications", fields: [] },
198
+ { id: "tbl_2", sdkName: "orders", fields: [] },
199
+ ],
200
+ });
201
+ const keys = ziteKeys(source);
202
+ (0, vitest_1.expect)(new Set(keys).size).toBe(keys.length);
203
+ (0, vitest_1.expect)(keys).toContain("notifications2");
204
+ });
205
+ });
@@ -0,0 +1,2 @@
1
+ export { createCaller } from '../caller/index.js';
2
+ export type { EndpointConfig } from '../caller/index.js';
@@ -0,0 +1 @@
1
+ export { createCaller } from '../caller/index.js';
package/dist/esm/cli.js CHANGED
File without changes
@@ -0,0 +1,2 @@
1
+ export { createTableClient } from '../runtime/index.js';
2
+ export type { TableClient } from '../runtime/index.js';
@@ -0,0 +1 @@
1
+ export { createTableClient } from '../runtime/index.js';
@@ -14,18 +14,7 @@ export type ZiteSchemaTable = {
14
14
  export type ZiteSchema = {
15
15
  tables: ZiteSchemaTable[];
16
16
  };
17
- export declare function toPascalCase(name: string): string;
18
- export declare function toCamelCase(name: string): string;
19
- /**
20
- * camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
21
- * "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
22
- *
23
- * Deliberately not folded into toCamelCase: that also derives endpoint
24
- * identifiers from existing filenames on every generate, where normalizing
25
- * would rename a working app's `api.sendSMS`. This is only for names being
26
- * chosen for the first time — generateSchema preserves existing sdkNames.
27
- */
28
- export declare function toSdkName(name: string): string;
17
+ export { toPascalCase, toCamelCase, toSdkName } from "./sdkNames.js";
29
18
  /**
30
19
  * Build a ZiteSchema from a Database API response.
31
20
  *
@@ -39,7 +28,7 @@ export declare function generateSchema(database: Database, existingSchema?: Zite
39
28
  * Generate .zite/db.ts purely from ZiteSchema.
40
29
  * Pure function — no external data needed beyond what's in the schema file.
41
30
  */
42
- export declare function generateDbTs(schema: ZiteSchema): string;
31
+ export declare function generateDbTs(inputSchema: ZiteSchema): string;
43
32
  export type EndpointFileInfo = {
44
33
  fileName: string;
45
34
  content?: string;
@@ -1,4 +1,5 @@
1
1
  import { parse } from "@babel/parser";
2
+ import { allocateSchemaNames, describeRenames, keepValidSdkName, normalizeSchemaNames, toCamelCase, toPascalCase, toSdkName, } from "./sdkNames.js";
2
3
  const AUTH_USERS_TABLE_ID = "zite_user";
3
4
  /**
4
5
  * What a field's value looks like when a record is READ back.
@@ -170,47 +171,9 @@ const withDateFormatExample = (format) => {
170
171
  ? `"${format}" format (e.g. ${example})`
171
172
  : `"${format}" format`;
172
173
  };
173
- export function toPascalCase(name) {
174
- const pascal = name
175
- .replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
176
- .replace(/^(.)/, (_, c) => c.toUpperCase())
177
- // Drop leftover non-alphanumerics (e.g. a trailing ">" from "</p>") so the
178
- // sdkName is always a valid identifier in .zite/db.ts.
179
- .replace(/[^a-zA-Z0-9]+/g, "");
180
- if (!pascal)
181
- return "_";
182
- return /^[0-9]/.test(pascal) ? `_${pascal}` : pascal; // can't start with a digit
183
- }
184
- export function toCamelCase(name) {
185
- const pascal = toPascalCase(name);
186
- return pascal.charAt(0).toLowerCase() + pascal.slice(1);
187
- }
188
- /**
189
- * camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
190
- * "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
191
- *
192
- * Deliberately not folded into toCamelCase: that also derives endpoint
193
- * identifiers from existing filenames on every generate, where normalizing
194
- * would rename a working app's `api.sendSMS`. This is only for names being
195
- * chosen for the first time — generateSchema preserves existing sdkNames.
196
- */
197
- export function toSdkName(name) {
198
- const deAcronymed = name
199
- .replace(/([A-Z]+)([A-Z][a-z])/g, (_, run, next) => run.charAt(0) + run.slice(1).toLowerCase() + next)
200
- .replace(/([A-Z])([A-Z]+)/g, (_, first, rest) => first + rest.toLowerCase());
201
- return toCamelCase(deAcronymed);
202
- }
203
- /**
204
- * Existing sdkNames are preserved across syncs so user code keeps compiling,
205
- * but schemas written before the sanitizer stripped trailing symbols can carry
206
- * invalid identifiers (e.g. "timeSeconds)"). Keep an existing name only when
207
- * it's a valid identifier; otherwise fall through to recomputing it.
208
- */
209
- function keepValidSdkName(sdkName) {
210
- if (!sdkName)
211
- return undefined;
212
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(sdkName) ? sdkName : undefined;
213
- }
174
+ // Owned by ./sdkNames.ts (which must not import back into this module);
175
+ // re-exported so the published surface is unchanged.
176
+ export { toPascalCase, toCamelCase, toSdkName } from "./sdkNames.js";
214
177
  /**
215
178
  * `null` is how you CLEAR a cell — every scalar write schema in
216
179
  * `flexible-inputs.ts` ends in `.nullable()` and update runs with
@@ -353,7 +316,7 @@ export function generateSchema(database, existingSchema) {
353
316
  for (const t of existingSchema?.tables ?? []) {
354
317
  existingTableById.set(t.id, t);
355
318
  }
356
- const tables = [];
319
+ const drafts = [];
357
320
  for (const table of database.tables) {
358
321
  if (table.id === AUTH_USERS_TABLE_ID)
359
322
  continue;
@@ -362,23 +325,44 @@ export function generateSchema(database, existingSchema) {
362
325
  for (const f of existingTable?.fields ?? []) {
363
326
  existingFieldById.set(f.id, f);
364
327
  }
365
- const fields = [];
366
- for (const field of table.fields) {
367
- const existing = existingFieldById.get(field.id);
328
+ // `sdkName` is filled in by `allocateSchemaNames` below; the draft carries
329
+ // what each name would like to be and whether user code already depends on
330
+ // it. A name from the existing schema is locked — it is what the app is
331
+ // compiling against — and only moves if it is reserved or collides.
332
+ const fields = table.fields.map((field) => {
333
+ const existing = keepValidSdkName(existingFieldById.get(field.id)?.sdkName);
368
334
  const { id: _id, order: _order, ...definition } = field;
369
- fields.push({
370
- id: field.id,
371
- sdkName: keepValidSdkName(existing?.sdkName) ?? toSdkName(field.name),
372
- definition,
373
- });
374
- }
375
- tables.push({
376
- id: table.id,
377
- sdkName: keepValidSdkName(existingTable?.sdkName) ?? toSdkName(table.name),
378
- primaryFieldId: table.primaryFieldId,
335
+ return {
336
+ field: { id: field.id, sdkName: "", definition },
337
+ draft: {
338
+ preferred: existing ?? toSdkName(field.name),
339
+ locked: existing !== undefined,
340
+ },
341
+ };
342
+ });
343
+ const existingName = keepValidSdkName(existingTable?.sdkName);
344
+ drafts.push({
345
+ table: {
346
+ id: table.id,
347
+ sdkName: "",
348
+ primaryFieldId: table.primaryFieldId,
349
+ fields: [],
350
+ },
351
+ draft: {
352
+ preferred: existingName ?? toSdkName(table.name),
353
+ locked: existingName !== undefined,
354
+ },
379
355
  fields,
380
356
  });
381
357
  }
358
+ const { tables, renames } = allocateSchemaNames(drafts);
359
+ if (renames.length > 0) {
360
+ // Never silent: a rename means the accessor a developer would reach for is
361
+ // not the one that got emitted.
362
+ for (const line of describeRenames(renames)) {
363
+ console.warn(`[zitejs] SDK name collision resolved: ${line}`);
364
+ }
365
+ }
382
366
  return { tables };
383
367
  }
384
368
  function generateSentinelSdkTypes() {
@@ -466,8 +450,20 @@ function buildLinkTableComments(schema) {
466
450
  * Generate .zite/db.ts purely from ZiteSchema.
467
451
  * Pure function — no external data needed beyond what's in the schema file.
468
452
  */
469
- export function generateDbTs(schema) {
453
+ export function generateDbTs(inputSchema) {
470
454
  const lines = [];
455
+ // Defensive, and idempotent: a schema whose names are already unique and
456
+ // unreserved normalizes to itself. It matters for a `zite.schema.json`
457
+ // committed before allocation existed — the sandbox's boot-time
458
+ // `zitejs generate` reads that file directly, with no `generateSchema` pass
459
+ // in front of it, and would otherwise emit an object literal with a
460
+ // duplicate key (TS1117) that no build can recover from.
461
+ const { schema, renames } = normalizeSchemaNames(inputSchema);
462
+ if (renames.length > 0) {
463
+ for (const line of describeRenames(renames)) {
464
+ console.warn(`[zitejs] Repaired SDK name in zite.schema.json: ${line}`);
465
+ }
466
+ }
471
467
  const tables = schema.tables.filter((table) => table.id !== AUTH_USERS_TABLE_ID);
472
468
  lines.push("// Auto-generated by zitejs generate. Do not edit manually.");
473
469
  lines.push("//");
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Allocation of the identifiers `generateDbTs` emits.
3
+ *
4
+ * Every accessor on the generated `zite` object, and every field key on a
5
+ * record type, has to be unique — and `generateSchema` used to choose them with
6
+ * `toSdkName` and no memory at all. Two consequences, both seen in the wild:
7
+ *
8
+ * - A table named "Notifications" allocated `notifications`, which
9
+ * `generateDbTs` also emits for the platform's notifications client. The
10
+ * sentinel is written last, so it won: the table lost its client entirely
11
+ * and typed as `{ create(params: NotificationsCreateParams) }`.
12
+ * - Two fields whose display names normalize alike both claimed one accessor,
13
+ * and the second silently overwrote the first in the emitted type. No
14
+ * error, no diagnostic — just a column you could no longer read. Zite 1.0's
15
+ * generator de-duplicated with numeric suffixes; 2.0 dropped that.
16
+ *
17
+ * `allocateSchemaNames` is idempotent: a schema whose names are already unique
18
+ * and unreserved allocates to itself. That is what lets `generateDbTs` run it
19
+ * defensively over its input — a schema file written before this existed
20
+ * repairs itself on the next generate instead of emitting TypeScript that
21
+ * cannot compile.
22
+ */
23
+ import type { ZiteSchema, ZiteSchemaField, ZiteSchemaTable } from "./lib.js";
24
+ export declare function toPascalCase(name: string): string;
25
+ export declare function toCamelCase(name: string): string;
26
+ /**
27
+ * camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
28
+ * "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
29
+ *
30
+ * Deliberately not folded into toCamelCase: that also derives endpoint
31
+ * identifiers from existing filenames on every generate, where normalizing
32
+ * would rename a working app's `api.sendSMS`. This is only for names being
33
+ * chosen for the first time — generateSchema preserves existing sdkNames.
34
+ */
35
+ export declare function toSdkName(name: string): string;
36
+ /**
37
+ * Accessors `generateDbTs` puts on the `zite` object itself, after the tables.
38
+ * A table that allocates one of these produces a duplicate key.
39
+ */
40
+ export declare const RESERVED_TABLE_ACCESSORS: readonly ["sql", "notifications", "auth"];
41
+ /**
42
+ * Never safe as a generated key, in any namespace. Assigning `__proto__` in an
43
+ * object literal sets the prototype rather than defining a property, and
44
+ * `constructor` / `prototype` shadow members every object already carries.
45
+ */
46
+ export declare const RESERVED_IDENTIFIERS: readonly ["__proto__", "constructor", "prototype"];
47
+ /**
48
+ * `id` is emitted by hand on every record type and filtered out of every input
49
+ * type, so a field that allocated it vanished from both. Reserving it means a
50
+ * field genuinely named "ID" gets a usable accessor instead.
51
+ */
52
+ export declare const RESERVED_FIELD_ACCESSORS: readonly ["id"];
53
+ /** A name that could not be kept, reported so a rename is never silent. */
54
+ export interface SdkNameRename {
55
+ kind: "table" | "field";
56
+ /** The table this happened in; the table itself for `kind: 'table'`. */
57
+ tableId: string;
58
+ fieldId?: string;
59
+ from: string;
60
+ to: string;
61
+ }
62
+ /**
63
+ * Existing sdkNames are preserved across syncs so user code keeps compiling,
64
+ * but a schema written before the sanitizer stripped trailing symbols can carry
65
+ * an invalid identifier (e.g. `timeSeconds)`). Keep one only when it is a valid
66
+ * identifier; otherwise the caller recomputes it from the display name.
67
+ */
68
+ export declare function keepValidSdkName(sdkName: string | undefined): string | undefined;
69
+ /** What a table/field would like to be called, and how hard it is holding on. */
70
+ interface NameDraft {
71
+ preferred: string;
72
+ /**
73
+ * True when the name is already baked into a committed schema and user code
74
+ * is compiling against it. Locked names are claimed first, so a fresh name
75
+ * can never displace one; a locked name still moves when it is reserved or
76
+ * when two locked names collide, because the alternative is a file that does
77
+ * not compile.
78
+ */
79
+ locked: boolean;
80
+ }
81
+ export interface SchemaNameDraft {
82
+ table: ZiteSchemaTable;
83
+ draft: NameDraft;
84
+ fields: Array<{
85
+ field: ZiteSchemaField;
86
+ draft: NameDraft;
87
+ }>;
88
+ }
89
+ /**
90
+ * Resolve every drafted name to a unique, unreserved one.
91
+ *
92
+ * Two passes per namespace: locked names claim first in declaration order, then
93
+ * fresh ones fill in around them. Without that ordering a new table could take
94
+ * an accessor an existing app already imports.
95
+ */
96
+ export declare function allocateSchemaNames(drafts: SchemaNameDraft[]): {
97
+ tables: ZiteSchemaTable[];
98
+ renames: SdkNameRename[];
99
+ };
100
+ /**
101
+ * Repair a schema whose names may already be unique — the idempotent case — or
102
+ * may predate allocation entirely. Everything is treated as locked: these names
103
+ * are what user code compiles against, so only a genuine conflict moves one.
104
+ */
105
+ export declare function normalizeSchemaNames(schema: ZiteSchema): {
106
+ schema: ZiteSchema;
107
+ renames: SdkNameRename[];
108
+ };
109
+ /** One line per rename, for a generator that has no logger of its own. */
110
+ export declare function describeRenames(renames: SdkNameRename[]): string[];
111
+ export {};