lazypock 0.7.0 → 0.8.1

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/dist/index.cjs CHANGED
@@ -519,9 +519,10 @@ var CollectionService = class _CollectionService {
519
519
  * const t = await client.collection("posts").select("id", "title").getList();
520
520
  * // GET /api/posts?fields=id,title
521
521
  *
522
- * // All visible fields (hidden fields are excluded server-side)
522
+ * // All visible fields (implicit system keys id/created/updated/… are
523
+ * // kept; hidden fields are excluded via the projection)
523
524
  * const all = await client.collection("posts").select("*").getList();
524
- * // GET /api/posts?fields=id,title,published,… (schema known)
525
+ * // GET /api/posts?fields=id,created,updated,collectionId,collectionName,title,published,… (schema known)
525
526
  * ```
526
527
  *
527
528
  * When no schema is known, the default (no `select()` call) sends no
@@ -554,7 +555,8 @@ var CollectionService = class _CollectionService {
554
555
  * Fields to send with reads:
555
556
  * 1. explicit `options.fields` (caller wins)
556
557
  * 2. `select()` preset
557
- * 3. schema default — all visible (non-hidden, non-system) fields
558
+ * 3. schema default — all visible (non-hidden) fields plus the implicit
559
+ * system keys (`id`, `created`, `updated`, `collectionId`, `collectionName`)
558
560
  */
559
561
  effectiveFields(optionsFields) {
560
562
  if (optionsFields !== void 0) return optionsFields;
@@ -567,15 +569,35 @@ var CollectionService = class _CollectionService {
567
569
  return this.visibleFields();
568
570
  }
569
571
  /**
570
- * All non-hidden, non-system, non-password field names from the schema.
571
- * `undefined` when no schema is available (server decides).
572
+ * All non-hidden, non-password, non-autodate field names from the schema,
573
+ * prefixed with the implicit system keys that are part of every record
574
+ * (`id`, `created`, `updated`, `collectionId`, `collectionName`).
575
+ *
576
+ * The system keys never appear in the schema (they are implied for every
577
+ * collection) but MUST be listed explicitly when projecting — the server
578
+ * applies strict projection, so unrequested fields are dropped. Without
579
+ * them, `getList`/`getOne` responses lose `id` (and `created`/`updated`),
580
+ * breaking selection, edits, and relation references.
581
+ *
582
+ * `undefined` when no schema fields are available (server decides — its
583
+ * default returns every non-password field, including the system keys).
572
584
  */
573
585
  visibleFields() {
574
586
  if (!this.schema?.fields) return void 0;
575
587
  const visible = this.schema.fields.filter(
576
588
  (f) => !f.hidden && f.type !== "password" && f.type !== "autodate"
577
589
  ).map((f) => f.name);
578
- return visible.length > 0 ? visible.join(",") : void 0;
590
+ if (visible.length === 0) return void 0;
591
+ return [
592
+ .../* @__PURE__ */ new Set([
593
+ "id",
594
+ "created",
595
+ "updated",
596
+ "collectionId",
597
+ "collectionName",
598
+ ...visible
599
+ ])
600
+ ].join(",");
579
601
  }
580
602
  /** Warn once when an expand field is not a relation (schema known). */
581
603
  validateExpand(expand) {
@@ -1461,6 +1483,12 @@ function generateTypes(collections, options = {}) {
1461
1483
  body
1462
1484
  })}`
1463
1485
  );
1486
+ const createLines = fields.map((f) => createDataMemberLine(f)).filter((l) => l !== "");
1487
+ sections.push(
1488
+ `export interface ${typeName}CreateData${renderInterface({
1489
+ body: createLines.join("\n")
1490
+ })}`
1491
+ );
1464
1492
  }
1465
1493
  sections.push(`export interface AuthRecord extends BaseRecord {
1466
1494
  email: string;
@@ -1471,6 +1499,10 @@ function generateTypes(collections, options = {}) {
1471
1499
  ).join("\n");
1472
1500
  sections.push(`export interface LazypockCollections {
1473
1501
  ${mapEntries}
1502
+ }`);
1503
+ const createMapEntries = filtered.map((c) => ` "${c.name}": ${collectionTypeName(c.name)}CreateData;`).join("\n");
1504
+ sections.push(`export interface LazypockCreateData {
1505
+ ${createMapEntries}
1474
1506
  }`);
1475
1507
  const schemaEntries = collections.map(
1476
1508
  (c) => ` {
@@ -1494,6 +1526,10 @@ ${schemaEntries}
1494
1526
  * Collection access is fully type-checked:
1495
1527
  * client.collection("posts").create({ title: "x" }) // title must exist
1496
1528
  *
1529
+ * For auth collections the generated *CreateData type includes the
1530
+ * write-only password field, so creating a user is type-safe:
1531
+ * client.collection("users").create({ email, password }) // \u2713
1532
+ *
1497
1533
  * The schema snapshot is wired into the client automatically, so hidden
1498
1534
  * fields are excluded from responses and select/expand are validated.
1499
1535
  */
@@ -1508,10 +1544,16 @@ export function createClient(options: LazypockClientOptions): TypedClient {
1508
1544
  }
1509
1545
 
1510
1546
  export class TypedClient extends LazypockClient {
1511
- override collection<T extends string>(name: T): T extends keyof LazypockCollections
1512
- ? CollectionService<LazypockCollections[T]>
1513
- : CollectionService<unknown> {
1514
- return super.collection(name) as T extends keyof LazypockCollections ? CollectionService<LazypockCollections[T]> : CollectionService<unknown>;
1547
+ // K extends keyof LazypockCollections (rather than a generic string with a
1548
+ // conditional return) so the IDE suggests collection names and unknown names
1549
+ // are rejected at compile time:
1550
+ // client.collection("posts") // suggested + typed
1551
+ // client.collection("nope") // TS error
1552
+ //
1553
+ // create()/update() take the collection's *CreateData \u2014 the read model
1554
+ // omits password/hidden fields, but the write model carries them.
1555
+ override collection<K extends keyof LazypockCollections>(name: K): CollectionService<LazypockCollections[K], LazypockCreateData[K]> {
1556
+ return super.collection(name) as CollectionService<LazypockCollections[K], LazypockCreateData[K]>;
1515
1557
  }
1516
1558
  }
1517
1559
  `);
@@ -1532,6 +1574,14 @@ function memberLine(f) {
1532
1574
  if (type === "never") return "";
1533
1575
  return ` ${JSON.stringify(key)}${req}: ${type};`;
1534
1576
  }
1577
+ function createDataMemberLine(f) {
1578
+ if (f.type === "autodate") return "";
1579
+ const key = fieldKey(f.name);
1580
+ const req = f.required ? "" : "?";
1581
+ const type = f.type === "password" ? "string" : fieldTypeScriptType(f);
1582
+ if (type === "never") return "";
1583
+ return ` ${JSON.stringify(key)}${req}: ${type};`;
1584
+ }
1535
1585
 
1536
1586
  // src/lazypock.ts
1537
1587
  var LazypockClient = class {
@@ -1543,6 +1593,7 @@ var LazypockClient = class {
1543
1593
  this.collectionCache = /* @__PURE__ */ new Map();
1544
1594
  const baseUrl = options.baseUrl.replace(/\/+$/, "");
1545
1595
  this.authStore = options.authStore ?? new AuthStore(options.storage ?? memoryStorage);
1596
+ this.authReady = options.authStore ? Promise.resolve() : this.authStore.init();
1546
1597
  this.http = new HttpClient(baseUrl, this.authStore);
1547
1598
  this.realtime = options.realtime ?? new RealtimeService();
1548
1599
  if (!options.realtime) {