rastack 0.0.16 → 0.0.20
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/CHANGELOG.md +43876 -43013
- package/dist/.prettierrc +7 -7
- package/dist/compile/analyze.js +19 -11
- package/dist/compile/index.js +26 -17
- package/dist/compile/manifest.js +2 -3
- package/dist/compile/openapi.js +5 -8
- package/dist/compile/program.js +19 -10
- package/dist/csv-schema.js +5 -6
- package/dist/define/index.js +2 -2
- package/dist/entity-generation/delete-method.js +8 -10
- package/dist/entity-generation/form.js +80 -82
- package/dist/entity-generation/get-method.js +35 -36
- package/dist/entity-generation/imports.js +24 -20
- package/dist/entity-generation/sync-method.d.ts +1 -1
- package/dist/entity-generation/sync-method.js +45 -46
- package/dist/entity-generation/update-method.js +9 -10
- package/dist/rad-wasm-build.d.ts +1 -1
- package/dist/rad-wasm-build.js +15 -6
- package/dist/rad.js +9 -2
- package/dist/schema/camel-to-pastel.js +1 -2
- package/dist/schema/capitalise-first-letter.js +1 -2
- package/dist/schema/extract-response.js +3 -4
- package/dist/schema/fetch-schema.js +4 -16
- package/dist/schema/remove-non-model-paths.js +1 -2
- package/dist/schema/to-camel-case.js +1 -2
- package/dist/schema/to-pastel-case.js +1 -2
- package/dist/schema-convert.js +22 -33
- package/dist/schema-entities.js +177 -189
- package/dist/schema-fetch.js +46 -63
- package/dist/schema-full.js +23 -36
- package/dist/schema-index.js +16 -27
- package/dist/schema-params.js +11 -22
- package/dist/seed.js +95 -97
- package/hooks/form/form.ts +207 -207
- package/hooks/form/index.ts +8 -8
- package/hooks/form/interfaces.ts +217 -217
- package/hooks/form/structure.ts +39 -39
- package/hooks/form/validate-schema.ts +49 -49
- package/hooks/index.ts +3 -3
- package/hooks/query/api.ts +42 -42
- package/hooks/query/delete.ts +45 -45
- package/hooks/query/fetch.ts +48 -48
- package/hooks/query/index.ts +21 -21
- package/hooks/query/interfaces.ts +111 -111
- package/hooks/query/list.ts +286 -286
- package/hooks/query/update.ts +88 -88
- package/hooks/query/url.ts +31 -31
- package/hooks/real-time/index.ts +1 -1
- package/hooks/real-time/pusher.ts +43 -43
- package/jest.config.cjs +6 -6
- package/package.json +57 -57
- package/provider/index.ts +13 -13
- package/provider/provider.tsx +187 -187
- package/provider/types.ts +114 -114
- package/provider/warehouse.ts +167 -167
- package/provider/wasm.ts +124 -124
- package/runtime.ts +3 -3
- package/src/.prettierrc +7 -7
- package/src/compile/analyze.ts +224 -224
- package/src/compile/index.ts +86 -86
- package/src/compile/manifest.ts +10 -10
- package/src/compile/model.ts +69 -69
- package/src/compile/openapi.ts +266 -266
- package/src/compile/program.ts +40 -40
- package/src/csv-schema.ts +187 -187
- package/src/define/index.ts +162 -162
- package/src/entity-generation/delete-method.ts +37 -37
- package/src/entity-generation/form.ts +169 -169
- package/src/entity-generation/get-method.ts +80 -80
- package/src/entity-generation/imports.ts +110 -110
- package/src/entity-generation/sync-method.ts +222 -222
- package/src/entity-generation/update-method.ts +38 -38
- package/src/index.ts +77 -77
- package/src/rad-compile.ts +88 -88
- package/src/rad-wasm-build.ts +102 -102
- package/src/rad.ts +101 -101
- package/src/scan.ts +89 -89
- package/src/schema/camel-to-pastel.ts +3 -3
- package/src/schema/capitalise-first-letter.ts +3 -3
- package/src/schema/extract-response.ts +38 -38
- package/src/schema/fetch-schema.ts +12 -12
- package/src/schema/remove-non-model-paths.ts +13 -13
- package/src/schema/to-camel-case.ts +7 -7
- package/src/schema/to-pastel-case.ts +6 -6
- package/src/schema-convert.ts +61 -61
- package/src/schema-entities.ts +401 -401
- package/src/schema-fetch.ts +82 -82
- package/src/schema-full.ts +38 -38
- package/src/schema-index.ts +29 -29
- package/src/schema-params.ts +116 -116
- package/src/seed.ts +297 -297
- package/sync/engine.ts +392 -392
- package/sync/hooks.ts +450 -450
- package/sync/index.ts +8 -8
- package/sync/persistence.ts +237 -237
- package/sync/provider.tsx +91 -91
- package/sync/registry.ts +36 -36
- package/sync/store.ts +126 -126
- package/sync/transactions.ts +300 -300
- package/sync/types.ts +94 -94
- package/test/compile.spec.ts +192 -192
- package/test/csv-schema.spec.ts +143 -143
- package/test/schema-entities.spec.ts +688 -688
- package/tsconfig.json +24 -24
- package/types.ts +18 -18
package/dist/schema-index.js
CHANGED
|
@@ -1,34 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const path_1 = require("path");
|
|
13
4
|
const fs_1 = require("fs");
|
|
14
|
-
function main() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return `${formSchemaExport}\n${schemaExport}`;
|
|
27
|
-
});
|
|
28
|
-
let results = yield Promise.all(compilePromises);
|
|
29
|
-
indexFileData = indexFileData + results.join("\n");
|
|
30
|
-
const outputFile = (0, path_1.join)(basePath, "index.ts");
|
|
31
|
-
(0, fs_1.writeFileSync)(outputFile, indexFileData);
|
|
5
|
+
async function main() {
|
|
6
|
+
console.log("Generating Schema Index");
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const basePath = args[0];
|
|
9
|
+
const schemaFolderPath = (0, path_1.join)(basePath, "form-schema");
|
|
10
|
+
let indexFileData = 'export * from "./interface";\nexport * from "./params";\n';
|
|
11
|
+
const schemaFiles = (0, fs_1.readdirSync)(schemaFolderPath);
|
|
12
|
+
let compilePromises = schemaFiles.map((schemaFile) => {
|
|
13
|
+
const schemaFileName = schemaFile.replace(".json", "");
|
|
14
|
+
const formSchemaExport = `export { default as Deref${schemaFileName} } from "./form-schema/${schemaFile}";`;
|
|
15
|
+
const schemaExport = `export { default as Schema${schemaFileName} } from "./api-schema/${schemaFile}";`;
|
|
16
|
+
return `${formSchemaExport}\n${schemaExport}`;
|
|
32
17
|
});
|
|
18
|
+
let results = await Promise.all(compilePromises);
|
|
19
|
+
indexFileData = indexFileData + results.join("\n");
|
|
20
|
+
const outputFile = (0, path_1.join)(basePath, "index.ts");
|
|
21
|
+
(0, fs_1.writeFileSync)(outputFile, indexFileData);
|
|
33
22
|
}
|
|
34
23
|
main();
|
package/dist/schema-params.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const fs_1 = require("fs");
|
|
13
4
|
const path_1 = require("path");
|
|
@@ -77,24 +68,22 @@ function generateInterfacesFiles(pathParams, schemaPath) {
|
|
|
77
68
|
}
|
|
78
69
|
return `${param.name}${param.required ? "" : "?"}: ${paramSchemaType};`;
|
|
79
70
|
});
|
|
80
|
-
return `export interface ${interfaceName} {
|
|
81
|
-
${interfaceValues.join("\n")}
|
|
71
|
+
return `export interface ${interfaceName} {
|
|
72
|
+
${interfaceValues.join("\n")}
|
|
82
73
|
}`;
|
|
83
74
|
});
|
|
84
75
|
const interfaceFileValuesString = interfaceFileValues.join("\n");
|
|
85
76
|
const interfaceFile = (0, path_1.join)(schemaPath, `params.ts`);
|
|
86
77
|
(0, fs_1.writeFileSync)(interfaceFile, interfaceFileValuesString, { flag: "w" });
|
|
87
78
|
}
|
|
88
|
-
function main() {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
generateInterfacesFiles(pathParams, schemaPath);
|
|
98
|
-
});
|
|
79
|
+
async function main() {
|
|
80
|
+
console.log("Generating Schema Parameter Definitions");
|
|
81
|
+
const args = process.argv.slice(2);
|
|
82
|
+
const url = args[0];
|
|
83
|
+
const schemaPath = args[1];
|
|
84
|
+
const data = await (0, fetch_schema_1.fetchSchema)(url);
|
|
85
|
+
const paths = data.paths;
|
|
86
|
+
const pathParams = generateParams(paths);
|
|
87
|
+
generateInterfacesFiles(pathParams, schemaPath);
|
|
99
88
|
}
|
|
100
89
|
main();
|
package/dist/seed.js
CHANGED
|
@@ -15,19 +15,9 @@
|
|
|
15
15
|
* ICEBERG_WAREHOUSE gs://... path to Iceberg warehouse root
|
|
16
16
|
* ICEBERG_CATALOG_URI sqlite:///... or http://... catalog URI
|
|
17
17
|
*/
|
|
18
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
19
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
20
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
21
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
22
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
23
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
24
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
28
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
29
20
|
};
|
|
30
|
-
var _a, _b;
|
|
31
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
22
|
const fs_1 = __importDefault(require("fs"));
|
|
33
23
|
const path_1 = __importDefault(require("path"));
|
|
@@ -41,8 +31,8 @@ function getArg(flag) {
|
|
|
41
31
|
const i = args.indexOf(flag);
|
|
42
32
|
return i !== -1 && args[i + 1] ? args[i + 1] : null;
|
|
43
33
|
}
|
|
44
|
-
const env =
|
|
45
|
-
const source =
|
|
34
|
+
const env = getArg("--env") ?? "dev";
|
|
35
|
+
const source = getArg("--source") ?? path_1.default.join(process.cwd(), "myapp-dev");
|
|
46
36
|
const repoRoot = process.cwd();
|
|
47
37
|
// ---------------------------------------------------------------------------
|
|
48
38
|
// Step 1: resolve CSV files
|
|
@@ -57,14 +47,21 @@ function downloadFromGcs(gcsUri) {
|
|
|
57
47
|
const tmpDir = path_1.default.join(repoRoot, ".rad", "tmp", "seed");
|
|
58
48
|
fs_1.default.mkdirSync(tmpDir, { recursive: true });
|
|
59
49
|
console.log(`Downloading CSVs from ${gcsUri} ...`);
|
|
50
|
+
// `rad seed` is a local/CI developer tool; `gcsUri` is an operator-supplied
|
|
51
|
+
// --source argument (a gs:// bucket the operator controls), not untrusted
|
|
52
|
+
// network input, so there is no command-injection surface here.
|
|
60
53
|
try {
|
|
54
|
+
// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
|
|
61
55
|
(0, child_process_1.execSync)(`gcloud storage cp "${gcsUri}*.csv" "${tmpDir}/" --quiet`, {
|
|
62
56
|
stdio: "inherit",
|
|
63
57
|
});
|
|
64
58
|
}
|
|
65
|
-
catch
|
|
59
|
+
catch {
|
|
66
60
|
// gcloud storage cp uses gsutil-style globs — fall back
|
|
67
|
-
|
|
61
|
+
// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
|
|
62
|
+
(0, child_process_1.execSync)(`gsutil -m cp "${gcsUri}*.csv" "${tmpDir}/"`, {
|
|
63
|
+
stdio: "inherit",
|
|
64
|
+
});
|
|
68
65
|
}
|
|
69
66
|
return (0, csv_schema_1.discoverCsvFiles)(tmpDir);
|
|
70
67
|
}
|
|
@@ -74,7 +71,9 @@ function downloadFromGcs(gcsUri) {
|
|
|
74
71
|
function validateSchema(csvPath) {
|
|
75
72
|
const { schema, piiViolations } = (0, csv_schema_1.inferSchema)(csvPath, repoRoot);
|
|
76
73
|
if (piiViolations.length > 0) {
|
|
77
|
-
const list = piiViolations
|
|
74
|
+
const list = piiViolations
|
|
75
|
+
.map((v) => ` ${v.column}: ${v.reason}`)
|
|
76
|
+
.join("\n");
|
|
78
77
|
throw new Error(`PII detected in ${path_1.default.basename(csvPath)}:\n${list}\n` +
|
|
79
78
|
`Remove PII data before seeding. Run "rad scan" to review.`);
|
|
80
79
|
}
|
|
@@ -135,7 +134,7 @@ function writeFingerprint(schema) {
|
|
|
135
134
|
rowCount: schema.rowCount,
|
|
136
135
|
seededAt: new Date().toISOString(),
|
|
137
136
|
env,
|
|
138
|
-
previousFingerprint: prev
|
|
137
|
+
previousFingerprint: prev ?? null,
|
|
139
138
|
};
|
|
140
139
|
fs_1.default.writeFileSync(registryPath, JSON.stringify(record, null, 2));
|
|
141
140
|
if (changed) {
|
|
@@ -147,104 +146,103 @@ function writeFingerprint(schema) {
|
|
|
147
146
|
// Step 5: build a Python seed script and run it via django-iceberg
|
|
148
147
|
// ---------------------------------------------------------------------------
|
|
149
148
|
function buildPythonSeedScript(schemas, csvPaths) {
|
|
150
|
-
var _a, _b;
|
|
151
149
|
const namespace = env;
|
|
152
|
-
const warehouse =
|
|
153
|
-
const catalogUri =
|
|
150
|
+
const warehouse = process.env.ICEBERG_WAREHOUSE ?? "data/warehouse";
|
|
151
|
+
const catalogUri = process.env.ICEBERG_CATALOG_URI ?? "sqlite:///data/catalog.db";
|
|
154
152
|
const tableBlocks = schemas
|
|
155
153
|
.map((schema, i) => {
|
|
156
154
|
const ddl = buildCreateTableSql(schema, namespace).replace(/`/g, "\\`");
|
|
157
155
|
const csvPathEscaped = csvPaths[i].replace(/\\/g, "/");
|
|
158
|
-
return `
|
|
159
|
-
# --- ${schema.tableName} ---
|
|
160
|
-
ddl = """${ddl}"""
|
|
161
|
-
cat.execute(ddl)
|
|
162
|
-
df = pl.read_csv("${csvPathEscaped}", infer_schema_length=1000)
|
|
163
|
-
tbl = cat.load_table("${namespace}.${schema.tableName}")
|
|
164
|
-
tbl.overwrite(df.to_arrow())
|
|
165
|
-
print(f" Seeded ${schema.tableName}: ${schema.rowCount} rows")
|
|
156
|
+
return `
|
|
157
|
+
# --- ${schema.tableName} ---
|
|
158
|
+
ddl = """${ddl}"""
|
|
159
|
+
cat.execute(ddl)
|
|
160
|
+
df = pl.read_csv("${csvPathEscaped}", infer_schema_length=1000)
|
|
161
|
+
tbl = cat.load_table("${namespace}.${schema.tableName}")
|
|
162
|
+
tbl.overwrite(df.to_arrow())
|
|
163
|
+
print(f" Seeded ${schema.tableName}: ${schema.rowCount} rows")
|
|
166
164
|
`;
|
|
167
165
|
})
|
|
168
166
|
.join("\n");
|
|
169
|
-
return `
|
|
170
|
-
import polars as pl
|
|
171
|
-
from pyiceberg.catalog import load_catalog
|
|
172
|
-
|
|
173
|
-
cat = load_catalog(
|
|
174
|
-
"default",
|
|
175
|
-
**{
|
|
176
|
-
"uri": "${catalogUri}",
|
|
177
|
-
"warehouse": "${warehouse}",
|
|
178
|
-
}
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
try:
|
|
182
|
-
cat.create_namespace("${namespace}")
|
|
183
|
-
except Exception:
|
|
184
|
-
pass # namespace already exists
|
|
185
|
-
|
|
186
|
-
${tableBlocks}
|
|
187
|
-
|
|
188
|
-
print("Seed complete.")
|
|
167
|
+
return `
|
|
168
|
+
import polars as pl
|
|
169
|
+
from pyiceberg.catalog import load_catalog
|
|
170
|
+
|
|
171
|
+
cat = load_catalog(
|
|
172
|
+
"default",
|
|
173
|
+
**{
|
|
174
|
+
"uri": "${catalogUri}",
|
|
175
|
+
"warehouse": "${warehouse}",
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
cat.create_namespace("${namespace}")
|
|
181
|
+
except Exception:
|
|
182
|
+
pass # namespace already exists
|
|
183
|
+
|
|
184
|
+
${tableBlocks}
|
|
185
|
+
|
|
186
|
+
print("Seed complete.")
|
|
189
187
|
`.trim();
|
|
190
188
|
}
|
|
191
189
|
// ---------------------------------------------------------------------------
|
|
192
190
|
// Main
|
|
193
191
|
// ---------------------------------------------------------------------------
|
|
194
|
-
function main() {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
const rel = path_1.default.relative(repoRoot, csvPath);
|
|
207
|
-
process.stdout.write(` Validating ${rel} ... `);
|
|
208
|
-
try {
|
|
209
|
-
const schema = validateSchema(csvPath);
|
|
210
|
-
schemas.push(schema);
|
|
211
|
-
console.log(`OK [${schema.columns.length} cols, ${schema.rowCount} rows]`);
|
|
212
|
-
}
|
|
213
|
-
catch (err) {
|
|
214
|
-
console.error(`FAIL\n${err.message}`);
|
|
215
|
-
process.exit(1);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Write fingerprints before seeding so CI can detect schema drift
|
|
219
|
-
for (const schema of schemas) {
|
|
220
|
-
writeFingerprint(schema);
|
|
221
|
-
}
|
|
222
|
-
// Emit DDL summary
|
|
223
|
-
const ddlDir = path_1.default.join(repoRoot, ".rad", "ddl");
|
|
224
|
-
fs_1.default.mkdirSync(ddlDir, { recursive: true });
|
|
225
|
-
for (const schema of schemas) {
|
|
226
|
-
const ddl = buildCreateTableSql(schema, env);
|
|
227
|
-
fs_1.default.writeFileSync(path_1.default.join(ddlDir, `${schema.tableName}.sql`), ddl + "\n");
|
|
228
|
-
}
|
|
229
|
-
console.log(`\nDDL written to .rad/ddl/`);
|
|
230
|
-
// Run Python seed via pyiceberg if available
|
|
231
|
-
const seedScript = buildPythonSeedScript(schemas, files);
|
|
232
|
-
const scriptPath = path_1.default.join(repoRoot, ".rad", "tmp", "seed.py");
|
|
233
|
-
fs_1.default.mkdirSync(path_1.default.dirname(scriptPath), { recursive: true });
|
|
234
|
-
fs_1.default.writeFileSync(scriptPath, seedScript);
|
|
235
|
-
const pythonBin = (_a = process.env.PYTHON) !== null && _a !== void 0 ? _a : "python";
|
|
192
|
+
async function main() {
|
|
193
|
+
console.log(`\nrad seed env=${env} source=${source}\n`);
|
|
194
|
+
const files = resolveFiles();
|
|
195
|
+
if (files.length === 0) {
|
|
196
|
+
console.log("No CSV files found. Nothing to seed.");
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
console.log(`Found ${files.length} CSV file(s):\n`);
|
|
200
|
+
const schemas = [];
|
|
201
|
+
for (const csvPath of files) {
|
|
202
|
+
const rel = path_1.default.relative(repoRoot, csvPath);
|
|
203
|
+
process.stdout.write(` Validating ${rel} ... `);
|
|
236
204
|
try {
|
|
237
|
-
|
|
238
|
-
|
|
205
|
+
const schema = validateSchema(csvPath);
|
|
206
|
+
schemas.push(schema);
|
|
207
|
+
console.log(`OK [${schema.columns.length} cols, ${schema.rowCount} rows]`);
|
|
239
208
|
}
|
|
240
|
-
catch (
|
|
241
|
-
console.error(
|
|
242
|
-
" pip install pyiceberg polars pyarrow\n\n" +
|
|
243
|
-
`Generated seed script: ${scriptPath}`);
|
|
209
|
+
catch (err) {
|
|
210
|
+
console.error(`FAIL\n${err.message}`);
|
|
244
211
|
process.exit(1);
|
|
245
212
|
}
|
|
246
|
-
|
|
247
|
-
|
|
213
|
+
}
|
|
214
|
+
// Write fingerprints before seeding so CI can detect schema drift
|
|
215
|
+
for (const schema of schemas) {
|
|
216
|
+
writeFingerprint(schema);
|
|
217
|
+
}
|
|
218
|
+
// Emit DDL summary
|
|
219
|
+
const ddlDir = path_1.default.join(repoRoot, ".rad", "ddl");
|
|
220
|
+
fs_1.default.mkdirSync(ddlDir, { recursive: true });
|
|
221
|
+
for (const schema of schemas) {
|
|
222
|
+
const ddl = buildCreateTableSql(schema, env);
|
|
223
|
+
fs_1.default.writeFileSync(path_1.default.join(ddlDir, `${schema.tableName}.sql`), ddl + "\n");
|
|
224
|
+
}
|
|
225
|
+
console.log(`\nDDL written to .rad/ddl/`);
|
|
226
|
+
// Run Python seed via pyiceberg if available
|
|
227
|
+
const seedScript = buildPythonSeedScript(schemas, files);
|
|
228
|
+
const scriptPath = path_1.default.join(repoRoot, ".rad", "tmp", "seed.py");
|
|
229
|
+
fs_1.default.mkdirSync(path_1.default.dirname(scriptPath), { recursive: true });
|
|
230
|
+
fs_1.default.writeFileSync(scriptPath, seedScript);
|
|
231
|
+
const pythonBin = process.env.PYTHON ?? "python";
|
|
232
|
+
try {
|
|
233
|
+
console.log(`\nSeeding Iceberg namespace "${env}" ...\n`);
|
|
234
|
+
// Runs an internally-generated seed script with the operator-configured
|
|
235
|
+
// python binary; no untrusted input, so no command-injection surface.
|
|
236
|
+
// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process
|
|
237
|
+
(0, child_process_1.execSync)(`${pythonBin} "${scriptPath}"`, { stdio: "inherit" });
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
console.error("\nPython seed step failed. Ensure pyiceberg and polars are installed:\n" +
|
|
241
|
+
" pip install pyiceberg polars pyarrow\n\n" +
|
|
242
|
+
`Generated seed script: ${scriptPath}`);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
console.log("\nDone.");
|
|
248
246
|
}
|
|
249
247
|
main().catch((err) => {
|
|
250
248
|
console.error(err);
|