@pylonsync/sdk 0.3.268 → 0.3.270

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.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.3.268",
6
+ "version": "0.3.270",
7
7
  "type": "module",
8
8
  "main": "src/index.ts",
9
9
  "types": "src/index.ts",
package/src/index.ts CHANGED
@@ -43,6 +43,16 @@ export type CrdtAnnotation =
43
43
  | "movable-list"
44
44
  | "tree";
45
45
 
46
+ /**
47
+ * Insert-time default marker stored on a field definition. Apps never
48
+ * construct these directly — they come from `.default(v)` / `.defaultNow()`
49
+ * / `.owner()` on a field builder. The runtime + codegen read them.
50
+ */
51
+ export type DefaultMarker =
52
+ | { kind: "value"; value: unknown }
53
+ | { kind: "now" }
54
+ | { kind: "owner" };
55
+
46
56
  export interface FieldDefinition {
47
57
  type: FieldType;
48
58
  optional: boolean;
@@ -119,6 +129,16 @@ export interface FieldDefinition {
119
129
  * pipeline upgrades them to ciphertext.
120
130
  */
121
131
  encrypted?: boolean;
132
+ /**
133
+ * Insert-time default. Set via `.default(value)` / `.defaultNow()` /
134
+ * `.owner()` on the field builder; recorded for the runtime + codegen.
135
+ */
136
+ default?: DefaultMarker;
137
+ /**
138
+ * Allowed values for `field.enum([...])` — recorded so codegen emits a
139
+ * precise literal-union type instead of a wide `string`.
140
+ */
141
+ enumValues?: readonly string[];
122
142
  }
123
143
 
124
144
  interface FieldBuilder {
@@ -194,6 +214,16 @@ interface FieldBuilder {
194
214
  * stays unspoofable.
195
215
  */
196
216
  owner(): FieldBuilder;
217
+ /**
218
+ * Set a static insert-time default, recorded for the runtime +
219
+ * codegen. Example: `enabled: field.bool().default(true)`.
220
+ */
221
+ default(value: unknown): FieldBuilder;
222
+ /**
223
+ * Default a datetime field to insert-time `now()`. Example:
224
+ * `createdAt: field.datetime().defaultNow()`.
225
+ */
226
+ defaultNow(): FieldBuilder;
197
227
  }
198
228
 
199
229
  function createFieldBuilder(type: FieldType): FieldBuilder {
@@ -224,11 +254,13 @@ function buildField(def: FieldDefinition): FieldBuilder {
224
254
  owner() {
225
255
  // Dynamic default filled by the auth-aware pipeline; also lock
226
256
  // the field on update so ownership can't be reassigned via PATCH.
227
- return buildField({
228
- ...def,
229
- readonly: true,
230
- default: { kind: "owner" },
231
- } as FieldDefinition);
257
+ return buildField({ ...def, readonly: true, default: { kind: "owner" } });
258
+ },
259
+ default(value: unknown) {
260
+ return buildField({ ...def, default: { kind: "value", value } });
261
+ },
262
+ defaultNow() {
263
+ return buildField({ ...def, default: { kind: "now" } });
232
264
  },
233
265
  };
234
266
  }
@@ -250,6 +282,18 @@ export const field = {
250
282
  datetime: () => createFieldBuilder("datetime"),
251
283
  richtext: () => createFieldBuilder("richtext"),
252
284
  id: (target: string) => createFieldBuilder(`id(${target})`),
285
+ /**
286
+ * `field.enum(["pending", "paid", "failed"])` — stored as a string with
287
+ * allowed-values metadata so codegen emits a precise literal union
288
+ * (`"pending" | "paid" | "failed"`) instead of a wide `string`.
289
+ */
290
+ enum: (values: readonly string[]) =>
291
+ buildField({
292
+ type: "string",
293
+ optional: false,
294
+ unique: false,
295
+ enumValues: values,
296
+ }),
253
297
  };
254
298
 
255
299
  // ---------------------------------------------------------------------------
@@ -1506,124 +1550,10 @@ export const audit: Behavior = {
1506
1550
  },
1507
1551
  };
1508
1552
 
1509
- /**
1510
- * Internal sentinel apps don't construct these directly. The
1511
- * `field.X` builders gain `default(val)` / `defaultNow()` chainables
1512
- * below; this is just the shape stored on the field definition for
1513
- * the runtime to read.
1514
- */
1515
- type DefaultMarker =
1516
- | { kind: "value"; value: unknown }
1517
- | { kind: "now" }
1518
- | { kind: "owner" };
1519
-
1520
- /**
1521
- * Augment FieldBuilder with the new `default()` / `defaultNow()`
1522
- * chainables. Runtime support for actually filling these values on
1523
- * insert lands as part of v0.4.1; until then the markers are
1524
- * recorded in the manifest for tooling + the codegen layer.
1525
- */
1526
- declare module "./index" {
1527
- // (Empty — the `default*` methods are added at runtime via the
1528
- // patched buildField below. Apps see them via the FieldBuilder
1529
- // surface declared above.)
1530
- }
1531
-
1532
- // Field builder with chainable `.default()` / `.defaultNow()`. All
1533
- // other chainables (`optional`, `unique`, `crdt`, `serverOnly`,
1534
- // `readonly`) are reimplemented here to return another
1535
- // `buildFieldWithDefaults` — without this, calling `.optional()`
1536
- // after `.default()` would drop the default markers off the chain
1537
- // (codex Wave-3 review: the previous `{ ...base, default, defaultNow }`
1538
- // pattern delegated optional/unique to the original buildField which
1539
- // returned a builder lacking `.default()`). Recursion through the
1540
- // same constructor keeps the surface stable regardless of chain
1541
- // order.
1542
- function buildFieldWithDefaults(
1543
- def: FieldDefinition & {
1544
- default?: DefaultMarker;
1545
- enumValues?: readonly string[];
1546
- },
1547
- ): FieldBuilder & {
1548
- default(value: unknown): ReturnType<typeof buildFieldWithDefaults>;
1549
- defaultNow(): ReturnType<typeof buildFieldWithDefaults>;
1550
- owner(): ReturnType<typeof buildFieldWithDefaults>;
1551
- } {
1552
- return {
1553
- _def: def,
1554
- optional() {
1555
- return buildFieldWithDefaults({ ...def, optional: true });
1556
- },
1557
- unique() {
1558
- return buildFieldWithDefaults({ ...def, unique: true });
1559
- },
1560
- crdt(annotation) {
1561
- return buildFieldWithDefaults({ ...def, crdt: annotation });
1562
- },
1563
- serverOnly() {
1564
- return buildFieldWithDefaults({ ...def, serverOnly: true });
1565
- },
1566
- readonly() {
1567
- return buildFieldWithDefaults({ ...def, readonly: true });
1568
- },
1569
- encrypted() {
1570
- return buildFieldWithDefaults({ ...def, encrypted: true });
1571
- },
1572
- default(value: unknown) {
1573
- return buildFieldWithDefaults({
1574
- ...def,
1575
- default: { kind: "value", value },
1576
- });
1577
- },
1578
- defaultNow() {
1579
- return buildFieldWithDefaults({ ...def, default: { kind: "now" } });
1580
- },
1581
- owner() {
1582
- // Server-stamped owner: a dynamic default the auth-aware
1583
- // pipeline fills + enforces, plus `readonly` so the owner can't
1584
- // be reassigned via a later PATCH. See FieldBuilder.owner().
1585
- return buildFieldWithDefaults({
1586
- ...def,
1587
- readonly: true,
1588
- default: { kind: "owner" },
1589
- });
1590
- },
1591
- };
1592
- }
1593
- // Re-export `field` with the patched builder so callers picking up
1594
- // the new SDK get the chainables transparently. The old `field`
1595
- // surface still works — `.default()` / `.defaultNow()` are additive.
1596
- // We intentionally re-export from the same name so existing imports
1597
- // (`import { field } from "@pylonsync/sdk"`) keep working AND gain
1598
- // the new methods without a code change.
1599
- Object.assign(field, {
1600
- string: () => buildFieldWithDefaults({ type: "string", optional: false, unique: false }),
1601
- int: () => buildFieldWithDefaults({ type: "int", optional: false, unique: false }),
1602
- float: () => buildFieldWithDefaults({ type: "float", optional: false, unique: false }),
1603
- number: () => buildFieldWithDefaults({ type: "float", optional: false, unique: false }),
1604
- bool: () => buildFieldWithDefaults({ type: "bool", optional: false, unique: false }),
1605
- boolean: () => buildFieldWithDefaults({ type: "bool", optional: false, unique: false }),
1606
- datetime: () => buildFieldWithDefaults({ type: "datetime", optional: false, unique: false }),
1607
- richtext: () => buildFieldWithDefaults({ type: "richtext", optional: false, unique: false }),
1608
- id: (target: string) => buildFieldWithDefaults({ type: `id(${target})` as FieldType, optional: false, unique: false }),
1609
- /**
1610
- * `field.enum(["pending", "paid", "failed"])` — stored as a string
1611
- * with allowed-values metadata. Runtime enforcement (CHECK
1612
- * constraint or insert-time validation) lands in a follow-up
1613
- * patch; for now the values flow through to codegen so the
1614
- * generated client gets a precise `"pending" | "paid" | "failed"`
1615
- * literal-union type instead of a wide `string`.
1616
- */
1617
- enum(values: readonly string[]) {
1618
- const def: FieldDefinition & { enumValues?: readonly string[] } = {
1619
- type: "string",
1620
- optional: false,
1621
- unique: false,
1622
- enumValues: values,
1623
- };
1624
- return buildFieldWithDefaults(def);
1625
- },
1626
- });
1553
+ // `field` builders (`default` / `defaultNow` / `owner` / `enum`) are all
1554
+ // implemented directly on `buildField` above and typed on the FieldBuilder
1555
+ // interface, so `field.datetime().defaultNow()` and `field.enum([...])`
1556
+ // are real, statically-typed chainables no runtime augmentation needed.
1627
1557
 
1628
1558
  /** Variadic index helper — `e.idx("customer", "createdAt")` reads
1629
1559
  * better than the options-object form for the common case. */
package/src/studio.ts CHANGED
@@ -360,7 +360,7 @@ export interface StudioConfig {
360
360
  * the framework's "access denied" page (no point sending them back
361
361
  * to a login they're already past).
362
362
  *
363
- * Example: `loginUrl: "/login"` — cloud.pylonsync.com handles `/login`
363
+ * Example: `loginUrl: "/login"` — www.pylonsync.com handles `/login`
364
364
  * at the dashboard, and the user's existing session cookie lifts
365
365
  * them to admin via `auth.user.adminField` on the way back.
366
366
  */