turbine-orm 0.36.1 → 0.38.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.
@@ -20,8 +20,9 @@
20
20
  * $N params compiled through the query builders
21
21
  * • Read routes run in a READ ONLY transaction (belt-and-suspenders)
22
22
  * • Write routes (only when `--write` is set) run in a plain BEGIN/COMMIT
23
- * transaction, require a matching Origin header (CSRF), and target exactly
24
- * one row by its full primary key
23
+ * transaction, require a matching Origin header (CSRF), and address every
24
+ * row by its full primary key (single row, or a capped `rows` array of
25
+ * PK-addressed statements run atomically)
25
26
  * • 30s statement timeout via parameterized set_config()
26
27
  * • Per-session rate limiting, cross-origin refusal, security headers, and a
27
28
  * per-request CSP nonce for the inline script (no `unsafe-inline`)
@@ -30,12 +31,14 @@
30
31
  * every row-bearing response (the literal `•• redacted ••`) unless the server
31
32
  * was started with `--show-pii`.
32
33
  *
33
- * Write model (opt-in): update/insert/delete a single row. DDL and multi-row or
34
- * unconditional writes are deliberately unsupported. Use the CLI or migrate for
35
- * schema changes and bulk operations.
34
+ * Write model (opt-in): update a single row; insert/delete one row or a capped
35
+ * list of PK-addressed rows in one all-or-nothing transaction. DDL and
36
+ * predicate-based (unconditional) writes are deliberately unsupported. Use the
37
+ * CLI or migrate for schema changes and true bulk operations.
36
38
  */
37
39
  import { type IncomingMessage, type ServerResponse } from 'node:http';
38
- import pg from 'pg';
40
+ import type { PgCompatPool } from '../client.js';
41
+ import type { Dialect } from '../dialect.js';
39
42
  import type { SchemaMetadata, TableMetadata } from '../schema.js';
40
43
  export interface StudioOptions {
41
44
  url: string;
@@ -58,6 +61,13 @@ export interface StudioOptions {
58
61
  * Reveal PII-tagged column values instead of redacting them. Default `false`.
59
62
  */
60
63
  showPii?: boolean;
64
+ /**
65
+ * Boot with a seeded, in-memory sample database instead of connecting to a
66
+ * real one (no DATABASE_URL required). Backed by Turbine's own SQLite engine
67
+ * over `node:sqlite` `:memory:`; nothing is ever persisted. Enables the live
68
+ * three-mode switcher (`/api/demo/mode`). Default `false`.
69
+ */
70
+ demo?: boolean;
61
71
  }
62
72
  export interface StudioHandle {
63
73
  /** Shut down the server + pool cleanly. */
@@ -68,7 +78,14 @@ export interface StudioHandle {
68
78
  url: string;
69
79
  }
70
80
  export interface StudioContext {
71
- pool: pg.Pool;
81
+ /**
82
+ * The pg-compatible pool. A real `pg.Pool` in normal mode, a `SqlitePool`
83
+ * over an in-memory database in demo mode. Typed as the minimal
84
+ * `PgCompatPool` contract so both shapes work through one code path (pg.Pool
85
+ * satisfies it; the query builders take `pg.Pool` via a cast, matching the
86
+ * external-pool seam in client.ts).
87
+ */
88
+ pool: PgCompatPool;
72
89
  metadata: SchemaMetadata;
73
90
  options: StudioOptions;
74
91
  authToken: string;
@@ -85,11 +102,29 @@ export interface StudioContext {
85
102
  }>;
86
103
  /**
87
104
  * True when write mode is enabled (`--write`): the `/api/row/*` routes exist
88
- * and the UI renders write affordances. Absent/false → read-only.
105
+ * and the UI renders write affordances. Absent/false → read-only. In demo
106
+ * mode this is toggled live by the `/api/demo/mode` switcher.
89
107
  */
90
108
  writable?: boolean;
91
109
  /** True when PII redaction is disabled (`--show-pii`). Absent/false → redact. */
92
110
  showPii?: boolean;
111
+ /**
112
+ * True when Studio is running against the seeded in-memory demo store
113
+ * (`--demo`). Branches the handful of Postgres-specific statements onto their
114
+ * SQLite equivalents and enables the `/api/demo/mode` live switcher.
115
+ */
116
+ demo?: boolean;
117
+ /**
118
+ * SQL dialect the builder/write handlers compile against. Absent → Postgres
119
+ * (the default). Set to the SQLite dialect in demo mode.
120
+ */
121
+ dialect?: Dialect;
122
+ /**
123
+ * Demo mode only: saved queries live here instead of on disk, honoring the
124
+ * "nothing you do here is saved anywhere" promise. Absent in normal mode
125
+ * (saved queries persist to `<stateDir>/studio-queries.json`).
126
+ */
127
+ memorySavedQueries?: SavedQueriesFile;
93
128
  }
94
129
  /**
95
130
  * Start the Studio server. Returns a handle with the session token, a pre-built
@@ -102,14 +137,29 @@ export interface StudioContext {
102
137
  */
103
138
  export declare function startStudio(options: StudioOptions): Promise<StudioHandle>;
104
139
  export declare function handleRequest(req: IncomingMessage, res: ServerResponse, ctx: StudioContext): Promise<void>;
140
+ export declare function apiDemoMode(req: IncomingMessage, res: ServerResponse, ctx: StudioContext): Promise<void>;
105
141
  export declare function apiTableRows(res: ServerResponse, ctx: StudioContext, rawTableName: string, params: URLSearchParams): Promise<void>;
106
142
  export declare function resolveColumnName(table: TableMetadata, nameOrField: string): string | null;
107
143
  export declare function isTextishType(pgType: string): boolean;
108
144
  export declare function escapeLikePattern(s: string): string;
109
145
  export declare function apiBuilder(req: IncomingMessage, res: ServerResponse, ctx: StudioContext): Promise<void>;
110
146
  export declare function apiRowWrite(req: IncomingMessage, res: ServerResponse, ctx: StudioContext, op: 'update' | 'insert' | 'delete'): Promise<void>;
147
+ interface SavedQuery {
148
+ id: string;
149
+ table: string;
150
+ name: string;
151
+ /** Studio only saves visual-builder queries — there is no raw-SQL surface. */
152
+ kind: 'builder';
153
+ args?: unknown;
154
+ createdAt: string;
155
+ }
156
+ interface SavedQueriesFile {
157
+ version: 1;
158
+ queries: SavedQuery[];
159
+ }
111
160
  export declare function apiListSavedQueries(res: ServerResponse, ctx: StudioContext, params: URLSearchParams): void;
112
161
  export declare function apiCreateSavedQuery(req: IncomingMessage, res: ServerResponse, ctx: StudioContext): Promise<void>;
113
162
  export declare function apiDeleteSavedQuery(res: ServerResponse, ctx: StudioContext, id: string): void;
114
163
  /** The literal replacement value for a redacted PII cell. */
115
164
  export declare const PII_REDACTED = "\u2022\u2022 redacted \u2022\u2022";
165
+ export {};