@aurabase/gen 0.4.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aurabase
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @aurabase/gen
2
+
3
+ Générateur de types TypeScript `Database` pour le SDK Aurabase : introspecte le schéma d'un projet et produit un fichier de types compatible avec l'inférence de `@aurabase/db` (parité `Database` façon Supabase).
4
+
5
+ ![npm](https://img.shields.io/npm/v/@aurabase/gen) ![license](https://img.shields.io/badge/license-MIT-blue)
6
+
7
+ > Pre-release — pas encore publié sur npm.
8
+
9
+ Fait partie de l'écosystème du SDK **[aurabase](../aurabase)**, mais publié et installé **séparément** : contrairement aux autres packages `@aurabase/*`, le méta-package `aurabase` ne dépend pas de `@aurabase/gen` — c'est un outil de développement (CLI de génération de types), pas une dépendance runtime de votre application.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm i -D @aurabase/gen
15
+ ```
16
+
17
+ > S'installe typiquement en devDependency (ou s'exécute via `npx` sans installation) : c'est un outil exécuté ponctuellement (local ou CI) pour régénérer un fichier `.ts`, pas un module importé par votre application en production.
18
+
19
+ ## Usage
20
+
21
+ ### CLI `aurabase-gen`
22
+
23
+ ```bash
24
+ npx aurabase-gen --url http://localhost:8080 --project my-project --key aura_anon_xxx --out database.types.ts
25
+ ```
26
+
27
+ Options complètes :
28
+
29
+ ```
30
+ aurabase-gen --url <baseUrl> --project <id> [--key <apiKey>] [--out database.types.ts] [--schema public] [--type-name Database]
31
+ ```
32
+
33
+ Sans `--out`, la sortie est écrite sur `stdout` plutôt que dans un fichier.
34
+
35
+ ### Utilisation programmatique
36
+
37
+ ```ts
38
+ import { generateDatabaseTypes } from '@aurabase/gen'
39
+ import type { SchemaTable } from '@aurabase/core'
40
+
41
+ const tables: SchemaTable[] = [
42
+ {
43
+ name: 'posts',
44
+ primary_key: 'id',
45
+ columns: [
46
+ { name: 'id', col_type: 'uuid', nullable: false, unique: true, default_val: 'gen_random_uuid()', references: null },
47
+ { name: 'title', col_type: 'text', nullable: false, unique: false, default_val: null, references: null },
48
+ ],
49
+ indexes: [],
50
+ rls_enabled: false,
51
+ realtime_enabled: false,
52
+ },
53
+ ]
54
+
55
+ const source = generateDatabaseTypes(tables, { schemaName: 'public', typeName: 'Database' })
56
+ ```
57
+
58
+ ### Workflow complet (typage bout-en-bout avec `@aurabase/db`)
59
+
60
+ ```bash
61
+ npx aurabase-gen --url http://localhost:8080 --project my-project --key aura_anon_xxx --out database.types.ts
62
+ ```
63
+
64
+ ```ts
65
+ import { createClient } from '@aurabase/aurabase-js'
66
+ import type { Database } from './database.types' // fichier généré à l'étape précédente
67
+
68
+ const aura = createClient<Database>('http://localhost:8080', 'my-project', 'aura_anon_xxx')
69
+
70
+ // select()/insert()/update() sont désormais inférés depuis les colonnes réelles de `posts`.
71
+ const { data } = await aura.db.from('posts').select('id,title').eq('id', 'post-id').single()
72
+ ```
73
+
74
+ ## Limitations
75
+
76
+ - `Views`, `Functions`, `Enums` et `CompositeTypes` sont toujours générés vides (`Record<string, never>`) — seules les `Tables` sont introspectées et typées.
77
+ - Un seul schéma à la fois (`--schema`, défaut `public`) : pas de génération multi-schémas en une seule invocation.
78
+ - Dépend de l'endpoint `/schema` exposé par `aura.db.schema()` côté backend — un projet ou une clé sans droit de lecture du schéma ne peut pas générer de types (erreur explicite, pas de repli silencieux).
79
+ - Pas de détection de types enum Postgres dédiés : un `col_type` non reconnu retombe sur `unknown`.
80
+ - Le fichier généré est un instantané : il ne se met pas à jour automatiquement quand le schéma change côté backend (pas de mode watch).
81
+
82
+ ## Documentation
83
+
84
+ Référence complète du SDK (tous les services, types partagés, SSR) : [README racine](../../README.md).
package/dist/cli.cjs ADDED
@@ -0,0 +1,334 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var fs = require('fs');
5
+ var aurabaseJs = require('@aurabase/aurabase-js');
6
+
7
+ // src/generate.ts
8
+ function enumRef(name, ctx) {
9
+ return ctx.enumNames.has(name) ? `${ctx.typeName}['${ctx.schemaName}']['Enums']['${name}']` : (
10
+ // Enum inconnu du bloc Enums → auto-référence non résoluble → repli textuel.
11
+ "string"
12
+ );
13
+ }
14
+ function mapColType(colType, ctx) {
15
+ if (typeof colType === "string") {
16
+ switch (colType) {
17
+ case "text":
18
+ case "varchar":
19
+ case "bpchar":
20
+ case "uuid":
21
+ case "timestamp":
22
+ case "timestamptz":
23
+ case "date":
24
+ case "time":
25
+ case "bytea":
26
+ case "numeric":
27
+ return "string";
28
+ case "int":
29
+ case "int2":
30
+ case "int4":
31
+ case "int8":
32
+ case "bigint":
33
+ case "float":
34
+ case "float4":
35
+ case "float8":
36
+ return "number";
37
+ case "bool":
38
+ return "boolean";
39
+ case "json":
40
+ case "jsonb":
41
+ return "Json";
42
+ default:
43
+ return "unknown";
44
+ }
45
+ }
46
+ if (colType && typeof colType === "object") {
47
+ if ("array" in colType) return `${mapColType(colType.array, ctx)}[]`;
48
+ if ("vector" in colType) return "number[]";
49
+ if ("enum" in colType) return enumRef(String(colType.enum), ctx);
50
+ }
51
+ return "unknown";
52
+ }
53
+ function mapPgType(raw, ctx) {
54
+ if (raw.startsWith("_")) return `${mapPgType(raw.slice(1), ctx)}[]`;
55
+ switch (raw) {
56
+ case "int2":
57
+ case "int4":
58
+ case "int8":
59
+ case "float4":
60
+ case "float8":
61
+ return "number";
62
+ case "numeric":
63
+ return "string";
64
+ case "bool":
65
+ return "boolean";
66
+ case "text":
67
+ case "varchar":
68
+ case "bpchar":
69
+ case "citext":
70
+ case "uuid":
71
+ case "date":
72
+ case "time":
73
+ case "timetz":
74
+ case "timestamp":
75
+ case "timestamptz":
76
+ case "bytea":
77
+ return "string";
78
+ case "json":
79
+ case "jsonb":
80
+ return "Json";
81
+ case "void":
82
+ return "undefined";
83
+ case "record":
84
+ return "unknown";
85
+ default:
86
+ return ctx.enumNames.has(raw) ? enumRef(raw, ctx) : "unknown";
87
+ }
88
+ }
89
+ function tsType(col, ctx) {
90
+ const base = mapColType(col.col_type, ctx);
91
+ return col.nullable ? `${base} | null` : base;
92
+ }
93
+ function genRow(cols, ctx) {
94
+ return cols.map((c) => ` ${c.name}: ${tsType(c, ctx)}`).join("\n");
95
+ }
96
+ var AUTO_COLS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at"]);
97
+ function isInsertOptional(col) {
98
+ return col.nullable || col.default_val != null || AUTO_COLS.has(col.name);
99
+ }
100
+ function genInsert(cols, ctx) {
101
+ return cols.map((c) => ` ${c.name}${isInsertOptional(c) ? "?" : ""}: ${tsType(c, ctx)}`).join("\n");
102
+ }
103
+ function genUpdate(cols, ctx) {
104
+ return cols.map((c) => ` ${c.name}?: ${tsType(c, ctx)}`).join("\n");
105
+ }
106
+ function genRelationships(t) {
107
+ const fks = t.columns.filter((c) => c.references);
108
+ if (fks.length === 0) return "[]";
109
+ const groups = /* @__PURE__ */ new Map();
110
+ for (const c of fks) {
111
+ const ref = c.references;
112
+ const name = ref.constraint_name ?? `${t.name}_${c.name}_fkey`;
113
+ const key = ref.constraint_name ?? `\0synthetic\0${c.name}`;
114
+ let g = groups.get(key);
115
+ if (!g) {
116
+ g = { name, columns: [], refTable: ref.table, refColumns: [], cols: [] };
117
+ groups.set(key, g);
118
+ }
119
+ g.columns.push(c.name);
120
+ g.refColumns.push(ref.column);
121
+ g.cols.push(c);
122
+ }
123
+ const entries = [...groups.values()].map((g) => {
124
+ const isOneToOne = g.cols.every((c) => c.unique || t.primary_key === c.name);
125
+ const cols = g.columns.map((c) => `'${c}'`).join(", ");
126
+ const refCols = g.refColumns.map((c) => `'${c}'`).join(", ");
127
+ return ` {
128
+ foreignKeyName: '${g.name}'
129
+ columns: [${cols}]
130
+ isOneToOne: ${isOneToOne}
131
+ referencedRelation: '${g.refTable}'
132
+ referencedColumns: [${refCols}]
133
+ }`;
134
+ });
135
+ return `[
136
+ ${entries.join(",\n")}
137
+ ]`;
138
+ }
139
+ function genFunctionArgs(fn, ctx) {
140
+ const inputArgs = fn.args.filter((a) => a.mode.toUpperCase() !== "OUT");
141
+ if (inputArgs.length === 0) return "Record<string, never>";
142
+ const entries = inputArgs.map((a) => `${a.name}: ${mapPgType(a.data_type, ctx)}`).join("; ");
143
+ return `{ ${entries} }`;
144
+ }
145
+ function mapReturnType(fn, ctx) {
146
+ const base = mapPgType(fn.returns, ctx);
147
+ if (!fn.is_set_returning) return base;
148
+ return base === "unknown" ? "Record<string, unknown>[]" : `${base}[]`;
149
+ }
150
+ function genSetofOptions(fn, ctx) {
151
+ if (!fn.is_set_returning) return null;
152
+ const to = ctx.relationNames.has(fn.returns) ? fn.returns : fn.name;
153
+ return `{ isSetofReturn: true; isOneToOne: false; to: '${to}'; from: '*' }`;
154
+ }
155
+ function genFunctionsBody(functions, ctx) {
156
+ if (functions.length === 0) return "Record<string, never>";
157
+ const groups = /* @__PURE__ */ new Map();
158
+ for (const fn of functions) {
159
+ const g = groups.get(fn.name);
160
+ if (g) g.push(fn);
161
+ else groups.set(fn.name, [fn]);
162
+ }
163
+ const entries = [...groups.values()].map((overloads) => {
164
+ const argsUnion = uniq(overloads.map((fn) => genFunctionArgs(fn, ctx))).join(" | ");
165
+ const returnsUnion = uniq(overloads.map((fn) => mapReturnType(fn, ctx))).join(" | ");
166
+ const lines = [
167
+ ` ${overloads[0].name}: {`,
168
+ ` Args: ${argsUnion}`,
169
+ ` Returns: ${returnsUnion}`
170
+ ];
171
+ if (overloads.length === 1) {
172
+ const setofOptions = genSetofOptions(overloads[0], ctx);
173
+ if (setofOptions) lines.push(` SetofOptions: ${setofOptions}`);
174
+ }
175
+ lines.push(" }");
176
+ return lines.join("\n");
177
+ });
178
+ return `{
179
+ ${entries.join("\n")}
180
+ }`;
181
+ }
182
+ function uniq(items) {
183
+ return [...new Set(items)];
184
+ }
185
+ function genEnumsBody(enums) {
186
+ if (enums.length === 0) return "Record<string, never>";
187
+ const entries = enums.map((e) => {
188
+ const union = e.values.length === 0 ? "never" : e.values.map((v) => `'${v}'`).join(" | ");
189
+ return ` ${e.name}: ${union}`;
190
+ });
191
+ return `{
192
+ ${entries.join("\n")}
193
+ }`;
194
+ }
195
+ function genViewsBody(views, ctx) {
196
+ if (views.length === 0) return "Record<string, never>";
197
+ const entries = views.map(
198
+ (v) => ` ${v.name}: {
199
+ Row: {
200
+ ${genRow(v.columns, ctx)}
201
+ }
202
+ Relationships: []
203
+ }`
204
+ );
205
+ return `{
206
+ ${entries.join("\n")}
207
+ }`;
208
+ }
209
+ var HEADER = `// ============================================================
210
+ // Types TypeScript auto-g\xE9n\xE9r\xE9s par Aurabase (@aurabase/gen)
211
+ // NE PAS MODIFIER \u2014 r\xE9g\xE9n\xE9rer avec \`npx @aurabase/gen\`
212
+ // ============================================================
213
+ `;
214
+ function generateDatabaseTypes(tables, options = {}) {
215
+ const schemaName = options.schemaName ?? "public";
216
+ const typeName = options.typeName ?? "Database";
217
+ const enums = options.enums ?? [];
218
+ const views = options.views ?? [];
219
+ const relationNames = new Set([...tables, ...views].map((r) => r.name));
220
+ const ctx = { typeName, schemaName, enumNames: new Set(enums.map((e) => e.name)), relationNames };
221
+ const functionsBody = genFunctionsBody(options.functions ?? [], ctx);
222
+ const enumsBody = genEnumsBody(enums);
223
+ const viewsBody = genViewsBody(views, ctx);
224
+ const tablesBody = tables.length === 0 ? "Record<string, never>" : `{
225
+ ${tables.map(
226
+ (t) => ` ${t.name}: {
227
+ Row: {
228
+ ${genRow(t.columns, ctx)}
229
+ }
230
+ Insert: {
231
+ ${genInsert(t.columns, ctx)}
232
+ }
233
+ Update: {
234
+ ${genUpdate(t.columns, ctx)}
235
+ }
236
+ Relationships: ${genRelationships(t)}
237
+ }`
238
+ ).join("\n")}
239
+ }`;
240
+ return `${HEADER}
241
+ export type Json =
242
+ | string
243
+ | number
244
+ | boolean
245
+ | null
246
+ | { [key: string]: Json | undefined }
247
+ | Json[]
248
+
249
+ export interface ${typeName} {
250
+ ${schemaName}: {
251
+ Tables: ${tablesBody}
252
+ Views: ${viewsBody}
253
+ Functions: ${functionsBody}
254
+ Enums: ${enumsBody}
255
+ CompositeTypes: Record<string, never>
256
+ }
257
+ }
258
+ `;
259
+ }
260
+
261
+ // src/cli.ts
262
+ function parseArgs(argv) {
263
+ const a = {};
264
+ for (let i = 0; i < argv.length; i++) {
265
+ const v = argv[i + 1];
266
+ switch (argv[i]) {
267
+ case "--url":
268
+ a.url = v;
269
+ i++;
270
+ break;
271
+ case "--project":
272
+ a.project = v;
273
+ i++;
274
+ break;
275
+ case "--key":
276
+ a.key = v;
277
+ i++;
278
+ break;
279
+ case "--out":
280
+ a.out = v;
281
+ i++;
282
+ break;
283
+ case "--schema":
284
+ a.schema = v;
285
+ i++;
286
+ break;
287
+ case "--type-name":
288
+ a.typeName = v;
289
+ i++;
290
+ break;
291
+ }
292
+ }
293
+ return a;
294
+ }
295
+ var USAGE = `Usage: aurabase-gen --url <baseUrl> --project <id> [--key <apiKey>] [--out database.types.ts] [--schema public] [--type-name Database]`;
296
+ async function main() {
297
+ const args = parseArgs(process.argv.slice(2));
298
+ if (!args.url || !args.project) {
299
+ console.error(USAGE);
300
+ process.exit(1);
301
+ }
302
+ const client = aurabaseJs.createClient(args.url, args.project, args.key);
303
+ const { data, error } = await client.db.schema();
304
+ if (error) {
305
+ console.error(`[aurabase-gen] Erreur de r\xE9cup\xE9ration du sch\xE9ma : ${error.message}`);
306
+ process.exit(1);
307
+ }
308
+ const tables = data?.tables ?? [];
309
+ const functions = data?.functions ?? [];
310
+ const enums = data?.enums ?? [];
311
+ const views = data?.views ?? [];
312
+ if (tables.length === 0) {
313
+ console.error("[aurabase-gen] Avertissement : sch\xE9ma vide (aucune table).");
314
+ }
315
+ const output = generateDatabaseTypes(tables, {
316
+ schemaName: args.schema,
317
+ typeName: args.typeName,
318
+ functions,
319
+ enums,
320
+ views
321
+ });
322
+ if (args.out) {
323
+ fs.writeFileSync(args.out, output);
324
+ console.error(
325
+ `[aurabase-gen] \u2713 Types \xE9crits dans ${args.out} (${tables.length} table(s), ${functions.length} fonction(s), ${enums.length} enum(s), ${views.length} vue(s)).`
326
+ );
327
+ } else {
328
+ process.stdout.write(output);
329
+ }
330
+ }
331
+ main().catch((e) => {
332
+ console.error("[aurabase-gen]", e instanceof Error ? e.message : e);
333
+ process.exit(1);
334
+ });
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,332 @@
1
+ #!/usr/bin/env node
2
+ import { writeFileSync } from 'fs';
3
+ import { createClient } from '@aurabase/aurabase-js';
4
+
5
+ // src/generate.ts
6
+ function enumRef(name, ctx) {
7
+ return ctx.enumNames.has(name) ? `${ctx.typeName}['${ctx.schemaName}']['Enums']['${name}']` : (
8
+ // Enum inconnu du bloc Enums → auto-référence non résoluble → repli textuel.
9
+ "string"
10
+ );
11
+ }
12
+ function mapColType(colType, ctx) {
13
+ if (typeof colType === "string") {
14
+ switch (colType) {
15
+ case "text":
16
+ case "varchar":
17
+ case "bpchar":
18
+ case "uuid":
19
+ case "timestamp":
20
+ case "timestamptz":
21
+ case "date":
22
+ case "time":
23
+ case "bytea":
24
+ case "numeric":
25
+ return "string";
26
+ case "int":
27
+ case "int2":
28
+ case "int4":
29
+ case "int8":
30
+ case "bigint":
31
+ case "float":
32
+ case "float4":
33
+ case "float8":
34
+ return "number";
35
+ case "bool":
36
+ return "boolean";
37
+ case "json":
38
+ case "jsonb":
39
+ return "Json";
40
+ default:
41
+ return "unknown";
42
+ }
43
+ }
44
+ if (colType && typeof colType === "object") {
45
+ if ("array" in colType) return `${mapColType(colType.array, ctx)}[]`;
46
+ if ("vector" in colType) return "number[]";
47
+ if ("enum" in colType) return enumRef(String(colType.enum), ctx);
48
+ }
49
+ return "unknown";
50
+ }
51
+ function mapPgType(raw, ctx) {
52
+ if (raw.startsWith("_")) return `${mapPgType(raw.slice(1), ctx)}[]`;
53
+ switch (raw) {
54
+ case "int2":
55
+ case "int4":
56
+ case "int8":
57
+ case "float4":
58
+ case "float8":
59
+ return "number";
60
+ case "numeric":
61
+ return "string";
62
+ case "bool":
63
+ return "boolean";
64
+ case "text":
65
+ case "varchar":
66
+ case "bpchar":
67
+ case "citext":
68
+ case "uuid":
69
+ case "date":
70
+ case "time":
71
+ case "timetz":
72
+ case "timestamp":
73
+ case "timestamptz":
74
+ case "bytea":
75
+ return "string";
76
+ case "json":
77
+ case "jsonb":
78
+ return "Json";
79
+ case "void":
80
+ return "undefined";
81
+ case "record":
82
+ return "unknown";
83
+ default:
84
+ return ctx.enumNames.has(raw) ? enumRef(raw, ctx) : "unknown";
85
+ }
86
+ }
87
+ function tsType(col, ctx) {
88
+ const base = mapColType(col.col_type, ctx);
89
+ return col.nullable ? `${base} | null` : base;
90
+ }
91
+ function genRow(cols, ctx) {
92
+ return cols.map((c) => ` ${c.name}: ${tsType(c, ctx)}`).join("\n");
93
+ }
94
+ var AUTO_COLS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at"]);
95
+ function isInsertOptional(col) {
96
+ return col.nullable || col.default_val != null || AUTO_COLS.has(col.name);
97
+ }
98
+ function genInsert(cols, ctx) {
99
+ return cols.map((c) => ` ${c.name}${isInsertOptional(c) ? "?" : ""}: ${tsType(c, ctx)}`).join("\n");
100
+ }
101
+ function genUpdate(cols, ctx) {
102
+ return cols.map((c) => ` ${c.name}?: ${tsType(c, ctx)}`).join("\n");
103
+ }
104
+ function genRelationships(t) {
105
+ const fks = t.columns.filter((c) => c.references);
106
+ if (fks.length === 0) return "[]";
107
+ const groups = /* @__PURE__ */ new Map();
108
+ for (const c of fks) {
109
+ const ref = c.references;
110
+ const name = ref.constraint_name ?? `${t.name}_${c.name}_fkey`;
111
+ const key = ref.constraint_name ?? `\0synthetic\0${c.name}`;
112
+ let g = groups.get(key);
113
+ if (!g) {
114
+ g = { name, columns: [], refTable: ref.table, refColumns: [], cols: [] };
115
+ groups.set(key, g);
116
+ }
117
+ g.columns.push(c.name);
118
+ g.refColumns.push(ref.column);
119
+ g.cols.push(c);
120
+ }
121
+ const entries = [...groups.values()].map((g) => {
122
+ const isOneToOne = g.cols.every((c) => c.unique || t.primary_key === c.name);
123
+ const cols = g.columns.map((c) => `'${c}'`).join(", ");
124
+ const refCols = g.refColumns.map((c) => `'${c}'`).join(", ");
125
+ return ` {
126
+ foreignKeyName: '${g.name}'
127
+ columns: [${cols}]
128
+ isOneToOne: ${isOneToOne}
129
+ referencedRelation: '${g.refTable}'
130
+ referencedColumns: [${refCols}]
131
+ }`;
132
+ });
133
+ return `[
134
+ ${entries.join(",\n")}
135
+ ]`;
136
+ }
137
+ function genFunctionArgs(fn, ctx) {
138
+ const inputArgs = fn.args.filter((a) => a.mode.toUpperCase() !== "OUT");
139
+ if (inputArgs.length === 0) return "Record<string, never>";
140
+ const entries = inputArgs.map((a) => `${a.name}: ${mapPgType(a.data_type, ctx)}`).join("; ");
141
+ return `{ ${entries} }`;
142
+ }
143
+ function mapReturnType(fn, ctx) {
144
+ const base = mapPgType(fn.returns, ctx);
145
+ if (!fn.is_set_returning) return base;
146
+ return base === "unknown" ? "Record<string, unknown>[]" : `${base}[]`;
147
+ }
148
+ function genSetofOptions(fn, ctx) {
149
+ if (!fn.is_set_returning) return null;
150
+ const to = ctx.relationNames.has(fn.returns) ? fn.returns : fn.name;
151
+ return `{ isSetofReturn: true; isOneToOne: false; to: '${to}'; from: '*' }`;
152
+ }
153
+ function genFunctionsBody(functions, ctx) {
154
+ if (functions.length === 0) return "Record<string, never>";
155
+ const groups = /* @__PURE__ */ new Map();
156
+ for (const fn of functions) {
157
+ const g = groups.get(fn.name);
158
+ if (g) g.push(fn);
159
+ else groups.set(fn.name, [fn]);
160
+ }
161
+ const entries = [...groups.values()].map((overloads) => {
162
+ const argsUnion = uniq(overloads.map((fn) => genFunctionArgs(fn, ctx))).join(" | ");
163
+ const returnsUnion = uniq(overloads.map((fn) => mapReturnType(fn, ctx))).join(" | ");
164
+ const lines = [
165
+ ` ${overloads[0].name}: {`,
166
+ ` Args: ${argsUnion}`,
167
+ ` Returns: ${returnsUnion}`
168
+ ];
169
+ if (overloads.length === 1) {
170
+ const setofOptions = genSetofOptions(overloads[0], ctx);
171
+ if (setofOptions) lines.push(` SetofOptions: ${setofOptions}`);
172
+ }
173
+ lines.push(" }");
174
+ return lines.join("\n");
175
+ });
176
+ return `{
177
+ ${entries.join("\n")}
178
+ }`;
179
+ }
180
+ function uniq(items) {
181
+ return [...new Set(items)];
182
+ }
183
+ function genEnumsBody(enums) {
184
+ if (enums.length === 0) return "Record<string, never>";
185
+ const entries = enums.map((e) => {
186
+ const union = e.values.length === 0 ? "never" : e.values.map((v) => `'${v}'`).join(" | ");
187
+ return ` ${e.name}: ${union}`;
188
+ });
189
+ return `{
190
+ ${entries.join("\n")}
191
+ }`;
192
+ }
193
+ function genViewsBody(views, ctx) {
194
+ if (views.length === 0) return "Record<string, never>";
195
+ const entries = views.map(
196
+ (v) => ` ${v.name}: {
197
+ Row: {
198
+ ${genRow(v.columns, ctx)}
199
+ }
200
+ Relationships: []
201
+ }`
202
+ );
203
+ return `{
204
+ ${entries.join("\n")}
205
+ }`;
206
+ }
207
+ var HEADER = `// ============================================================
208
+ // Types TypeScript auto-g\xE9n\xE9r\xE9s par Aurabase (@aurabase/gen)
209
+ // NE PAS MODIFIER \u2014 r\xE9g\xE9n\xE9rer avec \`npx @aurabase/gen\`
210
+ // ============================================================
211
+ `;
212
+ function generateDatabaseTypes(tables, options = {}) {
213
+ const schemaName = options.schemaName ?? "public";
214
+ const typeName = options.typeName ?? "Database";
215
+ const enums = options.enums ?? [];
216
+ const views = options.views ?? [];
217
+ const relationNames = new Set([...tables, ...views].map((r) => r.name));
218
+ const ctx = { typeName, schemaName, enumNames: new Set(enums.map((e) => e.name)), relationNames };
219
+ const functionsBody = genFunctionsBody(options.functions ?? [], ctx);
220
+ const enumsBody = genEnumsBody(enums);
221
+ const viewsBody = genViewsBody(views, ctx);
222
+ const tablesBody = tables.length === 0 ? "Record<string, never>" : `{
223
+ ${tables.map(
224
+ (t) => ` ${t.name}: {
225
+ Row: {
226
+ ${genRow(t.columns, ctx)}
227
+ }
228
+ Insert: {
229
+ ${genInsert(t.columns, ctx)}
230
+ }
231
+ Update: {
232
+ ${genUpdate(t.columns, ctx)}
233
+ }
234
+ Relationships: ${genRelationships(t)}
235
+ }`
236
+ ).join("\n")}
237
+ }`;
238
+ return `${HEADER}
239
+ export type Json =
240
+ | string
241
+ | number
242
+ | boolean
243
+ | null
244
+ | { [key: string]: Json | undefined }
245
+ | Json[]
246
+
247
+ export interface ${typeName} {
248
+ ${schemaName}: {
249
+ Tables: ${tablesBody}
250
+ Views: ${viewsBody}
251
+ Functions: ${functionsBody}
252
+ Enums: ${enumsBody}
253
+ CompositeTypes: Record<string, never>
254
+ }
255
+ }
256
+ `;
257
+ }
258
+
259
+ // src/cli.ts
260
+ function parseArgs(argv) {
261
+ const a = {};
262
+ for (let i = 0; i < argv.length; i++) {
263
+ const v = argv[i + 1];
264
+ switch (argv[i]) {
265
+ case "--url":
266
+ a.url = v;
267
+ i++;
268
+ break;
269
+ case "--project":
270
+ a.project = v;
271
+ i++;
272
+ break;
273
+ case "--key":
274
+ a.key = v;
275
+ i++;
276
+ break;
277
+ case "--out":
278
+ a.out = v;
279
+ i++;
280
+ break;
281
+ case "--schema":
282
+ a.schema = v;
283
+ i++;
284
+ break;
285
+ case "--type-name":
286
+ a.typeName = v;
287
+ i++;
288
+ break;
289
+ }
290
+ }
291
+ return a;
292
+ }
293
+ var USAGE = `Usage: aurabase-gen --url <baseUrl> --project <id> [--key <apiKey>] [--out database.types.ts] [--schema public] [--type-name Database]`;
294
+ async function main() {
295
+ const args = parseArgs(process.argv.slice(2));
296
+ if (!args.url || !args.project) {
297
+ console.error(USAGE);
298
+ process.exit(1);
299
+ }
300
+ const client = createClient(args.url, args.project, args.key);
301
+ const { data, error } = await client.db.schema();
302
+ if (error) {
303
+ console.error(`[aurabase-gen] Erreur de r\xE9cup\xE9ration du sch\xE9ma : ${error.message}`);
304
+ process.exit(1);
305
+ }
306
+ const tables = data?.tables ?? [];
307
+ const functions = data?.functions ?? [];
308
+ const enums = data?.enums ?? [];
309
+ const views = data?.views ?? [];
310
+ if (tables.length === 0) {
311
+ console.error("[aurabase-gen] Avertissement : sch\xE9ma vide (aucune table).");
312
+ }
313
+ const output = generateDatabaseTypes(tables, {
314
+ schemaName: args.schema,
315
+ typeName: args.typeName,
316
+ functions,
317
+ enums,
318
+ views
319
+ });
320
+ if (args.out) {
321
+ writeFileSync(args.out, output);
322
+ console.error(
323
+ `[aurabase-gen] \u2713 Types \xE9crits dans ${args.out} (${tables.length} table(s), ${functions.length} fonction(s), ${enums.length} enum(s), ${views.length} vue(s)).`
324
+ );
325
+ } else {
326
+ process.stdout.write(output);
327
+ }
328
+ }
329
+ main().catch((e) => {
330
+ console.error("[aurabase-gen]", e instanceof Error ? e.message : e);
331
+ process.exit(1);
332
+ });
package/dist/index.cjs ADDED
@@ -0,0 +1,257 @@
1
+ 'use strict';
2
+
3
+ // src/generate.ts
4
+ function enumRef(name, ctx) {
5
+ return ctx.enumNames.has(name) ? `${ctx.typeName}['${ctx.schemaName}']['Enums']['${name}']` : (
6
+ // Enum inconnu du bloc Enums → auto-référence non résoluble → repli textuel.
7
+ "string"
8
+ );
9
+ }
10
+ function mapColType(colType, ctx) {
11
+ if (typeof colType === "string") {
12
+ switch (colType) {
13
+ case "text":
14
+ case "varchar":
15
+ case "bpchar":
16
+ case "uuid":
17
+ case "timestamp":
18
+ case "timestamptz":
19
+ case "date":
20
+ case "time":
21
+ case "bytea":
22
+ case "numeric":
23
+ return "string";
24
+ case "int":
25
+ case "int2":
26
+ case "int4":
27
+ case "int8":
28
+ case "bigint":
29
+ case "float":
30
+ case "float4":
31
+ case "float8":
32
+ return "number";
33
+ case "bool":
34
+ return "boolean";
35
+ case "json":
36
+ case "jsonb":
37
+ return "Json";
38
+ default:
39
+ return "unknown";
40
+ }
41
+ }
42
+ if (colType && typeof colType === "object") {
43
+ if ("array" in colType) return `${mapColType(colType.array, ctx)}[]`;
44
+ if ("vector" in colType) return "number[]";
45
+ if ("enum" in colType) return enumRef(String(colType.enum), ctx);
46
+ }
47
+ return "unknown";
48
+ }
49
+ function mapPgType(raw, ctx) {
50
+ if (raw.startsWith("_")) return `${mapPgType(raw.slice(1), ctx)}[]`;
51
+ switch (raw) {
52
+ case "int2":
53
+ case "int4":
54
+ case "int8":
55
+ case "float4":
56
+ case "float8":
57
+ return "number";
58
+ case "numeric":
59
+ return "string";
60
+ case "bool":
61
+ return "boolean";
62
+ case "text":
63
+ case "varchar":
64
+ case "bpchar":
65
+ case "citext":
66
+ case "uuid":
67
+ case "date":
68
+ case "time":
69
+ case "timetz":
70
+ case "timestamp":
71
+ case "timestamptz":
72
+ case "bytea":
73
+ return "string";
74
+ case "json":
75
+ case "jsonb":
76
+ return "Json";
77
+ case "void":
78
+ return "undefined";
79
+ case "record":
80
+ return "unknown";
81
+ default:
82
+ return ctx.enumNames.has(raw) ? enumRef(raw, ctx) : "unknown";
83
+ }
84
+ }
85
+ function tsType(col, ctx) {
86
+ const base = mapColType(col.col_type, ctx);
87
+ return col.nullable ? `${base} | null` : base;
88
+ }
89
+ function genRow(cols, ctx) {
90
+ return cols.map((c) => ` ${c.name}: ${tsType(c, ctx)}`).join("\n");
91
+ }
92
+ var AUTO_COLS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at"]);
93
+ function isInsertOptional(col) {
94
+ return col.nullable || col.default_val != null || AUTO_COLS.has(col.name);
95
+ }
96
+ function genInsert(cols, ctx) {
97
+ return cols.map((c) => ` ${c.name}${isInsertOptional(c) ? "?" : ""}: ${tsType(c, ctx)}`).join("\n");
98
+ }
99
+ function genUpdate(cols, ctx) {
100
+ return cols.map((c) => ` ${c.name}?: ${tsType(c, ctx)}`).join("\n");
101
+ }
102
+ function genRelationships(t) {
103
+ const fks = t.columns.filter((c) => c.references);
104
+ if (fks.length === 0) return "[]";
105
+ const groups = /* @__PURE__ */ new Map();
106
+ for (const c of fks) {
107
+ const ref = c.references;
108
+ const name = ref.constraint_name ?? `${t.name}_${c.name}_fkey`;
109
+ const key = ref.constraint_name ?? `\0synthetic\0${c.name}`;
110
+ let g = groups.get(key);
111
+ if (!g) {
112
+ g = { name, columns: [], refTable: ref.table, refColumns: [], cols: [] };
113
+ groups.set(key, g);
114
+ }
115
+ g.columns.push(c.name);
116
+ g.refColumns.push(ref.column);
117
+ g.cols.push(c);
118
+ }
119
+ const entries = [...groups.values()].map((g) => {
120
+ const isOneToOne = g.cols.every((c) => c.unique || t.primary_key === c.name);
121
+ const cols = g.columns.map((c) => `'${c}'`).join(", ");
122
+ const refCols = g.refColumns.map((c) => `'${c}'`).join(", ");
123
+ return ` {
124
+ foreignKeyName: '${g.name}'
125
+ columns: [${cols}]
126
+ isOneToOne: ${isOneToOne}
127
+ referencedRelation: '${g.refTable}'
128
+ referencedColumns: [${refCols}]
129
+ }`;
130
+ });
131
+ return `[
132
+ ${entries.join(",\n")}
133
+ ]`;
134
+ }
135
+ function genFunctionArgs(fn, ctx) {
136
+ const inputArgs = fn.args.filter((a) => a.mode.toUpperCase() !== "OUT");
137
+ if (inputArgs.length === 0) return "Record<string, never>";
138
+ const entries = inputArgs.map((a) => `${a.name}: ${mapPgType(a.data_type, ctx)}`).join("; ");
139
+ return `{ ${entries} }`;
140
+ }
141
+ function mapReturnType(fn, ctx) {
142
+ const base = mapPgType(fn.returns, ctx);
143
+ if (!fn.is_set_returning) return base;
144
+ return base === "unknown" ? "Record<string, unknown>[]" : `${base}[]`;
145
+ }
146
+ function genSetofOptions(fn, ctx) {
147
+ if (!fn.is_set_returning) return null;
148
+ const to = ctx.relationNames.has(fn.returns) ? fn.returns : fn.name;
149
+ return `{ isSetofReturn: true; isOneToOne: false; to: '${to}'; from: '*' }`;
150
+ }
151
+ function genFunctionsBody(functions, ctx) {
152
+ if (functions.length === 0) return "Record<string, never>";
153
+ const groups = /* @__PURE__ */ new Map();
154
+ for (const fn of functions) {
155
+ const g = groups.get(fn.name);
156
+ if (g) g.push(fn);
157
+ else groups.set(fn.name, [fn]);
158
+ }
159
+ const entries = [...groups.values()].map((overloads) => {
160
+ const argsUnion = uniq(overloads.map((fn) => genFunctionArgs(fn, ctx))).join(" | ");
161
+ const returnsUnion = uniq(overloads.map((fn) => mapReturnType(fn, ctx))).join(" | ");
162
+ const lines = [
163
+ ` ${overloads[0].name}: {`,
164
+ ` Args: ${argsUnion}`,
165
+ ` Returns: ${returnsUnion}`
166
+ ];
167
+ if (overloads.length === 1) {
168
+ const setofOptions = genSetofOptions(overloads[0], ctx);
169
+ if (setofOptions) lines.push(` SetofOptions: ${setofOptions}`);
170
+ }
171
+ lines.push(" }");
172
+ return lines.join("\n");
173
+ });
174
+ return `{
175
+ ${entries.join("\n")}
176
+ }`;
177
+ }
178
+ function uniq(items) {
179
+ return [...new Set(items)];
180
+ }
181
+ function genEnumsBody(enums) {
182
+ if (enums.length === 0) return "Record<string, never>";
183
+ const entries = enums.map((e) => {
184
+ const union = e.values.length === 0 ? "never" : e.values.map((v) => `'${v}'`).join(" | ");
185
+ return ` ${e.name}: ${union}`;
186
+ });
187
+ return `{
188
+ ${entries.join("\n")}
189
+ }`;
190
+ }
191
+ function genViewsBody(views, ctx) {
192
+ if (views.length === 0) return "Record<string, never>";
193
+ const entries = views.map(
194
+ (v) => ` ${v.name}: {
195
+ Row: {
196
+ ${genRow(v.columns, ctx)}
197
+ }
198
+ Relationships: []
199
+ }`
200
+ );
201
+ return `{
202
+ ${entries.join("\n")}
203
+ }`;
204
+ }
205
+ var HEADER = `// ============================================================
206
+ // Types TypeScript auto-g\xE9n\xE9r\xE9s par Aurabase (@aurabase/gen)
207
+ // NE PAS MODIFIER \u2014 r\xE9g\xE9n\xE9rer avec \`npx @aurabase/gen\`
208
+ // ============================================================
209
+ `;
210
+ function generateDatabaseTypes(tables, options = {}) {
211
+ const schemaName = options.schemaName ?? "public";
212
+ const typeName = options.typeName ?? "Database";
213
+ const enums = options.enums ?? [];
214
+ const views = options.views ?? [];
215
+ const relationNames = new Set([...tables, ...views].map((r) => r.name));
216
+ const ctx = { typeName, schemaName, enumNames: new Set(enums.map((e) => e.name)), relationNames };
217
+ const functionsBody = genFunctionsBody(options.functions ?? [], ctx);
218
+ const enumsBody = genEnumsBody(enums);
219
+ const viewsBody = genViewsBody(views, ctx);
220
+ const tablesBody = tables.length === 0 ? "Record<string, never>" : `{
221
+ ${tables.map(
222
+ (t) => ` ${t.name}: {
223
+ Row: {
224
+ ${genRow(t.columns, ctx)}
225
+ }
226
+ Insert: {
227
+ ${genInsert(t.columns, ctx)}
228
+ }
229
+ Update: {
230
+ ${genUpdate(t.columns, ctx)}
231
+ }
232
+ Relationships: ${genRelationships(t)}
233
+ }`
234
+ ).join("\n")}
235
+ }`;
236
+ return `${HEADER}
237
+ export type Json =
238
+ | string
239
+ | number
240
+ | boolean
241
+ | null
242
+ | { [key: string]: Json | undefined }
243
+ | Json[]
244
+
245
+ export interface ${typeName} {
246
+ ${schemaName}: {
247
+ Tables: ${tablesBody}
248
+ Views: ${viewsBody}
249
+ Functions: ${functionsBody}
250
+ Enums: ${enumsBody}
251
+ CompositeTypes: Record<string, never>
252
+ }
253
+ }
254
+ `;
255
+ }
256
+
257
+ exports.generateDatabaseTypes = generateDatabaseTypes;
@@ -0,0 +1,12 @@
1
+ import { SchemaFunction, SchemaEnum, SchemaTable } from '@aurabase/core';
2
+
3
+ interface GenerateOptions {
4
+ schemaName?: string;
5
+ typeName?: string;
6
+ functions?: SchemaFunction[];
7
+ enums?: SchemaEnum[];
8
+ views?: SchemaTable[];
9
+ }
10
+ declare function generateDatabaseTypes(tables: SchemaTable[], options?: GenerateOptions): string;
11
+
12
+ export { type GenerateOptions, generateDatabaseTypes };
@@ -0,0 +1,12 @@
1
+ import { SchemaFunction, SchemaEnum, SchemaTable } from '@aurabase/core';
2
+
3
+ interface GenerateOptions {
4
+ schemaName?: string;
5
+ typeName?: string;
6
+ functions?: SchemaFunction[];
7
+ enums?: SchemaEnum[];
8
+ views?: SchemaTable[];
9
+ }
10
+ declare function generateDatabaseTypes(tables: SchemaTable[], options?: GenerateOptions): string;
11
+
12
+ export { type GenerateOptions, generateDatabaseTypes };
package/dist/index.js ADDED
@@ -0,0 +1,255 @@
1
+ // src/generate.ts
2
+ function enumRef(name, ctx) {
3
+ return ctx.enumNames.has(name) ? `${ctx.typeName}['${ctx.schemaName}']['Enums']['${name}']` : (
4
+ // Enum inconnu du bloc Enums → auto-référence non résoluble → repli textuel.
5
+ "string"
6
+ );
7
+ }
8
+ function mapColType(colType, ctx) {
9
+ if (typeof colType === "string") {
10
+ switch (colType) {
11
+ case "text":
12
+ case "varchar":
13
+ case "bpchar":
14
+ case "uuid":
15
+ case "timestamp":
16
+ case "timestamptz":
17
+ case "date":
18
+ case "time":
19
+ case "bytea":
20
+ case "numeric":
21
+ return "string";
22
+ case "int":
23
+ case "int2":
24
+ case "int4":
25
+ case "int8":
26
+ case "bigint":
27
+ case "float":
28
+ case "float4":
29
+ case "float8":
30
+ return "number";
31
+ case "bool":
32
+ return "boolean";
33
+ case "json":
34
+ case "jsonb":
35
+ return "Json";
36
+ default:
37
+ return "unknown";
38
+ }
39
+ }
40
+ if (colType && typeof colType === "object") {
41
+ if ("array" in colType) return `${mapColType(colType.array, ctx)}[]`;
42
+ if ("vector" in colType) return "number[]";
43
+ if ("enum" in colType) return enumRef(String(colType.enum), ctx);
44
+ }
45
+ return "unknown";
46
+ }
47
+ function mapPgType(raw, ctx) {
48
+ if (raw.startsWith("_")) return `${mapPgType(raw.slice(1), ctx)}[]`;
49
+ switch (raw) {
50
+ case "int2":
51
+ case "int4":
52
+ case "int8":
53
+ case "float4":
54
+ case "float8":
55
+ return "number";
56
+ case "numeric":
57
+ return "string";
58
+ case "bool":
59
+ return "boolean";
60
+ case "text":
61
+ case "varchar":
62
+ case "bpchar":
63
+ case "citext":
64
+ case "uuid":
65
+ case "date":
66
+ case "time":
67
+ case "timetz":
68
+ case "timestamp":
69
+ case "timestamptz":
70
+ case "bytea":
71
+ return "string";
72
+ case "json":
73
+ case "jsonb":
74
+ return "Json";
75
+ case "void":
76
+ return "undefined";
77
+ case "record":
78
+ return "unknown";
79
+ default:
80
+ return ctx.enumNames.has(raw) ? enumRef(raw, ctx) : "unknown";
81
+ }
82
+ }
83
+ function tsType(col, ctx) {
84
+ const base = mapColType(col.col_type, ctx);
85
+ return col.nullable ? `${base} | null` : base;
86
+ }
87
+ function genRow(cols, ctx) {
88
+ return cols.map((c) => ` ${c.name}: ${tsType(c, ctx)}`).join("\n");
89
+ }
90
+ var AUTO_COLS = /* @__PURE__ */ new Set(["id", "created_at", "updated_at"]);
91
+ function isInsertOptional(col) {
92
+ return col.nullable || col.default_val != null || AUTO_COLS.has(col.name);
93
+ }
94
+ function genInsert(cols, ctx) {
95
+ return cols.map((c) => ` ${c.name}${isInsertOptional(c) ? "?" : ""}: ${tsType(c, ctx)}`).join("\n");
96
+ }
97
+ function genUpdate(cols, ctx) {
98
+ return cols.map((c) => ` ${c.name}?: ${tsType(c, ctx)}`).join("\n");
99
+ }
100
+ function genRelationships(t) {
101
+ const fks = t.columns.filter((c) => c.references);
102
+ if (fks.length === 0) return "[]";
103
+ const groups = /* @__PURE__ */ new Map();
104
+ for (const c of fks) {
105
+ const ref = c.references;
106
+ const name = ref.constraint_name ?? `${t.name}_${c.name}_fkey`;
107
+ const key = ref.constraint_name ?? `\0synthetic\0${c.name}`;
108
+ let g = groups.get(key);
109
+ if (!g) {
110
+ g = { name, columns: [], refTable: ref.table, refColumns: [], cols: [] };
111
+ groups.set(key, g);
112
+ }
113
+ g.columns.push(c.name);
114
+ g.refColumns.push(ref.column);
115
+ g.cols.push(c);
116
+ }
117
+ const entries = [...groups.values()].map((g) => {
118
+ const isOneToOne = g.cols.every((c) => c.unique || t.primary_key === c.name);
119
+ const cols = g.columns.map((c) => `'${c}'`).join(", ");
120
+ const refCols = g.refColumns.map((c) => `'${c}'`).join(", ");
121
+ return ` {
122
+ foreignKeyName: '${g.name}'
123
+ columns: [${cols}]
124
+ isOneToOne: ${isOneToOne}
125
+ referencedRelation: '${g.refTable}'
126
+ referencedColumns: [${refCols}]
127
+ }`;
128
+ });
129
+ return `[
130
+ ${entries.join(",\n")}
131
+ ]`;
132
+ }
133
+ function genFunctionArgs(fn, ctx) {
134
+ const inputArgs = fn.args.filter((a) => a.mode.toUpperCase() !== "OUT");
135
+ if (inputArgs.length === 0) return "Record<string, never>";
136
+ const entries = inputArgs.map((a) => `${a.name}: ${mapPgType(a.data_type, ctx)}`).join("; ");
137
+ return `{ ${entries} }`;
138
+ }
139
+ function mapReturnType(fn, ctx) {
140
+ const base = mapPgType(fn.returns, ctx);
141
+ if (!fn.is_set_returning) return base;
142
+ return base === "unknown" ? "Record<string, unknown>[]" : `${base}[]`;
143
+ }
144
+ function genSetofOptions(fn, ctx) {
145
+ if (!fn.is_set_returning) return null;
146
+ const to = ctx.relationNames.has(fn.returns) ? fn.returns : fn.name;
147
+ return `{ isSetofReturn: true; isOneToOne: false; to: '${to}'; from: '*' }`;
148
+ }
149
+ function genFunctionsBody(functions, ctx) {
150
+ if (functions.length === 0) return "Record<string, never>";
151
+ const groups = /* @__PURE__ */ new Map();
152
+ for (const fn of functions) {
153
+ const g = groups.get(fn.name);
154
+ if (g) g.push(fn);
155
+ else groups.set(fn.name, [fn]);
156
+ }
157
+ const entries = [...groups.values()].map((overloads) => {
158
+ const argsUnion = uniq(overloads.map((fn) => genFunctionArgs(fn, ctx))).join(" | ");
159
+ const returnsUnion = uniq(overloads.map((fn) => mapReturnType(fn, ctx))).join(" | ");
160
+ const lines = [
161
+ ` ${overloads[0].name}: {`,
162
+ ` Args: ${argsUnion}`,
163
+ ` Returns: ${returnsUnion}`
164
+ ];
165
+ if (overloads.length === 1) {
166
+ const setofOptions = genSetofOptions(overloads[0], ctx);
167
+ if (setofOptions) lines.push(` SetofOptions: ${setofOptions}`);
168
+ }
169
+ lines.push(" }");
170
+ return lines.join("\n");
171
+ });
172
+ return `{
173
+ ${entries.join("\n")}
174
+ }`;
175
+ }
176
+ function uniq(items) {
177
+ return [...new Set(items)];
178
+ }
179
+ function genEnumsBody(enums) {
180
+ if (enums.length === 0) return "Record<string, never>";
181
+ const entries = enums.map((e) => {
182
+ const union = e.values.length === 0 ? "never" : e.values.map((v) => `'${v}'`).join(" | ");
183
+ return ` ${e.name}: ${union}`;
184
+ });
185
+ return `{
186
+ ${entries.join("\n")}
187
+ }`;
188
+ }
189
+ function genViewsBody(views, ctx) {
190
+ if (views.length === 0) return "Record<string, never>";
191
+ const entries = views.map(
192
+ (v) => ` ${v.name}: {
193
+ Row: {
194
+ ${genRow(v.columns, ctx)}
195
+ }
196
+ Relationships: []
197
+ }`
198
+ );
199
+ return `{
200
+ ${entries.join("\n")}
201
+ }`;
202
+ }
203
+ var HEADER = `// ============================================================
204
+ // Types TypeScript auto-g\xE9n\xE9r\xE9s par Aurabase (@aurabase/gen)
205
+ // NE PAS MODIFIER \u2014 r\xE9g\xE9n\xE9rer avec \`npx @aurabase/gen\`
206
+ // ============================================================
207
+ `;
208
+ function generateDatabaseTypes(tables, options = {}) {
209
+ const schemaName = options.schemaName ?? "public";
210
+ const typeName = options.typeName ?? "Database";
211
+ const enums = options.enums ?? [];
212
+ const views = options.views ?? [];
213
+ const relationNames = new Set([...tables, ...views].map((r) => r.name));
214
+ const ctx = { typeName, schemaName, enumNames: new Set(enums.map((e) => e.name)), relationNames };
215
+ const functionsBody = genFunctionsBody(options.functions ?? [], ctx);
216
+ const enumsBody = genEnumsBody(enums);
217
+ const viewsBody = genViewsBody(views, ctx);
218
+ const tablesBody = tables.length === 0 ? "Record<string, never>" : `{
219
+ ${tables.map(
220
+ (t) => ` ${t.name}: {
221
+ Row: {
222
+ ${genRow(t.columns, ctx)}
223
+ }
224
+ Insert: {
225
+ ${genInsert(t.columns, ctx)}
226
+ }
227
+ Update: {
228
+ ${genUpdate(t.columns, ctx)}
229
+ }
230
+ Relationships: ${genRelationships(t)}
231
+ }`
232
+ ).join("\n")}
233
+ }`;
234
+ return `${HEADER}
235
+ export type Json =
236
+ | string
237
+ | number
238
+ | boolean
239
+ | null
240
+ | { [key: string]: Json | undefined }
241
+ | Json[]
242
+
243
+ export interface ${typeName} {
244
+ ${schemaName}: {
245
+ Tables: ${tablesBody}
246
+ Views: ${viewsBody}
247
+ Functions: ${functionsBody}
248
+ Enums: ${enumsBody}
249
+ CompositeTypes: Record<string, never>
250
+ }
251
+ }
252
+ `;
253
+ }
254
+
255
+ export { generateDatabaseTypes };
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@aurabase/gen",
3
+ "version": "0.4.0",
4
+ "description": "Générateur de types TypeScript Database pour le SDK Aurabase (CLI aurabase-gen)",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "aurabase-gen": "./dist/cli.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "import": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "require": {
19
+ "types": "./dist/index.d.cts",
20
+ "default": "./dist/index.cjs"
21
+ }
22
+ }
23
+ },
24
+ "sideEffects": false,
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "engines": {
31
+ "node": ">=20.0.0"
32
+ },
33
+ "license": "MIT",
34
+ "author": "Aurabase",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/daylami555/aurabase.git",
38
+ "directory": "aurabase-js/packages/gen"
39
+ },
40
+ "homepage": "https://github.com/daylami555/aurabase/tree/main/aurabase-js/packages/gen#readme",
41
+ "bugs": {
42
+ "url": "https://github.com/daylami555/aurabase/issues"
43
+ },
44
+ "keywords": [
45
+ "aurabase",
46
+ "baas",
47
+ "sdk",
48
+ "generator",
49
+ "types"
50
+ ],
51
+ "dependencies": {
52
+ "@aurabase/core": "0.4.0",
53
+ "@aurabase/aurabase-js": "0.4.0"
54
+ },
55
+ "devDependencies": {
56
+ "tsup": "^8.0.0",
57
+ "typescript": "^5.5.0",
58
+ "vitest": "^4.1.6",
59
+ "@types/node": "20.14.15"
60
+ },
61
+ "scripts": {
62
+ "build": "tsup",
63
+ "test": "vitest run --passWithNoTests",
64
+ "typecheck": "tsc --noEmit"
65
+ }
66
+ }