greenseed 0.1.0 → 0.1.1

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.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var dotenv = require('dotenv');
5
4
  var sade = require('sade');
6
- var path = require('path');
7
5
  var v = require('valibot');
8
- var fs = require('fs');
6
+ var dotenv = require('dotenv');
7
+ var path2 = require('path');
9
8
  var postgres = require('postgres');
9
+ var fs = require('fs');
10
10
 
11
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
12
 
@@ -28,28 +28,114 @@ function _interopNamespace(e) {
28
28
  return Object.freeze(n);
29
29
  }
30
30
 
31
- var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
32
31
  var sade__default = /*#__PURE__*/_interopDefault(sade);
33
- var path__default = /*#__PURE__*/_interopDefault(path);
34
32
  var v__namespace = /*#__PURE__*/_interopNamespace(v);
35
- var fs__default = /*#__PURE__*/_interopDefault(fs);
33
+ var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
34
+ var path2__default = /*#__PURE__*/_interopDefault(path2);
36
35
  var postgres__default = /*#__PURE__*/_interopDefault(postgres);
36
+ var fs__default = /*#__PURE__*/_interopDefault(fs);
37
37
 
38
- // src/core/parsers/index.ts
39
- var parsers = {
40
- json(content, fileName) {
41
- try {
42
- return JSON.parse(content);
43
- } catch (err) {
44
- throw new Error(`Invalid JSON in ${fileName}: ${String(err)}`);
38
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
39
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
40
+ }) : x)(function(x) {
41
+ if (typeof require !== "undefined") return require.apply(this, arguments);
42
+ throw Error('Dynamic require of "' + x + '" is not supported');
43
+ });
44
+ function connect(url) {
45
+ return postgres__default.default(url, { max: 10, idle_timeout: 20 });
46
+ }
47
+ async function check(sql) {
48
+ try {
49
+ await sql`select 1`;
50
+ } catch (err) {
51
+ throw new Error("Database connection failed");
52
+ }
53
+ }
54
+ async function tableExists(sql, schema, table) {
55
+ const res = await sql`
56
+ select to_regclass(${schema + "." + table}) is not null as exists
57
+ `;
58
+ if (!res[0]) {
59
+ throw new Error("Failed checking table: " + schema + "." + table);
60
+ }
61
+ return res[0].exists;
62
+ }
63
+ async function validateTables(sql, tables) {
64
+ for (const t of tables) {
65
+ const ok = await tableExists(sql, t.schema, t.table);
66
+ if (!ok) {
67
+ throw new Error("Missing table: " + t.schema + "." + t.table);
45
68
  }
46
- },
47
- validateArray(data, fileName) {
48
- if (!Array.isArray(data)) {
49
- throw new Error(`Data in ${fileName} is not an array`);
69
+ }
70
+ }
71
+ async function metadata(sql, schema, table) {
72
+ const cols = await sql`
73
+ select column_name
74
+ from information_schema.columns
75
+ where table_schema = ${schema}
76
+ and table_name = ${table}
77
+ order by ordinal_position
78
+ `;
79
+ return { columns: cols.map((c) => c.column_name) };
80
+ }
81
+ async function insert(sql, schema, table, rows, columns, primaryKeys) {
82
+ if (primaryKeys.length === 0) {
83
+ throw new Error("No primary keys for " + schema + "." + table);
84
+ }
85
+ const q = await sql`
86
+ insert into ${sql(schema + "." + table)}
87
+ ${sql(rows, columns)}
88
+ on conflict (${sql(primaryKeys)}) do nothing
89
+ returning ${sql(primaryKeys[0] ?? [])}
90
+ `;
91
+ return q.length;
92
+ }
93
+ function exists(p) {
94
+ return fs__default.default.existsSync(p);
95
+ }
96
+ function readFile(p) {
97
+ try {
98
+ return fs__default.default.readFileSync(p, "utf8");
99
+ } catch (err) {
100
+ throw new Error("Failed to read file: " + p);
101
+ }
102
+ }
103
+ function resolvePath(p) {
104
+ return path2__default.default.resolve(process.cwd(), p);
105
+ }
106
+ function loadJsonArray(p, onMissing) {
107
+ if (!exists(p)) {
108
+ if (onMissing === "skip") {
109
+ return [];
50
110
  }
51
- return data;
111
+ throw new Error("Source file not found: " + p);
112
+ }
113
+ const raw = readFile(p);
114
+ let parsed;
115
+ try {
116
+ parsed = JSON.parse(raw);
117
+ } catch {
118
+ throw new Error("Invalid JSON: " + p);
119
+ }
120
+ if (!Array.isArray(parsed)) {
121
+ throw new Error("Data is not an array: " + p);
52
122
  }
123
+ return parsed;
124
+ }
125
+ function chunk(data, size) {
126
+ const out = [];
127
+ for (let i = 0; i < data.length; i += size) {
128
+ out.push(data.slice(i, i + size));
129
+ }
130
+ return out;
131
+ }
132
+
133
+ // src/app.ts
134
+ var C = {
135
+ reset: "\x1B[0m",
136
+ green: "\x1B[32m",
137
+ yellow: "\x1B[33m",
138
+ gray: "\x1B[90m"
53
139
  };
54
140
  var ConfigSchema = v__namespace.object({
55
141
  seedFileExtensions: v__namespace.array(v__namespace.picklist([".json"])),
@@ -64,286 +150,69 @@ var ConfigSchema = v__namespace.object({
64
150
  })
65
151
  )
66
152
  });
67
- var fileSystem = {
68
- exists(filePath) {
69
- return fs__default.default.existsSync(filePath);
70
- },
71
- read(filePath) {
72
- try {
73
- return fs__default.default.readFileSync(filePath, "utf8");
74
- } catch (err) {
75
- throw new Error(`Failed to read file at ${filePath}: ${String(err)}`);
76
- }
77
- },
78
- getExtension(filePath) {
79
- return path__default.default.extname(filePath).toLowerCase();
80
- },
81
- resolvePath(filePath) {
82
- return path__default.default.resolve(process.cwd(), filePath);
153
+ async function run(opts) {
154
+ dotenv__default.default.config();
155
+ const configPath = resolvePath(opts.config || "seed.config.json");
156
+ const raw = __require(configPath);
157
+ const parsed = v__namespace.safeParse(ConfigSchema, raw);
158
+ if (!parsed.success) {
159
+ throw new Error("Invalid configuration");
83
160
  }
84
- };
85
-
86
- // src/config/manager.ts
87
- var configManager = {
88
- getConfigPath(opts) {
89
- const fileName = opts.config || "seed.config.json";
90
- return fileSystem.resolvePath(fileName);
91
- },
92
- load(opts) {
93
- const configPath = this.getConfigPath(opts);
94
- if (!fileSystem.exists(configPath)) {
95
- throw new Error(`Config file not found at ${configPath}`);
96
- }
97
- const content = fileSystem.read(configPath);
98
- const data = parsers.json(content, path__default.default.basename(configPath));
99
- const result = v__namespace.safeParse(ConfigSchema, data);
100
- if (!result.success) {
101
- const errors = result.issues.map((issue) => `- ${issue.message}`).join("\n");
102
- throw new Error(`Invalid configuration:
103
- ${errors}`);
104
- }
105
- return result.output;
106
- },
107
- getDatabaseUrl(opts, config) {
108
- const varName = opts.dbvar && opts.dbvar.length > 0 ? opts.dbvar : config.databaseUrlEnvVar || "DATABASE_URL";
109
- const url = process.env[varName];
110
- if (!url) {
111
- throw new Error(
112
- `Database URL environment variable "${varName}" is not set`
113
- );
114
- }
115
- return url;
116
- },
117
- getConfigDir(opts) {
118
- const configPath = this.getConfigPath(opts);
119
- return path__default.default.dirname(configPath);
161
+ const config = parsed.output;
162
+ const dbVar = opts.dbvar && opts.dbvar.length > 0 ? opts.dbvar : config.databaseUrlEnvVar;
163
+ const dbUrl = process.env[dbVar];
164
+ if (!dbUrl) {
165
+ throw new Error("Missing DB env var: " + dbVar);
120
166
  }
121
- };
122
- var databaseConnection = {
123
- create(url) {
124
- return postgres__default.default(url, { max: 10, idle_timeout: 20 });
125
- },
126
- async checkConnection(sql) {
127
- try {
128
- await sql`select 1`;
129
- } catch (err) {
130
- const msg = err instanceof postgres__default.default.PostgresError ? err.message : String(err);
131
- throw new Error(`Failed to connect to database: ${msg}`);
132
- }
133
- }
134
- };
135
-
136
- // src/core/database/operations.ts
137
- var databaseOperations = {
138
- async tableExists(sql, tableName, schemaName) {
139
- try {
140
- const [result] = await sql`
141
- SELECT to_regclass(${schemaName + "." + tableName}) IS NOT NULL AS exists
142
- `;
143
- if (!result) {
144
- throw new Error(
145
- `Failed to check existence of table ${schemaName}.${tableName}`
146
- );
147
- }
148
- return result.exists;
149
- } catch (err) {
150
- throw new Error(
151
- `Failed to validate table ${schemaName}.${tableName}: ${String(err)}`
152
- );
153
- }
154
- },
155
- async validateTables(sql, tables) {
156
- const checks = await Promise.all(
157
- tables.map(async (t) => ({
158
- table: t.table,
159
- schema: t.schema,
160
- exists: await this.tableExists(sql, t.table, t.schema)
161
- }))
167
+ const sql = connect(dbUrl);
168
+ await check(sql);
169
+ await validateTables(
170
+ sql,
171
+ config.tables.map((t) => ({
172
+ table: t.table,
173
+ schema: t.schema
174
+ }))
175
+ );
176
+ console.log(C.gray + "Starting seed process" + C.reset);
177
+ for (const t of config.tables) {
178
+ const source = path2__default.default.resolve(path2__default.default.dirname(configPath), t.source);
179
+ const rows = loadJsonArray(source, config.onMissingFile || "error");
180
+ if (rows.length === 0) {
181
+ console.log(C.yellow + "Skipped " + t.table + C.reset);
182
+ continue;
183
+ }
184
+ const meta = await metadata(sql, t.schema, t.table);
185
+ const validCols = Object.keys(rows[0]).filter(
186
+ (c) => meta.columns.includes(c)
162
187
  );
163
- const missing = checks.filter((c) => !c.exists);
164
- if (missing.length > 0) {
165
- const missingNames = missing.map((m) => `${m.schema}.${m.table}`).join(", ");
166
- throw new Error(`Missing tables: ${missingNames}`);
167
- }
168
- },
169
- async getTableMetadata(sql, tableName, schemaName) {
170
- try {
171
- const columns = await sql`
172
- select column_name
173
- from information_schema.columns
174
- where table_schema = ${schemaName}
175
- and table_name = ${tableName}
176
- order by ordinal_position
177
- `;
178
- const primaryKeys = await sql`
179
- select a.attname as column_name
180
- from pg_index i
181
- join pg_attribute a on a.attrelid = i.indrelid and a.attnum = any(i.indkey)
182
- join pg_class c on c.oid = i.indrelid
183
- join pg_namespace n on n.oid = c.relnamespace
184
- where n.nspname = ${schemaName}
185
- and c.relname = ${tableName}
186
- and i.indisprimary
187
- `;
188
- return {
189
- columns: columns.map((c) => c.column_name),
190
- primaryKeys: primaryKeys.map((pk) => pk.column_name)
191
- };
192
- } catch (err) {
193
- throw new Error(
194
- `Failed to get metadata for table ${schemaName}.${tableName}: ${String(err)}`
188
+ let inserted = 0;
189
+ for (const part of chunk(rows, 1e3)) {
190
+ inserted += await insert(
191
+ sql,
192
+ t.schema,
193
+ t.table,
194
+ part,
195
+ validCols,
196
+ t.primaryKeys
195
197
  );
196
198
  }
197
- },
198
- async insertData(sql, tableName, schemaName, data, columns, primaryKeys) {
199
- if (primaryKeys.length === 0) {
200
- throw new Error(
201
- `Table ${schemaName}.${tableName} has no primary keys defined`
202
- );
203
- }
204
- const qualifiedTable = `${schemaName}.${tableName}`;
205
- const result = await sql`
206
- INSERT INTO ${sql(qualifiedTable)} ${sql(data, columns)}
207
- ON CONFLICT (${sql(primaryKeys)}) DO NOTHING
208
- RETURNING ${sql(primaryKeys[0] || [])}
209
- `;
210
- return result.length;
211
- }
212
- };
213
- var dataLoader = {
214
- load(sourcePath, config, configDir) {
215
- const fullPath = path__default.default.isAbsolute(sourcePath) ? sourcePath : path__default.default.resolve(configDir, sourcePath);
216
- if (!fileSystem.exists(fullPath)) {
217
- const onMissingFile = config.onMissingFile || "error";
218
- if (onMissingFile === "skip") {
219
- console.warn(`Warning: Source file not found at ${fullPath}. Skipping.`);
220
- return [];
221
- } else {
222
- throw new Error(`Source file not found at ${fullPath}`);
223
- }
224
- }
225
- const content = fileSystem.read(fullPath);
226
- const ext = fileSystem.getExtension(fullPath);
227
- if (ext === ".json") {
228
- const data = parsers.json(content, sourcePath);
229
- return parsers.validateArray(data, sourcePath);
230
- }
231
- throw new Error(`Unsupported file extension: ${ext}`);
232
- },
233
- chunkData(data, chunkSize) {
234
- const chunks = [];
235
- for (let i = 0; i < data.length; i += chunkSize) {
236
- chunks.push(data.slice(i, i + chunkSize));
237
- }
238
- return chunks;
239
- }
240
- };
241
-
242
- // src/services/seeder.ts
243
- var seeder = {
244
- async seedTable(sql, tableConfig, config, configDir) {
245
- const data = dataLoader.load(tableConfig.source, config, configDir);
246
- if (data.length === 0) {
247
- return {
248
- table: tableConfig.table,
249
- schema: tableConfig.schema,
250
- totalRecords: 0,
251
- insertedRecords: 0
252
- };
253
- }
254
- const metadata = await databaseOperations.getTableMetadata(
255
- sql,
256
- tableConfig.table,
257
- tableConfig.schema
258
- );
259
- const dataColumns = Object.keys(data[0] || {});
260
- const validColumns = dataColumns.filter(
261
- (col) => metadata.columns.includes(col)
199
+ console.log(
200
+ C.green + t.schema + "." + t.table + ": " + inserted + "/" + rows.length + C.reset
262
201
  );
263
- if (validColumns.length === 0) {
264
- throw new Error(
265
- `No valid columns found in data for table ${tableConfig.schema}.${tableConfig.table}`
266
- );
267
- }
268
- const chunks = dataLoader.chunkData(data, 1e3);
269
- let insertedCount = 0;
270
- for (const chunk of chunks) {
271
- try {
272
- const inserted = await databaseOperations.insertData(
273
- sql,
274
- tableConfig.table,
275
- tableConfig.schema,
276
- chunk,
277
- validColumns,
278
- tableConfig.primaryKeys
279
- );
280
- insertedCount += inserted;
281
- } catch (err) {
282
- const msg = err instanceof postgres__default.default.PostgresError ? err.message : String(err);
283
- throw new Error(
284
- `Failed to insert data into ${tableConfig.schema}.${tableConfig.table}: ${msg}`
285
- );
286
- }
287
- }
288
- return {
289
- table: tableConfig.table,
290
- schema: tableConfig.schema,
291
- totalRecords: data.length,
292
- insertedRecords: insertedCount
293
- };
294
- },
295
- async execute(config, sql, configDir) {
296
- const tables = config.tables.map((t) => ({
297
- table: t.table,
298
- schema: t.schema
299
- }));
300
- await databaseOperations.validateTables(sql, tables);
301
- console.log("Starting seed process.");
302
- for (const tableConfig of config.tables) {
303
- try {
304
- const result = await this.seedTable(sql, tableConfig, config, configDir);
305
- if (result.totalRecords === 0) {
306
- console.log(
307
- `No data to insert for table "${result.schema}.${result.table}"`
308
- );
309
- } else {
310
- console.log(
311
- `Table "${result.schema}.${result.table}": Processed ${result.totalRecords} records, inserted ${result.insertedRecords} new rows.`
312
- );
313
- }
314
- } catch (err) {
315
- throw new Error(
316
- `Failed to seed table "${tableConfig.schema}.${tableConfig.table}": ${String(err)}`
317
- );
318
- }
319
- }
320
- console.log("Seed process completed.");
321
- }
322
- };
323
-
324
- // src/services/application.ts
325
- var application = {
326
- async run(opts) {
327
- try {
328
- const config = configManager.load(opts);
329
- const configDir = configManager.getConfigDir(opts);
330
- const dbUrl = configManager.getDatabaseUrl(opts, config);
331
- const sql = databaseConnection.create(dbUrl);
332
- await databaseConnection.checkConnection(sql);
333
- await seeder.execute(config, sql, configDir);
334
- await sql.end();
335
- } catch (err) {
336
- console.error(String(err));
337
- process.exit(1);
338
- }
339
202
  }
340
- };
203
+ await sql.end();
204
+ console.log(C.green + "Seed completed" + C.reset);
205
+ }
341
206
 
342
207
  // src/cli.ts
343
208
  var prog = sade__default.default("greenseed");
344
- prog.command("push").option("-c, --config <file>", "Path to config file", "seed.config.json").option("-d, --dbvar <name>", "Database URL env var name (overrides config)").action(async (opts) => {
345
- dotenv__default.default.config();
346
- await application.run(opts);
209
+ prog.command("push").option("-c, --config <file>", "Config file", "seed.config.json").option("-d, --dbvar <name>", "DB env var override").action(async (opts) => {
210
+ try {
211
+ await run(opts);
212
+ } catch (err) {
213
+ console.error("\x1B[31m" + String(err) + "\x1B[0m");
214
+ process.exit(1);
215
+ }
347
216
  });
348
217
  prog.parse(process.argv);
349
218
  //# sourceMappingURL=cli.cjs.map
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/parsers/index.ts","../src/types/index.ts","../src/utils/file-system.ts","../src/config/manager.ts","../src/core/database/connection.ts","../src/core/database/operations.ts","../src/core/loaders/data-loader.ts","../src/services/seeder.ts","../src/services/application.ts","../src/cli.ts"],"names":["v","fs","path","v2","postgres","sade","dotenv"],"mappings":"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","file":"cli.cjs","sourcesContent":["export const parsers = {\n\tjson(content: string, fileName: string): unknown {\n\t\ttry {\n\t\t\treturn JSON.parse(content)\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Invalid JSON in ${fileName}: ${String(err)}`)\n\t\t}\n\t},\n\n\tvalidateArray(data: unknown, fileName: string): Record<string, any>[] {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Data in ${fileName} is not an array`)\n\t\t}\n\t\treturn data as Record<string, any>[]\n\t},\n}\n","import * as v from \"valibot\"\n\nexport const ConfigSchema = v.object({\n\tseedFileExtensions: v.array(v.picklist([\".json\"])),\n\tdatabaseUrlEnvVar: v.string(),\n\tonMissingFile: v.optional(v.picklist([\"skip\", \"error\"]), \"error\"),\n\ttables: v.array(\n\t\tv.object({\n\t\t\ttable: v.string(),\n\t\t\tschema: v.optional(v.string(), \"public\"),\n\t\t\tprimaryKeys: v.array(v.string()),\n\t\t\tsource: v.string(),\n\t\t}),\n\t),\n})\n\nexport type Config = v.InferOutput<typeof ConfigSchema>\n\nexport type TableConfig = {\n\ttable: string\n\tschema: string\n\tprimaryKeys: string[]\n\tsource: string\n}\n\nexport type TableMetadata = {\n\tcolumns: string[]\n\tprimaryKeys: string[]\n}\n\nexport type SeedResult = {\n\ttable: string\n\tschema: string\n\ttotalRecords: number\n\tinsertedRecords: number\n}\n\nexport type Opts = {\n\tconfig: string\n\tdbvar?: string\n}\n","import fs from \"fs\"\nimport path from \"path\"\n\nexport const fileSystem = {\n\texists(filePath: string): boolean {\n\t\treturn fs.existsSync(filePath)\n\t},\n\n\tread(filePath: string): string {\n\t\ttry {\n\t\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Failed to read file at ${filePath}: ${String(err)}`)\n\t\t}\n\t},\n\n\tgetExtension(filePath: string): string {\n\t\treturn path.extname(filePath).toLowerCase()\n\t},\n\n\tresolvePath(filePath: string): string {\n\t\treturn path.resolve(process.cwd(), filePath)\n\t},\n}\n","import path from \"path\"\nimport * as v from \"valibot\"\nimport { parsers } from \"../core/parsers\"\nimport type { Config, Opts } from \"../types\"\nimport { ConfigSchema } from \"../types\"\nimport { fileSystem } from \"../utils/file-system\"\n\nexport const configManager = {\n\tgetConfigPath(opts: Opts): string {\n\t\tconst fileName = opts.config || \"seed.config.json\"\n\t\treturn fileSystem.resolvePath(fileName)\n\t},\n\n\tload(opts: Opts): Config {\n\t\tconst configPath = this.getConfigPath(opts)\n\n\t\tif (!fileSystem.exists(configPath)) {\n\t\t\tthrow new Error(`Config file not found at ${configPath}`)\n\t\t}\n\n\t\tconst content = fileSystem.read(configPath)\n\t\tconst data = parsers.json(content, path.basename(configPath))\n\t\tconst result = v.safeParse(ConfigSchema, data)\n\n\t\tif (!result.success) {\n\t\t\tconst errors = result.issues\n\t\t\t\t.map((issue) => `- ${issue.message}`)\n\t\t\t\t.join(\"\\n\")\n\t\t\tthrow new Error(`Invalid configuration:\\n${errors}`)\n\t\t}\n\n\t\treturn result.output\n\t},\n\n\tgetDatabaseUrl(opts: Opts, config: Config): string {\n\t\tconst varName =\n\t\t\topts.dbvar && opts.dbvar.length > 0\n\t\t\t\t? opts.dbvar\n\t\t\t\t: config.databaseUrlEnvVar || \"DATABASE_URL\"\n\n\t\tconst url = process.env[varName]\n\t\tif (!url) {\n\t\t\tthrow new Error(\n\t\t\t\t`Database URL environment variable \"${varName}\" is not set`,\n\t\t\t)\n\t\t}\n\t\treturn url\n\t},\n\n\tgetConfigDir(opts: Opts): string {\n\t\tconst configPath = this.getConfigPath(opts)\n\t\treturn path.dirname(configPath)\n\t},\n}\n","import postgres from \"postgres\"\n\nexport const databaseConnection = {\n\tcreate(url: string): postgres.Sql {\n\t\treturn postgres(url, { max: 10, idle_timeout: 20 })\n\t},\n\n\tasync checkConnection(sql: postgres.Sql): Promise<void> {\n\t\ttry {\n\t\t\tawait sql`select 1`\n\t\t} catch (err) {\n\t\t\tconst msg =\n\t\t\t\terr instanceof postgres.PostgresError ? err.message : String(err)\n\t\t\tthrow new Error(`Failed to connect to database: ${msg}`)\n\t\t}\n\t},\n}\n","import postgres from \"postgres\"\nimport type { TableMetadata } from \"../../types\"\n\nexport const databaseOperations = {\n\tasync tableExists(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\tconst [result] = await sql<{ exists: boolean }[]>`\n\t\t\t\tSELECT to_regclass(${schemaName + \".\" + tableName}) IS NOT NULL AS exists\n\t\t\t`\n\n\t\t\tif (!result) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to check existence of table ${schemaName}.${tableName}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn result.exists\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to validate table ${schemaName}.${tableName}: ${String(err)}`,\n\t\t\t)\n\t\t}\n\t},\n\n\tasync validateTables(\n\t\tsql: postgres.Sql,\n\t\ttables: Array<{ table: string; schema: string }>,\n\t): Promise<void> {\n\t\tconst checks = await Promise.all(\n\t\t\ttables.map(async (t) => ({\n\t\t\t\ttable: t.table,\n\t\t\t\tschema: t.schema,\n\t\t\t\texists: await this.tableExists(sql, t.table, t.schema),\n\t\t\t})),\n\t\t)\n\n\t\tconst missing = checks.filter((c) => !c.exists)\n\t\tif (missing.length > 0) {\n\t\t\tconst missingNames = missing\n\t\t\t\t.map((m) => `${m.schema}.${m.table}`)\n\t\t\t\t.join(\", \")\n\t\t\tthrow new Error(`Missing tables: ${missingNames}`)\n\t\t}\n\t},\n\n\tasync getTableMetadata(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t): Promise<TableMetadata> {\n\t\ttry {\n\t\t\tconst columns = await sql<{ column_name: string }[]>`\n\t\t\t\tselect column_name\n\t\t\t\tfrom information_schema.columns\n\t\t\t\twhere table_schema = ${schemaName}\n\t\t\t\tand table_name = ${tableName}\n\t\t\t\torder by ordinal_position\n\t\t\t`\n\n\t\t\tconst primaryKeys = await sql<{ column_name: string }[]>`\n\t\t\t\tselect a.attname as column_name\n\t\t\t\tfrom pg_index i\n\t\t\t\tjoin pg_attribute a on a.attrelid = i.indrelid and a.attnum = any(i.indkey)\n\t\t\t\tjoin pg_class c on c.oid = i.indrelid\n\t\t\t\tjoin pg_namespace n on n.oid = c.relnamespace\n\t\t\t\twhere n.nspname = ${schemaName}\n\t\t\t\tand c.relname = ${tableName}\n\t\t\t\tand i.indisprimary\n\t\t\t`\n\n\t\t\treturn {\n\t\t\t\tcolumns: columns.map((c) => c.column_name),\n\t\t\t\tprimaryKeys: primaryKeys.map((pk) => pk.column_name),\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to get metadata for table ${schemaName}.${tableName}: ${String(err)}`,\n\t\t\t)\n\t\t}\n\t},\n\n\tasync insertData(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t\tdata: Record<string, any>[],\n\t\tcolumns: string[],\n\t\tprimaryKeys: string[],\n\t): Promise<number> {\n\t\tif (primaryKeys.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table ${schemaName}.${tableName} has no primary keys defined`,\n\t\t\t)\n\t\t}\n\n\t\tconst qualifiedTable = `${schemaName}.${tableName}`\n\t\tconst result = await sql`\n\t\t\tINSERT INTO ${sql(qualifiedTable)} ${sql(data, columns)}\n\t\t\tON CONFLICT (${sql(primaryKeys)}) DO NOTHING\n\t\t\tRETURNING ${sql(primaryKeys[0] || [])}\n\t\t`\n\n\t\treturn result.length\n\t},\n}\n","import path from \"path\"\nimport type { Config } from \"../../types\"\nimport { fileSystem } from \"../../utils/file-system\"\nimport { parsers } from \"../parsers\"\n\nexport const dataLoader = {\n\tload(\n\t\tsourcePath: string,\n\t\tconfig: Config,\n\t\tconfigDir: string,\n\t): Record<string, any>[] {\n\t\tconst fullPath = path.isAbsolute(sourcePath)\n\t\t\t? sourcePath\n\t\t\t: path.resolve(configDir, sourcePath)\n\n\t\tif (!fileSystem.exists(fullPath)) {\n\t\t\tconst onMissingFile = config.onMissingFile || \"error\"\n\n\t\t\tif (onMissingFile === \"skip\") {\n\t\t\t\tconsole.warn(`Warning: Source file not found at ${fullPath}. Skipping.`)\n\t\t\t\treturn []\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Source file not found at ${fullPath}`)\n\t\t\t}\n\t\t}\n\n\t\tconst content = fileSystem.read(fullPath)\n\t\tconst ext = fileSystem.getExtension(fullPath)\n\n\t\tif (ext === \".json\") {\n\t\t\tconst data = parsers.json(content, sourcePath)\n\t\t\treturn parsers.validateArray(data, sourcePath)\n\t\t}\n\n\t\tthrow new Error(`Unsupported file extension: ${ext}`)\n\t},\n\n\tchunkData<T>(data: T[], chunkSize: number): T[][] {\n\t\tconst chunks: T[][] = []\n\t\tfor (let i = 0; i < data.length; i += chunkSize) {\n\t\t\tchunks.push(data.slice(i, i + chunkSize))\n\t\t}\n\t\treturn chunks\n\t},\n}\n","import postgres from \"postgres\"\nimport { databaseOperations } from \"../core/database/operations\"\nimport { dataLoader } from \"../core/loaders/data-loader\"\nimport type { Config, SeedResult, TableConfig } from \"../types\"\n\nexport const seeder = {\n\tasync seedTable(\n\t\tsql: postgres.Sql,\n\t\ttableConfig: TableConfig,\n\t\tconfig: Config,\n\t\tconfigDir: string,\n\t): Promise<SeedResult> {\n\t\tconst data = dataLoader.load(tableConfig.source, config, configDir)\n\n\t\tif (data.length === 0) {\n\t\t\treturn {\n\t\t\t\ttable: tableConfig.table,\n\t\t\t\tschema: tableConfig.schema,\n\t\t\t\ttotalRecords: 0,\n\t\t\t\tinsertedRecords: 0,\n\t\t\t}\n\t\t}\n\n\t\tconst metadata = await databaseOperations.getTableMetadata(\n\t\t\tsql,\n\t\t\ttableConfig.table,\n\t\t\ttableConfig.schema,\n\t\t)\n\n\t\tconst dataColumns = Object.keys(data[0] || {})\n\t\tconst validColumns = dataColumns.filter((col) =>\n\t\t\tmetadata.columns.includes(col),\n\t\t)\n\n\t\tif (validColumns.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No valid columns found in data for table ${tableConfig.schema}.${tableConfig.table}`,\n\t\t\t)\n\t\t}\n\n\t\tconst chunks = dataLoader.chunkData(data, 1000)\n\t\tlet insertedCount = 0\n\n\t\tfor (const chunk of chunks) {\n\t\t\ttry {\n\t\t\t\tconst inserted = await databaseOperations.insertData(\n\t\t\t\t\tsql,\n\t\t\t\t\ttableConfig.table,\n\t\t\t\t\ttableConfig.schema,\n\t\t\t\t\tchunk,\n\t\t\t\t\tvalidColumns,\n\t\t\t\t\ttableConfig.primaryKeys,\n\t\t\t\t)\n\t\t\t\tinsertedCount += inserted\n\t\t\t} catch (err) {\n\t\t\t\tconst msg =\n\t\t\t\t\terr instanceof postgres.PostgresError ? err.message : String(err)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to insert data into ${tableConfig.schema}.${tableConfig.table}: ${msg}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttable: tableConfig.table,\n\t\t\tschema: tableConfig.schema,\n\t\t\ttotalRecords: data.length,\n\t\t\tinsertedRecords: insertedCount,\n\t\t}\n\t},\n\n\tasync execute(\n\t\tconfig: Config,\n\t\tsql: postgres.Sql,\n\t\tconfigDir: string,\n\t): Promise<void> {\n\t\tconst tables = config.tables.map((t) => ({\n\t\t\ttable: t.table,\n\t\t\tschema: t.schema,\n\t\t}))\n\t\tawait databaseOperations.validateTables(sql, tables)\n\n\t\tconsole.log(\"Starting seed process.\")\n\n\t\tfor (const tableConfig of config.tables) {\n\t\t\ttry {\n\t\t\t\tconst result = await this.seedTable(sql, tableConfig, config, configDir)\n\n\t\t\t\tif (result.totalRecords === 0) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`No data to insert for table \"${result.schema}.${result.table}\"`,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Table \"${result.schema}.${result.table}\": Processed ${result.totalRecords} records, inserted ${result.insertedRecords} new rows.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to seed table \"${tableConfig.schema}.${tableConfig.table}\": ${String(err)}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconsole.log(\"Seed process completed.\")\n\t},\n}\n","import { configManager } from \"../config/manager\"\nimport { databaseConnection } from \"../core/database\"\nimport type { Opts } from \"../types\"\nimport { seeder } from \"./seeder\"\n\nexport const application = {\n\tasync run(opts: Opts): Promise<void> {\n\t\ttry {\n\t\t\tconst config = configManager.load(opts)\n\t\t\tconst configDir = configManager.getConfigDir(opts)\n\t\t\tconst dbUrl = configManager.getDatabaseUrl(opts, config)\n\t\t\tconst sql = databaseConnection.create(dbUrl)\n\n\t\t\tawait databaseConnection.checkConnection(sql)\n\t\t\tawait seeder.execute(config, sql, configDir)\n\t\t\tawait sql.end()\n\t\t} catch (err) {\n\t\t\tconsole.error(String(err))\n\t\t\tprocess.exit(1)\n\t\t}\n\t},\n}\n","#!/usr/bin/env node\nimport dotenv from \"dotenv\"\nimport sade from \"sade\"\nimport { application } from \"./services/application\"\nimport type { Opts } from \"./types\"\n\nconst prog = sade(\"greenseed\")\n\nprog\n\t.command(\"push\")\n\t.option(\"-c, --config <file>\", \"Path to config file\", \"seed.config.json\")\n\t.option(\"-d, --dbvar <name>\", \"Database URL env var name (overrides config)\")\n\t.action(async (opts: Opts) => {\n\t\tdotenv.config()\n\t\tawait application.run(opts)\n\t})\n\nprog.parse(process.argv)\n"]}
1
+ {"version":3,"sources":["../src/db.ts","../src/fs.ts","../src/app.ts","../src/cli.ts"],"names":["postgres","fs","path","v","dotenv","sade"],"mappings":"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","file":"cli.cjs","sourcesContent":["import postgres from \"postgres\"\n\nexport function connect(url: string): postgres.Sql {\n\treturn postgres(url, { max: 10, idle_timeout: 20 })\n}\n\nexport async function check(sql: postgres.Sql): Promise<void> {\n\ttry {\n\t\tawait sql`select 1`\n\t} catch (err) {\n\t\tthrow new Error(\"Database connection failed\")\n\t}\n}\n\nexport async function tableExists(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n): Promise<boolean> {\n\tconst res = await sql<{ exists: boolean }[]>`\n\t\tselect to_regclass(${schema + \".\" + table}) is not null as exists\n\t`\n\tif (!res[0]) {\n\t\tthrow new Error(\"Failed checking table: \" + schema + \".\" + table)\n\t}\n\treturn res[0].exists\n}\n\nexport async function validateTables(\n\tsql: postgres.Sql,\n\ttables: { schema: string; table: string }[],\n): Promise<void> {\n\tfor (const t of tables) {\n\t\tconst ok = await tableExists(sql, t.schema, t.table)\n\t\tif (!ok) {\n\t\t\tthrow new Error(\"Missing table: \" + t.schema + \".\" + t.table)\n\t\t}\n\t}\n}\n\nexport async function metadata(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n): Promise<{ columns: string[] }> {\n\tconst cols = await sql<{ column_name: string }[]>`\n\t\tselect column_name\n\t\tfrom information_schema.columns\n\t\twhere table_schema = ${schema}\n\t\tand table_name = ${table}\n\t\torder by ordinal_position\n\t`\n\treturn { columns: cols.map(c => c.column_name) }\n}\n\nexport async function insert(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n\trows: Record<string, any>[],\n\tcolumns: string[],\n\tprimaryKeys: string[],\n): Promise<number> {\n\tif (primaryKeys.length === 0) {\n\t\tthrow new Error(\"No primary keys for \" + schema + \".\" + table)\n\t}\n\n\tconst q = await sql`\n\t\tinsert into ${sql(schema + \".\" + table)}\n\t\t${sql(rows, columns)}\n\t\ton conflict (${sql(primaryKeys)}) do nothing\n\t\treturning ${sql(primaryKeys[0] ?? [])}\n\t`\n\treturn q.length\n}\n","import fs from \"fs\"\nimport path from \"path\"\n\nexport function exists(p: string): boolean {\n\treturn fs.existsSync(p)\n}\n\nexport function readFile(p: string): string {\n\ttry {\n\t\treturn fs.readFileSync(p, \"utf8\")\n\t} catch (err) {\n\t\tthrow new Error(\"Failed to read file: \" + p)\n\t}\n}\n\nexport function resolvePath(p: string): string {\n\treturn path.resolve(process.cwd(), p)\n}\n\nexport function ext(p: string): string {\n\treturn path.extname(p).toLowerCase()\n}\n\nexport function loadJsonArray(p: string, onMissing: \"skip\" | \"error\"): any[] {\n\tif (!exists(p)) {\n\t\tif (onMissing === \"skip\") {\n\t\t\treturn []\n\t\t}\n\t\tthrow new Error(\"Source file not found: \" + p)\n\t}\n\n\tconst raw = readFile(p)\n\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(raw)\n\t} catch {\n\t\tthrow new Error(\"Invalid JSON: \" + p)\n\t}\n\n\tif (!Array.isArray(parsed)) {\n\t\tthrow new Error(\"Data is not an array: \" + p)\n\t}\n\n\treturn parsed\n}\n\nexport function chunk<T>(data: T[], size: number): T[][] {\n\tconst out: T[][] = []\n\tfor (let i = 0; i < data.length; i += size) {\n\t\tout.push(data.slice(i, i + size))\n\t}\n\treturn out\n}\n","import * as v from \"valibot\"\nimport dotenv from \"dotenv\"\nimport path from \"path\"\nimport { connect, check, validateTables, metadata, insert } from \"./db\"\nimport { resolvePath, loadJsonArray, chunk } from \"./fs\"\n\nconst C = {\n\treset: \"\\x1b[0m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tred: \"\\x1b[31m\",\n\tgray: \"\\x1b[90m\",\n}\n\nconst ConfigSchema = v.object({\n\tseedFileExtensions: v.array(v.picklist([\".json\"])),\n\tdatabaseUrlEnvVar: v.string(),\n\tonMissingFile: v.optional(v.picklist([\"skip\", \"error\"]), \"error\"),\n\ttables: v.array(\n\t\tv.object({\n\t\t\ttable: v.string(),\n\t\t\tschema: v.optional(v.string(), \"public\"),\n\t\t\tprimaryKeys: v.array(v.string()),\n\t\t\tsource: v.string(),\n\t\t}),\n\t),\n})\n\ntype Opts = { config: string; dbvar?: string }\n\nexport async function run(opts: Opts): Promise<void> {\n\tdotenv.config()\n\n\tconst configPath = resolvePath(opts.config || \"seed.config.json\")\n\tconst raw = require(configPath)\n\tconst parsed = v.safeParse(ConfigSchema, raw)\n\n\tif (!parsed.success) {\n\t\tthrow new Error(\"Invalid configuration\")\n\t}\n\n\tconst config = parsed.output\n\tconst dbVar =\n\t\topts.dbvar && opts.dbvar.length > 0\n\t\t\t? opts.dbvar\n\t\t\t: config.databaseUrlEnvVar\n\n\tconst dbUrl = process.env[dbVar]\n\tif (!dbUrl) {\n\t\tthrow new Error(\"Missing DB env var: \" + dbVar)\n\t}\n\n\tconst sql = connect(dbUrl)\n\tawait check(sql)\n\n\tawait validateTables(\n\t\tsql,\n\t\tconfig.tables.map(t => ({\n\t\t\ttable: t.table,\n\t\t\tschema: t.schema,\n\t\t})),\n\t)\n\n\tconsole.log(C.gray + \"Starting seed process\" + C.reset)\n\n\tfor (const t of config.tables) {\n\t\tconst source = path.resolve(path.dirname(configPath), t.source)\n\t\tconst rows = loadJsonArray(source, config.onMissingFile || \"error\")\n\n\t\tif (rows.length === 0) {\n\t\t\tconsole.log(C.yellow + \"Skipped \" + t.table + C.reset)\n\t\t\tcontinue\n\t\t}\n\n\t\tconst meta = await metadata(sql, t.schema, t.table)\n\t\tconst validCols = Object.keys(rows[0]).filter(c =>\n\t\t\tmeta.columns.includes(c),\n\t\t)\n\n\t\tlet inserted = 0\n\t\tfor (const part of chunk(rows, 1000)) {\n\t\t\tinserted += await insert(\n\t\t\t\tsql,\n\t\t\t\tt.schema,\n\t\t\t\tt.table,\n\t\t\t\tpart,\n\t\t\t\tvalidCols,\n\t\t\t\tt.primaryKeys,\n\t\t\t)\n\t\t}\n\n\t\tconsole.log(\n\t\t\tC.green +\n\t\t\t\tt.schema +\n\t\t\t\t\".\" +\n\t\t\t\tt.table +\n\t\t\t\t\": \" +\n\t\t\t\tinserted +\n\t\t\t\t\"/\" +\n\t\t\t\trows.length +\n\t\t\t\tC.reset,\n\t\t)\n\t}\n\n\tawait sql.end()\n\tconsole.log(C.green + \"Seed completed\" + C.reset)\n}\n","#!/usr/bin/env node\nimport sade from \"sade\"\nimport { run } from \"./app\"\n\nconst prog = sade(\"greenseed\")\n\nprog\n\t.command(\"push\")\n\t.option(\"-c, --config <file>\", \"Config file\", \"seed.config.json\")\n\t.option(\"-d, --dbvar <name>\", \"DB env var override\")\n\t.action(async opts => {\n\t\ttry {\n\t\t\tawait run(opts)\n\t\t} catch (err) {\n\t\t\tconsole.error(\"\\x1b[31m\" + String(err) + \"\\x1b[0m\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t})\n\nprog.parse(process.argv)\n"]}
package/dist/cli.js CHANGED
@@ -1,26 +1,112 @@
1
1
  #!/usr/bin/env node
2
- import dotenv from 'dotenv';
3
2
  import sade from 'sade';
4
- import path from 'path';
5
3
  import * as v from 'valibot';
6
- import fs from 'fs';
4
+ import dotenv from 'dotenv';
5
+ import path2 from 'path';
7
6
  import postgres from 'postgres';
7
+ import fs from 'fs';
8
8
 
9
- // src/core/parsers/index.ts
10
- var parsers = {
11
- json(content, fileName) {
12
- try {
13
- return JSON.parse(content);
14
- } catch (err) {
15
- throw new Error(`Invalid JSON in ${fileName}: ${String(err)}`);
16
- }
17
- },
18
- validateArray(data, fileName) {
19
- if (!Array.isArray(data)) {
20
- throw new Error(`Data in ${fileName} is not an array`);
9
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
10
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
11
+ }) : x)(function(x) {
12
+ if (typeof require !== "undefined") return require.apply(this, arguments);
13
+ throw Error('Dynamic require of "' + x + '" is not supported');
14
+ });
15
+ function connect(url) {
16
+ return postgres(url, { max: 10, idle_timeout: 20 });
17
+ }
18
+ async function check(sql) {
19
+ try {
20
+ await sql`select 1`;
21
+ } catch (err) {
22
+ throw new Error("Database connection failed");
23
+ }
24
+ }
25
+ async function tableExists(sql, schema, table) {
26
+ const res = await sql`
27
+ select to_regclass(${schema + "." + table}) is not null as exists
28
+ `;
29
+ if (!res[0]) {
30
+ throw new Error("Failed checking table: " + schema + "." + table);
31
+ }
32
+ return res[0].exists;
33
+ }
34
+ async function validateTables(sql, tables) {
35
+ for (const t of tables) {
36
+ const ok = await tableExists(sql, t.schema, t.table);
37
+ if (!ok) {
38
+ throw new Error("Missing table: " + t.schema + "." + t.table);
21
39
  }
22
- return data;
23
40
  }
41
+ }
42
+ async function metadata(sql, schema, table) {
43
+ const cols = await sql`
44
+ select column_name
45
+ from information_schema.columns
46
+ where table_schema = ${schema}
47
+ and table_name = ${table}
48
+ order by ordinal_position
49
+ `;
50
+ return { columns: cols.map((c) => c.column_name) };
51
+ }
52
+ async function insert(sql, schema, table, rows, columns, primaryKeys) {
53
+ if (primaryKeys.length === 0) {
54
+ throw new Error("No primary keys for " + schema + "." + table);
55
+ }
56
+ const q = await sql`
57
+ insert into ${sql(schema + "." + table)}
58
+ ${sql(rows, columns)}
59
+ on conflict (${sql(primaryKeys)}) do nothing
60
+ returning ${sql(primaryKeys[0] ?? [])}
61
+ `;
62
+ return q.length;
63
+ }
64
+ function exists(p) {
65
+ return fs.existsSync(p);
66
+ }
67
+ function readFile(p) {
68
+ try {
69
+ return fs.readFileSync(p, "utf8");
70
+ } catch (err) {
71
+ throw new Error("Failed to read file: " + p);
72
+ }
73
+ }
74
+ function resolvePath(p) {
75
+ return path2.resolve(process.cwd(), p);
76
+ }
77
+ function loadJsonArray(p, onMissing) {
78
+ if (!exists(p)) {
79
+ if (onMissing === "skip") {
80
+ return [];
81
+ }
82
+ throw new Error("Source file not found: " + p);
83
+ }
84
+ const raw = readFile(p);
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(raw);
88
+ } catch {
89
+ throw new Error("Invalid JSON: " + p);
90
+ }
91
+ if (!Array.isArray(parsed)) {
92
+ throw new Error("Data is not an array: " + p);
93
+ }
94
+ return parsed;
95
+ }
96
+ function chunk(data, size) {
97
+ const out = [];
98
+ for (let i = 0; i < data.length; i += size) {
99
+ out.push(data.slice(i, i + size));
100
+ }
101
+ return out;
102
+ }
103
+
104
+ // src/app.ts
105
+ var C = {
106
+ reset: "\x1B[0m",
107
+ green: "\x1B[32m",
108
+ yellow: "\x1B[33m",
109
+ gray: "\x1B[90m"
24
110
  };
25
111
  var ConfigSchema = v.object({
26
112
  seedFileExtensions: v.array(v.picklist([".json"])),
@@ -35,286 +121,69 @@ var ConfigSchema = v.object({
35
121
  })
36
122
  )
37
123
  });
38
- var fileSystem = {
39
- exists(filePath) {
40
- return fs.existsSync(filePath);
41
- },
42
- read(filePath) {
43
- try {
44
- return fs.readFileSync(filePath, "utf8");
45
- } catch (err) {
46
- throw new Error(`Failed to read file at ${filePath}: ${String(err)}`);
47
- }
48
- },
49
- getExtension(filePath) {
50
- return path.extname(filePath).toLowerCase();
51
- },
52
- resolvePath(filePath) {
53
- return path.resolve(process.cwd(), filePath);
54
- }
55
- };
56
-
57
- // src/config/manager.ts
58
- var configManager = {
59
- getConfigPath(opts) {
60
- const fileName = opts.config || "seed.config.json";
61
- return fileSystem.resolvePath(fileName);
62
- },
63
- load(opts) {
64
- const configPath = this.getConfigPath(opts);
65
- if (!fileSystem.exists(configPath)) {
66
- throw new Error(`Config file not found at ${configPath}`);
67
- }
68
- const content = fileSystem.read(configPath);
69
- const data = parsers.json(content, path.basename(configPath));
70
- const result = v.safeParse(ConfigSchema, data);
71
- if (!result.success) {
72
- const errors = result.issues.map((issue) => `- ${issue.message}`).join("\n");
73
- throw new Error(`Invalid configuration:
74
- ${errors}`);
75
- }
76
- return result.output;
77
- },
78
- getDatabaseUrl(opts, config) {
79
- const varName = opts.dbvar && opts.dbvar.length > 0 ? opts.dbvar : config.databaseUrlEnvVar || "DATABASE_URL";
80
- const url = process.env[varName];
81
- if (!url) {
82
- throw new Error(
83
- `Database URL environment variable "${varName}" is not set`
84
- );
85
- }
86
- return url;
87
- },
88
- getConfigDir(opts) {
89
- const configPath = this.getConfigPath(opts);
90
- return path.dirname(configPath);
124
+ async function run(opts) {
125
+ dotenv.config();
126
+ const configPath = resolvePath(opts.config || "seed.config.json");
127
+ const raw = __require(configPath);
128
+ const parsed = v.safeParse(ConfigSchema, raw);
129
+ if (!parsed.success) {
130
+ throw new Error("Invalid configuration");
91
131
  }
92
- };
93
- var databaseConnection = {
94
- create(url) {
95
- return postgres(url, { max: 10, idle_timeout: 20 });
96
- },
97
- async checkConnection(sql) {
98
- try {
99
- await sql`select 1`;
100
- } catch (err) {
101
- const msg = err instanceof postgres.PostgresError ? err.message : String(err);
102
- throw new Error(`Failed to connect to database: ${msg}`);
103
- }
132
+ const config = parsed.output;
133
+ const dbVar = opts.dbvar && opts.dbvar.length > 0 ? opts.dbvar : config.databaseUrlEnvVar;
134
+ const dbUrl = process.env[dbVar];
135
+ if (!dbUrl) {
136
+ throw new Error("Missing DB env var: " + dbVar);
104
137
  }
105
- };
106
-
107
- // src/core/database/operations.ts
108
- var databaseOperations = {
109
- async tableExists(sql, tableName, schemaName) {
110
- try {
111
- const [result] = await sql`
112
- SELECT to_regclass(${schemaName + "." + tableName}) IS NOT NULL AS exists
113
- `;
114
- if (!result) {
115
- throw new Error(
116
- `Failed to check existence of table ${schemaName}.${tableName}`
117
- );
118
- }
119
- return result.exists;
120
- } catch (err) {
121
- throw new Error(
122
- `Failed to validate table ${schemaName}.${tableName}: ${String(err)}`
123
- );
124
- }
125
- },
126
- async validateTables(sql, tables) {
127
- const checks = await Promise.all(
128
- tables.map(async (t) => ({
129
- table: t.table,
130
- schema: t.schema,
131
- exists: await this.tableExists(sql, t.table, t.schema)
132
- }))
138
+ const sql = connect(dbUrl);
139
+ await check(sql);
140
+ await validateTables(
141
+ sql,
142
+ config.tables.map((t) => ({
143
+ table: t.table,
144
+ schema: t.schema
145
+ }))
146
+ );
147
+ console.log(C.gray + "Starting seed process" + C.reset);
148
+ for (const t of config.tables) {
149
+ const source = path2.resolve(path2.dirname(configPath), t.source);
150
+ const rows = loadJsonArray(source, config.onMissingFile || "error");
151
+ if (rows.length === 0) {
152
+ console.log(C.yellow + "Skipped " + t.table + C.reset);
153
+ continue;
154
+ }
155
+ const meta = await metadata(sql, t.schema, t.table);
156
+ const validCols = Object.keys(rows[0]).filter(
157
+ (c) => meta.columns.includes(c)
133
158
  );
134
- const missing = checks.filter((c) => !c.exists);
135
- if (missing.length > 0) {
136
- const missingNames = missing.map((m) => `${m.schema}.${m.table}`).join(", ");
137
- throw new Error(`Missing tables: ${missingNames}`);
138
- }
139
- },
140
- async getTableMetadata(sql, tableName, schemaName) {
141
- try {
142
- const columns = await sql`
143
- select column_name
144
- from information_schema.columns
145
- where table_schema = ${schemaName}
146
- and table_name = ${tableName}
147
- order by ordinal_position
148
- `;
149
- const primaryKeys = await sql`
150
- select a.attname as column_name
151
- from pg_index i
152
- join pg_attribute a on a.attrelid = i.indrelid and a.attnum = any(i.indkey)
153
- join pg_class c on c.oid = i.indrelid
154
- join pg_namespace n on n.oid = c.relnamespace
155
- where n.nspname = ${schemaName}
156
- and c.relname = ${tableName}
157
- and i.indisprimary
158
- `;
159
- return {
160
- columns: columns.map((c) => c.column_name),
161
- primaryKeys: primaryKeys.map((pk) => pk.column_name)
162
- };
163
- } catch (err) {
164
- throw new Error(
165
- `Failed to get metadata for table ${schemaName}.${tableName}: ${String(err)}`
159
+ let inserted = 0;
160
+ for (const part of chunk(rows, 1e3)) {
161
+ inserted += await insert(
162
+ sql,
163
+ t.schema,
164
+ t.table,
165
+ part,
166
+ validCols,
167
+ t.primaryKeys
166
168
  );
167
169
  }
168
- },
169
- async insertData(sql, tableName, schemaName, data, columns, primaryKeys) {
170
- if (primaryKeys.length === 0) {
171
- throw new Error(
172
- `Table ${schemaName}.${tableName} has no primary keys defined`
173
- );
174
- }
175
- const qualifiedTable = `${schemaName}.${tableName}`;
176
- const result = await sql`
177
- INSERT INTO ${sql(qualifiedTable)} ${sql(data, columns)}
178
- ON CONFLICT (${sql(primaryKeys)}) DO NOTHING
179
- RETURNING ${sql(primaryKeys[0] || [])}
180
- `;
181
- return result.length;
182
- }
183
- };
184
- var dataLoader = {
185
- load(sourcePath, config, configDir) {
186
- const fullPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(configDir, sourcePath);
187
- if (!fileSystem.exists(fullPath)) {
188
- const onMissingFile = config.onMissingFile || "error";
189
- if (onMissingFile === "skip") {
190
- console.warn(`Warning: Source file not found at ${fullPath}. Skipping.`);
191
- return [];
192
- } else {
193
- throw new Error(`Source file not found at ${fullPath}`);
194
- }
195
- }
196
- const content = fileSystem.read(fullPath);
197
- const ext = fileSystem.getExtension(fullPath);
198
- if (ext === ".json") {
199
- const data = parsers.json(content, sourcePath);
200
- return parsers.validateArray(data, sourcePath);
201
- }
202
- throw new Error(`Unsupported file extension: ${ext}`);
203
- },
204
- chunkData(data, chunkSize) {
205
- const chunks = [];
206
- for (let i = 0; i < data.length; i += chunkSize) {
207
- chunks.push(data.slice(i, i + chunkSize));
208
- }
209
- return chunks;
210
- }
211
- };
212
-
213
- // src/services/seeder.ts
214
- var seeder = {
215
- async seedTable(sql, tableConfig, config, configDir) {
216
- const data = dataLoader.load(tableConfig.source, config, configDir);
217
- if (data.length === 0) {
218
- return {
219
- table: tableConfig.table,
220
- schema: tableConfig.schema,
221
- totalRecords: 0,
222
- insertedRecords: 0
223
- };
224
- }
225
- const metadata = await databaseOperations.getTableMetadata(
226
- sql,
227
- tableConfig.table,
228
- tableConfig.schema
170
+ console.log(
171
+ C.green + t.schema + "." + t.table + ": " + inserted + "/" + rows.length + C.reset
229
172
  );
230
- const dataColumns = Object.keys(data[0] || {});
231
- const validColumns = dataColumns.filter(
232
- (col) => metadata.columns.includes(col)
233
- );
234
- if (validColumns.length === 0) {
235
- throw new Error(
236
- `No valid columns found in data for table ${tableConfig.schema}.${tableConfig.table}`
237
- );
238
- }
239
- const chunks = dataLoader.chunkData(data, 1e3);
240
- let insertedCount = 0;
241
- for (const chunk of chunks) {
242
- try {
243
- const inserted = await databaseOperations.insertData(
244
- sql,
245
- tableConfig.table,
246
- tableConfig.schema,
247
- chunk,
248
- validColumns,
249
- tableConfig.primaryKeys
250
- );
251
- insertedCount += inserted;
252
- } catch (err) {
253
- const msg = err instanceof postgres.PostgresError ? err.message : String(err);
254
- throw new Error(
255
- `Failed to insert data into ${tableConfig.schema}.${tableConfig.table}: ${msg}`
256
- );
257
- }
258
- }
259
- return {
260
- table: tableConfig.table,
261
- schema: tableConfig.schema,
262
- totalRecords: data.length,
263
- insertedRecords: insertedCount
264
- };
265
- },
266
- async execute(config, sql, configDir) {
267
- const tables = config.tables.map((t) => ({
268
- table: t.table,
269
- schema: t.schema
270
- }));
271
- await databaseOperations.validateTables(sql, tables);
272
- console.log("Starting seed process.");
273
- for (const tableConfig of config.tables) {
274
- try {
275
- const result = await this.seedTable(sql, tableConfig, config, configDir);
276
- if (result.totalRecords === 0) {
277
- console.log(
278
- `No data to insert for table "${result.schema}.${result.table}"`
279
- );
280
- } else {
281
- console.log(
282
- `Table "${result.schema}.${result.table}": Processed ${result.totalRecords} records, inserted ${result.insertedRecords} new rows.`
283
- );
284
- }
285
- } catch (err) {
286
- throw new Error(
287
- `Failed to seed table "${tableConfig.schema}.${tableConfig.table}": ${String(err)}`
288
- );
289
- }
290
- }
291
- console.log("Seed process completed.");
292
173
  }
293
- };
294
-
295
- // src/services/application.ts
296
- var application = {
297
- async run(opts) {
298
- try {
299
- const config = configManager.load(opts);
300
- const configDir = configManager.getConfigDir(opts);
301
- const dbUrl = configManager.getDatabaseUrl(opts, config);
302
- const sql = databaseConnection.create(dbUrl);
303
- await databaseConnection.checkConnection(sql);
304
- await seeder.execute(config, sql, configDir);
305
- await sql.end();
306
- } catch (err) {
307
- console.error(String(err));
308
- process.exit(1);
309
- }
310
- }
311
- };
174
+ await sql.end();
175
+ console.log(C.green + "Seed completed" + C.reset);
176
+ }
312
177
 
313
178
  // src/cli.ts
314
179
  var prog = sade("greenseed");
315
- prog.command("push").option("-c, --config <file>", "Path to config file", "seed.config.json").option("-d, --dbvar <name>", "Database URL env var name (overrides config)").action(async (opts) => {
316
- dotenv.config();
317
- await application.run(opts);
180
+ prog.command("push").option("-c, --config <file>", "Config file", "seed.config.json").option("-d, --dbvar <name>", "DB env var override").action(async (opts) => {
181
+ try {
182
+ await run(opts);
183
+ } catch (err) {
184
+ console.error("\x1B[31m" + String(err) + "\x1B[0m");
185
+ process.exit(1);
186
+ }
318
187
  });
319
188
  prog.parse(process.argv);
320
189
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/parsers/index.ts","../src/types/index.ts","../src/utils/file-system.ts","../src/config/manager.ts","../src/core/database/connection.ts","../src/core/database/operations.ts","../src/core/loaders/data-loader.ts","../src/services/seeder.ts","../src/services/application.ts","../src/cli.ts"],"names":["path","v2","postgres"],"mappings":"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","file":"cli.js","sourcesContent":["export const parsers = {\n\tjson(content: string, fileName: string): unknown {\n\t\ttry {\n\t\t\treturn JSON.parse(content)\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Invalid JSON in ${fileName}: ${String(err)}`)\n\t\t}\n\t},\n\n\tvalidateArray(data: unknown, fileName: string): Record<string, any>[] {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Data in ${fileName} is not an array`)\n\t\t}\n\t\treturn data as Record<string, any>[]\n\t},\n}\n","import * as v from \"valibot\"\n\nexport const ConfigSchema = v.object({\n\tseedFileExtensions: v.array(v.picklist([\".json\"])),\n\tdatabaseUrlEnvVar: v.string(),\n\tonMissingFile: v.optional(v.picklist([\"skip\", \"error\"]), \"error\"),\n\ttables: v.array(\n\t\tv.object({\n\t\t\ttable: v.string(),\n\t\t\tschema: v.optional(v.string(), \"public\"),\n\t\t\tprimaryKeys: v.array(v.string()),\n\t\t\tsource: v.string(),\n\t\t}),\n\t),\n})\n\nexport type Config = v.InferOutput<typeof ConfigSchema>\n\nexport type TableConfig = {\n\ttable: string\n\tschema: string\n\tprimaryKeys: string[]\n\tsource: string\n}\n\nexport type TableMetadata = {\n\tcolumns: string[]\n\tprimaryKeys: string[]\n}\n\nexport type SeedResult = {\n\ttable: string\n\tschema: string\n\ttotalRecords: number\n\tinsertedRecords: number\n}\n\nexport type Opts = {\n\tconfig: string\n\tdbvar?: string\n}\n","import fs from \"fs\"\nimport path from \"path\"\n\nexport const fileSystem = {\n\texists(filePath: string): boolean {\n\t\treturn fs.existsSync(filePath)\n\t},\n\n\tread(filePath: string): string {\n\t\ttry {\n\t\t\treturn fs.readFileSync(filePath, \"utf8\")\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Failed to read file at ${filePath}: ${String(err)}`)\n\t\t}\n\t},\n\n\tgetExtension(filePath: string): string {\n\t\treturn path.extname(filePath).toLowerCase()\n\t},\n\n\tresolvePath(filePath: string): string {\n\t\treturn path.resolve(process.cwd(), filePath)\n\t},\n}\n","import path from \"path\"\nimport * as v from \"valibot\"\nimport { parsers } from \"../core/parsers\"\nimport type { Config, Opts } from \"../types\"\nimport { ConfigSchema } from \"../types\"\nimport { fileSystem } from \"../utils/file-system\"\n\nexport const configManager = {\n\tgetConfigPath(opts: Opts): string {\n\t\tconst fileName = opts.config || \"seed.config.json\"\n\t\treturn fileSystem.resolvePath(fileName)\n\t},\n\n\tload(opts: Opts): Config {\n\t\tconst configPath = this.getConfigPath(opts)\n\n\t\tif (!fileSystem.exists(configPath)) {\n\t\t\tthrow new Error(`Config file not found at ${configPath}`)\n\t\t}\n\n\t\tconst content = fileSystem.read(configPath)\n\t\tconst data = parsers.json(content, path.basename(configPath))\n\t\tconst result = v.safeParse(ConfigSchema, data)\n\n\t\tif (!result.success) {\n\t\t\tconst errors = result.issues\n\t\t\t\t.map((issue) => `- ${issue.message}`)\n\t\t\t\t.join(\"\\n\")\n\t\t\tthrow new Error(`Invalid configuration:\\n${errors}`)\n\t\t}\n\n\t\treturn result.output\n\t},\n\n\tgetDatabaseUrl(opts: Opts, config: Config): string {\n\t\tconst varName =\n\t\t\topts.dbvar && opts.dbvar.length > 0\n\t\t\t\t? opts.dbvar\n\t\t\t\t: config.databaseUrlEnvVar || \"DATABASE_URL\"\n\n\t\tconst url = process.env[varName]\n\t\tif (!url) {\n\t\t\tthrow new Error(\n\t\t\t\t`Database URL environment variable \"${varName}\" is not set`,\n\t\t\t)\n\t\t}\n\t\treturn url\n\t},\n\n\tgetConfigDir(opts: Opts): string {\n\t\tconst configPath = this.getConfigPath(opts)\n\t\treturn path.dirname(configPath)\n\t},\n}\n","import postgres from \"postgres\"\n\nexport const databaseConnection = {\n\tcreate(url: string): postgres.Sql {\n\t\treturn postgres(url, { max: 10, idle_timeout: 20 })\n\t},\n\n\tasync checkConnection(sql: postgres.Sql): Promise<void> {\n\t\ttry {\n\t\t\tawait sql`select 1`\n\t\t} catch (err) {\n\t\t\tconst msg =\n\t\t\t\terr instanceof postgres.PostgresError ? err.message : String(err)\n\t\t\tthrow new Error(`Failed to connect to database: ${msg}`)\n\t\t}\n\t},\n}\n","import postgres from \"postgres\"\nimport type { TableMetadata } from \"../../types\"\n\nexport const databaseOperations = {\n\tasync tableExists(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\tconst [result] = await sql<{ exists: boolean }[]>`\n\t\t\t\tSELECT to_regclass(${schemaName + \".\" + tableName}) IS NOT NULL AS exists\n\t\t\t`\n\n\t\t\tif (!result) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to check existence of table ${schemaName}.${tableName}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn result.exists\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to validate table ${schemaName}.${tableName}: ${String(err)}`,\n\t\t\t)\n\t\t}\n\t},\n\n\tasync validateTables(\n\t\tsql: postgres.Sql,\n\t\ttables: Array<{ table: string; schema: string }>,\n\t): Promise<void> {\n\t\tconst checks = await Promise.all(\n\t\t\ttables.map(async (t) => ({\n\t\t\t\ttable: t.table,\n\t\t\t\tschema: t.schema,\n\t\t\t\texists: await this.tableExists(sql, t.table, t.schema),\n\t\t\t})),\n\t\t)\n\n\t\tconst missing = checks.filter((c) => !c.exists)\n\t\tif (missing.length > 0) {\n\t\t\tconst missingNames = missing\n\t\t\t\t.map((m) => `${m.schema}.${m.table}`)\n\t\t\t\t.join(\", \")\n\t\t\tthrow new Error(`Missing tables: ${missingNames}`)\n\t\t}\n\t},\n\n\tasync getTableMetadata(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t): Promise<TableMetadata> {\n\t\ttry {\n\t\t\tconst columns = await sql<{ column_name: string }[]>`\n\t\t\t\tselect column_name\n\t\t\t\tfrom information_schema.columns\n\t\t\t\twhere table_schema = ${schemaName}\n\t\t\t\tand table_name = ${tableName}\n\t\t\t\torder by ordinal_position\n\t\t\t`\n\n\t\t\tconst primaryKeys = await sql<{ column_name: string }[]>`\n\t\t\t\tselect a.attname as column_name\n\t\t\t\tfrom pg_index i\n\t\t\t\tjoin pg_attribute a on a.attrelid = i.indrelid and a.attnum = any(i.indkey)\n\t\t\t\tjoin pg_class c on c.oid = i.indrelid\n\t\t\t\tjoin pg_namespace n on n.oid = c.relnamespace\n\t\t\t\twhere n.nspname = ${schemaName}\n\t\t\t\tand c.relname = ${tableName}\n\t\t\t\tand i.indisprimary\n\t\t\t`\n\n\t\t\treturn {\n\t\t\t\tcolumns: columns.map((c) => c.column_name),\n\t\t\t\tprimaryKeys: primaryKeys.map((pk) => pk.column_name),\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to get metadata for table ${schemaName}.${tableName}: ${String(err)}`,\n\t\t\t)\n\t\t}\n\t},\n\n\tasync insertData(\n\t\tsql: postgres.Sql,\n\t\ttableName: string,\n\t\tschemaName: string,\n\t\tdata: Record<string, any>[],\n\t\tcolumns: string[],\n\t\tprimaryKeys: string[],\n\t): Promise<number> {\n\t\tif (primaryKeys.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table ${schemaName}.${tableName} has no primary keys defined`,\n\t\t\t)\n\t\t}\n\n\t\tconst qualifiedTable = `${schemaName}.${tableName}`\n\t\tconst result = await sql`\n\t\t\tINSERT INTO ${sql(qualifiedTable)} ${sql(data, columns)}\n\t\t\tON CONFLICT (${sql(primaryKeys)}) DO NOTHING\n\t\t\tRETURNING ${sql(primaryKeys[0] || [])}\n\t\t`\n\n\t\treturn result.length\n\t},\n}\n","import path from \"path\"\nimport type { Config } from \"../../types\"\nimport { fileSystem } from \"../../utils/file-system\"\nimport { parsers } from \"../parsers\"\n\nexport const dataLoader = {\n\tload(\n\t\tsourcePath: string,\n\t\tconfig: Config,\n\t\tconfigDir: string,\n\t): Record<string, any>[] {\n\t\tconst fullPath = path.isAbsolute(sourcePath)\n\t\t\t? sourcePath\n\t\t\t: path.resolve(configDir, sourcePath)\n\n\t\tif (!fileSystem.exists(fullPath)) {\n\t\t\tconst onMissingFile = config.onMissingFile || \"error\"\n\n\t\t\tif (onMissingFile === \"skip\") {\n\t\t\t\tconsole.warn(`Warning: Source file not found at ${fullPath}. Skipping.`)\n\t\t\t\treturn []\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Source file not found at ${fullPath}`)\n\t\t\t}\n\t\t}\n\n\t\tconst content = fileSystem.read(fullPath)\n\t\tconst ext = fileSystem.getExtension(fullPath)\n\n\t\tif (ext === \".json\") {\n\t\t\tconst data = parsers.json(content, sourcePath)\n\t\t\treturn parsers.validateArray(data, sourcePath)\n\t\t}\n\n\t\tthrow new Error(`Unsupported file extension: ${ext}`)\n\t},\n\n\tchunkData<T>(data: T[], chunkSize: number): T[][] {\n\t\tconst chunks: T[][] = []\n\t\tfor (let i = 0; i < data.length; i += chunkSize) {\n\t\t\tchunks.push(data.slice(i, i + chunkSize))\n\t\t}\n\t\treturn chunks\n\t},\n}\n","import postgres from \"postgres\"\nimport { databaseOperations } from \"../core/database/operations\"\nimport { dataLoader } from \"../core/loaders/data-loader\"\nimport type { Config, SeedResult, TableConfig } from \"../types\"\n\nexport const seeder = {\n\tasync seedTable(\n\t\tsql: postgres.Sql,\n\t\ttableConfig: TableConfig,\n\t\tconfig: Config,\n\t\tconfigDir: string,\n\t): Promise<SeedResult> {\n\t\tconst data = dataLoader.load(tableConfig.source, config, configDir)\n\n\t\tif (data.length === 0) {\n\t\t\treturn {\n\t\t\t\ttable: tableConfig.table,\n\t\t\t\tschema: tableConfig.schema,\n\t\t\t\ttotalRecords: 0,\n\t\t\t\tinsertedRecords: 0,\n\t\t\t}\n\t\t}\n\n\t\tconst metadata = await databaseOperations.getTableMetadata(\n\t\t\tsql,\n\t\t\ttableConfig.table,\n\t\t\ttableConfig.schema,\n\t\t)\n\n\t\tconst dataColumns = Object.keys(data[0] || {})\n\t\tconst validColumns = dataColumns.filter((col) =>\n\t\t\tmetadata.columns.includes(col),\n\t\t)\n\n\t\tif (validColumns.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No valid columns found in data for table ${tableConfig.schema}.${tableConfig.table}`,\n\t\t\t)\n\t\t}\n\n\t\tconst chunks = dataLoader.chunkData(data, 1000)\n\t\tlet insertedCount = 0\n\n\t\tfor (const chunk of chunks) {\n\t\t\ttry {\n\t\t\t\tconst inserted = await databaseOperations.insertData(\n\t\t\t\t\tsql,\n\t\t\t\t\ttableConfig.table,\n\t\t\t\t\ttableConfig.schema,\n\t\t\t\t\tchunk,\n\t\t\t\t\tvalidColumns,\n\t\t\t\t\ttableConfig.primaryKeys,\n\t\t\t\t)\n\t\t\t\tinsertedCount += inserted\n\t\t\t} catch (err) {\n\t\t\t\tconst msg =\n\t\t\t\t\terr instanceof postgres.PostgresError ? err.message : String(err)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to insert data into ${tableConfig.schema}.${tableConfig.table}: ${msg}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttable: tableConfig.table,\n\t\t\tschema: tableConfig.schema,\n\t\t\ttotalRecords: data.length,\n\t\t\tinsertedRecords: insertedCount,\n\t\t}\n\t},\n\n\tasync execute(\n\t\tconfig: Config,\n\t\tsql: postgres.Sql,\n\t\tconfigDir: string,\n\t): Promise<void> {\n\t\tconst tables = config.tables.map((t) => ({\n\t\t\ttable: t.table,\n\t\t\tschema: t.schema,\n\t\t}))\n\t\tawait databaseOperations.validateTables(sql, tables)\n\n\t\tconsole.log(\"Starting seed process.\")\n\n\t\tfor (const tableConfig of config.tables) {\n\t\t\ttry {\n\t\t\t\tconst result = await this.seedTable(sql, tableConfig, config, configDir)\n\n\t\t\t\tif (result.totalRecords === 0) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`No data to insert for table \"${result.schema}.${result.table}\"`,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Table \"${result.schema}.${result.table}\": Processed ${result.totalRecords} records, inserted ${result.insertedRecords} new rows.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to seed table \"${tableConfig.schema}.${tableConfig.table}\": ${String(err)}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconsole.log(\"Seed process completed.\")\n\t},\n}\n","import { configManager } from \"../config/manager\"\nimport { databaseConnection } from \"../core/database\"\nimport type { Opts } from \"../types\"\nimport { seeder } from \"./seeder\"\n\nexport const application = {\n\tasync run(opts: Opts): Promise<void> {\n\t\ttry {\n\t\t\tconst config = configManager.load(opts)\n\t\t\tconst configDir = configManager.getConfigDir(opts)\n\t\t\tconst dbUrl = configManager.getDatabaseUrl(opts, config)\n\t\t\tconst sql = databaseConnection.create(dbUrl)\n\n\t\t\tawait databaseConnection.checkConnection(sql)\n\t\t\tawait seeder.execute(config, sql, configDir)\n\t\t\tawait sql.end()\n\t\t} catch (err) {\n\t\t\tconsole.error(String(err))\n\t\t\tprocess.exit(1)\n\t\t}\n\t},\n}\n","#!/usr/bin/env node\nimport dotenv from \"dotenv\"\nimport sade from \"sade\"\nimport { application } from \"./services/application\"\nimport type { Opts } from \"./types\"\n\nconst prog = sade(\"greenseed\")\n\nprog\n\t.command(\"push\")\n\t.option(\"-c, --config <file>\", \"Path to config file\", \"seed.config.json\")\n\t.option(\"-d, --dbvar <name>\", \"Database URL env var name (overrides config)\")\n\t.action(async (opts: Opts) => {\n\t\tdotenv.config()\n\t\tawait application.run(opts)\n\t})\n\nprog.parse(process.argv)\n"]}
1
+ {"version":3,"sources":["../src/db.ts","../src/fs.ts","../src/app.ts","../src/cli.ts"],"names":["path"],"mappings":"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","file":"cli.js","sourcesContent":["import postgres from \"postgres\"\n\nexport function connect(url: string): postgres.Sql {\n\treturn postgres(url, { max: 10, idle_timeout: 20 })\n}\n\nexport async function check(sql: postgres.Sql): Promise<void> {\n\ttry {\n\t\tawait sql`select 1`\n\t} catch (err) {\n\t\tthrow new Error(\"Database connection failed\")\n\t}\n}\n\nexport async function tableExists(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n): Promise<boolean> {\n\tconst res = await sql<{ exists: boolean }[]>`\n\t\tselect to_regclass(${schema + \".\" + table}) is not null as exists\n\t`\n\tif (!res[0]) {\n\t\tthrow new Error(\"Failed checking table: \" + schema + \".\" + table)\n\t}\n\treturn res[0].exists\n}\n\nexport async function validateTables(\n\tsql: postgres.Sql,\n\ttables: { schema: string; table: string }[],\n): Promise<void> {\n\tfor (const t of tables) {\n\t\tconst ok = await tableExists(sql, t.schema, t.table)\n\t\tif (!ok) {\n\t\t\tthrow new Error(\"Missing table: \" + t.schema + \".\" + t.table)\n\t\t}\n\t}\n}\n\nexport async function metadata(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n): Promise<{ columns: string[] }> {\n\tconst cols = await sql<{ column_name: string }[]>`\n\t\tselect column_name\n\t\tfrom information_schema.columns\n\t\twhere table_schema = ${schema}\n\t\tand table_name = ${table}\n\t\torder by ordinal_position\n\t`\n\treturn { columns: cols.map(c => c.column_name) }\n}\n\nexport async function insert(\n\tsql: postgres.Sql,\n\tschema: string,\n\ttable: string,\n\trows: Record<string, any>[],\n\tcolumns: string[],\n\tprimaryKeys: string[],\n): Promise<number> {\n\tif (primaryKeys.length === 0) {\n\t\tthrow new Error(\"No primary keys for \" + schema + \".\" + table)\n\t}\n\n\tconst q = await sql`\n\t\tinsert into ${sql(schema + \".\" + table)}\n\t\t${sql(rows, columns)}\n\t\ton conflict (${sql(primaryKeys)}) do nothing\n\t\treturning ${sql(primaryKeys[0] ?? [])}\n\t`\n\treturn q.length\n}\n","import fs from \"fs\"\nimport path from \"path\"\n\nexport function exists(p: string): boolean {\n\treturn fs.existsSync(p)\n}\n\nexport function readFile(p: string): string {\n\ttry {\n\t\treturn fs.readFileSync(p, \"utf8\")\n\t} catch (err) {\n\t\tthrow new Error(\"Failed to read file: \" + p)\n\t}\n}\n\nexport function resolvePath(p: string): string {\n\treturn path.resolve(process.cwd(), p)\n}\n\nexport function ext(p: string): string {\n\treturn path.extname(p).toLowerCase()\n}\n\nexport function loadJsonArray(p: string, onMissing: \"skip\" | \"error\"): any[] {\n\tif (!exists(p)) {\n\t\tif (onMissing === \"skip\") {\n\t\t\treturn []\n\t\t}\n\t\tthrow new Error(\"Source file not found: \" + p)\n\t}\n\n\tconst raw = readFile(p)\n\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(raw)\n\t} catch {\n\t\tthrow new Error(\"Invalid JSON: \" + p)\n\t}\n\n\tif (!Array.isArray(parsed)) {\n\t\tthrow new Error(\"Data is not an array: \" + p)\n\t}\n\n\treturn parsed\n}\n\nexport function chunk<T>(data: T[], size: number): T[][] {\n\tconst out: T[][] = []\n\tfor (let i = 0; i < data.length; i += size) {\n\t\tout.push(data.slice(i, i + size))\n\t}\n\treturn out\n}\n","import * as v from \"valibot\"\nimport dotenv from \"dotenv\"\nimport path from \"path\"\nimport { connect, check, validateTables, metadata, insert } from \"./db\"\nimport { resolvePath, loadJsonArray, chunk } from \"./fs\"\n\nconst C = {\n\treset: \"\\x1b[0m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tred: \"\\x1b[31m\",\n\tgray: \"\\x1b[90m\",\n}\n\nconst ConfigSchema = v.object({\n\tseedFileExtensions: v.array(v.picklist([\".json\"])),\n\tdatabaseUrlEnvVar: v.string(),\n\tonMissingFile: v.optional(v.picklist([\"skip\", \"error\"]), \"error\"),\n\ttables: v.array(\n\t\tv.object({\n\t\t\ttable: v.string(),\n\t\t\tschema: v.optional(v.string(), \"public\"),\n\t\t\tprimaryKeys: v.array(v.string()),\n\t\t\tsource: v.string(),\n\t\t}),\n\t),\n})\n\ntype Opts = { config: string; dbvar?: string }\n\nexport async function run(opts: Opts): Promise<void> {\n\tdotenv.config()\n\n\tconst configPath = resolvePath(opts.config || \"seed.config.json\")\n\tconst raw = require(configPath)\n\tconst parsed = v.safeParse(ConfigSchema, raw)\n\n\tif (!parsed.success) {\n\t\tthrow new Error(\"Invalid configuration\")\n\t}\n\n\tconst config = parsed.output\n\tconst dbVar =\n\t\topts.dbvar && opts.dbvar.length > 0\n\t\t\t? opts.dbvar\n\t\t\t: config.databaseUrlEnvVar\n\n\tconst dbUrl = process.env[dbVar]\n\tif (!dbUrl) {\n\t\tthrow new Error(\"Missing DB env var: \" + dbVar)\n\t}\n\n\tconst sql = connect(dbUrl)\n\tawait check(sql)\n\n\tawait validateTables(\n\t\tsql,\n\t\tconfig.tables.map(t => ({\n\t\t\ttable: t.table,\n\t\t\tschema: t.schema,\n\t\t})),\n\t)\n\n\tconsole.log(C.gray + \"Starting seed process\" + C.reset)\n\n\tfor (const t of config.tables) {\n\t\tconst source = path.resolve(path.dirname(configPath), t.source)\n\t\tconst rows = loadJsonArray(source, config.onMissingFile || \"error\")\n\n\t\tif (rows.length === 0) {\n\t\t\tconsole.log(C.yellow + \"Skipped \" + t.table + C.reset)\n\t\t\tcontinue\n\t\t}\n\n\t\tconst meta = await metadata(sql, t.schema, t.table)\n\t\tconst validCols = Object.keys(rows[0]).filter(c =>\n\t\t\tmeta.columns.includes(c),\n\t\t)\n\n\t\tlet inserted = 0\n\t\tfor (const part of chunk(rows, 1000)) {\n\t\t\tinserted += await insert(\n\t\t\t\tsql,\n\t\t\t\tt.schema,\n\t\t\t\tt.table,\n\t\t\t\tpart,\n\t\t\t\tvalidCols,\n\t\t\t\tt.primaryKeys,\n\t\t\t)\n\t\t}\n\n\t\tconsole.log(\n\t\t\tC.green +\n\t\t\t\tt.schema +\n\t\t\t\t\".\" +\n\t\t\t\tt.table +\n\t\t\t\t\": \" +\n\t\t\t\tinserted +\n\t\t\t\t\"/\" +\n\t\t\t\trows.length +\n\t\t\t\tC.reset,\n\t\t)\n\t}\n\n\tawait sql.end()\n\tconsole.log(C.green + \"Seed completed\" + C.reset)\n}\n","#!/usr/bin/env node\nimport sade from \"sade\"\nimport { run } from \"./app\"\n\nconst prog = sade(\"greenseed\")\n\nprog\n\t.command(\"push\")\n\t.option(\"-c, --config <file>\", \"Config file\", \"seed.config.json\")\n\t.option(\"-d, --dbvar <name>\", \"DB env var override\")\n\t.action(async opts => {\n\t\ttry {\n\t\t\tawait run(opts)\n\t\t} catch (err) {\n\t\t\tconsole.error(\"\\x1b[31m\" + String(err) + \"\\x1b[0m\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t})\n\nprog.parse(process.argv)\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greenseed",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "author": "Mohit Khatri",
5
5
  "main": "./dist/cli.js",
6
6
  "module": "./dist/index.js",