postgresdk 0.18.30 → 0.19.0

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 postgresdk contributors
3
+ Copyright (c) 2026 postgresdk contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -55,6 +55,7 @@ const filtered = await sdk.users.list({
55
55
  - ✅ **Runtime Validation** - Zod schemas for request/response validation
56
56
  - 🔗 **Smart Relationships** - Automatic handling of 1:N and M:N relationships with eager loading
57
57
  - 🔍 **Vector Search** - Built-in pgvector support for similarity search with multiple distance metrics
58
+ - ⚡ **Atomic Transactions** - Execute multiple operations atomically via `sdk.$transaction([...])`
58
59
  - 🔐 **Built-in Auth** - API key and JWT authentication
59
60
  - 🎯 **Zero Config** - Works out of the box with sensible defaults
60
61
  - 📦 **Lightweight** - Minimal dependencies, optimized bundle size
@@ -124,7 +125,7 @@ const sdk = new SDK({ baseUrl: "http://localhost:3000" });
124
125
  const user = await sdk.users.create({ name: "Alice", email: "alice@example.com" });
125
126
  const users = await sdk.users.list({ include: { posts: true } });
126
127
  await sdk.users.update(user.id, { name: "Alice Smith" });
127
- await sdk.users.delete(user.id);
128
+ await sdk.users.hardDelete(user.id);
128
129
  ```
129
130
 
130
131
  ---
@@ -145,10 +146,12 @@ export default {
145
146
  // Optional (with defaults)
146
147
  schema: "public", // Database schema to introspect
147
148
  outDir: "./api", // Output directory (or { client: "./sdk", server: "./api" })
148
- softDeleteColumn: null, // Column name for soft deletes (e.g., "deleted_at")
149
- softDeleteColumnOverrides: { // Per-table overrides (null = disable soft delete for that table)
150
- // captures: "hidden_at", // different column name for a specific table
151
- // audit_logs: null, // hard deletes only for this table
149
+ delete: { // Soft/hard delete configuration (optional)
150
+ softDeleteColumn: "deleted_at", // Column name for soft deletes (omit = hard deletes only)
151
+ exposeHardDelete: true, // Also expose hardDelete() set false to disable (default: true)
152
+ softDeleteColumnOverrides: { // Per-table overrides
153
+ // audit_logs: null, // hard deletes only for this table
154
+ },
152
155
  },
153
156
  numericMode: "auto", // "auto" | "number" | "string" - How to type numeric columns
154
157
  includeMethodsDepth: 2, // Max depth for nested includes
@@ -567,8 +570,50 @@ const users = result.data; // Array of users
567
570
  // Update
568
571
  const updated = await sdk.users.update(123, { name: "Robert" });
569
572
 
573
+ // Upsert — insert if no conflict, update otherwise (Prisma-style)
574
+ const upserted = await sdk.users.upsert({
575
+ where: { email: "alice@example.com" }, // conflict target (must be a unique constraint)
576
+ create: { email: "alice@example.com", name: "Alice" },
577
+ update: { name: "Alice Updated" },
578
+ });
579
+
570
580
  // Delete
571
- const deleted = await sdk.users.delete(123);
581
+ const deleted = await sdk.users.hardDelete(123); // permanent deletion
582
+ // await sdk.users.softDelete(123); // soft-delete (when softDeleteColumn is configured)
583
+ ```
584
+
585
+ #### Atomic Transactions
586
+
587
+ Execute multiple operations in a single PostgreSQL transaction — all succeed or all roll back:
588
+
589
+ ```typescript
590
+ const [order, updatedUser] = await sdk.$transaction([
591
+ sdk.orders.$create({ user_id: user.id, total: 99 }),
592
+ sdk.users.$update(user.id, { last_order_at: new Date().toISOString() }),
593
+ ]);
594
+ // TypeScript infers: [SelectOrders, SelectUsers | null]
595
+ ```
596
+
597
+ - `$create`, `$update`, `$delete`, `$upsert` are **lazy builders** — nothing executes until `$transaction` is called
598
+ - All ops are Zod-validated **before** `BEGIN` is issued (fail-fast, no partial state)
599
+ - On any failure the transaction rolls back; an error is thrown with a `.failedAt` index
600
+
601
+ ```typescript
602
+ try {
603
+ const results = await sdk.$transaction([
604
+ sdk.inventory.$update(itemId, { stock: newStock }),
605
+ sdk.orders.$create({ item_id: itemId, qty: 1 }),
606
+ sdk.audit_log.$create({ action: "purchase", item_id: itemId }),
607
+ // $upsert also works inside transactions:
608
+ sdk.users.$upsert({
609
+ where: { email: "alice@example.com" },
610
+ create: { email: "alice@example.com", name: "Alice" },
611
+ update: { name: "Alice Updated" },
612
+ }),
613
+ ]);
614
+ } catch (err: any) {
615
+ console.error(`Failed at op ${err.failedAt}:`, err.message);
616
+ }
572
617
  ```
573
618
 
574
619
  #### Relationships & Eager Loading
@@ -744,7 +789,13 @@ const nested = await sdk.users.list({
744
789
  }
745
790
  });
746
791
 
747
- // Soft deletes — when softDeleteColumn is configured, deleted records are hidden by default.
792
+ // Soft deletes — when `delete.softDeleteColumn` is configured in postgresdk.config.ts,
793
+ // the SDK exposes softDelete() and hardDelete() instead of a single delete():
794
+ //
795
+ // softDelete(id) → sets the soft-delete column (e.g. deleted_at = NOW())
796
+ // hardDelete(id) → permanent DELETE (available unless exposeHardDelete: false)
797
+ //
798
+ // Soft-deleted rows are hidden from list/getByPk by default.
748
799
  // Pass includeSoftDeleted: true to opt into seeing them (e.g., for admin/recovery UIs).
749
800
  const allUsers = await sdk.users.list({ includeSoftDeleted: true });
750
801
  const deletedUser = await sdk.users.getByPk("123", { includeSoftDeleted: true });
@@ -786,7 +837,7 @@ const updated = await sdk.users.update(
786
837
  );
787
838
 
788
839
  const fetched = await sdk.users.getByPk(userId, { select: ['id', 'name'] });
789
- const deleted = await sdk.users.delete(userId, { select: ['id', 'email'] });
840
+ const deleted = await sdk.users.hardDelete(userId, { select: ['id', 'email'] });
790
841
 
791
842
  // Nested select/exclude in includes
792
843
  const withNestedSelect = await sdk.authors.list({
@@ -11,4 +11,5 @@ export declare function parseExistingConfig(configPath: string): {
11
11
  raw: string;
12
12
  };
13
13
  export declare function extractConfigFields(configContent: string): ConfigField[];
14
- export declare function generateMergedConfig(existingFields: ConfigField[], mergeStrategy: "keep-existing" | "use-defaults" | "interactive", userChoices?: Map<string, any> | undefined): string;
14
+ export type MergeChoice = "keep" | "new";
15
+ export declare function generateMergedConfig(existingFields: ConfigField[], mergeStrategy: "keep-existing" | "use-defaults" | "interactive", userChoices?: Map<string, MergeChoice> | undefined): string;