zitejs 0.9.69 → 0.9.70

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.
@@ -26,8 +26,8 @@ const FIELD_TYPE_MAP = {
26
26
  single_select: "string",
27
27
  multiple_select: "string[]",
28
28
  checkbox: "boolean",
29
- date: "string",
30
- datetime: "string",
29
+ date: "string | null",
30
+ datetime: "string | null",
31
31
  attachments: "Array<{ url: string; name?: string }>",
32
32
  linked_record: "string | string[]",
33
33
  lookup: "unknown",
@@ -54,14 +54,31 @@ const DURATION_FORMAT_EXAMPLES = {
54
54
  "h:mm:ss.sss": "1:23:03.000",
55
55
  };
56
56
  function toPascalCase(name) {
57
- return name
57
+ const pascal = name
58
58
  .replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
59
- .replace(/^(.)/, (_, c) => c.toUpperCase());
59
+ .replace(/^(.)/, (_, c) => c.toUpperCase())
60
+ // Drop leftover non-alphanumerics (e.g. a trailing ">" from "</p>") so the
61
+ // sdkName is always a valid identifier in .zite/db.ts.
62
+ .replace(/[^a-zA-Z0-9]+/g, "");
63
+ if (!pascal)
64
+ return "_";
65
+ return /^[0-9]/.test(pascal) ? `_${pascal}` : pascal; // can't start with a digit
60
66
  }
61
67
  function toCamelCase(name) {
62
68
  const pascal = toPascalCase(name);
63
69
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
64
70
  }
71
+ /**
72
+ * Existing sdkNames are preserved across syncs so user code keeps compiling,
73
+ * but schemas written before the sanitizer stripped trailing symbols can carry
74
+ * invalid identifiers (e.g. "timeSeconds)"). Keep an existing name only when
75
+ * it's a valid identifier; otherwise fall through to recomputing it.
76
+ */
77
+ function keepValidSdkName(sdkName) {
78
+ if (!sdkName)
79
+ return undefined;
80
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(sdkName) ? sdkName : undefined;
81
+ }
65
82
  function tsTypeForSchemaField(def) {
66
83
  if (def.type === "single_select" || def.type === "multiple_select") {
67
84
  const options = def.template
@@ -104,11 +121,11 @@ function fieldJsdoc(schemaField, table) {
104
121
  if (def.type === "date") {
105
122
  const tpl = def.template;
106
123
  if (tpl.dateFormat)
107
- parts.push(`Date-only field (YYYY-MM-DD string), display as "${tpl.dateFormat}" format`);
124
+ parts.push(`Date-only field (YYYY-MM-DD string), null when unset, display as "${tpl.dateFormat}" format`);
108
125
  }
109
126
  if (def.type === "datetime") {
110
127
  const tpl = def.template;
111
- const timeParts = ["Date+time field (ISO 8601 timestamp)"];
128
+ const timeParts = ["Date+time field (ISO 8601 timestamp), null when unset"];
112
129
  if (tpl.dateFormat)
113
130
  timeParts.push(`date: ${tpl.dateFormat}`);
114
131
  if (tpl.timeFormat)
@@ -192,13 +209,13 @@ function generateSchema(database, existingSchema) {
192
209
  const { id: _id, order: _order, ...definition } = field;
193
210
  fields.push({
194
211
  id: field.id,
195
- sdkName: existing?.sdkName ?? toCamelCase(field.name),
212
+ sdkName: keepValidSdkName(existing?.sdkName) ?? toCamelCase(field.name),
196
213
  definition,
197
214
  });
198
215
  }
199
216
  tables.push({
200
217
  id: table.id,
201
- sdkName: existingTable?.sdkName ?? toCamelCase(table.name),
218
+ sdkName: keepValidSdkName(existingTable?.sdkName) ?? toCamelCase(table.name),
202
219
  primaryFieldId: table.primaryFieldId,
203
220
  fields,
204
221
  });
@@ -14,8 +14,8 @@ const FIELD_TYPE_MAP = {
14
14
  single_select: "string",
15
15
  multiple_select: "string[]",
16
16
  checkbox: "boolean",
17
- date: "string",
18
- datetime: "string",
17
+ date: "string | null",
18
+ datetime: "string | null",
19
19
  attachments: "Array<{ url: string; name?: string }>",
20
20
  linked_record: "string | string[]",
21
21
  lookup: "unknown",
@@ -42,14 +42,31 @@ const DURATION_FORMAT_EXAMPLES = {
42
42
  "h:mm:ss.sss": "1:23:03.000",
43
43
  };
44
44
  export function toPascalCase(name) {
45
- return name
45
+ const pascal = name
46
46
  .replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
47
- .replace(/^(.)/, (_, c) => c.toUpperCase());
47
+ .replace(/^(.)/, (_, c) => c.toUpperCase())
48
+ // Drop leftover non-alphanumerics (e.g. a trailing ">" from "</p>") so the
49
+ // sdkName is always a valid identifier in .zite/db.ts.
50
+ .replace(/[^a-zA-Z0-9]+/g, "");
51
+ if (!pascal)
52
+ return "_";
53
+ return /^[0-9]/.test(pascal) ? `_${pascal}` : pascal; // can't start with a digit
48
54
  }
49
55
  export function toCamelCase(name) {
50
56
  const pascal = toPascalCase(name);
51
57
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
52
58
  }
59
+ /**
60
+ * Existing sdkNames are preserved across syncs so user code keeps compiling,
61
+ * but schemas written before the sanitizer stripped trailing symbols can carry
62
+ * invalid identifiers (e.g. "timeSeconds)"). Keep an existing name only when
63
+ * it's a valid identifier; otherwise fall through to recomputing it.
64
+ */
65
+ function keepValidSdkName(sdkName) {
66
+ if (!sdkName)
67
+ return undefined;
68
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(sdkName) ? sdkName : undefined;
69
+ }
53
70
  function tsTypeForSchemaField(def) {
54
71
  if (def.type === "single_select" || def.type === "multiple_select") {
55
72
  const options = def.template
@@ -92,11 +109,11 @@ function fieldJsdoc(schemaField, table) {
92
109
  if (def.type === "date") {
93
110
  const tpl = def.template;
94
111
  if (tpl.dateFormat)
95
- parts.push(`Date-only field (YYYY-MM-DD string), display as "${tpl.dateFormat}" format`);
112
+ parts.push(`Date-only field (YYYY-MM-DD string), null when unset, display as "${tpl.dateFormat}" format`);
96
113
  }
97
114
  if (def.type === "datetime") {
98
115
  const tpl = def.template;
99
- const timeParts = ["Date+time field (ISO 8601 timestamp)"];
116
+ const timeParts = ["Date+time field (ISO 8601 timestamp), null when unset"];
100
117
  if (tpl.dateFormat)
101
118
  timeParts.push(`date: ${tpl.dateFormat}`);
102
119
  if (tpl.timeFormat)
@@ -180,13 +197,13 @@ export function generateSchema(database, existingSchema) {
180
197
  const { id: _id, order: _order, ...definition } = field;
181
198
  fields.push({
182
199
  id: field.id,
183
- sdkName: existing?.sdkName ?? toCamelCase(field.name),
200
+ sdkName: keepValidSdkName(existing?.sdkName) ?? toCamelCase(field.name),
184
201
  definition,
185
202
  });
186
203
  }
187
204
  tables.push({
188
205
  id: table.id,
189
- sdkName: existingTable?.sdkName ?? toCamelCase(table.name),
206
+ sdkName: keepValidSdkName(existingTable?.sdkName) ?? toCamelCase(table.name),
190
207
  primaryFieldId: table.primaryFieldId,
191
208
  fields,
192
209
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zitejs",
3
- "version": "0.9.69",
3
+ "version": "0.9.70",
4
4
  "description": "The Zite framework — build apps on Zite Database",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",