@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.js CHANGED
@@ -1719,11 +1719,16 @@ var init_ir_generator = __esm({
1719
1719
  });
1720
1720
 
1721
1721
  // src/json-schema/generator.ts
1722
+ import { noopLogger as noopLogger2 } from "@formspec/core";
1722
1723
  function generateJsonSchema(form, options) {
1724
+ const logger = (options?.logger ?? noopLogger2).child({ stage: "ir" });
1723
1725
  const metadata = options?.metadata;
1724
1726
  const vendorPrefix = options?.vendorPrefix;
1725
1727
  const enumSerialization = options?.enumSerialization;
1728
+ logger.debug("canonicalizing chain DSL to IR");
1726
1729
  const ir = canonicalizeChainDSL(form, metadata !== void 0 ? { metadata } : void 0);
1730
+ const schemaLogger = (options?.logger ?? noopLogger2).child({ stage: "schema" });
1731
+ schemaLogger.debug("generating JSON Schema from IR");
1727
1732
  const internalOptions = vendorPrefix === void 0 && enumSerialization === void 0 ? void 0 : {
1728
1733
  ...vendorPrefix !== void 0 && { vendorPrefix },
1729
1734
  ...enumSerialization !== void 0 && { enumSerialization }
@@ -2010,11 +2015,16 @@ var init_ir_generator2 = __esm({
2010
2015
  });
2011
2016
 
2012
2017
  // src/ui-schema/generator.ts
2018
+ import { noopLogger as noopLogger3 } from "@formspec/core";
2013
2019
  function generateUiSchema(form, options) {
2020
+ const logger = (options?.logger ?? noopLogger3).child({ stage: "ir" });
2021
+ logger.debug("canonicalizing chain DSL to IR for UI Schema generation");
2014
2022
  const ir = canonicalizeChainDSL(
2015
2023
  form,
2016
2024
  options?.metadata !== void 0 ? { metadata: options.metadata } : void 0
2017
2025
  );
2026
+ const schemaLogger = (options?.logger ?? noopLogger3).child({ stage: "schema" });
2027
+ schemaLogger.debug("generating UI Schema from IR");
2018
2028
  return generateUiSchemaFromIR(ir);
2019
2029
  }
2020
2030
  var init_generator2 = __esm({
@@ -2493,39 +2503,85 @@ function isNonReferenceIdentifier(node) {
2493
2503
  }
2494
2504
  return false;
2495
2505
  }
2496
- function statementReferencesImportedName(statement, importedNames) {
2506
+ function astReferencesImportedName(root, importedNames) {
2497
2507
  if (importedNames.size === 0) {
2498
2508
  return false;
2499
2509
  }
2500
- let referencesImportedName = false;
2510
+ let found = false;
2501
2511
  const visit = (node) => {
2502
- if (referencesImportedName) {
2503
- return;
2504
- }
2512
+ if (found) return;
2505
2513
  if (ts4.isIdentifier(node) && importedNames.has(node.text) && !isNonReferenceIdentifier(node)) {
2506
- referencesImportedName = true;
2514
+ found = true;
2507
2515
  return;
2508
2516
  }
2509
2517
  ts4.forEachChild(node, visit);
2510
2518
  };
2511
- visit(statement);
2512
- return referencesImportedName;
2519
+ visit(root);
2520
+ return found;
2521
+ }
2522
+ function getObjectMembers(statement) {
2523
+ if (ts4.isInterfaceDeclaration(statement)) {
2524
+ return statement.members;
2525
+ }
2526
+ if (ts4.isTypeLiteralNode(statement.type)) {
2527
+ return statement.type.members;
2528
+ }
2529
+ return void 0;
2530
+ }
2531
+ function rewriteImportedMemberTypes(statement, sourceFile, importedNames) {
2532
+ const members = getObjectMembers(statement);
2533
+ if (members === void 0) {
2534
+ return null;
2535
+ }
2536
+ const replacements = [];
2537
+ for (const member of members) {
2538
+ if (!ts4.isPropertySignature(member)) {
2539
+ if (astReferencesImportedName(member, importedNames)) {
2540
+ return null;
2541
+ }
2542
+ continue;
2543
+ }
2544
+ const typeAnnotation = member.type;
2545
+ if (typeAnnotation === void 0) continue;
2546
+ if (astReferencesImportedName(typeAnnotation, importedNames)) {
2547
+ replacements.push({
2548
+ start: typeAnnotation.getStart(sourceFile),
2549
+ end: typeAnnotation.getEnd()
2550
+ });
2551
+ }
2552
+ }
2553
+ if (replacements.length === 0) {
2554
+ return statement.getText(sourceFile);
2555
+ }
2556
+ const stmtStart = statement.getStart(sourceFile);
2557
+ let result = statement.getText(sourceFile);
2558
+ for (const { start, end } of [...replacements].reverse()) {
2559
+ result = result.slice(0, start - stmtStart) + "unknown" + result.slice(end - stmtStart);
2560
+ }
2561
+ return result;
2513
2562
  }
2514
2563
  function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
2515
2564
  const importedNames = collectImportedNames(sourceFile);
2516
2565
  const importedNamesToSkip = new Set(
2517
2566
  [...importedNames].filter((name) => !extensionTypeNames.has(name))
2518
2567
  );
2519
- return sourceFile.statements.filter((statement) => {
2520
- if (ts4.isImportDeclaration(statement)) return false;
2521
- if (ts4.isImportEqualsDeclaration(statement)) return false;
2522
- if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
2523
- return false;
2524
- if (statementReferencesImportedName(statement, importedNamesToSkip)) {
2525
- return false;
2568
+ const result = [];
2569
+ for (const statement of sourceFile.statements) {
2570
+ if (ts4.isImportDeclaration(statement)) continue;
2571
+ if (ts4.isImportEqualsDeclaration(statement)) continue;
2572
+ if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0) continue;
2573
+ if (!astReferencesImportedName(statement, importedNamesToSkip)) {
2574
+ result.push(statement.getText(sourceFile));
2575
+ continue;
2526
2576
  }
2527
- return true;
2528
- }).map((statement) => statement.getText(sourceFile));
2577
+ if (ts4.isInterfaceDeclaration(statement) || ts4.isTypeAliasDeclaration(statement)) {
2578
+ const rewritten = rewriteImportedMemberTypes(statement, sourceFile, importedNamesToSkip);
2579
+ if (rewritten !== null) {
2580
+ result.push(rewritten);
2581
+ }
2582
+ }
2583
+ }
2584
+ return result;
2529
2585
  }
2530
2586
  function pushUniqueCompilerDiagnostics(target, additions) {
2531
2587
  for (const diagnostic of additions) {
@@ -4385,10 +4441,22 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
4385
4441
  sourceNode
4386
4442
  );
4387
4443
  if (customTypeLookup !== null) {
4444
+ const typeId = customTypeIdFromLookup(customTypeLookup);
4445
+ let payload = null;
4446
+ if (customTypeLookup.registration.extractPayload !== void 0) {
4447
+ try {
4448
+ payload = customTypeLookup.registration.extractPayload(type, checker) ?? null;
4449
+ } catch (cause) {
4450
+ throw new Error(
4451
+ `extractPayload for custom type "${customTypeLookup.registration.typeName}" in extension "${customTypeLookup.extensionId}" threw`,
4452
+ { cause }
4453
+ );
4454
+ }
4455
+ }
4388
4456
  return {
4389
4457
  kind: "custom",
4390
- typeId: customTypeIdFromLookup(customTypeLookup),
4391
- payload: null
4458
+ typeId,
4459
+ payload
4392
4460
  };
4393
4461
  }
4394
4462
  const primitiveAlias = tryResolveNamedPrimitiveAlias(
@@ -6927,9 +6995,12 @@ __export(index_exports, {
6927
6995
  uiSchemaSchema: () => uiSchema,
6928
6996
  writeSchemas: () => writeSchemas
6929
6997
  });
6998
+ import { noopLogger as noopLogger4 } from "@formspec/core";
6930
6999
  import * as fs from "fs";
6931
7000
  import * as path3 from "path";
6932
7001
  function buildFormSchemas(form, options) {
7002
+ const logger = options?.logger ?? noopLogger4;
7003
+ logger.debug("buildFormSchemas: starting schema generation");
6933
7004
  return {
6934
7005
  jsonSchema: generateJsonSchema(form, options),
6935
7006
  uiSchema: generateUiSchema(form, options)
@@ -6942,12 +7013,15 @@ function writeSchemas(form, options) {
6942
7013
  indent = 2,
6943
7014
  vendorPrefix,
6944
7015
  enumSerialization,
6945
- metadata
7016
+ metadata,
7017
+ logger: rawLogger
6946
7018
  } = options;
6947
- const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? void 0 : {
7019
+ const logger = (rawLogger ?? noopLogger4).child({ stage: "write" });
7020
+ const buildOptions = vendorPrefix === void 0 && enumSerialization === void 0 && metadata === void 0 ? { logger: rawLogger } : {
6948
7021
  ...vendorPrefix !== void 0 && { vendorPrefix },
6949
7022
  ...enumSerialization !== void 0 && { enumSerialization },
6950
- ...metadata !== void 0 && { metadata }
7023
+ ...metadata !== void 0 && { metadata },
7024
+ logger: rawLogger
6951
7025
  };
6952
7026
  const { jsonSchema, uiSchema: uiSchema2 } = buildFormSchemas(form, buildOptions);
6953
7027
  if (!fs.existsSync(outDir)) {
@@ -6955,7 +7029,9 @@ function writeSchemas(form, options) {
6955
7029
  }
6956
7030
  const jsonSchemaPath = path3.join(outDir, `${name}-schema.json`);
6957
7031
  const uiSchemaPath = path3.join(outDir, `${name}-uischema.json`);
7032
+ logger.debug("writing JSON Schema", { path: jsonSchemaPath });
6958
7033
  fs.writeFileSync(jsonSchemaPath, JSON.stringify(jsonSchema, null, indent));
7034
+ logger.debug("writing UI Schema", { path: uiSchemaPath });
6959
7035
  fs.writeFileSync(uiSchemaPath, JSON.stringify(uiSchema2, null, indent));
6960
7036
  return { jsonSchemaPath, uiSchemaPath };
6961
7037
  }
@@ -6983,6 +7059,33 @@ var init_index = __esm({
6983
7059
  // src/cli.ts
6984
7060
  import * as path4 from "path";
6985
7061
  import { pathToFileURL } from "url";
7062
+
7063
+ // src/cli/logger.ts
7064
+ import { createRequire } from "module";
7065
+ import { isNamespaceEnabled, noopLogger } from "@formspec/core";
7066
+ var require2 = createRequire(import.meta.url);
7067
+ function createLogger(namespace) {
7068
+ const debugEnv = process.env["DEBUG"] ?? "";
7069
+ if (!isNamespaceEnabled(debugEnv, namespace)) {
7070
+ return noopLogger;
7071
+ }
7072
+ const pinoModule = require2("pino");
7073
+ const pino = typeof pinoModule === "function" ? pinoModule : pinoModule.default;
7074
+ const isTTY = process.stderr.isTTY;
7075
+ if (isTTY) {
7076
+ const pinoPretty = require2("pino-pretty");
7077
+ const prettyTransport = pinoPretty.default ?? pinoPretty;
7078
+ const stream = prettyTransport({ destination: 2, colorize: true, sync: true });
7079
+ return pino({ name: namespace, level: "debug" }, stream);
7080
+ }
7081
+ return pino(
7082
+ { name: namespace, level: "debug" },
7083
+ pino.destination({ dest: 2, sync: true })
7084
+ );
7085
+ }
7086
+
7087
+ // src/cli.ts
7088
+ var log = createLogger("formspec:build");
6986
7089
  function printHelp() {
6987
7090
  console.log(`
6988
7091
  FormSpec Build CLI - Generate JSON Schema and UI Schema
@@ -7072,6 +7175,7 @@ function parseArgs(args) {
7072
7175
  if (!name) {
7073
7176
  name = path4.basename(inputFile, path4.extname(inputFile));
7074
7177
  }
7178
+ log.debug("Arguments parsed", { inputFile, outDir, name, enumSerialization });
7075
7179
  return { inputFile, outDir, name, enumSerialization };
7076
7180
  }
7077
7181
  async function main() {
@@ -7082,11 +7186,14 @@ async function main() {
7082
7186
  }
7083
7187
  const { inputFile, outDir, name, enumSerialization } = options;
7084
7188
  const absoluteInput = path4.resolve(process.cwd(), inputFile);
7189
+ log.debug("Resolved input file", { absoluteInput });
7085
7190
  try {
7086
7191
  const fileUrl = pathToFileURL(absoluteInput).href;
7192
+ log.debug("Loading form module", { fileUrl });
7087
7193
  const module = await import(fileUrl);
7088
7194
  const form = module["default"] ?? module["form"];
7089
7195
  if (!form || typeof form !== "object" || !("elements" in form)) {
7196
+ log.error("Input file does not export a valid FormSpec", { fileUrl });
7090
7197
  console.error("Error: Input file must export a FormSpec as default export or as 'form'");
7091
7198
  console.error("Example:");
7092
7199
  console.error(' export default formspec(field.text("name"));');
@@ -7094,18 +7201,22 @@ async function main() {
7094
7201
  console.error(' export const form = formspec(field.text("name"));');
7095
7202
  process.exit(1);
7096
7203
  }
7204
+ log.debug("Form module loaded, generating schemas");
7097
7205
  const { writeSchemas: writeSchemas2 } = await Promise.resolve().then(() => (init_index(), index_exports));
7098
7206
  const { jsonSchemaPath, uiSchemaPath } = writeSchemas2(
7099
7207
  form,
7100
7208
  { outDir, name, enumSerialization }
7101
7209
  );
7210
+ log.debug("Schemas written", { jsonSchemaPath, uiSchemaPath });
7102
7211
  console.log("Generated:");
7103
7212
  console.log(` ${jsonSchemaPath}`);
7104
7213
  console.log(` ${uiSchemaPath}`);
7105
7214
  } catch (error) {
7106
7215
  if (error instanceof Error) {
7216
+ log.child({ err: error.message }).error("Schema generation failed");
7107
7217
  console.error(`Error: ${error.message}`);
7108
7218
  } else {
7219
+ log.error("Schema generation failed with unknown error");
7109
7220
  console.error("Error:", error);
7110
7221
  }
7111
7222
  process.exit(1);