@deessejs/collections 0.2.0 → 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/dist/cli.js +344 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +116 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -8
- package/dist/index.mjs.map +1 -1
- package/dist/next/index.js +15 -2
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +15 -2
- package/dist/next/index.mjs.map +1 -1
- package/package.json +5 -2
package/dist/cli.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/cli.ts
|
|
32
|
+
var cli_exports = {};
|
|
33
|
+
__export(cli_exports, {
|
|
34
|
+
main: () => main,
|
|
35
|
+
parseArgs: () => parseArgs,
|
|
36
|
+
printUsage: () => printUsage,
|
|
37
|
+
validatePath: () => validatePath
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(cli_exports);
|
|
40
|
+
var import_process = __toESM(require("process"));
|
|
41
|
+
|
|
42
|
+
// src/migrations.ts
|
|
43
|
+
var import_node_postgres = require("drizzle-orm/node-postgres");
|
|
44
|
+
|
|
45
|
+
// src/schema.ts
|
|
46
|
+
var import_pg_core = require("drizzle-orm/pg-core");
|
|
47
|
+
var buildTable = (collection) => {
|
|
48
|
+
const columns = {
|
|
49
|
+
// Add default id column
|
|
50
|
+
id: (0, import_pg_core.serial)("id").primaryKey()
|
|
51
|
+
};
|
|
52
|
+
for (const [fieldName, fieldDef] of Object.entries(collection.fields)) {
|
|
53
|
+
if (fieldName === "id") continue;
|
|
54
|
+
const fieldType = fieldDef.fieldType;
|
|
55
|
+
const fieldTypeName = fieldType.name || fieldType.type || "text";
|
|
56
|
+
switch (fieldTypeName) {
|
|
57
|
+
case "text":
|
|
58
|
+
columns[fieldName] = (0, import_pg_core.text)(fieldName);
|
|
59
|
+
break;
|
|
60
|
+
case "varchar":
|
|
61
|
+
columns[fieldName] = (0, import_pg_core.varchar)(fieldName, { length: 255 });
|
|
62
|
+
break;
|
|
63
|
+
case "number":
|
|
64
|
+
case "integer":
|
|
65
|
+
columns[fieldName] = (0, import_pg_core.integer)(fieldName);
|
|
66
|
+
break;
|
|
67
|
+
case "boolean":
|
|
68
|
+
columns[fieldName] = (0, import_pg_core.boolean)(fieldName);
|
|
69
|
+
break;
|
|
70
|
+
case "timestamp":
|
|
71
|
+
columns[fieldName] = (0, import_pg_core.timestamp)(fieldName);
|
|
72
|
+
break;
|
|
73
|
+
case "uuid":
|
|
74
|
+
columns[fieldName] = (0, import_pg_core.uuid)(fieldName);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
columns[fieldName] = (0, import_pg_core.text)(fieldName);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return (0, import_pg_core.pgTable)(collection.slug, columns);
|
|
81
|
+
};
|
|
82
|
+
var buildSchema = (collections) => {
|
|
83
|
+
const tables = {};
|
|
84
|
+
for (const coll of collections) {
|
|
85
|
+
tables[coll.slug] = buildTable(coll);
|
|
86
|
+
}
|
|
87
|
+
return tables;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/migrations.ts
|
|
91
|
+
async function getDrizzleKitApi() {
|
|
92
|
+
const api = require("drizzle-kit/api");
|
|
93
|
+
return api;
|
|
94
|
+
}
|
|
95
|
+
var push = async (adapter, collections, options = {}) => {
|
|
96
|
+
const { verbose = false, dryRun = false } = options;
|
|
97
|
+
const schema = buildSchema(collections);
|
|
98
|
+
const pool = await adapter.getPool();
|
|
99
|
+
const db = (0, import_node_postgres.drizzle)(pool, { schema });
|
|
100
|
+
const { pushSchema } = await getDrizzleKitApi();
|
|
101
|
+
if (verbose) {
|
|
102
|
+
console.log("[collections] Building schema from collections...");
|
|
103
|
+
console.log("[collections] Tables:", Object.keys(schema).join(", "));
|
|
104
|
+
}
|
|
105
|
+
const result = await pushSchema(schema, db);
|
|
106
|
+
if (verbose) {
|
|
107
|
+
if (result.warnings.length > 0) {
|
|
108
|
+
console.log("[collections] Warnings:");
|
|
109
|
+
result.warnings.forEach((w) => console.log(" -", w));
|
|
110
|
+
}
|
|
111
|
+
console.log("[collections] Statements to execute:", result.statementsToExecute.length);
|
|
112
|
+
}
|
|
113
|
+
if (dryRun) {
|
|
114
|
+
console.log("[collections] Dry run - not applying changes");
|
|
115
|
+
if (verbose) {
|
|
116
|
+
console.log("[collections] SQL statements:");
|
|
117
|
+
result.statementsToExecute.forEach((stmt) => console.log(" ", stmt));
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await result.apply();
|
|
122
|
+
if (verbose) {
|
|
123
|
+
console.log("[collections] Schema pushed successfully");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var generate = async (_adapter, collections, options = {}) => {
|
|
127
|
+
const { verbose = false, out = "./drizzle" } = options;
|
|
128
|
+
const schema = buildSchema(collections);
|
|
129
|
+
const { generateDrizzleJson } = await getDrizzleKitApi();
|
|
130
|
+
if (verbose) {
|
|
131
|
+
console.log("[collections] Building schema from collections...");
|
|
132
|
+
console.log("[collections] Tables:", Object.keys(schema).join(", "));
|
|
133
|
+
}
|
|
134
|
+
const currentSnapshot = generateDrizzleJson(schema);
|
|
135
|
+
if (verbose) {
|
|
136
|
+
console.log("[collections] Current snapshot ID:", currentSnapshot.id);
|
|
137
|
+
}
|
|
138
|
+
const migrationSQL = [
|
|
139
|
+
"-- Generated migration",
|
|
140
|
+
`-- Snapshot: ${currentSnapshot.id}`,
|
|
141
|
+
"",
|
|
142
|
+
"-- Tables will be created based on current collections schema",
|
|
143
|
+
...currentSnapshot.tables?.map((table) => `-- Table: ${table}`) ?? []
|
|
144
|
+
];
|
|
145
|
+
const { writeFileSync, mkdirSync } = await import("fs");
|
|
146
|
+
try {
|
|
147
|
+
mkdirSync(out, { recursive: true });
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
151
|
+
const filename = `${out}/migration-${timestamp2}.sql`;
|
|
152
|
+
writeFileSync(filename, migrationSQL.join("\n"));
|
|
153
|
+
if (verbose) {
|
|
154
|
+
console.log("[collections] Migration written to:", filename);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var migrate = async (adapter, options = {}) => {
|
|
158
|
+
const { verbose = false } = options;
|
|
159
|
+
const pool = await adapter.getPool();
|
|
160
|
+
if (verbose) {
|
|
161
|
+
console.log("[collections] Applying migrations...");
|
|
162
|
+
}
|
|
163
|
+
const { readdirSync, readFileSync } = await import("fs");
|
|
164
|
+
const migrationsPath = adapter.config.migrationsPath ?? "./migrations";
|
|
165
|
+
try {
|
|
166
|
+
const files = readdirSync(migrationsPath).filter((f) => f.endsWith(".sql")).sort();
|
|
167
|
+
if (files.length === 0) {
|
|
168
|
+
if (verbose) {
|
|
169
|
+
console.log("[collections] No migration files found");
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
for (const file of files) {
|
|
174
|
+
if (verbose) {
|
|
175
|
+
console.log("[collections] Applying migration:", file);
|
|
176
|
+
}
|
|
177
|
+
const sql = readFileSync(`${migrationsPath}/${file}`, "utf-8");
|
|
178
|
+
await pool.query(sql);
|
|
179
|
+
}
|
|
180
|
+
if (verbose) {
|
|
181
|
+
console.log("[collections] Migrations applied successfully");
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (verbose) {
|
|
185
|
+
console.log("[collections] No migrations directory or error:", error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/adapter.ts
|
|
191
|
+
var pgAdapter = (config) => {
|
|
192
|
+
let pool = null;
|
|
193
|
+
return {
|
|
194
|
+
type: "postgres",
|
|
195
|
+
config: {
|
|
196
|
+
url: config.url,
|
|
197
|
+
migrationsPath: config.migrationsPath ?? "./migrations"
|
|
198
|
+
},
|
|
199
|
+
getPool: async () => {
|
|
200
|
+
if (!pool) {
|
|
201
|
+
const { Pool } = await import("pg");
|
|
202
|
+
pool = new Pool({
|
|
203
|
+
connectionString: config.url
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return pool;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/cli.ts
|
|
212
|
+
function printUsage() {
|
|
213
|
+
console.log(`
|
|
214
|
+
@deessejs/collections CLI
|
|
215
|
+
|
|
216
|
+
Usage: collections <command> [options]
|
|
217
|
+
|
|
218
|
+
Commands:
|
|
219
|
+
db:push Push schema to database (development mode)
|
|
220
|
+
db:generate Generate migration files
|
|
221
|
+
db:migrate Apply pending migrations
|
|
222
|
+
|
|
223
|
+
Global Options:
|
|
224
|
+
--out <path> Output directory for migrations (default: ./drizzle)
|
|
225
|
+
--verbose Enable verbose output
|
|
226
|
+
--dry-run Dry run mode (only for db:push)
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
collections db:push
|
|
230
|
+
collections db:push --verbose
|
|
231
|
+
collections db:generate
|
|
232
|
+
collections db:migrate --verbose
|
|
233
|
+
collections db:push --dry-run
|
|
234
|
+
`);
|
|
235
|
+
}
|
|
236
|
+
function validatePath(path, name) {
|
|
237
|
+
if (path.includes("..")) {
|
|
238
|
+
console.error(`Error: ${name} path cannot contain ".." (path traversal not allowed)`);
|
|
239
|
+
import_process.default.exit(1);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function parseArgs() {
|
|
243
|
+
const args = import_process.default.argv.slice(2);
|
|
244
|
+
const options = {
|
|
245
|
+
verbose: false,
|
|
246
|
+
dryRun: false,
|
|
247
|
+
out: "./drizzle"
|
|
248
|
+
};
|
|
249
|
+
let command = null;
|
|
250
|
+
let dryRunWarningShown = false;
|
|
251
|
+
for (let i = 0; i < args.length; i++) {
|
|
252
|
+
const arg = args[i];
|
|
253
|
+
if (arg === "db:push" || arg === "db:generate" || arg === "db:migrate") {
|
|
254
|
+
command = arg;
|
|
255
|
+
} else if (arg === "--verbose" || arg === "-v") {
|
|
256
|
+
options.verbose = true;
|
|
257
|
+
} else if (arg === "--dry-run") {
|
|
258
|
+
options.dryRun = true;
|
|
259
|
+
if (command && command !== "db:push" && !dryRunWarningShown) {
|
|
260
|
+
console.warn("Warning: --dry-run is only applicable to db:push command");
|
|
261
|
+
dryRunWarningShown = true;
|
|
262
|
+
}
|
|
263
|
+
} else if (arg === "--out" || arg === "-o") {
|
|
264
|
+
const outValue = args[++i];
|
|
265
|
+
if (!outValue || outValue.startsWith("-")) {
|
|
266
|
+
console.error("Error: --out requires a value");
|
|
267
|
+
printUsage();
|
|
268
|
+
import_process.default.exit(1);
|
|
269
|
+
}
|
|
270
|
+
validatePath(outValue, "--out");
|
|
271
|
+
options.out = outValue;
|
|
272
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
273
|
+
printUsage();
|
|
274
|
+
import_process.default.exit(0);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return { command, options };
|
|
278
|
+
}
|
|
279
|
+
async function main() {
|
|
280
|
+
const { command, options } = parseArgs();
|
|
281
|
+
if (!command) {
|
|
282
|
+
console.error("Error: No command specified");
|
|
283
|
+
printUsage();
|
|
284
|
+
import_process.default.exit(1);
|
|
285
|
+
}
|
|
286
|
+
if (options.verbose) {
|
|
287
|
+
console.log("[collections] Command:", command);
|
|
288
|
+
console.log("[collections] Options:", options);
|
|
289
|
+
}
|
|
290
|
+
if (options.dryRun && command !== "db:push") {
|
|
291
|
+
console.warn("Warning: --dry-run is only applicable to db:push command, ignoring");
|
|
292
|
+
options.dryRun = false;
|
|
293
|
+
}
|
|
294
|
+
const dbUrl = import_process.default.env.DATABASE_URL;
|
|
295
|
+
if (!dbUrl) {
|
|
296
|
+
console.error("Error: DATABASE_URL environment variable is required");
|
|
297
|
+
console.error('Set it with: export DATABASE_URL="postgres://user:pass@localhost:5432/db"');
|
|
298
|
+
import_process.default.exit(1);
|
|
299
|
+
}
|
|
300
|
+
const adapter = pgAdapter({ url: dbUrl });
|
|
301
|
+
try {
|
|
302
|
+
switch (command) {
|
|
303
|
+
case "db:push":
|
|
304
|
+
if (options.verbose) {
|
|
305
|
+
console.log("[collections] Pushing schema to database...");
|
|
306
|
+
}
|
|
307
|
+
await push(adapter, [], options);
|
|
308
|
+
console.log("Schema pushed successfully");
|
|
309
|
+
break;
|
|
310
|
+
case "db:generate":
|
|
311
|
+
if (options.verbose) {
|
|
312
|
+
console.log("[collections] Generating migrations...");
|
|
313
|
+
}
|
|
314
|
+
await generate(adapter, [], options);
|
|
315
|
+
console.log("Migrations generated successfully");
|
|
316
|
+
break;
|
|
317
|
+
case "db:migrate":
|
|
318
|
+
if (options.verbose) {
|
|
319
|
+
console.log("[collections] Applying migrations...");
|
|
320
|
+
}
|
|
321
|
+
await migrate(adapter, options);
|
|
322
|
+
console.log("Migrations applied successfully");
|
|
323
|
+
break;
|
|
324
|
+
default:
|
|
325
|
+
console.error(`Error: Unknown command "${command}"`);
|
|
326
|
+
printUsage();
|
|
327
|
+
import_process.default.exit(1);
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
331
|
+
import_process.default.exit(1);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
if (import_process.default.argv[1]?.includes("cli")) {
|
|
335
|
+
main();
|
|
336
|
+
}
|
|
337
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
338
|
+
0 && (module.exports = {
|
|
339
|
+
main,
|
|
340
|
+
parseArgs,
|
|
341
|
+
printUsage,
|
|
342
|
+
validatePath
|
|
343
|
+
});
|
|
344
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/migrations.ts","../src/schema.ts","../src/adapter.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\n/**\r\n * CLI entry point for @deessejs/collections\r\n *\r\n * Provides commands for database migrations and schema management\r\n */\r\n\r\nimport process from 'process'\r\n\r\nimport { push, generate, migrate, type MigrationOptions } from './migrations'\r\nimport { pgAdapter } from './adapter'\r\n\r\n/**\r\n * Print usage information\r\n */\r\nfunction printUsage(): void {\r\n console.log(`\r\n@deessejs/collections CLI\r\n\r\nUsage: collections <command> [options]\r\n\r\nCommands:\r\n db:push Push schema to database (development mode)\r\n db:generate Generate migration files\r\n db:migrate Apply pending migrations\r\n\r\nGlobal Options:\r\n --out <path> Output directory for migrations (default: ./drizzle)\r\n --verbose Enable verbose output\r\n --dry-run Dry run mode (only for db:push)\r\n\r\nExamples:\r\n collections db:push\r\n collections db:push --verbose\r\n collections db:generate\r\n collections db:migrate --verbose\r\n collections db:push --dry-run\r\n`)\r\n}\r\n\r\n/**\r\n * Validate path to prevent path traversal attacks\r\n */\r\nfunction validatePath(path: string, name: string): void {\r\n if (path.includes('..')) {\r\n console.error(`Error: ${name} path cannot contain \"..\" (path traversal not allowed)`)\r\n process.exit(1)\r\n }\r\n}\r\n\r\n/**\r\n * Parse command line arguments\r\n */\r\nfunction parseArgs(): {\r\n command: string | null\r\n options: MigrationOptions\r\n} {\r\n const args = process.argv.slice(2)\r\n const options: MigrationOptions = {\r\n verbose: false,\r\n dryRun: false,\r\n out: './drizzle'\r\n }\r\n\r\n let command: string | null = null\r\n let dryRunWarningShown = false\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i]\r\n\r\n if (arg === 'db:push' || arg === 'db:generate' || arg === 'db:migrate') {\r\n command = arg\r\n } else if (arg === '--verbose' || arg === '-v') {\r\n options.verbose = true\r\n } else if (arg === '--dry-run') {\r\n options.dryRun = true\r\n // Warn if --dry-run is used with non-push command\r\n if (command && command !== 'db:push' && !dryRunWarningShown) {\r\n console.warn('Warning: --dry-run is only applicable to db:push command')\r\n dryRunWarningShown = true\r\n }\r\n } else if (arg === '--out' || arg === '-o') {\r\n const outValue = args[++i]\r\n if (!outValue || outValue.startsWith('-')) {\r\n console.error('Error: --out requires a value')\r\n printUsage()\r\n process.exit(1)\r\n }\r\n validatePath(outValue, '--out')\r\n options.out = outValue\r\n } else if (arg === '--help' || arg === '-h') {\r\n printUsage()\r\n process.exit(0)\r\n }\r\n }\r\n\r\n return { command, options }\r\n}\r\n\r\n/**\r\n * Main CLI function\r\n */\r\nasync function main(): Promise<void> {\r\n const { command, options } = parseArgs()\r\n\r\n if (!command) {\r\n console.error('Error: No command specified')\r\n printUsage()\r\n process.exit(1)\r\n }\r\n\r\n if (options.verbose) {\r\n console.log('[collections] Command:', command)\r\n console.log('[collections] Options:', options)\r\n }\r\n\r\n // Validate --dry-run is only used with db:push\r\n if (options.dryRun && command !== 'db:push') {\r\n console.warn('Warning: --dry-run is only applicable to db:push command, ignoring')\r\n options.dryRun = false\r\n }\r\n\r\n // Get database URL from environment or prompt\r\n const dbUrl = process.env.DATABASE_URL\r\n if (!dbUrl) {\r\n console.error('Error: DATABASE_URL environment variable is required')\r\n console.error('Set it with: export DATABASE_URL=\"postgres://user:pass@localhost:5432/db\"')\r\n process.exit(1)\r\n }\r\n\r\n const adapter = pgAdapter({ url: dbUrl })\r\n\r\n try {\r\n switch (command) {\r\n case 'db:push':\r\n if (options.verbose) {\r\n console.log('[collections] Pushing schema to database...')\r\n }\r\n await push(adapter, [], options)\r\n console.log('Schema pushed successfully')\r\n break\r\n\r\n case 'db:generate':\r\n if (options.verbose) {\r\n console.log('[collections] Generating migrations...')\r\n }\r\n await generate(adapter, [], options)\r\n console.log('Migrations generated successfully')\r\n break\r\n\r\n case 'db:migrate':\r\n if (options.verbose) {\r\n console.log('[collections] Applying migrations...')\r\n }\r\n await migrate(adapter, options)\r\n console.log('Migrations applied successfully')\r\n break\r\n\r\n default:\r\n console.error(`Error: Unknown command \"${command}\"`)\r\n printUsage()\r\n process.exit(1)\r\n }\r\n } catch (error) {\r\n console.error('Error:', error instanceof Error ? error.message : error)\r\n process.exit(1)\r\n }\r\n}\r\n\r\n// Export for testing\r\nexport { main, parseArgs, printUsage, validatePath }\r\n\r\n// Run if executed directly (not when imported for tests)\r\nif (process.argv[1]?.includes('cli')) {\r\n main()\r\n}\r\n","import { drizzle } from 'drizzle-orm/node-postgres'\r\n\r\nimport type { PgAdapter } from './adapter'\r\nimport type { Collection } from './collection'\r\nimport { buildSchema } from './schema'\r\n\r\n/**\r\n * Get drizzle-kit API lazily to avoid import errors during module load\r\n */\r\nasync function getDrizzleKitApi() {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const api = require('drizzle-kit/api')\r\n return api\r\n}\r\n\r\n/**\r\n * Migration options\r\n */\r\nexport type MigrationOptions = {\r\n /** Output directory for generated files */\r\n out?: string\r\n /** Enable verbose output */\r\n verbose?: boolean\r\n /** Dry run mode - don't apply changes */\r\n dryRun?: boolean\r\n}\r\n\r\n/**\r\n * Push schema to database (development mode)\r\n *\r\n * Uses drizzle-kit programmatic API to push schema changes to the database\r\n *\r\n * @example\r\n * import { push } from '@deessejs/collections'\r\n * import { pgAdapter } from '@deessejs/collections'\r\n *\r\n * const adapter = pgAdapter({ url: process.env.DATABASE_URL })\r\n * await push(adapter, collections)\r\n */\r\nexport const push = async (\r\n adapter: PgAdapter,\r\n collections: Collection[],\r\n options: MigrationOptions = {}\r\n): Promise<void> => {\r\n const { verbose = false, dryRun = false } = options\r\n\r\n // Build schema from collections\r\n const schema = buildSchema(collections)\r\n\r\n // Get pool and create drizzle instance\r\n const pool = await adapter.getPool()\r\n const db = drizzle(pool, { schema })\r\n\r\n // Use drizzle-kit API\r\n const { pushSchema } = await getDrizzleKitApi()\r\n\r\n if (verbose) {\r\n console.log('[collections] Building schema from collections...')\r\n console.log('[collections] Tables:', Object.keys(schema).join(', '))\r\n }\r\n\r\n // Use pushSchema directly\r\n const result = await pushSchema(schema as Record<string, unknown>, db)\r\n\r\n if (verbose) {\r\n if (result.warnings.length > 0) {\r\n console.log('[collections] Warnings:')\r\n result.warnings.forEach((w: string) => console.log(' -', w))\r\n }\r\n console.log('[collections] Statements to execute:', result.statementsToExecute.length)\r\n }\r\n\r\n if (dryRun) {\r\n console.log('[collections] Dry run - not applying changes')\r\n if (verbose) {\r\n console.log('[collections] SQL statements:')\r\n result.statementsToExecute.forEach((stmt: string) => console.log(' ', stmt))\r\n }\r\n return\r\n }\r\n\r\n // Apply changes\r\n await result.apply()\r\n\r\n if (verbose) {\r\n console.log('[collections] Schema pushed successfully')\r\n }\r\n}\r\n\r\n/**\r\n * Generate migration files\r\n *\r\n * Uses drizzle-kit programmatic API to generate migration SQL files\r\n *\r\n * @example\r\n * import { generate } from '@deessejs/collections'\r\n * import { pgAdapter } from '@deessejs/collections'\r\n *\r\n * const adapter = pgAdapter({ url: process.env.DATABASE_URL })\r\n * await generate(adapter, collections, { out: './migrations' })\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nexport const generate = async (\r\n _adapter: PgAdapter,\r\n collections: Collection[],\r\n options: MigrationOptions = {}\r\n): Promise<void> => {\r\n const { verbose = false, out = './drizzle' } = options\r\n\r\n // Build schema from collections\r\n const schema = buildSchema(collections)\r\n\r\n // Use drizzle-kit API\r\n const { generateDrizzleJson } = await getDrizzleKitApi()\r\n\r\n if (verbose) {\r\n console.log('[collections] Building schema from collections...')\r\n console.log('[collections] Tables:', Object.keys(schema).join(', '))\r\n }\r\n\r\n // Generate current schema snapshot\r\n const currentSnapshot = generateDrizzleJson(schema as Record<string, unknown>)\r\n\r\n // For now, we'll create a basic migration\r\n // In a full implementation, we'd need to:\r\n // 1. Read existing migrations from the database\r\n // 2. Get the previous snapshot\r\n // 3. Generate migration between prev and current\r\n\r\n if (verbose) {\r\n console.log('[collections] Current snapshot ID:', currentSnapshot.id)\r\n }\r\n\r\n // For simplicity, we'll just output the current schema as a migration\r\n // This is a simplified version - full implementation would track migrations\r\n const migrationSQL = [\r\n '-- Generated migration',\r\n `-- Snapshot: ${currentSnapshot.id}`,\r\n '',\r\n '-- Tables will be created based on current collections schema',\r\n ...currentSnapshot.tables?.map((table: string) => `-- Table: ${table}`) ?? []\r\n ]\r\n\r\n // Write to file\r\n const { writeFileSync, mkdirSync } = await import('fs')\r\n try {\r\n mkdirSync(out, { recursive: true })\r\n } catch {\r\n // Directory might already exist\r\n }\r\n\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-')\r\n const filename = `${out}/migration-${timestamp}.sql`\r\n\r\n writeFileSync(filename, migrationSQL.join('\\n'))\r\n\r\n if (verbose) {\r\n console.log('[collections] Migration written to:', filename)\r\n }\r\n}\r\n\r\n/**\r\n * Apply migrations\r\n *\r\n * Uses drizzle-kit programmatic API to apply pending migrations\r\n *\r\n * @example\r\n * import { migrate } from '@deessejs/collections'\r\n * import { pgAdapter } from '@deessejs/collections'\r\n *\r\n * const adapter = pgAdapter({ url: process.env.DATABASE_URL })\r\n * await migrate(adapter)\r\n */\r\nexport const migrate = async (\r\n adapter: PgAdapter,\r\n options: MigrationOptions = {}\r\n): Promise<void> => {\r\n const { verbose = false } = options\r\n\r\n // Get pool\r\n const pool = await adapter.getPool()\r\n\r\n if (verbose) {\r\n console.log('[collections] Applying migrations...')\r\n }\r\n\r\n // For migrations, we use the same approach as push\r\n // The migrations table tracks which migrations have been applied\r\n // This is a simplified version\r\n\r\n // Get all migration files\r\n const { readdirSync, readFileSync } = await import('fs')\r\n const migrationsPath = adapter.config.migrationsPath ?? './migrations'\r\n\r\n try {\r\n const files = readdirSync(migrationsPath)\r\n .filter(f => f.endsWith('.sql'))\r\n .sort()\r\n\r\n if (files.length === 0) {\r\n if (verbose) {\r\n console.log('[collections] No migration files found')\r\n }\r\n return\r\n }\r\n\r\n // Execute each migration\r\n for (const file of files) {\r\n if (verbose) {\r\n console.log('[collections] Applying migration:', file)\r\n }\r\n\r\n const sql = readFileSync(`${migrationsPath}/${file}`, 'utf-8')\r\n await pool.query(sql)\r\n }\r\n\r\n if (verbose) {\r\n console.log('[collections] Migrations applied successfully')\r\n }\r\n } catch (error) {\r\n if (verbose) {\r\n console.log('[collections] No migrations directory or error:', error)\r\n }\r\n // If no migrations directory, just return\r\n }\r\n}\r\n","import { pgTable, serial, text, timestamp, uuid, varchar, boolean, integer } from 'drizzle-orm/pg-core'\r\n\r\nimport type { Collection } from './collection'\r\n\r\n/**\r\n * Build Drizzle table from collection definition\r\n */\r\nexport const buildTable = (collection: Collection) => {\r\n // Build columns object\r\n const columns: Record<string, unknown> = {\r\n // Add default id column\r\n id: serial('id').primaryKey()\r\n }\r\n\r\n // Build columns from fields\r\n for (const [fieldName, fieldDef] of Object.entries(collection.fields)) {\r\n // Skip the id field if explicitly defined in fields\r\n if (fieldName === 'id') continue\r\n\r\n const fieldType = fieldDef.fieldType as { name?: string; type?: string }\r\n const fieldTypeName = fieldType.name || fieldType.type || 'text'\r\n\r\n switch (fieldTypeName) {\r\n case 'text':\r\n columns[fieldName] = text(fieldName)\r\n break\r\n case 'varchar':\r\n columns[fieldName] = varchar(fieldName, { length: 255 })\r\n break\r\n case 'number':\r\n case 'integer':\r\n columns[fieldName] = integer(fieldName)\r\n break\r\n case 'boolean':\r\n columns[fieldName] = boolean(fieldName)\r\n break\r\n case 'timestamp':\r\n columns[fieldName] = timestamp(fieldName)\r\n break\r\n case 'uuid':\r\n columns[fieldName] = uuid(fieldName)\r\n break\r\n default:\r\n columns[fieldName] = text(fieldName)\r\n }\r\n }\r\n\r\n return pgTable(collection.slug, columns as Record<string, ReturnType<typeof text>>)\r\n}\r\n\r\n/**\r\n * Build all tables from collections\r\n */\r\nexport const buildSchema = (collections: Collection[]) => {\r\n const tables: Record<string, ReturnType<typeof pgTable>> = {}\r\n\r\n for (const coll of collections) {\r\n tables[coll.slug] = buildTable(coll)\r\n }\r\n\r\n return tables\r\n}\r\n","/**\r\n * PostgreSQL adapter configuration\r\n */\r\nexport type PgAdapterConfig = {\r\n url: string\r\n migrationsPath?: string\r\n}\r\n\r\n/**\r\n * PostgreSQL adapter\r\n *\r\n * @example\r\n * const adapter = pgAdapter({\r\n * url: 'postgres://user:pass@localhost:5432/db'\r\n * })\r\n *\r\n * // Get pool for drizzle\r\n * const pool = adapter.getPool()\r\n */\r\nexport interface PgAdapter {\r\n type: 'postgres'\r\n config: PgAdapterConfig\r\n /** Get the underlying connection pool */\r\n getPool: () => Promise<import('pg').Pool>\r\n}\r\n\r\n/**\r\n * Database adapter type\r\n */\r\nexport type DatabaseAdapter = PgAdapter\r\n\r\n/**\r\n * Creates a PostgreSQL adapter\r\n *\r\n * @example\r\n * const adapter = pgAdapter({\r\n * url: 'postgres://user:pass@localhost:5432/db'\r\n * })\r\n *\r\n * // Get pool for drizzle\r\n * const pool = await adapter.getPool()\r\n */\r\nexport const pgAdapter = (config: PgAdapterConfig): PgAdapter => {\r\n let pool: import('pg').Pool | null = null\r\n\r\n return {\r\n type: 'postgres',\r\n config: {\r\n url: config.url,\r\n migrationsPath: config.migrationsPath ?? './migrations'\r\n },\r\n getPool: async () => {\r\n if (!pool) {\r\n const { Pool } = await import('pg')\r\n pool = new Pool({\r\n connectionString: config.url\r\n })\r\n }\r\n return pool\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["timestamp","process","process"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc2) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -721,11 +731,21 @@ var createCollectionOperations = (_collection, _slug, _db, _table, _hooks) => {
|
|
|
721
731
|
|
|
722
732
|
// src/adapter.ts
|
|
723
733
|
var pgAdapter = (config) => {
|
|
734
|
+
let pool = null;
|
|
724
735
|
return {
|
|
725
736
|
type: "postgres",
|
|
726
737
|
config: {
|
|
727
738
|
url: config.url,
|
|
728
739
|
migrationsPath: config.migrationsPath ?? "./migrations"
|
|
740
|
+
},
|
|
741
|
+
getPool: async () => {
|
|
742
|
+
if (!pool) {
|
|
743
|
+
const { Pool: Pool2 } = await import("pg");
|
|
744
|
+
pool = new Pool2({
|
|
745
|
+
connectionString: config.url
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
return pool;
|
|
729
749
|
}
|
|
730
750
|
};
|
|
731
751
|
};
|
|
@@ -776,21 +796,109 @@ var buildSchema = (collections) => {
|
|
|
776
796
|
};
|
|
777
797
|
|
|
778
798
|
// src/migrations.ts
|
|
779
|
-
var
|
|
799
|
+
var import_node_postgres = require("drizzle-orm/node-postgres");
|
|
800
|
+
async function getDrizzleKitApi() {
|
|
801
|
+
const api = require("drizzle-kit/api");
|
|
802
|
+
return api;
|
|
803
|
+
}
|
|
804
|
+
var push = async (adapter, collections, options = {}) => {
|
|
805
|
+
const { verbose = false, dryRun = false } = options;
|
|
780
806
|
const schema = buildSchema(collections);
|
|
781
|
-
|
|
807
|
+
const pool = await adapter.getPool();
|
|
808
|
+
const db = (0, import_node_postgres.drizzle)(pool, { schema });
|
|
809
|
+
const { pushSchema } = await getDrizzleKitApi();
|
|
810
|
+
if (verbose) {
|
|
811
|
+
console.log("[collections] Building schema from collections...");
|
|
812
|
+
console.log("[collections] Tables:", Object.keys(schema).join(", "));
|
|
813
|
+
}
|
|
814
|
+
const result = await pushSchema(schema, db);
|
|
815
|
+
if (verbose) {
|
|
816
|
+
if (result.warnings.length > 0) {
|
|
817
|
+
console.log("[collections] Warnings:");
|
|
818
|
+
result.warnings.forEach((w) => console.log(" -", w));
|
|
819
|
+
}
|
|
820
|
+
console.log("[collections] Statements to execute:", result.statementsToExecute.length);
|
|
821
|
+
}
|
|
822
|
+
if (dryRun) {
|
|
823
|
+
console.log("[collections] Dry run - not applying changes");
|
|
824
|
+
if (verbose) {
|
|
825
|
+
console.log("[collections] SQL statements:");
|
|
826
|
+
result.statementsToExecute.forEach((stmt) => console.log(" ", stmt));
|
|
827
|
+
}
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
await result.apply();
|
|
831
|
+
if (verbose) {
|
|
832
|
+
console.log("[collections] Schema pushed successfully");
|
|
833
|
+
}
|
|
782
834
|
};
|
|
783
|
-
var generate = async (_adapter, collections) => {
|
|
835
|
+
var generate = async (_adapter, collections, options = {}) => {
|
|
836
|
+
const { verbose = false, out = "./drizzle" } = options;
|
|
784
837
|
const schema = buildSchema(collections);
|
|
785
|
-
|
|
838
|
+
const { generateDrizzleJson } = await getDrizzleKitApi();
|
|
839
|
+
if (verbose) {
|
|
840
|
+
console.log("[collections] Building schema from collections...");
|
|
841
|
+
console.log("[collections] Tables:", Object.keys(schema).join(", "));
|
|
842
|
+
}
|
|
843
|
+
const currentSnapshot = generateDrizzleJson(schema);
|
|
844
|
+
if (verbose) {
|
|
845
|
+
console.log("[collections] Current snapshot ID:", currentSnapshot.id);
|
|
846
|
+
}
|
|
847
|
+
const migrationSQL = [
|
|
848
|
+
"-- Generated migration",
|
|
849
|
+
`-- Snapshot: ${currentSnapshot.id}`,
|
|
850
|
+
"",
|
|
851
|
+
"-- Tables will be created based on current collections schema",
|
|
852
|
+
...currentSnapshot.tables?.map((table) => `-- Table: ${table}`) ?? []
|
|
853
|
+
];
|
|
854
|
+
const { writeFileSync, mkdirSync } = await import("fs");
|
|
855
|
+
try {
|
|
856
|
+
mkdirSync(out, { recursive: true });
|
|
857
|
+
} catch {
|
|
858
|
+
}
|
|
859
|
+
const timestamp3 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
860
|
+
const filename = `${out}/migration-${timestamp3}.sql`;
|
|
861
|
+
writeFileSync(filename, migrationSQL.join("\n"));
|
|
862
|
+
if (verbose) {
|
|
863
|
+
console.log("[collections] Migration written to:", filename);
|
|
864
|
+
}
|
|
786
865
|
};
|
|
787
|
-
var migrate = async (adapter) => {
|
|
788
|
-
|
|
866
|
+
var migrate = async (adapter, options = {}) => {
|
|
867
|
+
const { verbose = false } = options;
|
|
868
|
+
const pool = await adapter.getPool();
|
|
869
|
+
if (verbose) {
|
|
870
|
+
console.log("[collections] Applying migrations...");
|
|
871
|
+
}
|
|
872
|
+
const { readdirSync, readFileSync } = await import("fs");
|
|
873
|
+
const migrationsPath = adapter.config.migrationsPath ?? "./migrations";
|
|
874
|
+
try {
|
|
875
|
+
const files = readdirSync(migrationsPath).filter((f2) => f2.endsWith(".sql")).sort();
|
|
876
|
+
if (files.length === 0) {
|
|
877
|
+
if (verbose) {
|
|
878
|
+
console.log("[collections] No migration files found");
|
|
879
|
+
}
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
for (const file of files) {
|
|
883
|
+
if (verbose) {
|
|
884
|
+
console.log("[collections] Applying migration:", file);
|
|
885
|
+
}
|
|
886
|
+
const sql = readFileSync(`${migrationsPath}/${file}`, "utf-8");
|
|
887
|
+
await pool.query(sql);
|
|
888
|
+
}
|
|
889
|
+
if (verbose) {
|
|
890
|
+
console.log("[collections] Migrations applied successfully");
|
|
891
|
+
}
|
|
892
|
+
} catch (error) {
|
|
893
|
+
if (verbose) {
|
|
894
|
+
console.log("[collections] No migrations directory or error:", error);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
789
897
|
};
|
|
790
898
|
|
|
791
899
|
// src/config.ts
|
|
792
900
|
var import_pg = require("pg");
|
|
793
|
-
var
|
|
901
|
+
var import_node_postgres2 = require("drizzle-orm/node-postgres");
|
|
794
902
|
var defineConfig = (options) => {
|
|
795
903
|
let pool = null;
|
|
796
904
|
let dbInstance = null;
|
|
@@ -800,7 +908,7 @@ var defineConfig = (options) => {
|
|
|
800
908
|
connectionString: options.database.config.url
|
|
801
909
|
});
|
|
802
910
|
schema = buildSchema(options.collections);
|
|
803
|
-
dbInstance = (0,
|
|
911
|
+
dbInstance = (0, import_node_postgres2.drizzle)(pool, { schema });
|
|
804
912
|
}
|
|
805
913
|
const collectionsMap = {};
|
|
806
914
|
const collectionNames = [];
|