@deessejs/collections 0.2.0 → 0.3.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 ADDED
@@ -0,0 +1,354 @@
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_process2 = __toESM(require("process"));
41
+
42
+ // src/migrations.ts
43
+ var import_child_process = require("child_process");
44
+ var import_path = require("path");
45
+ var import_process = __toESM(require("process"));
46
+ function runCommand(command, args, options = {}) {
47
+ return new Promise((resolve2, reject) => {
48
+ if (options.verbose) {
49
+ console.log(`[collections] Running: ${command} ${args.join(" ")}`);
50
+ }
51
+ const child = (0, import_child_process.spawn)(command, args, {
52
+ stdio: options.verbose ? "inherit" : "pipe",
53
+ shell: true,
54
+ cwd: import_process.default.cwd()
55
+ });
56
+ let output = "";
57
+ if (!options.verbose) {
58
+ child.stdout?.on("data", (data) => {
59
+ output += data.toString();
60
+ });
61
+ child.stderr?.on("data", (data) => {
62
+ output += data.toString();
63
+ });
64
+ }
65
+ child.on("close", (code) => {
66
+ if (code === 0) {
67
+ resolve2(code ?? 0);
68
+ } else {
69
+ reject(new Error(`Command failed with code ${code}: ${output}`));
70
+ }
71
+ });
72
+ child.on("error", (error) => {
73
+ reject(error);
74
+ });
75
+ });
76
+ }
77
+ function buildDrizzleConfig(options) {
78
+ const config = {
79
+ dialect: "postgresql",
80
+ schema: options.schemaPath,
81
+ out: options.out,
82
+ dbCredentials: {
83
+ url: options.dbUrl
84
+ }
85
+ };
86
+ if (options.migrationsTable) {
87
+ config.migrations = {
88
+ table: options.migrationsTable
89
+ };
90
+ }
91
+ return JSON.stringify(config, null, 2);
92
+ }
93
+ var push = async (adapter, _collections, options = {}) => {
94
+ const {
95
+ verbose = false,
96
+ dryRun = false,
97
+ out = "./drizzle",
98
+ configPath = "./collections/config.ts",
99
+ migrationsTable = "__drizzle_collections"
100
+ } = options;
101
+ const configContent = buildDrizzleConfig({
102
+ out,
103
+ schemaPath: configPath,
104
+ dbUrl: adapter.config.url,
105
+ migrationsTable
106
+ });
107
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
108
+ const { writeFileSync, unlinkSync } = await import("fs");
109
+ try {
110
+ writeFileSync(drizzleConfigPath, configContent);
111
+ const args = ["drizzle-kit", "push"];
112
+ if (dryRun) {
113
+ args.push("--dry-run");
114
+ }
115
+ if (verbose) {
116
+ args.push("--verbose");
117
+ }
118
+ await runCommand("npx", args, { verbose });
119
+ if (verbose) {
120
+ console.log("[collections] Schema pushed successfully");
121
+ }
122
+ } finally {
123
+ try {
124
+ unlinkSync(drizzleConfigPath);
125
+ } catch {
126
+ }
127
+ }
128
+ };
129
+ var generate = async (adapter, _collections, options = {}) => {
130
+ const {
131
+ verbose = false,
132
+ out = "./drizzle",
133
+ configPath = "./collections/config.ts",
134
+ migrationsTable = "__drizzle_collections"
135
+ } = options;
136
+ const configContent = buildDrizzleConfig({
137
+ out,
138
+ schemaPath: configPath,
139
+ dbUrl: adapter.config.url,
140
+ migrationsTable
141
+ });
142
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
143
+ const { writeFileSync, unlinkSync } = await import("fs");
144
+ try {
145
+ writeFileSync(drizzleConfigPath, configContent);
146
+ const args = ["drizzle-kit", "generate"];
147
+ if (verbose) {
148
+ args.push("--verbose");
149
+ }
150
+ await runCommand("npx", args, { verbose });
151
+ if (verbose) {
152
+ console.log("[collections] Migrations generated successfully");
153
+ }
154
+ } finally {
155
+ try {
156
+ unlinkSync(drizzleConfigPath);
157
+ } catch {
158
+ }
159
+ }
160
+ };
161
+ var migrate = async (adapter, options = {}) => {
162
+ const {
163
+ verbose = false,
164
+ out = "./drizzle",
165
+ configPath = "./collections/config.ts",
166
+ migrationsTable = "__drizzle_collections"
167
+ } = options;
168
+ const configContent = buildDrizzleConfig({
169
+ out,
170
+ schemaPath: configPath,
171
+ dbUrl: adapter.config.url,
172
+ migrationsTable
173
+ });
174
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
175
+ const { writeFileSync, unlinkSync } = await import("fs");
176
+ try {
177
+ writeFileSync(drizzleConfigPath, configContent);
178
+ const args = ["drizzle-kit", "migrate"];
179
+ if (verbose) {
180
+ args.push("--verbose");
181
+ }
182
+ await runCommand("npx", args, { verbose });
183
+ if (verbose) {
184
+ console.log("[collections] Migrations applied successfully");
185
+ }
186
+ } finally {
187
+ try {
188
+ unlinkSync(drizzleConfigPath);
189
+ } catch {
190
+ }
191
+ }
192
+ };
193
+
194
+ // src/adapter.ts
195
+ var pgAdapter = (config) => {
196
+ return {
197
+ type: "postgres",
198
+ config: {
199
+ url: config.url,
200
+ migrationsPath: config.migrationsPath ?? "./migrations"
201
+ }
202
+ };
203
+ };
204
+
205
+ // src/cli.ts
206
+ function printUsage() {
207
+ console.log(`
208
+ @deessejs/collections CLI
209
+
210
+ Usage: collections <command> [options]
211
+
212
+ Commands:
213
+ db:push Push schema to database (development mode)
214
+ db:generate Generate migration files
215
+ db:migrate Apply pending migrations
216
+
217
+ Global Options:
218
+ --config <path> Path to collections config file (default: ./collections/config.ts)
219
+ --out <path> Output directory for migrations (default: ./drizzle)
220
+ --migrations-table Custom migrations table name (default: __drizzle_collections)
221
+ --verbose Enable verbose output
222
+ --dry-run Dry run mode (only for db:push)
223
+
224
+ Examples:
225
+ collections db:push
226
+ collections db:push --verbose
227
+ collections db:generate
228
+ collections db:migrate --verbose
229
+ collections db:push --dry-run
230
+ collections db:push --config ./my-config.ts --out ./my-drizzle
231
+ `);
232
+ }
233
+ function validatePath(path, name) {
234
+ if (path.includes("..")) {
235
+ console.error(`Error: ${name} path cannot contain ".." (path traversal not allowed)`);
236
+ import_process2.default.exit(1);
237
+ }
238
+ }
239
+ function parseArgs() {
240
+ const args = import_process2.default.argv.slice(2);
241
+ const options = {
242
+ verbose: false,
243
+ dryRun: false,
244
+ out: "./drizzle",
245
+ configPath: "./collections/config.ts",
246
+ migrationsTable: "__drizzle_collections"
247
+ };
248
+ let command = null;
249
+ let dryRunWarningShown = false;
250
+ for (let i = 0; i < args.length; i++) {
251
+ const arg = args[i];
252
+ if (arg === "db:push" || arg === "db:generate" || arg === "db:migrate") {
253
+ command = arg;
254
+ } else if (arg === "--verbose" || arg === "-v") {
255
+ options.verbose = true;
256
+ } else if (arg === "--dry-run") {
257
+ options.dryRun = true;
258
+ if (command && command !== "db:push" && !dryRunWarningShown) {
259
+ console.warn("Warning: --dry-run is only applicable to db:push command");
260
+ dryRunWarningShown = true;
261
+ }
262
+ } else if (arg === "--out" || arg === "-o") {
263
+ const outValue = args[++i];
264
+ if (!outValue || outValue.startsWith("-")) {
265
+ console.error("Error: --out requires a value");
266
+ printUsage();
267
+ import_process2.default.exit(1);
268
+ }
269
+ validatePath(outValue, "--out");
270
+ options.out = outValue;
271
+ } else if (arg === "--config" || arg === "-c") {
272
+ const configValue = args[++i];
273
+ if (!configValue || configValue.startsWith("-")) {
274
+ console.error("Error: --config requires a value");
275
+ printUsage();
276
+ import_process2.default.exit(1);
277
+ }
278
+ validatePath(configValue, "--config");
279
+ options.configPath = configValue;
280
+ } else if (arg === "--migrations-table") {
281
+ options.migrationsTable = args[++i];
282
+ } else if (arg === "--help" || arg === "-h") {
283
+ printUsage();
284
+ import_process2.default.exit(0);
285
+ }
286
+ }
287
+ return { command, options };
288
+ }
289
+ async function main() {
290
+ const { command, options } = parseArgs();
291
+ if (!command) {
292
+ console.error("Error: No command specified");
293
+ printUsage();
294
+ import_process2.default.exit(1);
295
+ }
296
+ if (options.verbose) {
297
+ console.log("[collections] Command:", command);
298
+ console.log("[collections] Options:", options);
299
+ }
300
+ if (options.dryRun && command !== "db:push") {
301
+ console.warn("Warning: --dry-run is only applicable to db:push command, ignoring");
302
+ options.dryRun = false;
303
+ }
304
+ const dbUrl = import_process2.default.env.DATABASE_URL;
305
+ if (!dbUrl) {
306
+ console.error("Error: DATABASE_URL environment variable is required");
307
+ console.error('Set it with: export DATABASE_URL="postgres://user:pass@localhost:5432/db"');
308
+ import_process2.default.exit(1);
309
+ }
310
+ const adapter = pgAdapter({ url: dbUrl });
311
+ try {
312
+ switch (command) {
313
+ case "db:push":
314
+ if (options.verbose) {
315
+ console.log("[collections] Pushing schema to database...");
316
+ }
317
+ await push(adapter, [], options);
318
+ console.log("Schema pushed successfully");
319
+ break;
320
+ case "db:generate":
321
+ if (options.verbose) {
322
+ console.log("[collections] Generating migrations...");
323
+ }
324
+ await generate(adapter, [], options);
325
+ console.log("Migrations generated successfully");
326
+ break;
327
+ case "db:migrate":
328
+ if (options.verbose) {
329
+ console.log("[collections] Applying migrations...");
330
+ }
331
+ await migrate(adapter, options);
332
+ console.log("Migrations applied successfully");
333
+ break;
334
+ default:
335
+ console.error(`Error: Unknown command "${command}"`);
336
+ printUsage();
337
+ import_process2.default.exit(1);
338
+ }
339
+ } catch (error) {
340
+ console.error("Error:", error instanceof Error ? error.message : error);
341
+ import_process2.default.exit(1);
342
+ }
343
+ }
344
+ if (import_process2.default.argv[1]?.includes("cli")) {
345
+ main();
346
+ }
347
+ // Annotate the CommonJS export names for ESM import in node:
348
+ 0 && (module.exports = {
349
+ main,
350
+ parseArgs,
351
+ printUsage,
352
+ validatePath
353
+ });
354
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/migrations.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 --config <path> Path to collections config file (default: ./collections/config.ts)\r\n --out <path> Output directory for migrations (default: ./drizzle)\r\n --migrations-table Custom migrations table name (default: __drizzle_collections)\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 collections db:push --config ./my-config.ts --out ./my-drizzle\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 configPath: './collections/config.ts',\r\n migrationsTable: '__drizzle_collections'\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 === '--config' || arg === '-c') {\r\n const configValue = args[++i]\r\n if (!configValue || configValue.startsWith('-')) {\r\n console.error('Error: --config requires a value')\r\n printUsage()\r\n process.exit(1)\r\n }\r\n validatePath(configValue, '--config')\r\n options.configPath = configValue\r\n } else if (arg === '--migrations-table') {\r\n options.migrationsTable = args[++i]\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 { spawn } from 'child_process'\r\nimport { resolve } from 'path'\r\nimport process from 'process'\r\n\r\nimport type { PgAdapter } from './adapter'\r\nimport type { Collection } from './collection'\r\n\r\n/**\r\n * Migration options\r\n */\r\nexport type MigrationOptions = {\r\n /** Path to the config file */\r\n configPath?: string\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 /** Custom migrations table name */\r\n migrationsTable?: string\r\n}\r\n\r\n/**\r\n * Run a command and return a promise\r\n */\r\nfunction runCommand(command: string, args: string[], options: { verbose?: boolean } = {}): Promise<number> {\r\n return new Promise((resolve, reject) => {\r\n if (options.verbose) {\r\n console.log(`[collections] Running: ${command} ${args.join(' ')}`)\r\n }\r\n\r\n const child = spawn(command, args, {\r\n stdio: options.verbose ? 'inherit' : 'pipe',\r\n shell: true,\r\n cwd: process.cwd()\r\n })\r\n\r\n let output = ''\r\n if (!options.verbose) {\r\n child.stdout?.on('data', (data) => {\r\n output += data.toString()\r\n })\r\n child.stderr?.on('data', (data) => {\r\n output += data.toString()\r\n })\r\n }\r\n\r\n child.on('close', (code) => {\r\n if (code === 0) {\r\n resolve(code ?? 0)\r\n } else {\r\n reject(new Error(`Command failed with code ${code}: ${output}`))\r\n }\r\n })\r\n\r\n child.on('error', (error) => {\r\n reject(error)\r\n })\r\n })\r\n}\r\n\r\n/**\r\n * Build drizzle-kit config file content\r\n */\r\nfunction buildDrizzleConfig(options: {\r\n out: string\r\n schemaPath: string\r\n dbUrl: string\r\n migrationsTable?: string\r\n}): string {\r\n const config: Record<string, unknown> = {\r\n dialect: 'postgresql',\r\n schema: options.schemaPath,\r\n out: options.out,\r\n dbCredentials: {\r\n url: options.dbUrl\r\n }\r\n }\r\n\r\n if (options.migrationsTable) {\r\n config.migrations = {\r\n table: options.migrationsTable\r\n }\r\n }\r\n\r\n return JSON.stringify(config, null, 2)\r\n}\r\n\r\n/**\r\n * Push schema to database (development mode)\r\n *\r\n * Uses drizzle-kit CLI to push schema changes to the database\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 {\r\n verbose = false,\r\n dryRun = false,\r\n out = './drizzle',\r\n configPath = './collections/config.ts',\r\n migrationsTable = '__drizzle_collections'\r\n } = options\r\n\r\n // Build temporary drizzle config\r\n const configContent = buildDrizzleConfig({\r\n out,\r\n schemaPath: configPath,\r\n dbUrl: adapter.config.url,\r\n migrationsTable\r\n })\r\n\r\n const drizzleConfigPath = resolve(process.cwd(), './drizzle.config.json')\r\n const { writeFileSync, unlinkSync } = await import('fs')\r\n\r\n try {\r\n // Write config file\r\n writeFileSync(drizzleConfigPath, configContent)\r\n\r\n const args = ['drizzle-kit', 'push']\r\n\r\n if (dryRun) {\r\n args.push('--dry-run')\r\n }\r\n\r\n if (verbose) {\r\n args.push('--verbose')\r\n }\r\n\r\n await runCommand('npx', args, { verbose })\r\n\r\n if (verbose) {\r\n console.log('[collections] Schema pushed successfully')\r\n }\r\n } finally {\r\n // Cleanup config file\r\n try {\r\n unlinkSync(drizzleConfigPath)\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Generate migration files\r\n *\r\n * Uses drizzle-kit CLI to create migration files\r\n */\r\nexport const generate = async (\r\n adapter: PgAdapter,\r\n _collections: Collection[],\r\n options: MigrationOptions = {}\r\n): Promise<void> => {\r\n const {\r\n verbose = false,\r\n out = './drizzle',\r\n configPath = './collections/config.ts',\r\n migrationsTable = '__drizzle_collections'\r\n } = options\r\n\r\n // Build temporary drizzle config\r\n const configContent = buildDrizzleConfig({\r\n out,\r\n schemaPath: configPath,\r\n dbUrl: adapter.config.url,\r\n migrationsTable\r\n })\r\n\r\n const drizzleConfigPath = resolve(process.cwd(), './drizzle.config.json')\r\n const { writeFileSync, unlinkSync } = await import('fs')\r\n\r\n try {\r\n // Write config file\r\n writeFileSync(drizzleConfigPath, configContent)\r\n\r\n const args = ['drizzle-kit', 'generate']\r\n\r\n if (verbose) {\r\n args.push('--verbose')\r\n }\r\n\r\n await runCommand('npx', args, { verbose })\r\n\r\n if (verbose) {\r\n console.log('[collections] Migrations generated successfully')\r\n }\r\n } finally {\r\n // Cleanup config file\r\n try {\r\n unlinkSync(drizzleConfigPath)\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Apply migrations\r\n *\r\n * Uses drizzle-kit CLI to apply pending migrations\r\n */\r\nexport const migrate = async (\r\n adapter: PgAdapter,\r\n options: MigrationOptions = {}\r\n): Promise<void> => {\r\n const {\r\n verbose = false,\r\n out = './drizzle',\r\n configPath = './collections/config.ts',\r\n migrationsTable = '__drizzle_collections'\r\n } = options\r\n\r\n // Build temporary drizzle config\r\n const configContent = buildDrizzleConfig({\r\n out,\r\n schemaPath: configPath,\r\n dbUrl: adapter.config.url,\r\n migrationsTable\r\n })\r\n\r\n const drizzleConfigPath = resolve(process.cwd(), './drizzle.config.json')\r\n const { writeFileSync, unlinkSync } = await import('fs')\r\n\r\n try {\r\n // Write config file\r\n writeFileSync(drizzleConfigPath, configContent)\r\n\r\n const args = ['drizzle-kit', 'migrate']\r\n\r\n if (verbose) {\r\n args.push('--verbose')\r\n }\r\n\r\n await runCommand('npx', args, { verbose })\r\n\r\n if (verbose) {\r\n console.log('[collections] Migrations applied successfully')\r\n }\r\n } finally {\r\n // Cleanup config file\r\n try {\r\n unlinkSync(drizzleConfigPath)\r\n } catch {\r\n // Ignore cleanup errors\r\n }\r\n }\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\nexport interface PgAdapter {\r\n type: 'postgres'\r\n config: PgAdapterConfig\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\nexport const pgAdapter = (config: PgAdapterConfig): PgAdapter => {\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 }\r\n}\r\n"],"mappings":"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","names":["import_process","resolve","process","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
@@ -776,16 +786,155 @@ var buildSchema = (collections) => {
776
786
  };
777
787
 
778
788
  // src/migrations.ts
779
- var push = async (_adapter, collections) => {
780
- const schema = buildSchema(collections);
781
- console.log("[TODO] Push schema with collections:", Object.keys(schema));
789
+ var import_child_process = require("child_process");
790
+ var import_path = require("path");
791
+ var import_process = __toESM(require("process"));
792
+ function runCommand(command, args, options = {}) {
793
+ return new Promise((resolve2, reject) => {
794
+ if (options.verbose) {
795
+ console.log(`[collections] Running: ${command} ${args.join(" ")}`);
796
+ }
797
+ const child = (0, import_child_process.spawn)(command, args, {
798
+ stdio: options.verbose ? "inherit" : "pipe",
799
+ shell: true,
800
+ cwd: import_process.default.cwd()
801
+ });
802
+ let output = "";
803
+ if (!options.verbose) {
804
+ child.stdout?.on("data", (data) => {
805
+ output += data.toString();
806
+ });
807
+ child.stderr?.on("data", (data) => {
808
+ output += data.toString();
809
+ });
810
+ }
811
+ child.on("close", (code) => {
812
+ if (code === 0) {
813
+ resolve2(code ?? 0);
814
+ } else {
815
+ reject(new Error(`Command failed with code ${code}: ${output}`));
816
+ }
817
+ });
818
+ child.on("error", (error) => {
819
+ reject(error);
820
+ });
821
+ });
822
+ }
823
+ function buildDrizzleConfig(options) {
824
+ const config = {
825
+ dialect: "postgresql",
826
+ schema: options.schemaPath,
827
+ out: options.out,
828
+ dbCredentials: {
829
+ url: options.dbUrl
830
+ }
831
+ };
832
+ if (options.migrationsTable) {
833
+ config.migrations = {
834
+ table: options.migrationsTable
835
+ };
836
+ }
837
+ return JSON.stringify(config, null, 2);
838
+ }
839
+ var push = async (adapter, _collections, options = {}) => {
840
+ const {
841
+ verbose = false,
842
+ dryRun = false,
843
+ out = "./drizzle",
844
+ configPath = "./collections/config.ts",
845
+ migrationsTable = "__drizzle_collections"
846
+ } = options;
847
+ const configContent = buildDrizzleConfig({
848
+ out,
849
+ schemaPath: configPath,
850
+ dbUrl: adapter.config.url,
851
+ migrationsTable
852
+ });
853
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
854
+ const { writeFileSync, unlinkSync } = await import("fs");
855
+ try {
856
+ writeFileSync(drizzleConfigPath, configContent);
857
+ const args = ["drizzle-kit", "push"];
858
+ if (dryRun) {
859
+ args.push("--dry-run");
860
+ }
861
+ if (verbose) {
862
+ args.push("--verbose");
863
+ }
864
+ await runCommand("npx", args, { verbose });
865
+ if (verbose) {
866
+ console.log("[collections] Schema pushed successfully");
867
+ }
868
+ } finally {
869
+ try {
870
+ unlinkSync(drizzleConfigPath);
871
+ } catch {
872
+ }
873
+ }
782
874
  };
783
- var generate = async (_adapter, collections) => {
784
- const schema = buildSchema(collections);
785
- console.log("[TODO] Generate migration with collections:", Object.keys(schema));
875
+ var generate = async (adapter, _collections, options = {}) => {
876
+ const {
877
+ verbose = false,
878
+ out = "./drizzle",
879
+ configPath = "./collections/config.ts",
880
+ migrationsTable = "__drizzle_collections"
881
+ } = options;
882
+ const configContent = buildDrizzleConfig({
883
+ out,
884
+ schemaPath: configPath,
885
+ dbUrl: adapter.config.url,
886
+ migrationsTable
887
+ });
888
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
889
+ const { writeFileSync, unlinkSync } = await import("fs");
890
+ try {
891
+ writeFileSync(drizzleConfigPath, configContent);
892
+ const args = ["drizzle-kit", "generate"];
893
+ if (verbose) {
894
+ args.push("--verbose");
895
+ }
896
+ await runCommand("npx", args, { verbose });
897
+ if (verbose) {
898
+ console.log("[collections] Migrations generated successfully");
899
+ }
900
+ } finally {
901
+ try {
902
+ unlinkSync(drizzleConfigPath);
903
+ } catch {
904
+ }
905
+ }
786
906
  };
787
- var migrate = async (adapter) => {
788
- console.log("[TODO] Apply migrations from:", adapter.config.migrationsPath);
907
+ var migrate = async (adapter, options = {}) => {
908
+ const {
909
+ verbose = false,
910
+ out = "./drizzle",
911
+ configPath = "./collections/config.ts",
912
+ migrationsTable = "__drizzle_collections"
913
+ } = options;
914
+ const configContent = buildDrizzleConfig({
915
+ out,
916
+ schemaPath: configPath,
917
+ dbUrl: adapter.config.url,
918
+ migrationsTable
919
+ });
920
+ const drizzleConfigPath = (0, import_path.resolve)(import_process.default.cwd(), "./drizzle.config.json");
921
+ const { writeFileSync, unlinkSync } = await import("fs");
922
+ try {
923
+ writeFileSync(drizzleConfigPath, configContent);
924
+ const args = ["drizzle-kit", "migrate"];
925
+ if (verbose) {
926
+ args.push("--verbose");
927
+ }
928
+ await runCommand("npx", args, { verbose });
929
+ if (verbose) {
930
+ console.log("[collections] Migrations applied successfully");
931
+ }
932
+ } finally {
933
+ try {
934
+ unlinkSync(drizzleConfigPath);
935
+ } catch {
936
+ }
937
+ }
789
938
  };
790
939
 
791
940
  // src/config.ts