gencow 0.1.260 → 0.1.261

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.
@@ -86,6 +86,11 @@ const SAFE_LOCAL_ERROR_CODES = new Map([
86
86
  message: "Deploy stopped before upload: a backend source file could not be loaded.",
87
87
  stage: "codegen",
88
88
  action: (caught) => {
89
+ if (safeMissingExportName(caught)) {
90
+ const name = safeMissingExportName(caught);
91
+ const where = safeSourceLocation(caught) ? "at the location above " : "";
92
+ return `Retryable: yes, after the import of "${name}" ${where}names an export its module does not have — use an exported name, or export it from that module, then run \`npx gencow@latest codegen\` to confirm it passes, then rerun your deploy command.`;
93
+ }
89
94
  const cause =
90
95
  "the top-level code that throws during module load, or an import path that does not resolve (check the path and that the imported package is installed)";
91
96
  if (safeSourceLocation(caught)) {
@@ -169,6 +174,13 @@ function safeDisplayDir(caught) {
169
174
  }
170
175
  const SAFE_SOURCE_LOCATION_PATH = /^(?![/\\])(?!.*(?:^|\/)\.\.(?:\/|$))[^\u0000-\u001f\u007f]{1,240}$/u;
171
176
 
177
+ const SAFE_IMPORT_NAME = /^[A-Za-z_$][\w$]{0,127}$/u;
178
+
179
+ function safeMissingExportName(caught) {
180
+ const { missingExport } = caught;
181
+ return typeof missingExport === "string" && SAFE_IMPORT_NAME.test(missingExport) ? missingExport : null;
182
+ }
183
+
172
184
  function safeSourceLocation(caught) {
173
185
  const { sourceFile, line, column } = caught;
174
186
  if (typeof sourceFile !== "string" || !SAFE_SOURCE_LOCATION_PATH.test(sourceFile)) return null;
@@ -36,13 +36,24 @@ function toProjectRelativePath(rawPath, cwd, processCwd) {
36
36
  // esbuild prints one diagnostic per line (`<file>:<line>:<col>: ERROR: <text>`) and the
37
37
  // Bun loader prints `Could not resolve`/`Cannot find module` for an import path that does
38
38
  // not exist. Those are load failures: the source is well-formed, its import is not.
39
+ // `No matching export` is an import of a name its module does not export (esbuild, or the
40
+ // named-import check in codegen-named-import-check.ts); the module itself is well-formed.
39
41
  const DIAGNOSTIC_LINE_PATTERN = /ERROR: |Could not resolve "|Cannot find (?:module|package)\b/u;
40
- const UNRESOLVED_MODULE_PATTERN = /Could not resolve "|Cannot find (?:module|package)\b/u;
42
+ const UNRESOLVED_MODULE_PATTERN = /Could not resolve "|Cannot find (?:module|package)\b|No matching export in "/u;
43
+ const MISSING_EXPORT_PATTERN = /No matching export in "[^"\n]*" for import "([A-Za-z_$][\w$]{0,127})"/u;
41
44
 
42
45
  // The first diagnostic decides the class, matching how the first location is reported.
46
+ function firstDiagnosticLine(message) {
47
+ return message.split("\n").find((line) => DIAGNOSTIC_LINE_PATTERN.test(line)) ?? message;
48
+ }
49
+
43
50
  function isUnresolvedModuleFailure(message) {
44
- const firstDiagnostic = message.split("\n").find((line) => DIAGNOSTIC_LINE_PATTERN.test(line)) ?? message;
45
- return UNRESOLVED_MODULE_PATTERN.test(firstDiagnostic);
51
+ return UNRESOLVED_MODULE_PATTERN.test(firstDiagnosticLine(message));
52
+ }
53
+
54
+ // Returns the imported name of a missing-export diagnostic (identifier only), or null.
55
+ function findMissingExportName(message) {
56
+ return MISSING_EXPORT_PATTERN.exec(firstDiagnosticLine(message))?.[1] ?? null;
46
57
  }
47
58
 
48
59
  // Returns the first project-relative source location found in a raw message, or null.
@@ -67,7 +78,12 @@ export function classifyDeployCodegenFailure(error, { cwd, backendRoot = "gencow
67
78
  const location = findProjectSourceLocation(message, { cwd, processCwd });
68
79
  const backendLocation = location && location.sourceFile.startsWith(`${backendRoot}/`) ? location : null;
69
80
  if (isUnresolvedModuleFailure(message)) {
70
- return { code: CODEGEN_FAILURE_CODES.SOURCE_LOAD_FAILED, ...(backendLocation ?? {}) };
81
+ const missingExport = findMissingExportName(message);
82
+ return {
83
+ code: CODEGEN_FAILURE_CODES.SOURCE_LOAD_FAILED,
84
+ ...(backendLocation ?? {}),
85
+ ...(missingExport ? { missingExport } : {}),
86
+ };
71
87
  }
72
88
  if (location) {
73
89
  return {
@@ -140,6 +156,7 @@ export function createDeployCodegenFailure(classification, { correlationId } = {
140
156
  error.line = classification.line;
141
157
  if (classification.column !== undefined) error.column = classification.column;
142
158
  }
159
+ if (classification.missingExport !== undefined) error.missingExport = classification.missingExport;
143
160
  // Local reference only (no Platform request exists for a codegen failure).
144
161
  if (correlationId !== undefined) error.correlationId = correlationId;
145
162
  return error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.260",
3
+ "version": "0.1.261",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,11 +40,11 @@
40
40
  "ai": "^6.0.314",
41
41
  "better-auth": "1.7.11",
42
42
  "postgres": "^3.4.9",
43
- "@gencow/client": "0.2.8",
44
43
  "@gencow/react": "0.2.8",
44
+ "@gencow/client": "0.2.8",
45
+ "@gencow/server": "0.1.3",
45
46
  "@gencow/core": "0.1.47",
46
- "@gencow/shared": "0.0.0",
47
- "@gencow/server": "0.1.3"
47
+ "@gencow/shared": "0.0.0"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "node scripts/bundle-core.mjs && node scripts/bundle-shared.mjs && node scripts/bundle-server.mjs",