@lark-apaas/db-schema-sync 0.1.18 → 0.1.19-alpha.20260904074828

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/bin.js CHANGED
@@ -5,8 +5,9 @@ import {
5
5
  __require,
6
6
  __toESM,
7
7
  generateSchema,
8
- resolveEnvOptions
9
- } from "./chunk-7O4DEVTQ.js";
8
+ resolveEnvOptions,
9
+ validateGeneratedSchema
10
+ } from "./chunk-UWBHRXTA.js";
10
11
 
11
12
  // node_modules/dotenv/package.json
12
13
  var require_package = __commonJS({
@@ -411,19 +412,50 @@ import { writeFileSync, mkdirSync, existsSync } from "fs";
411
412
  // src/cli-args.ts
412
413
  function parseArgs(argv) {
413
414
  const args = argv.slice(2);
415
+ const command = args[0] === "validate" ? "validate" : "generate";
416
+ const optionArgs = command === "validate" ? args.slice(1) : args;
414
417
  const getArg = (name) => {
415
- const idx = args.indexOf(name);
416
- return idx !== -1 && args[idx + 1] ? args[idx + 1] : void 0;
418
+ const idx = optionArgs.indexOf(name);
419
+ return idx !== -1 && optionArgs[idx + 1] ? optionArgs[idx + 1] : void 0;
417
420
  };
418
- const hasFlag = (name) => args.includes(name);
421
+ const hasFlag = (name) => optionArgs.includes(name);
419
422
  return {
423
+ command,
420
424
  output: getArg("--output"),
425
+ input: getArg("--input"),
426
+ project: getArg("--project"),
421
427
  exportCustomTypes: hasFlag("--export-custom-types")
422
428
  };
423
429
  }
424
430
 
425
431
  // src/bin.ts
432
+ function getValidateExitCode(result) {
433
+ if (result.ok) return 0;
434
+ if (result.status === "invalid_artifact") return 2;
435
+ if (result.status === "inconclusive") return 3;
436
+ return 1;
437
+ }
426
438
  async function main() {
439
+ const cliArgs = parseArgs(process.argv);
440
+ if (cliArgs.command === "validate") {
441
+ if (!cliArgs.input) {
442
+ const output3 = {
443
+ ok: false,
444
+ status: "inconclusive",
445
+ errorType: "validation_runner_failed",
446
+ durationMs: 0,
447
+ message: "--input is required for validate command"
448
+ };
449
+ console.log(JSON.stringify(output3));
450
+ process.exit(1);
451
+ }
452
+ const output2 = validateGeneratedSchema({
453
+ input: cliArgs.input,
454
+ project: cliArgs.project
455
+ });
456
+ console.log(JSON.stringify(output2));
457
+ process.exit(getValidateExitCode(output2));
458
+ }
427
459
  for (const name of [".env.local", ".env"]) {
428
460
  const envPath = resolve(process.cwd(), name);
429
461
  if (existsSync(envPath)) {
@@ -431,25 +463,31 @@ async function main() {
431
463
  console.log(`[db-schema-sync] \u2713 Loaded ${name}`);
432
464
  }
433
465
  }
434
- const cliArgs = parseArgs(process.argv);
435
466
  const output = cliArgs.output || process.env.DB_SCHEMA_OUTPUT || "server/database/schema.ts";
436
467
  try {
437
468
  const options = resolveEnvOptions();
438
469
  console.log("[db-schema-sync] Starting...");
439
- console.log(`[db-schema-sync] app_id=${options.appId}, dbBranch=${options.dbBranch}, exportCustomTypes=${cliArgs.exportCustomTypes}`);
470
+ console.log(
471
+ `[db-schema-sync] app_id=${options.appId}, dbBranch=${options.dbBranch}, exportCustomTypes=${cliArgs.exportCustomTypes}`
472
+ );
440
473
  const schema = await generateSchema({
441
474
  ...options,
442
475
  exportCustomTypes: cliArgs.exportCustomTypes
443
476
  });
444
477
  if (!schema.includes("pgTable") && !schema.includes("pgView")) {
445
- console.warn("[db-schema-sync] \u26A0 Warning: No tables or views found in database. The generated schema will be empty.");
478
+ console.warn(
479
+ "[db-schema-sync] \u26A0 Warning: No tables or views found in database. The generated schema will be empty."
480
+ );
446
481
  }
447
482
  const outputPath = resolve(process.cwd(), output);
448
483
  mkdirSync(dirname(outputPath), { recursive: true });
449
484
  writeFileSync(outputPath, schema, "utf8");
450
485
  console.log(`[db-schema-sync] \u2713 Schema written to ${output}`);
451
486
  } catch (err) {
452
- console.error(`[db-schema-sync] \u2717 Failed:`, err instanceof Error ? err.message : String(err));
487
+ console.error(
488
+ `[db-schema-sync] \u2717 Failed:`,
489
+ err instanceof Error ? err.message : String(err)
490
+ );
453
491
  process.exit(1);
454
492
  }
455
493
  }
@@ -268,11 +268,11 @@ var require_dist = __commonJS({
268
268
  if (cached && cached.expiresAtMs - now > this.refreshBeforeMs) {
269
269
  return { token: cached.token, accessKey: cached.accessKey };
270
270
  }
271
- const result = this.readAndParse(filePath);
272
- if (result) {
273
- this.cache.set(filePath, result);
274
- if (result.expiresAtMs > now) {
275
- return { token: result.token, accessKey: result.accessKey };
271
+ const result2 = this.readAndParse(filePath);
272
+ if (result2) {
273
+ this.cache.set(filePath, result2);
274
+ if (result2.expiresAtMs > now) {
275
+ return { token: result2.token, accessKey: result2.accessKey };
276
276
  }
277
277
  }
278
278
  if (cached && cached.expiresAtMs > now) {
@@ -1157,15 +1157,15 @@ function toAsciiName(name) {
1157
1157
  return name;
1158
1158
  }
1159
1159
  try {
1160
- const result = [];
1160
+ const result2 = [];
1161
1161
  for (const char of name) {
1162
1162
  if (/[^\x00-\x7F]/.test(char) && import_tiny_pinyin.default.isSupported()) {
1163
- result.push(import_tiny_pinyin.default.convertToPinyin(char, "", true));
1163
+ result2.push(import_tiny_pinyin.default.convertToPinyin(char, "", true));
1164
1164
  } else {
1165
- result.push(char);
1165
+ result2.push(char);
1166
1166
  }
1167
1167
  }
1168
- return result.join("_") || name;
1168
+ return result2.join("_") || name;
1169
1169
  } catch {
1170
1170
  return name;
1171
1171
  }
@@ -1847,13 +1847,13 @@ var defaultModifiers = [
1847
1847
  }
1848
1848
  ];
1849
1849
  function applyModifiers(field, modifiers) {
1850
- let result = "";
1850
+ let result2 = "";
1851
1851
  for (const mod of modifiers) {
1852
1852
  if (mod.match(field)) {
1853
- result += mod.modify(field);
1853
+ result2 += mod.modify(field);
1854
1854
  }
1855
1855
  }
1856
- return result;
1856
+ return result2;
1857
1857
  }
1858
1858
 
1859
1859
  // src/generator/structures/enum.ts
@@ -1863,19 +1863,17 @@ function generateEnumCode(schema) {
1863
1863
  }
1864
1864
 
1865
1865
  // src/generator/structures/index-gen.ts
1866
- function generateIndexCode(idx, tableIdentifier, knownColumnProperties) {
1866
+ function generateIndexCode(idx, tableIdentifier) {
1867
1867
  const fn = idx.indexType === "unique" ? "uniqueIndex" : "index";
1868
- const propertyRefs = idx.indexColumns.map((col) => sanitizePropertyName(col));
1869
- const columns = propertyRefs.map((prop) => `table.${prop}`).join(", ");
1868
+ const columns = idx.indexColumns.map((col) => `table.${sanitizePropertyName(col)}`).join(", ");
1870
1869
  const escapedName = escapeDoubleQuote(idx.indexName);
1871
- const allColumnsKnown = knownColumnProperties === void 0 ? true : propertyRefs.every((prop) => knownColumnProperties.has(prop));
1872
- if (!columns || !allColumnsKnown) {
1873
- return `// Complex index: ${idx.indexDef || idx.indexName}`;
1874
- }
1875
1870
  const creationType = idx.indexCreationType || "btree";
1876
- if (creationType !== "btree") {
1871
+ if (creationType !== "btree" && columns) {
1877
1872
  return `${fn}("${escapedName}").using("${creationType}", ${columns})`;
1878
1873
  }
1874
+ if (!columns) {
1875
+ return `// Complex index: ${idx.indexDef || idx.indexName}`;
1876
+ }
1879
1877
  return `${fn}("${escapedName}").on(${columns})`;
1880
1878
  }
1881
1879
 
@@ -1901,18 +1899,16 @@ function generateForeignKeyCode(rel, tableIdentifier, tableIdentifierMap) {
1901
1899
 
1902
1900
  // src/generator/structures/table.ts
1903
1901
  function generateTableCode(table, schemaData, registry, modifiers, tableIdentifierMap) {
1904
- const knownColumnProperties = /* @__PURE__ */ new Set();
1905
1902
  const fieldLines = table.fields.map((field) => {
1906
1903
  const mapper = registry.resolve(field);
1907
1904
  const typeExpr = mapper.generate(field);
1908
1905
  const mods = applyModifiers(field, modifiers);
1909
1906
  const propName = sanitizePropertyName(field.fieldName);
1910
- knownColumnProperties.add(propName);
1911
1907
  return ` ${propName}: ${typeExpr}${mods},`;
1912
1908
  });
1913
1909
  const thirdArgParts = [];
1914
1910
  for (const idx of table.indexes) {
1915
- thirdArgParts.push(generateIndexCode(idx, table.identifier, knownColumnProperties));
1911
+ thirdArgParts.push(generateIndexCode(idx, table.identifier));
1916
1912
  }
1917
1913
  for (const rel of table.relationships) {
1918
1914
  thirdArgParts.push(generateForeignKeyCode(rel, table.identifier, tableIdentifierMap));
@@ -2032,10 +2028,10 @@ function runEnhancers(source, enhancers, context) {
2032
2028
  let current = source;
2033
2029
  const allStats = {};
2034
2030
  for (const enhancer of enhancers) {
2035
- const result = enhancer.enhance(current, context);
2036
- current = result.source;
2037
- if (result.stats) {
2038
- allStats[enhancer.name] = result.stats;
2031
+ const result2 = enhancer.enhance(current, context);
2032
+ current = result2.source;
2033
+ if (result2.stats) {
2034
+ allStats[enhancer.name] = result2.stats;
2039
2035
  }
2040
2036
  }
2041
2037
  return { source: current, allStats };
@@ -2350,7 +2346,7 @@ var jsonbCommentsEnhancer = {
2350
2346
  return { source, stats: { commentsAdded: 0 } };
2351
2347
  }
2352
2348
  const lines = source.split("\n");
2353
- const result = [];
2349
+ const result2 = [];
2354
2350
  let commentsAdded = 0;
2355
2351
  let currentTableName = null;
2356
2352
  for (let i = 0; i < lines.length; i++) {
@@ -2374,7 +2370,7 @@ var jsonbCommentsEnhancer = {
2374
2370
  const parsed = parseColumnComment(comment);
2375
2371
  const indentMatch = line.match(/^\s*/);
2376
2372
  const indent = indentMatch ? indentMatch[0] : "";
2377
- const prevLine = result[result.length - 1]?.trim() ?? "";
2373
+ const prevLine = result2[result2.length - 1]?.trim() ?? "";
2378
2374
  if (!prevLine.startsWith("/**") && !prevLine.startsWith("*") && !prevLine.startsWith("//")) {
2379
2375
  const commentLines = [];
2380
2376
  commentLines.push(`${indent}/**`);
@@ -2390,7 +2386,7 @@ var jsonbCommentsEnhancer = {
2390
2386
  commentLines.push(`${indent} * @type ${safeType}`);
2391
2387
  }
2392
2388
  commentLines.push(`${indent} */`);
2393
- result.push(...commentLines);
2389
+ result2.push(...commentLines);
2394
2390
  commentsAdded++;
2395
2391
  }
2396
2392
  }
@@ -2398,10 +2394,10 @@ var jsonbCommentsEnhancer = {
2398
2394
  if (line.match(/^\}\);?\s*$/) || line.match(/^}\s*,\s*\{/)) {
2399
2395
  currentTableName = null;
2400
2396
  }
2401
- result.push(line);
2397
+ result2.push(line);
2402
2398
  }
2403
2399
  return {
2404
- source: result.join("\n"),
2400
+ source: result2.join("\n"),
2405
2401
  stats: { commentsAdded }
2406
2402
  };
2407
2403
  }
@@ -2464,7 +2460,7 @@ var syncedCommentsEnhancer = {
2464
2460
  return { source };
2465
2461
  }
2466
2462
  const lines = source.split("\n");
2467
- const result = [];
2463
+ const result2 = [];
2468
2464
  let commentsAdded = 0;
2469
2465
  let currentSyncedFields = null;
2470
2466
  let insideTableBody = false;
@@ -2479,11 +2475,11 @@ var syncedCommentsEnhancer = {
2479
2475
  currentSyncedFields = syncedFields;
2480
2476
  insideTableBody = true;
2481
2477
  braceDepth = 0;
2482
- const prevLine = result[result.length - 1]?.trim() ?? "";
2478
+ const prevLine = result2[result2.length - 1]?.trim() ?? "";
2483
2479
  if (!prevLine.includes("Synced table")) {
2484
2480
  const indentMatch = line.match(/^\s*/);
2485
2481
  const indent = indentMatch ? indentMatch[0] : "";
2486
- result.push(`${indent}// ${TABLE_COMMENT}`);
2482
+ result2.push(`${indent}// ${TABLE_COMMENT}`);
2487
2483
  commentsAdded++;
2488
2484
  }
2489
2485
  }
@@ -2500,20 +2496,20 @@ var syncedCommentsEnhancer = {
2500
2496
  if (currentSyncedFields && braceDepth >= 1 && !tableMatch) {
2501
2497
  const columnName = extractColumnName(line);
2502
2498
  if (columnName && currentSyncedFields.has(columnName)) {
2503
- const prevLine = result[result.length - 1]?.trim() ?? "";
2499
+ const prevLine = result2[result2.length - 1]?.trim() ?? "";
2504
2500
  if (!prevLine.includes("Synced field")) {
2505
2501
  const indentMatch = line.match(/^\s*/);
2506
2502
  const indent = indentMatch ? indentMatch[0] : "";
2507
- result.push(`${indent}// ${FIELD_COMMENT}`);
2503
+ result2.push(`${indent}// ${FIELD_COMMENT}`);
2508
2504
  commentsAdded++;
2509
2505
  }
2510
2506
  }
2511
2507
  }
2512
2508
  }
2513
- result.push(line);
2509
+ result2.push(line);
2514
2510
  }
2515
2511
  return {
2516
- source: result.join("\n"),
2512
+ source: result2.join("\n"),
2517
2513
  stats: { commentsAdded }
2518
2514
  };
2519
2515
  }
@@ -2584,6 +2580,260 @@ var defaultEnhancers = [
2584
2580
  formatEnhancer
2585
2581
  ];
2586
2582
 
2583
+ // src/validator.ts
2584
+ import { spawnSync } from "child_process";
2585
+ import {
2586
+ existsSync,
2587
+ mkdtempSync,
2588
+ readFileSync,
2589
+ rmSync,
2590
+ writeFileSync
2591
+ } from "fs";
2592
+ import { tmpdir } from "os";
2593
+ import { dirname, delimiter, join, resolve } from "path";
2594
+ function truncateMessage(message) {
2595
+ return message.length > 500 ? `${message.slice(0, 500)}...` : message;
2596
+ }
2597
+ function result(params, startTime) {
2598
+ return {
2599
+ ...params,
2600
+ durationMs: Date.now() - startTime
2601
+ };
2602
+ }
2603
+ function findConfigFile(startDir, fileName) {
2604
+ let current = startDir;
2605
+ while (true) {
2606
+ const candidate = join(current, fileName);
2607
+ if (existsSync(candidate)) return candidate;
2608
+ const parent = dirname(current);
2609
+ if (parent === current) return void 0;
2610
+ current = parent;
2611
+ }
2612
+ }
2613
+ function findTsc(cwd) {
2614
+ const localTsc = join(
2615
+ cwd,
2616
+ "node_modules",
2617
+ ".bin",
2618
+ process.platform === "win32" ? "tsc.cmd" : "tsc"
2619
+ );
2620
+ if (existsSync(localTsc)) return localTsc;
2621
+ const pathEnv = process.env.PATH ?? "";
2622
+ for (const dir of pathEnv.split(delimiter)) {
2623
+ if (!dir) continue;
2624
+ const candidate = join(
2625
+ dir,
2626
+ process.platform === "win32" ? "tsc.cmd" : "tsc"
2627
+ );
2628
+ if (existsSync(candidate)) return candidate;
2629
+ }
2630
+ return void 0;
2631
+ }
2632
+ function resolveProjectPath(params) {
2633
+ if (params.project) return resolve(params.cwd, params.project);
2634
+ return findConfigFile(dirname(params.inputPath), "tsconfig.node.json") ?? findConfigFile(dirname(params.inputPath), "tsconfig.json");
2635
+ }
2636
+ function createValidationTsconfig(params) {
2637
+ const dir = mkdtempSync(join(tmpdir(), "db-schema-sync-validate-"));
2638
+ const configPath = join(dir, "tsconfig.schema-validation.json");
2639
+ const compilerOptions = {
2640
+ noEmit: true,
2641
+ skipLibCheck: true,
2642
+ types: [],
2643
+ rootDir: dirname(params.inputPath)
2644
+ };
2645
+ const config = params.projectPath ? {
2646
+ extends: params.projectPath,
2647
+ compilerOptions,
2648
+ files: [params.inputPath],
2649
+ include: [],
2650
+ exclude: []
2651
+ } : {
2652
+ compilerOptions: {
2653
+ target: "ES2022",
2654
+ module: "NodeNext",
2655
+ moduleResolution: "NodeNext",
2656
+ esModuleInterop: true,
2657
+ strict: false,
2658
+ ...compilerOptions
2659
+ },
2660
+ files: [params.inputPath],
2661
+ include: [],
2662
+ exclude: []
2663
+ };
2664
+ writeFileSync(configPath, JSON.stringify(config), "utf8");
2665
+ return { dir, path: configPath };
2666
+ }
2667
+ function runTsc(tscPath, cwd, args) {
2668
+ return spawnSync(tscPath, args, {
2669
+ cwd,
2670
+ encoding: "utf8",
2671
+ maxBuffer: 1024 * 1024
2672
+ });
2673
+ }
2674
+ function getTscOutput(output) {
2675
+ return truncateMessage(
2676
+ [output.stdout, output.stderr].filter(Boolean).join("\n").trim()
2677
+ );
2678
+ }
2679
+ function getFirstDiagnosticCode(output) {
2680
+ const match = output.match(/error TS(\d+):/);
2681
+ return match ? Number(match[1]) : void 0;
2682
+ }
2683
+ function isSyntaxDiagnostic(output) {
2684
+ const code = getFirstDiagnosticCode(output);
2685
+ return typeof code === "number" && code >= 1e3 && code < 2e3;
2686
+ }
2687
+ function isConfigDiagnostic(output) {
2688
+ const code = getFirstDiagnosticCode(output);
2689
+ return typeof code === "number" && code >= 5e3 && code < 6e3 || /tsconfig(?:\.[\w-]+)?\.json/i.test(output);
2690
+ }
2691
+ function isNoCheckUnsupported(output) {
2692
+ return /Unknown compiler option ['"]?--?noCheck['"]?/i.test(output);
2693
+ }
2694
+ function classifyFailedTscOutput(output) {
2695
+ if (isConfigDiagnostic(output)) {
2696
+ return {
2697
+ status: "inconclusive",
2698
+ errorType: "validation_runner_failed",
2699
+ message: output || "TypeScript validation runner failed"
2700
+ };
2701
+ }
2702
+ if (isSyntaxDiagnostic(output)) {
2703
+ return {
2704
+ status: "invalid_artifact",
2705
+ errorType: "generated_schema_syntax_error",
2706
+ message: output || "TypeScript syntax validation failed"
2707
+ };
2708
+ }
2709
+ if (getFirstDiagnosticCode(output) === void 0) {
2710
+ return {
2711
+ status: "inconclusive",
2712
+ errorType: "validation_runner_failed",
2713
+ message: output || "TypeScript validation runner failed"
2714
+ };
2715
+ }
2716
+ return {
2717
+ status: "invalid_artifact",
2718
+ errorType: "generated_schema_type_error",
2719
+ message: output || "TypeScript validation failed"
2720
+ };
2721
+ }
2722
+ function validateGeneratedSchema(options) {
2723
+ const startTime = Date.now();
2724
+ const cwd = options.cwd ?? process.cwd();
2725
+ const inputPath = resolve(cwd, options.input);
2726
+ try {
2727
+ if (!existsSync(inputPath)) {
2728
+ return result(
2729
+ {
2730
+ ok: false,
2731
+ status: "invalid_artifact",
2732
+ errorType: "generated_schema_missing",
2733
+ message: `Generated schema file not found: ${options.input}`
2734
+ },
2735
+ startTime
2736
+ );
2737
+ }
2738
+ if (!readFileSync(inputPath, "utf8").trim()) {
2739
+ return result(
2740
+ {
2741
+ ok: false,
2742
+ status: "invalid_artifact",
2743
+ errorType: "generated_schema_missing",
2744
+ message: `Generated schema file is empty: ${options.input}`
2745
+ },
2746
+ startTime
2747
+ );
2748
+ }
2749
+ const tscPath = findTsc(cwd);
2750
+ if (!tscPath) {
2751
+ return result(
2752
+ {
2753
+ ok: false,
2754
+ status: "inconclusive",
2755
+ errorType: "validation_runner_failed",
2756
+ message: "TypeScript compiler not found in sandbox. Please install project dependencies so node_modules/.bin/tsc is available."
2757
+ },
2758
+ startTime
2759
+ );
2760
+ }
2761
+ const projectPath = resolveProjectPath({
2762
+ cwd,
2763
+ inputPath,
2764
+ project: options.project
2765
+ });
2766
+ const tempConfig = createValidationTsconfig({ inputPath, projectPath });
2767
+ try {
2768
+ const syntaxOnly = runTsc(tscPath, cwd, [
2769
+ "--noEmit",
2770
+ "--pretty",
2771
+ "false",
2772
+ "--project",
2773
+ tempConfig.path,
2774
+ "--noCheck"
2775
+ ]);
2776
+ const syntaxOutput = getTscOutput(syntaxOnly);
2777
+ if (syntaxOnly.error) {
2778
+ throw syntaxOnly.error;
2779
+ }
2780
+ if (syntaxOnly.status !== 0 && !isNoCheckUnsupported(syntaxOutput)) {
2781
+ const failure = classifyFailedTscOutput(syntaxOutput);
2782
+ return result(
2783
+ {
2784
+ ok: false,
2785
+ ...failure
2786
+ },
2787
+ startTime
2788
+ );
2789
+ }
2790
+ const fullCheck = runTsc(tscPath, cwd, [
2791
+ "--noEmit",
2792
+ "--pretty",
2793
+ "false",
2794
+ "--project",
2795
+ tempConfig.path
2796
+ ]);
2797
+ const fullOutput = getTscOutput(fullCheck);
2798
+ if (fullCheck.error) {
2799
+ throw fullCheck.error;
2800
+ }
2801
+ if (fullCheck.status !== 0) {
2802
+ const failure = classifyFailedTscOutput(fullOutput);
2803
+ return result(
2804
+ {
2805
+ ok: false,
2806
+ ...failure
2807
+ },
2808
+ startTime
2809
+ );
2810
+ }
2811
+ } finally {
2812
+ rmSync(tempConfig.dir, { recursive: true, force: true });
2813
+ }
2814
+ return result(
2815
+ {
2816
+ ok: true,
2817
+ status: "success",
2818
+ errorType: "none"
2819
+ },
2820
+ startTime
2821
+ );
2822
+ } catch (error) {
2823
+ return result(
2824
+ {
2825
+ ok: false,
2826
+ status: "inconclusive",
2827
+ errorType: "validation_runner_failed",
2828
+ message: truncateMessage(
2829
+ error instanceof Error ? error.message : String(error)
2830
+ )
2831
+ },
2832
+ startTime
2833
+ );
2834
+ }
2835
+ }
2836
+
2587
2837
  // src/index.ts
2588
2838
  async function generateSchema(options) {
2589
2839
  const schemaData = await fetchSchemaData(options);
@@ -2607,6 +2857,7 @@ export {
2607
2857
  resolveEnvOptions,
2608
2858
  normalizeApiResponse,
2609
2859
  generateSchemaCode,
2860
+ validateGeneratedSchema,
2610
2861
  generateSchema,
2611
2862
  generateSchemaFromData
2612
2863
  };
package/dist/index.d.ts CHANGED
@@ -170,6 +170,22 @@ declare function normalizeApiResponse(response: ApiTableViewResponse | null | un
170
170
 
171
171
  declare function generateSchemaCode(data: SchemaData): string;
172
172
 
173
+ type SchemaValidationStatus = 'success' | 'invalid_artifact' | 'inconclusive';
174
+ type SchemaValidationErrorType = 'none' | 'generated_schema_missing' | 'generated_schema_syntax_error' | 'generated_schema_type_error' | 'validation_runner_failed';
175
+ interface SchemaValidationOutput {
176
+ ok: boolean;
177
+ status: SchemaValidationStatus;
178
+ errorType: SchemaValidationErrorType;
179
+ durationMs: number;
180
+ message?: string;
181
+ }
182
+ interface ValidateGeneratedSchemaOptions {
183
+ input: string;
184
+ project?: string;
185
+ cwd?: string;
186
+ }
187
+ declare function validateGeneratedSchema(options: ValidateGeneratedSchemaOptions): SchemaValidationOutput;
188
+
173
189
  interface GenerateSchemaOptions extends FetchOptions {
174
190
  /** Skip specific enhancers by name */
175
191
  skipEnhancers?: string[];
@@ -189,4 +205,4 @@ declare function generateSchemaFromData(schemaData: SchemaData, options?: {
189
205
  exportCustomTypes?: boolean;
190
206
  }): string;
191
207
 
192
- export { type EnumSchema, type FetchOptions, type FieldSchema, type GenerateSchemaOptions, type SchemaData, type TableSchema, type ViewSchema, generateSchema, generateSchemaCode, generateSchemaFromData, normalizeApiResponse, resolveEnvOptions };
208
+ export { type EnumSchema, type FetchOptions, type FieldSchema, type GenerateSchemaOptions, type SchemaData, type SchemaValidationErrorType, type SchemaValidationOutput, type SchemaValidationStatus, type TableSchema, type ViewSchema, generateSchema, generateSchemaCode, generateSchemaFromData, normalizeApiResponse, resolveEnvOptions, validateGeneratedSchema };
package/dist/index.js CHANGED
@@ -4,12 +4,14 @@ import {
4
4
  generateSchemaCode,
5
5
  generateSchemaFromData,
6
6
  normalizeApiResponse,
7
- resolveEnvOptions
8
- } from "./chunk-7O4DEVTQ.js";
7
+ resolveEnvOptions,
8
+ validateGeneratedSchema
9
+ } from "./chunk-UWBHRXTA.js";
9
10
  export {
10
11
  generateSchema,
11
12
  generateSchemaCode,
12
13
  generateSchemaFromData,
13
14
  normalizeApiResponse,
14
- resolveEnvOptions
15
+ resolveEnvOptions,
16
+ validateGeneratedSchema
15
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/db-schema-sync",
3
- "version": "0.1.18",
3
+ "version": "0.1.19-alpha.20260904074828",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",