@tetrascience-npm/request 0.2.0-beta.106.2 → 0.2.1-beta.112.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"generate-schemas.d.ts","sourceRoot":"","sources":["../../src/cli/generate-schemas.ts"],"names":[],"mappings":";AA8DA;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS5C;AAMD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CA6GnG"}
1
+ {"version":3,"file":"generate-schemas.d.ts","sourceRoot":"","sources":["../../src/cli/generate-schemas.ts"],"names":[],"mappings":";AA8DA;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAkEnG"}
@@ -39,14 +39,14 @@ exports.generateRequestSchemas = generateRequestSchemas;
39
39
  /**
40
40
  * Generates Zod request-body schemas from an OpenAPI spec.
41
41
  *
42
- * 1. Runs openapi-zod-client to get Zod schemas for all components
43
- * 2. Parses the OpenAPI spec to find which path+method has a request body
44
- * 3. Outputs a validation map: "METHOD /path" -> Zod schema
42
+ * Uses openapi-zod-client's programmatic API to:
43
+ * 1. Parse the OpenAPI spec into structured schema + endpoint data
44
+ * 2. Extract request body schema mappings from endpoint definitions
45
+ * 3. Output a validation map: "METHOD /path" -> Zod schema
45
46
  *
46
47
  * Usage:
47
48
  * generate-request-schemas --spec <path-to-openapi-yaml> --out <output-dir>
48
49
  */
49
- const child_process_1 = require("child_process");
50
50
  const fs = __importStar(require("fs"));
51
51
  const path = __importStar(require("path"));
52
52
  function parseArgs() {
@@ -100,103 +100,53 @@ function findBin(name) {
100
100
  console.error(`Error: ${name} not found. Install it as a devDependency: yarn add -D ${name}`);
101
101
  process.exit(1);
102
102
  }
103
- function findZodClientBin() {
104
- return findBin('openapi-zod-client');
105
- }
106
103
  function generateRequestSchemas(specPath, outDir, outFileName) {
107
- const tmpFile = path.join(outDir, '.zod-raw.ts');
108
104
  const outFile = path.join(outDir, outFileName || 'request-schemas.ts');
109
105
  fs.mkdirSync(outDir, { recursive: true });
110
- // 1. Generate full zodios output to a temp file
111
- const zodClientBin = findZodClientBin();
112
- (0, child_process_1.execSync)(`"${zodClientBin}" "${specPath}" -o "${tmpFile}" --export-schemas`, { stdio: 'inherit' });
113
- let raw;
106
+ // 1. Load OpenAPI spec and get structured schema/endpoint data via programmatic API
107
+ const spec = loadYaml(specPath);
108
+ let getZodClientTemplateContext;
114
109
  try {
115
- raw = fs.readFileSync(tmpFile, 'utf-8');
110
+ ({ getZodClientTemplateContext } = require('openapi-zod-client'));
116
111
  }
117
112
  catch {
118
- throw new Error(`Failed to read generated file: ${tmpFile}`);
119
- }
120
- // Extract schema section (everything before `const endpoints = makeApi(`)
121
- const endpointsIdx = raw.indexOf('const endpoints = makeApi(');
122
- if (endpointsIdx === -1) {
123
- fs.unlinkSync(tmpFile);
124
- throw new Error('Could not find endpoints definition in generated file');
113
+ console.error('Error: openapi-zod-client is required for schema generation. Install it as a devDependency: yarn add -D openapi-zod-client');
114
+ process.exit(1);
125
115
  }
126
- const schemaSection = raw
127
- .substring(0, endpointsIdx)
128
- .split('\n')
129
- .filter((l) => !l.startsWith('import '))
130
- .join('\n')
131
- .trim();
132
- // 2. Parse the OpenAPI spec to find request body -> schema name mappings
133
- const spec = loadYaml(specPath);
116
+ const ctx = getZodClientTemplateContext(spec, { shouldExportAllSchemas: true });
117
+ // 2. Build "METHOD /path" -> schema name map from endpoint definitions
118
+ // openapi-zod-client converts path params to Express format (:id),
119
+ // but openapi-fetch's schemaPath uses OpenAPI format ({id}).
120
+ const toOpenApiPath = (p) => p.replace(/:(\w+)/g, '{$1}');
134
121
  const bodyMap = {};
135
- for (const [pathStr, methods] of Object.entries(spec.paths || {})) {
136
- for (const [method, operation] of Object.entries(methods)) {
137
- if (method === 'parameters')
138
- continue;
139
- const op = operation;
140
- const requestBody = op.requestBody;
141
- if (!requestBody?.content?.['application/json']?.schema)
142
- continue;
143
- const schema = requestBody.content['application/json'].schema;
144
- const key = `${method.toUpperCase()} ${pathStr}`;
145
- if (schema.$ref) {
146
- const schemaName = schema.$ref.split('/').pop();
147
- bodyMap[key] = schemaName;
148
- }
149
- else if (schema.type === 'array' && schema.items?.$ref) {
150
- const opId = op.operationId?.replace(/-/g, '_');
151
- if (opId)
152
- bodyMap[key] = `${opId}_Body`;
153
- }
154
- else {
155
- const opId = op.operationId?.replace(/-/g, '_');
156
- if (opId)
157
- bodyMap[key] = `${opId}_Body`;
158
- }
159
- }
160
- }
161
- // 3. Verify all referenced schema names exist in the generated code
162
- const exportedSchemaNames = [...raw.matchAll(/^const (\w+)\s*=\s*z[.\s]/gm)].map((m) => m[1]);
163
- for (const [key, schemaName] of Object.entries(bodyMap)) {
164
- if (raw.includes(`const ${schemaName} =`) || raw.includes(`const ${schemaName}=`)) {
122
+ for (const endpoint of ctx.endpoints) {
123
+ const bodyParam = endpoint.parameters.find((p) => p.type === 'Body');
124
+ if (!bodyParam)
165
125
  continue;
166
- }
167
- // Try to find a schema with matching suffix
168
- const parts = schemaName.split('_');
169
- const resourceHint = parts.slice(1, -1).join('_');
170
- const fallback = exportedSchemaNames.find((name) => name.endsWith('_Body') && name.includes(resourceHint));
171
- if (fallback) {
172
- console.log(` info: ${key}: "${schemaName}" -> "${fallback}" (shared schema)`);
173
- bodyMap[key] = fallback;
174
- }
175
- else {
176
- console.warn(` warn: Schema "${schemaName}" for ${key} not found — skipping`);
177
- delete bodyMap[key];
178
- }
126
+ const key = `${endpoint.method.toUpperCase()} ${toOpenApiPath(endpoint.path)}`;
127
+ bodyMap[key] = bodyParam.schema;
179
128
  }
180
- // 4. Build output file
129
+ // 3. Build output file — schemas are already in dependency order (topologically sorted)
181
130
  const lines = [
182
131
  '// AUTO-GENERATED — do not edit. Run `generate-request-schemas` to regenerate.',
183
132
  "import { z } from 'zod'",
184
133
  '',
185
- schemaSection,
186
- '',
187
- '/**',
188
- ' * Map of "METHOD /path" -> Zod schema for request body validation.',
189
- ' * Used by the request validation middleware.',
190
- ' */',
191
- 'export const requestBodySchemas: Record<string, z.ZodTypeAny> = {',
192
134
  ];
135
+ for (const [name, code] of Object.entries(ctx.schemas)) {
136
+ lines.push(`const ${name} = ${code}`);
137
+ }
138
+ lines.push('');
139
+ lines.push('/**');
140
+ lines.push(' * Map of "METHOD /path" -> Zod schema for request body validation.');
141
+ lines.push(' * Used by the request validation middleware.');
142
+ lines.push(' */');
143
+ lines.push('export const requestBodySchemas: Record<string, z.ZodTypeAny> = {');
193
144
  for (const [key, schemaName] of Object.entries(bodyMap)) {
194
145
  lines.push(` '${key}': ${schemaName},`);
195
146
  }
196
147
  lines.push('}');
197
148
  lines.push('');
198
149
  fs.writeFileSync(outFile, lines.join('\n'));
199
- fs.unlinkSync(tmpFile);
200
150
  console.log(`\nGenerated ${outFile}`);
201
151
  console.log(` ${Object.keys(bodyMap).length} request body schemas mapped:`);
202
152
  for (const [key, schemaName] of Object.entries(bodyMap)) {
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAkBzC;AAaD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,MAAM,CA4E3F;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAsBT;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAOvC"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAkBzC;AAaD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,MAAM,CA4E3F;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAsBT;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAGvC"}
@@ -157,9 +157,5 @@ dist/
157
157
  }
158
158
  function generateYarnRc() {
159
159
  return `nodeLinker: node-modules
160
-
161
- npmScopes:
162
- tetrascience:
163
- npmRegistryServer: "https://tetrascience.jfrog.io/artifactory/api/npm/ts-npm-virtual/"
164
160
  `;
165
161
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tetrascience-npm/request",
3
- "version": "0.2.0-beta.106.2",
3
+ "version": "0.2.1-beta.112.2",
4
4
  "description": "Request tracking middleware for TetraScience services and data apps (client + server).",
5
5
  "license": "Apache-2.0",
6
6
  "packageManager": "yarn@4.1.0",