@formspec/build 0.1.0-alpha.52 → 0.1.0-alpha.54

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
@@ -1742,19 +1742,25 @@ var init_ir_generator = __esm({
1742
1742
 
1743
1743
  // src/json-schema/generator.ts
1744
1744
  function generateJsonSchema(form, options) {
1745
+ const logger = (options?.logger ?? import_core2.noopLogger).child({ stage: "ir" });
1745
1746
  const metadata = options?.metadata;
1746
1747
  const vendorPrefix = options?.vendorPrefix;
1747
1748
  const enumSerialization = options?.enumSerialization;
1749
+ logger.debug("canonicalizing chain DSL to IR");
1748
1750
  const ir = canonicalizeChainDSL(form, metadata !== void 0 ? { metadata } : void 0);
1751
+ const schemaLogger = (options?.logger ?? import_core2.noopLogger).child({ stage: "schema" });
1752
+ schemaLogger.debug("generating JSON Schema from IR");
1749
1753
  const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
1750
1754
  ...vendorPrefix !== void 0 && { vendorPrefix },
1751
1755
  ...enumSerialization !== void 0 && { enumSerialization }
1752
1756
  };
1753
1757
  return generateJsonSchemaFromIR(ir, internalOptions);
1754
1758
  }
1759
+ var import_core2;
1755
1760
  var init_generator = __esm({
1756
1761
  "src/json-schema/generator.ts"() {
1757
1762
  "use strict";
1763
+ import_core2 = require("@formspec/core");
1758
1764
  init_canonicalize();
1759
1765
  init_ir_generator();
1760
1766
  }
@@ -2034,15 +2040,21 @@ var init_ir_generator2 = __esm({
2034
2040
 
2035
2041
  // src/ui-schema/generator.ts
2036
2042
  function generateUiSchema(form, options) {
2043
+ const logger = (options?.logger ?? import_core3.noopLogger).child({ stage: "ir" });
2044
+ logger.debug("canonicalizing chain DSL to IR for UI Schema generation");
2037
2045
  const ir = canonicalizeChainDSL(
2038
2046
  form,
2039
2047
  options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
2040
2048
  );
2049
+ const schemaLogger = (options?.logger ?? import_core3.noopLogger).child({ stage: "schema" });
2050
+ schemaLogger.debug("generating UI Schema from IR");
2041
2051
  return generateUiSchemaFromIR(ir);
2042
2052
  }
2053
+ var import_core3;
2043
2054
  var init_generator2 = __esm({
2044
2055
  "src/ui-schema/generator.ts"() {
2045
2056
  "use strict";
2057
+ import_core3 = require("@formspec/core");
2046
2058
  init_canonicalize();
2047
2059
  init_ir_generator2();
2048
2060
  }
@@ -2490,39 +2502,85 @@ function isNonReferenceIdentifier(node) {
2490
2502
  }
2491
2503
  return false;
2492
2504
  }
2493
- function statementReferencesImportedName(statement, importedNames) {
2505
+ function astReferencesImportedName(root, importedNames) {
2494
2506
  if (importedNames.size === 0) {
2495
2507
  return false;
2496
2508
  }
2497
- let referencesImportedName = false;
2509
+ let found = false;
2498
2510
  const visit = (node) => {
2499
- if (referencesImportedName) {
2500
- return;
2501
- }
2511
+ if (found) return;
2502
2512
  if (ts4.isIdentifier(node) && importedNames.has(node.text) && !isNonReferenceIdentifier(node)) {
2503
- referencesImportedName = true;
2513
+ found = true;
2504
2514
  return;
2505
2515
  }
2506
2516
  ts4.forEachChild(node, visit);
2507
2517
  };
2508
- visit(statement);
2509
- return referencesImportedName;
2518
+ visit(root);
2519
+ return found;
2520
+ }
2521
+ function getObjectMembers(statement) {
2522
+ if (ts4.isInterfaceDeclaration(statement)) {
2523
+ return statement.members;
2524
+ }
2525
+ if (ts4.isTypeLiteralNode(statement.type)) {
2526
+ return statement.type.members;
2527
+ }
2528
+ return void 0;
2529
+ }
2530
+ function rewriteImportedMemberTypes(statement, sourceFile, importedNames) {
2531
+ const members = getObjectMembers(statement);
2532
+ if (members === void 0) {
2533
+ return null;
2534
+ }
2535
+ const replacements = [];
2536
+ for (const member of members) {
2537
+ if (!ts4.isPropertySignature(member)) {
2538
+ if (astReferencesImportedName(member, importedNames)) {
2539
+ return null;
2540
+ }
2541
+ continue;
2542
+ }
2543
+ const typeAnnotation = member.type;
2544
+ if (typeAnnotation === void 0) continue;
2545
+ if (astReferencesImportedName(typeAnnotation, importedNames)) {
2546
+ replacements.push({
2547
+ start: typeAnnotation.getStart(sourceFile),
2548
+ end: typeAnnotation.getEnd()
2549
+ });
2550
+ }
2551
+ }
2552
+ if (replacements.length === 0) {
2553
+ return statement.getText(sourceFile);
2554
+ }
2555
+ const stmtStart = statement.getStart(sourceFile);
2556
+ let result = statement.getText(sourceFile);
2557
+ for (const { start, end } of [...replacements].reverse()) {
2558
+ result = result.slice(0, start - stmtStart) + "unknown" + result.slice(end - stmtStart);
2559
+ }
2560
+ return result;
2510
2561
  }
2511
2562
  function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2512
2563
  const importedNames = collectImportedNames(sourceFile);
2513
2564
  const importedNamesToSkip = new Set(
2514
2565
  [...importedNames].filter((name) => !extensionTypeNames.has(name))
2515
2566
  );
2516
- return sourceFile.statements.filter((statement) => {
2517
- if (ts4.isImportDeclaration(statement)) return false;
2518
- if (ts4.isImportEqualsDeclaration(statement)) return false;
2519
- if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
2520
- return false;
2521
- if (statementReferencesImportedName(statement, importedNamesToSkip)) {
2522
- return false;
2567
+ const result = [];
2568
+ for (const statement of sourceFile.statements) {
2569
+ if (ts4.isImportDeclaration(statement)) continue;
2570
+ if (ts4.isImportEqualsDeclaration(statement)) continue;
2571
+ if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0) continue;
2572
+ if (!astReferencesImportedName(statement, importedNamesToSkip)) {
2573
+ result.push(statement.getText(sourceFile));
2574
+ continue;
2523
2575
  }
2524
- return true;
2525
- }).map((statement) => statement.getText(sourceFile));
2576
+ if (ts4.isInterfaceDeclaration(statement) || ts4.isTypeAliasDeclaration(statement)) {
2577
+ const rewritten = rewriteImportedMemberTypes(statement, sourceFile, importedNamesToSkip);
2578
+ if (rewritten !== null) {
2579
+ result.push(rewritten);
2580
+ }
2581
+ }
2582
+ }
2583
+ return result;
2526
2584
  }
2527
2585
  function pushUniqueCompilerDiagnostics(target, additions) {
2528
2586
  for (const diagnostic of additions) {
@@ -4382,10 +4440,22 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
4382
4440
  sourceNode
4383
4441
  );
4384
4442
  if (customTypeLookup !== null) {
4443
+ const typeId = customTypeIdFromLookup(customTypeLookup);
4444
+ let payload = null;
4445
+ if (customTypeLookup.registration.extractPayload !== void 0) {
4446
+ try {
4447
+ payload = customTypeLookup.registration.extractPayload(type, checker) ?? null;
4448
+ } catch (cause) {
4449
+ throw new Error(
4450
+ `extractPayload for custom type "${customTypeLookup.registration.typeName}" in extension "${customTypeLookup.extensionId}" threw`,
4451
+ { cause }
4452
+ );
4453
+ }
4454
+ }
4385
4455
  return {
4386
4456
  kind: "custom",
4387
- typeId: customTypeIdFromLookup(customTypeLookup),
4388
- payload: null
4457
+ typeId,
4458
+ payload
4389
4459
  };
4390
4460
  }
4391
4461
  const primitiveAlias = tryResolveNamedPrimitiveAlias(
@@ -6933,6 +7003,8 @@ __export(index_exports, {
6933
7003
  writeSchemas: () => writeSchemas
6934
7004
  });
6935
7005
  function buildFormSchemas(form, options) {
7006
+ const logger = options?.logger ?? import_core4.noopLogger;
7007
+ logger.debug("buildFormSchemas: starting schema generation");
6936
7008
  return {
6937
7009
  jsonSchema: generateJsonSchema(form, options),
6938
7010
  uiSchema: generateUiSchema(form, options)
@@ -6945,12 +7017,15 @@ function writeSchemas(form, options) {
6945
7017
  indent = 2,
6946
7018
  vendorPrefix,
6947
7019
  enumSerialization,
6948
- metadata
7020
+ metadata,
7021
+ logger: rawLogger
6949
7022
  } = options;
6950
- const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? void 0 : {
7023
+ const logger = (rawLogger ?? import_core4.noopLogger).child({ stage: "write" });
7024
+ const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? { logger: rawLogger } : {
6951
7025
  ...vendorPrefix !== void 0 && { vendorPrefix },
6952
7026
  ...enumSerialization !== void 0 && { enumSerialization },
6953
- ...metadata !== void 0 && { metadata }
7027
+ ...metadata !== void 0 && { metadata },
7028
+ logger: rawLogger
6954
7029
  };
6955
7030
  const { jsonSchema, uiSchema: uiSchema2 } = buildFormSchemas(form, buildOptions);
6956
7031
  if (!fs.existsSync(outDir)) {
@@ -6958,14 +7033,17 @@ function writeSchemas(form, options) {
6958
7033
  }
6959
7034
  const jsonSchemaPath = path3.join(outDir, `${name}-schema.json`);
6960
7035
  const uiSchemaPath = path3.join(outDir, `${name}-uischema.json`);
7036
+ logger.debug("writing JSON Schema", { path: jsonSchemaPath });
6961
7037
  fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
7038
+ logger.debug("writing UI Schema", { path: uiSchemaPath });
6962
7039
  fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
6963
7040
  return { jsonSchemaPath, uiSchemaPath };
6964
7041
  }
6965
- var fs, path3;
7042
+ var import_core4, fs, path3;
6966
7043
  var init_index = __esm({
6967
7044
  "src/index.ts"() {
6968
7045
  "use strict";
7046
+ import_core4 = require("@formspec/core");
6969
7047
  init_generator();
6970
7048
  init_generator2();
6971
7049
  init_ir_generator();
@@ -6989,6 +7067,34 @@ var init_index = __esm({
6989
7067
  // src/cli.ts
6990
7068
  var path4 = __toESM(require("path"), 1);
6991
7069
  var import_node_url = require("url");
7070
+
7071
+ // src/cli/logger.ts
7072
+ var import_node_module = require("module");
7073
+ var import_core = require("@formspec/core");
7074
+ var import_meta = {};
7075
+ var require2 = (0, import_node_module.createRequire)(import_meta.url);
7076
+ function createLogger(namespace) {
7077
+ const debugEnv = process.env["DEBUG"] ?? "";
7078
+ if (!(0, import_core.isNamespaceEnabled)(debugEnv, namespace)) {
7079
+ return import_core.noopLogger;
7080
+ }
7081
+ const pinoModule = require2("pino");
7082
+ const pino = typeof pinoModule === "function" ? pinoModule : pinoModule.default;
7083
+ const isTTY = process.stderr.isTTY;
7084
+ if (isTTY) {
7085
+ const pinoPretty = require2("pino-pretty");
7086
+ const prettyTransport = pinoPretty.default ?? pinoPretty;
7087
+ const stream = prettyTransport({ destination: 2, colorize: true, sync: true });
7088
+ return pino({ name: namespace, level: "debug" }, stream);
7089
+ }
7090
+ return pino(
7091
+ { name: namespace, level: "debug" },
7092
+ pino.destination({ dest: 2, sync: true })
7093
+ );
7094
+ }
7095
+
7096
+ // src/cli.ts
7097
+ var log = createLogger("formspec:build");
6992
7098
  function printHelp() {
6993
7099
  console.log(`
6994
7100
  FormSpec Build CLI - Generate JSON Schema and UI Schema
@@ -7078,6 +7184,7 @@ function parseArgs(args) {
7078
7184
  if (!name) {
7079
7185
  name = path4.basename(inputFile, path4.extname(inputFile));
7080
7186
  }
7187
+ log.debug("Arguments parsed", { inputFile, outDir, name, enumSerialization });
7081
7188
  return { inputFile, outDir, name, enumSerialization };
7082
7189
  }
7083
7190
  async function main() {
@@ -7088,11 +7195,14 @@ async function main() {
7088
7195
  }
7089
7196
  const { inputFile, outDir, name, enumSerialization } = options;
7090
7197
  const absoluteInput = path4.resolve(process.cwd(), inputFile);
7198
+ log.debug("Resolved input file", { absoluteInput });
7091
7199
  try {
7092
7200
  const fileUrl = (0, import_node_url.pathToFileURL)(absoluteInput).href;
7201
+ log.debug("Loading form module", { fileUrl });
7093
7202
  const module2 = await import(fileUrl);
7094
7203
  const form = module2["default"] ?? module2["form"];
7095
7204
  if (!form || typeof form !== "object" || !("elements" in form)) {
7205
+ log.error("Input file does not export a valid FormSpec", { fileUrl });
7096
7206
  console.error("Error: Input file must export a FormSpec as default export or as 'form'");
7097
7207
  console.error("Example:");
7098
7208
  console.error(' export default formspec(field.text("name"));');
@@ -7100,18 +7210,22 @@ async function main() {
7100
7210
  console.error(' export const form = formspec(field.text("name"));');
7101
7211
  process.exit(1);
7102
7212
  }
7213
+ log.debug("Form module loaded, generating schemas");
7103
7214
  const { writeSchemas: writeSchemas2 } = await Promise.resolve().then(() => (init_index(), index_exports));
7104
7215
  const { jsonSchemaPath, uiSchemaPath } = writeSchemas2(
7105
7216
  form,
7106
7217
  { outDir, name, enumSerialization }
7107
7218
  );
7219
+ log.debug("Schemas written", { jsonSchemaPath, uiSchemaPath });
7108
7220
  console.log("Generated:");
7109
7221
  console.log(` ${jsonSchemaPath}`);
7110
7222
  console.log(` ${uiSchemaPath}`);
7111
7223
  } catch (error) {
7112
7224
  if (error instanceof Error) {
7225
+ log.child({ err: error.message }).error("Schema generation failed");
7113
7226
  console.error(`Error: ${error.message}`);
7114
7227
  } else {
7228
+ log.error("Schema generation failed with unknown error");
7115
7229
  console.error("Error:", error);
7116
7230
  }
7117
7231
  process.exit(1);