@rexeus/typeweaver-gen 0.10.5 → 0.12.0

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/index.cjs CHANGED
@@ -124,6 +124,175 @@ var PathParameterMismatchError = class extends Error {
124
124
  }
125
125
  };
126
126
  //#endregion
127
+ //#region src/bodyNormalization.ts
128
+ const JSON_BODY_SCHEMA_TYPES = new Set([
129
+ "array",
130
+ "boolean",
131
+ "enum",
132
+ "intersection",
133
+ "literal",
134
+ "null",
135
+ "number",
136
+ "object",
137
+ "record",
138
+ "tuple",
139
+ "union"
140
+ ]);
141
+ const normalizeBody = (input) => {
142
+ if (input.bodySchema === void 0) return { warnings: [] };
143
+ const warnings = [];
144
+ const contentTypeHeader = extractContentTypeHeader(input.headerSchema);
145
+ if (contentTypeHeader.kind === "literal") return {
146
+ body: createNormalizedBody({
147
+ schema: input.bodySchema,
148
+ mediaType: contentTypeHeader.value,
149
+ mediaTypeSource: "content-type-header"
150
+ }),
151
+ warnings
152
+ };
153
+ if (contentTypeHeader.kind === "ambiguous") warnings.push({
154
+ code: "ambiguous-content-type-header",
155
+ message: "Content-Type header is present but does not have one unambiguous literal value; inferred body media type instead.",
156
+ location: input.location
157
+ });
158
+ else warnings.push({
159
+ code: "missing-content-type-header",
160
+ message: "Body schema is present without a Content-Type header; inferred body media type from schema.",
161
+ location: input.location
162
+ });
163
+ const inferred = inferBodyMediaType(input.bodySchema);
164
+ if (inferred.mediaTypeSource === "raw-fallback") warnings.push({
165
+ code: "raw-body-media-type-fallback",
166
+ message: "Body schema does not imply a concrete media type; used application/octet-stream raw transport fallback.",
167
+ location: input.location
168
+ });
169
+ return {
170
+ body: createNormalizedBody({
171
+ schema: input.bodySchema,
172
+ ...inferred
173
+ }),
174
+ warnings
175
+ };
176
+ };
177
+ const createNormalizedBody = (input) => {
178
+ return {
179
+ schema: input.schema,
180
+ mediaType: input.mediaType,
181
+ mediaTypeSource: input.mediaTypeSource,
182
+ transport: resolveTransport(input.mediaType)
183
+ };
184
+ };
185
+ const extractContentTypeHeader = (headerSchema) => {
186
+ const headerObject = unwrapOptional(headerSchema);
187
+ if (headerObject === void 0 || !isZodObject$1(headerObject)) return { kind: "absent" };
188
+ const contentTypeEntries = Object.entries(headerObject.shape).filter(([headerName]) => headerName.toLowerCase() === "content-type");
189
+ if (contentTypeEntries.length === 0) return { kind: "absent" };
190
+ const literalValues = contentTypeEntries.flatMap(([, schema]) => extractStringLiteralValues(schema));
191
+ const distinctValues = new Set(literalValues);
192
+ if (contentTypeEntries.length === 1 && distinctValues.size === 1) {
193
+ const [value] = distinctValues;
194
+ return value === void 0 ? { kind: "ambiguous" } : {
195
+ kind: "literal",
196
+ value
197
+ };
198
+ }
199
+ return { kind: "ambiguous" };
200
+ };
201
+ const inferBodyMediaType = (schema) => {
202
+ const inferenceSchema = unwrapMediaInferenceSchema(schema);
203
+ const schemaType = getSchemaType(inferenceSchema);
204
+ if (isTextBodySchema(inferenceSchema)) return {
205
+ mediaType: "text/plain",
206
+ mediaTypeSource: "body-schema"
207
+ };
208
+ if (schemaType === "any" || schemaType === "unknown") return {
209
+ mediaType: "application/octet-stream",
210
+ mediaTypeSource: "raw-fallback"
211
+ };
212
+ if (schemaType !== void 0 && JSON_BODY_SCHEMA_TYPES.has(schemaType)) return {
213
+ mediaType: "application/json",
214
+ mediaTypeSource: "body-schema"
215
+ };
216
+ return {
217
+ mediaType: "application/octet-stream",
218
+ mediaTypeSource: "raw-fallback"
219
+ };
220
+ };
221
+ const isTextBodySchema = (schema) => {
222
+ const schemaType = getSchemaType(schema);
223
+ if (schemaType === "string") return true;
224
+ if (schemaType === "literal") {
225
+ const values = literalSchemaValues(schema);
226
+ return values.length > 0 && values.every((value) => typeof value === "string");
227
+ }
228
+ if (schemaType === "enum") {
229
+ const values = enumSchemaValues(schema);
230
+ return values.length > 0 && values.every((value) => typeof value === "string");
231
+ }
232
+ return false;
233
+ };
234
+ const resolveTransport = (mediaType) => {
235
+ const normalizedMediaType = mediaType.split(";")[0]?.trim().toLowerCase();
236
+ if (normalizedMediaType === "application/json" || normalizedMediaType?.endsWith("+json") === true) return "json";
237
+ if (normalizedMediaType?.startsWith("text/") === true) return "text";
238
+ if (normalizedMediaType === "application/x-www-form-urlencoded") return "form-url-encoded";
239
+ if (normalizedMediaType === "multipart/form-data") return "multipart";
240
+ return "raw";
241
+ };
242
+ const unwrapMediaInferenceSchema = (schema) => {
243
+ const visitedSchemas = /* @__PURE__ */ new Set();
244
+ let current = schema;
245
+ while (current !== void 0 && !visitedSchemas.has(current)) {
246
+ visitedSchemas.add(current);
247
+ const definition = getSchemaDefinition(current);
248
+ const schemaType = definition?.type;
249
+ if (schemaType === "optional" || schemaType === "nullable" || schemaType === "default" || schemaType === "catch" || schemaType === "prefault" || schemaType === "readonly") {
250
+ current = definition?.innerType;
251
+ continue;
252
+ }
253
+ if (schemaType === "pipe") {
254
+ const outputType = getSchemaType(definition?.out);
255
+ if (outputType === void 0 || outputType === "transform") return;
256
+ current = definition?.out;
257
+ continue;
258
+ }
259
+ if (schemaType === "effects") {
260
+ current = definition?.schema;
261
+ continue;
262
+ }
263
+ return current;
264
+ }
265
+ return current;
266
+ };
267
+ const unwrapOptional = (schema) => {
268
+ return schema instanceof zod.z.ZodOptional ? schema.unwrap() : schema;
269
+ };
270
+ const isZodObject$1 = (schema) => {
271
+ return getSchemaType(schema) === "object" && "shape" in schema;
272
+ };
273
+ const extractStringLiteralValues = (schema) => {
274
+ const unwrappedSchema = unwrapOptional(schema);
275
+ if (unwrappedSchema === void 0) return [];
276
+ if (getSchemaType(unwrappedSchema) === "literal") return literalSchemaValues(unwrappedSchema).filter((value) => typeof value === "string");
277
+ if (getSchemaType(unwrappedSchema) === "enum") return enumSchemaValues(unwrappedSchema).filter((value) => typeof value === "string");
278
+ return [];
279
+ };
280
+ const literalSchemaValues = (schema) => {
281
+ const literalSchema = schema;
282
+ return Array.from(literalSchema?.values ?? []);
283
+ };
284
+ const enumSchemaValues = (schema) => {
285
+ const enumSchema = schema;
286
+ return enumSchema?.options ?? enumSchema?.def?.values ?? Object.values(enumSchema?.def?.entries ?? enumSchema?.enum ?? {});
287
+ };
288
+ const getSchemaType = (schema) => {
289
+ return getSchemaDefinition(schema)?.type;
290
+ };
291
+ const getSchemaDefinition = (schema) => {
292
+ const schemaWithDefinition = schema;
293
+ return schemaWithDefinition?.def ?? schemaWithDefinition?._def;
294
+ };
295
+ //#endregion
127
296
  //#region src/helpers/namingUtils.ts
128
297
  const startsWithDigit = (value) => /^[0-9]/u.test(value);
129
298
  const isSupportedIdentifierName = (value) => {
@@ -198,25 +367,49 @@ const validateInlineDerivedResponses = (definition, canonicalResponses) => {
198
367
  validateDerivedResponseAgainstCanonicalGraph(response, canonicalResponses);
199
368
  }
200
369
  };
201
- const normalizeResponseDefinition = (response) => {
370
+ const normalizeResponseDefinition = (response, location) => {
371
+ const body = normalizeBody({
372
+ bodySchema: response.body,
373
+ headerSchema: response.header,
374
+ location: {
375
+ ...location,
376
+ part: "response.body"
377
+ }
378
+ });
202
379
  return {
203
- name: response.name,
204
- statusCode: response.statusCode,
205
- statusCodeName: _rexeus_typeweaver_core.HttpStatusCodeNameMap[response.statusCode],
206
- description: response.description,
207
- header: response.header,
208
- body: response.body,
209
- kind: response.derived === void 0 ? "response" : "derived-response",
210
- derivedFrom: response.derived?.parentName,
211
- lineage: response.derived?.lineage,
212
- depth: response.derived?.depth
380
+ response: {
381
+ name: response.name,
382
+ statusCode: response.statusCode,
383
+ statusCodeName: _rexeus_typeweaver_core.HttpStatusCodeNameMap[response.statusCode],
384
+ description: response.description,
385
+ header: response.header,
386
+ body: body.body,
387
+ kind: response.derived === void 0 ? "response" : "derived-response",
388
+ derivedFrom: response.derived?.parentName,
389
+ lineage: response.derived?.lineage,
390
+ depth: response.derived?.depth
391
+ },
392
+ warnings: body.warnings
213
393
  };
214
394
  };
215
395
  const collectCanonicalResponses = (definition) => {
216
396
  const canonicalResponseDefinitions = collectCanonicalResponseDefinitions(definition);
397
+ const warnings = [];
217
398
  validateDerivedResponseGraph(canonicalResponseDefinitions);
218
399
  validateInlineDerivedResponses(definition, canonicalResponseDefinitions);
219
- return new Map(Array.from(canonicalResponseDefinitions.entries(), ([responseName, response]) => [responseName, normalizeResponseDefinition(response)]));
400
+ const responses = /* @__PURE__ */ new Map();
401
+ for (const [responseName, response] of canonicalResponseDefinitions) {
402
+ const normalized = normalizeResponseDefinition(response, {
403
+ responseName,
404
+ statusCode: response.statusCode
405
+ });
406
+ responses.set(responseName, normalized.response);
407
+ warnings.push(...normalized.warnings);
408
+ }
409
+ return {
410
+ responses,
411
+ warnings
412
+ };
220
413
  };
221
414
  //#endregion
222
415
  //#region src/normalizeSpec.ts
@@ -230,7 +423,7 @@ const validateRequestSchema = (operationId, requestPart, schema) => {
230
423
  if (!isZodType(schema)) throw new InvalidRequestSchemaError(operationId, requestPart);
231
424
  if (requestPart === "param" && !isZodObject(schema)) throw new InvalidRequestSchemaError(operationId, requestPart);
232
425
  };
233
- const validateRequest = (operationId, path, request) => {
426
+ const validateRequest = (resourceName, operationId, path, request) => {
234
427
  if (request.header !== void 0) validateRequestSchema(operationId, "header", request.header);
235
428
  if (request.param !== void 0) validateRequestSchema(operationId, "param", request.param);
236
429
  if (request.query !== void 0) validateRequestSchema(operationId, "query", request.query);
@@ -238,28 +431,51 @@ const validateRequest = (operationId, path, request) => {
238
431
  const pathParams = getPathParameterNames(path);
239
432
  const requestParams = request.param === void 0 ? [] : Object.keys(request.param.shape);
240
433
  if (pathParams.length !== requestParams.length || pathParams.some((pathParam) => !requestParams.includes(pathParam))) throw new PathParameterMismatchError(operationId, path, pathParams, requestParams);
241
- if (request.header === void 0 && request.param === void 0 && request.query === void 0 && request.body === void 0) return;
434
+ if (request.header === void 0 && request.param === void 0 && request.query === void 0 && request.body === void 0) return { warnings: [] };
435
+ const body = normalizeBody({
436
+ bodySchema: request.body,
437
+ headerSchema: request.header,
438
+ location: {
439
+ resourceName,
440
+ operationId,
441
+ part: "request.body"
442
+ }
443
+ });
242
444
  return {
243
- header: request.header,
244
- param: request.param,
245
- query: request.query,
246
- body: request.body
445
+ request: {
446
+ header: request.header,
447
+ param: request.param,
448
+ query: request.query,
449
+ body: body.body
450
+ },
451
+ warnings: body.warnings
247
452
  };
248
453
  };
249
- const normalizeOperationResponses = (responses) => {
250
- return responses.map((response) => {
251
- if ((0, _rexeus_typeweaver_core.isNamedResponseDefinition)(response)) return {
252
- responseName: response.name,
253
- source: "canonical"
254
- };
255
- return {
256
- responseName: response.name,
257
- source: "inline",
258
- response: normalizeResponseDefinition(response)
259
- };
260
- });
454
+ const normalizeOperationResponses = (resourceName, operationId, responses) => {
455
+ const warnings = [];
456
+ return {
457
+ responses: responses.map((response) => {
458
+ if ((0, _rexeus_typeweaver_core.isNamedResponseDefinition)(response)) return {
459
+ responseName: response.name,
460
+ source: "canonical"
461
+ };
462
+ const normalized = normalizeResponseDefinition(response, {
463
+ resourceName,
464
+ operationId,
465
+ responseName: response.name,
466
+ statusCode: response.statusCode
467
+ });
468
+ warnings.push(...normalized.warnings);
469
+ return {
470
+ responseName: response.name,
471
+ source: "inline",
472
+ response: normalized.response
473
+ };
474
+ }),
475
+ warnings
476
+ };
261
477
  };
262
- const normalizeOperation = (operationIds, routeKeys, operation) => {
478
+ const normalizeOperation = (resourceName, operationIds, routeKeys, operation) => {
263
479
  if (!isSupportedOperationId(operation.operationId)) throw new InvalidOperationIdError(operation.operationId);
264
480
  if (operationIds.has(operation.operationId)) throw new DuplicateOperationIdError(operation.operationId);
265
481
  operationIds.add(operation.operationId);
@@ -268,13 +484,18 @@ const normalizeOperation = (operationIds, routeKeys, operation) => {
268
484
  if (routeKeys.has(routeKey)) throw new DuplicateRouteError(operation.method, operation.path, normalizedPath);
269
485
  routeKeys.add(routeKey);
270
486
  if (operation.responses.length === 0) throw new EmptyOperationResponsesError(operation.operationId);
487
+ const request = validateRequest(resourceName, operation.operationId, operation.path, operation.request);
488
+ const responses = normalizeOperationResponses(resourceName, operation.operationId, operation.responses);
271
489
  return {
272
- operationId: operation.operationId,
273
- method: operation.method,
274
- path: operation.path,
275
- summary: operation.summary,
276
- request: validateRequest(operation.operationId, operation.path, operation.request),
277
- responses: normalizeOperationResponses(operation.responses)
490
+ operation: {
491
+ operationId: operation.operationId,
492
+ method: operation.method,
493
+ path: operation.path,
494
+ summary: operation.summary,
495
+ request: request.request,
496
+ responses: responses.responses
497
+ },
498
+ warnings: [...request.warnings, ...responses.warnings]
278
499
  };
279
500
  };
280
501
  const normalizeSpec = (definition) => {
@@ -284,16 +505,22 @@ const normalizeSpec = (definition) => {
284
505
  const canonicalResponses = collectCanonicalResponses(definition);
285
506
  const operationIds = /* @__PURE__ */ new Set();
286
507
  const routeKeys = /* @__PURE__ */ new Set();
508
+ const warnings = [...canonicalResponses.warnings];
287
509
  return {
288
510
  resources: resourceEntries.map(([resourceName, resource]) => {
289
511
  if (!isSupportedResourceName(resourceName)) throw new InvalidResourceNameError(resourceName);
290
512
  if (resource.operations.length === 0) throw new EmptyResourceOperationsError(resourceName);
291
513
  return {
292
514
  name: resourceName,
293
- operations: resource.operations.map((operation) => normalizeOperation(operationIds, routeKeys, operation))
515
+ operations: resource.operations.map((operation) => {
516
+ const normalized = normalizeOperation(resourceName, operationIds, routeKeys, operation);
517
+ warnings.push(...normalized.warnings);
518
+ return normalized.operation;
519
+ })
294
520
  };
295
521
  }),
296
- responses: Array.from(canonicalResponses.values())
522
+ responses: Array.from(canonicalResponses.responses.values()),
523
+ warnings
297
524
  };
298
525
  };
299
526
  //#endregion
@@ -478,6 +705,112 @@ var MissingCanonicalResponseError = class extends Error {
478
705
  };
479
706
  //#endregion
480
707
  //#region src/plugins/pluginContext.ts
708
+ const WINDOWS_DRIVE_PREFIX_PATTERN = /^[a-zA-Z]:/;
709
+ function pathContainsParentTraversal(projectPath) {
710
+ return projectPath.split("/").includes("..");
711
+ }
712
+ function pathEndsWithDirectorySeparator(projectPath) {
713
+ return projectPath.endsWith("/");
714
+ }
715
+ function pathNamesCurrentDirectory(projectPath) {
716
+ return projectPath === "." || projectPath.endsWith("/.");
717
+ }
718
+ function resolveSafeGeneratedFilePath(outputDir, requestedPath) {
719
+ if (requestedPath.length === 0) throwUnsafeGeneratedFilePath(requestedPath, "path must not be empty");
720
+ const projectPath = requestedPath.replace(/\\/g, "/");
721
+ if (node_path.default.isAbsolute(requestedPath) || node_path.default.posix.isAbsolute(projectPath) || node_path.default.win32.isAbsolute(requestedPath) || node_path.default.win32.isAbsolute(projectPath) || WINDOWS_DRIVE_PREFIX_PATTERN.test(requestedPath)) throwUnsafeGeneratedFilePath(requestedPath, "absolute paths are not allowed");
722
+ if (pathContainsParentTraversal(projectPath)) throwUnsafeGeneratedFilePath(requestedPath, "path contains parent-directory traversal");
723
+ if (pathEndsWithDirectorySeparator(projectPath)) throwUnsafeGeneratedFilePath(requestedPath, "path must name a file inside the output directory");
724
+ if (pathNamesCurrentDirectory(projectPath)) throwUnsafeGeneratedFilePath(requestedPath, "path must name a file inside the output directory");
725
+ const generatedPath = node_path.default.posix.normalize(projectPath);
726
+ if (generatedPath === ".") throwUnsafeGeneratedFilePath(requestedPath, "path must name a file inside the output directory");
727
+ if (pathContainsParentTraversal(generatedPath)) throwUnsafeGeneratedFilePath(requestedPath, "path contains parent-directory traversal");
728
+ const outputRoot = node_path.default.resolve(outputDir);
729
+ const fullPath = node_path.default.resolve(outputRoot, toNativePath(generatedPath));
730
+ if (!isStrictlyInsidePath(fullPath, outputRoot)) throwUnsafeGeneratedFilePath(requestedPath, "path escapes the output directory");
731
+ assertGeneratedPathHasNoSymlinkComponents({
732
+ outputRoot,
733
+ generatedPath,
734
+ requestedPath
735
+ });
736
+ return {
737
+ fullPath,
738
+ generatedPath
739
+ };
740
+ }
741
+ function toNativePath(projectPath) {
742
+ return projectPath.split("/").join(node_path.default.sep);
743
+ }
744
+ function assertGeneratedPathHasNoSymlinkComponents(config) {
745
+ assertExistingPathIsNotSymlink(config.outputRoot, config.requestedPath);
746
+ let currentPath = config.outputRoot;
747
+ for (const segment of config.generatedPath.split("/")) {
748
+ currentPath = node_path.default.join(currentPath, segment);
749
+ const pathStats = getExistingPathStats(currentPath);
750
+ if (pathStats === void 0) return;
751
+ assertPathStatsIsNotSymlink(pathStats, config.requestedPath);
752
+ if (!pathStats.isDirectory()) return;
753
+ }
754
+ }
755
+ function assertExistingPathIsNotSymlink(absolutePath, requestedPath) {
756
+ const pathStats = getExistingPathStats(absolutePath);
757
+ if (pathStats === void 0) return;
758
+ assertPathStatsIsNotSymlink(pathStats, requestedPath);
759
+ }
760
+ function assertPathStatsIsNotSymlink(pathStats, requestedPath) {
761
+ if (!pathStats.isSymbolicLink()) return;
762
+ throwUnsafeGeneratedFilePath(requestedPath, "path contains a symbolic link");
763
+ }
764
+ function getExistingPathStats(absolutePath) {
765
+ try {
766
+ return node_fs.default.lstatSync(absolutePath);
767
+ } catch (error) {
768
+ if (isMissingPathError(error)) return;
769
+ throw error;
770
+ }
771
+ }
772
+ function isMissingPathError(error) {
773
+ if (!(error instanceof Error)) return false;
774
+ return ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
775
+ }
776
+ function isStrictlyInsidePath(childPath, parentPath) {
777
+ const relativePath = node_path.default.relative(parentPath, childPath);
778
+ return relativePath !== "" && relativePath !== ".." && !relativePath.startsWith(`..${node_path.default.sep}`) && !node_path.default.isAbsolute(relativePath);
779
+ }
780
+ function throwUnsafeGeneratedFilePath(requestedPath, reason) {
781
+ throw new Error(`Unsafe generated file path '${requestedPath}': ${reason}. Generated writes must stay inside the output directory.`);
782
+ }
783
+ function revalidateGeneratedWritePath(outputDir, generatedPath) {
784
+ return resolveSafeGeneratedFilePath(outputDir, generatedPath);
785
+ }
786
+ function writeGeneratedFileByReplacingDestination(config) {
787
+ const existingFileMode = getExistingFileMode(revalidateGeneratedWritePath(config.outputDir, config.generatedPath).fullPath);
788
+ const tempParentPath = revalidateGeneratedWritePath(config.outputDir, config.generatedPath);
789
+ const destinationDir = node_path.default.dirname(tempParentPath.fullPath);
790
+ const tempDir = node_fs.default.mkdtempSync(node_path.default.join(destinationDir, ".typeweaver-"));
791
+ const tempFile = node_path.default.join(tempDir, "generated.tmp");
792
+ try {
793
+ revalidateGeneratedWritePath(config.outputDir, config.generatedPath);
794
+ node_fs.default.writeFileSync(tempFile, config.content, {
795
+ flag: "wx",
796
+ mode: existingFileMode ?? 438
797
+ });
798
+ if (existingFileMode !== void 0) node_fs.default.chmodSync(tempFile, existingFileMode);
799
+ const writablePath = revalidateGeneratedWritePath(config.outputDir, config.generatedPath);
800
+ node_fs.default.renameSync(tempFile, writablePath.fullPath);
801
+ return writablePath;
802
+ } finally {
803
+ node_fs.default.rmSync(tempDir, {
804
+ recursive: true,
805
+ force: true
806
+ });
807
+ }
808
+ }
809
+ function getExistingFileMode(absolutePath) {
810
+ const pathStats = getExistingPathStats(absolutePath);
811
+ if (pathStats?.isFile() !== true) return;
812
+ return pathStats.mode & 511;
813
+ }
481
814
  function createPluginContextBuilder() {
482
815
  const generatedFiles = /* @__PURE__ */ new Set();
483
816
  const createPluginContext = (params) => {
@@ -543,19 +876,25 @@ function createPluginContextBuilder() {
543
876
  getOperationOutputPaths,
544
877
  getResourceOutputDir,
545
878
  writeFile: (relativePath, content) => {
546
- const fullPath = node_path.default.join(params.outputDir, relativePath);
547
- const dir = node_path.default.dirname(fullPath);
879
+ const safePath = resolveSafeGeneratedFilePath(params.outputDir, relativePath);
880
+ const dir = node_path.default.dirname(safePath.fullPath);
548
881
  node_fs.default.mkdirSync(dir, { recursive: true });
549
- node_fs.default.writeFileSync(fullPath, content);
550
- generatedFiles.add(relativePath);
551
- console.info(`Generated: ${relativePath}`);
882
+ const writablePath = revalidateGeneratedWritePath(params.outputDir, safePath.generatedPath);
883
+ const generatedFile = writeGeneratedFileByReplacingDestination({
884
+ outputDir: params.outputDir,
885
+ generatedPath: writablePath.generatedPath,
886
+ content
887
+ });
888
+ generatedFiles.add(generatedFile.generatedPath);
889
+ console.info(`Generated: ${generatedFile.generatedPath}`);
552
890
  },
553
891
  renderTemplate: (templatePath, data) => {
554
892
  const fullTemplatePath = node_path.default.isAbsolute(templatePath) ? templatePath : node_path.default.join(params.templateDir, templatePath);
555
893
  return renderTemplate(node_fs.default.readFileSync(fullTemplatePath, "utf8"), data ?? {});
556
894
  },
557
895
  addGeneratedFile: (relativePath) => {
558
- generatedFiles.add(relativePath);
896
+ const safePath = resolveSafeGeneratedFilePath(params.outputDir, relativePath);
897
+ generatedFiles.add(safePath.generatedPath);
559
898
  },
560
899
  getGeneratedFiles: () => {
561
900
  return Array.from(generatedFiles);
package/dist/index.d.cts CHANGED
@@ -44,6 +44,28 @@ declare class InvalidOperationIdError extends Error {
44
44
  type NormalizedSpec = {
45
45
  readonly resources: readonly NormalizedResource[];
46
46
  readonly responses: readonly NormalizedResponse[];
47
+ readonly warnings: readonly NormalizedSpecWarning[];
48
+ };
49
+ type NormalizedBodyMediaTypeSource = "content-type-header" | "body-schema" | "raw-fallback";
50
+ type NormalizedBodyTransport = "json" | "text" | "form-url-encoded" | "multipart" | "raw";
51
+ type NormalizedHttpBody = {
52
+ readonly schema: HttpBodySchema;
53
+ readonly mediaType: string;
54
+ readonly mediaTypeSource: NormalizedBodyMediaTypeSource;
55
+ readonly transport: NormalizedBodyTransport;
56
+ };
57
+ type NormalizedSpecWarningCode = "ambiguous-content-type-header" | "missing-content-type-header" | "raw-body-media-type-fallback";
58
+ type NormalizedSpecWarningLocation = {
59
+ readonly part: "request.body" | "response.body";
60
+ readonly resourceName?: string;
61
+ readonly operationId?: string;
62
+ readonly responseName?: string;
63
+ readonly statusCode?: HttpStatusCode;
64
+ };
65
+ type NormalizedSpecWarning = {
66
+ readonly code: NormalizedSpecWarningCode;
67
+ readonly message: string;
68
+ readonly location: NormalizedSpecWarningLocation;
47
69
  };
48
70
  type NormalizedResource = {
49
71
  readonly name: string;
@@ -61,7 +83,7 @@ type NormalizedRequest = {
61
83
  readonly header?: HttpHeaderSchema;
62
84
  readonly param?: HttpParamSchema;
63
85
  readonly query?: HttpQuerySchema;
64
- readonly body?: HttpBodySchema;
86
+ readonly body?: NormalizedHttpBody;
65
87
  };
66
88
  type NormalizedResponse = {
67
89
  readonly name: string;
@@ -69,7 +91,7 @@ type NormalizedResponse = {
69
91
  readonly statusCodeName: string;
70
92
  readonly description: string;
71
93
  readonly header?: HttpHeaderSchema;
72
- readonly body?: HttpBodySchema;
94
+ readonly body?: NormalizedHttpBody;
73
95
  readonly kind: "response" | "derived-response";
74
96
  readonly derivedFrom?: string;
75
97
  readonly lineage?: readonly string[];
@@ -347,5 +369,5 @@ declare const compareRoutes: (a: {
347
369
  //#region src/helpers/templateEngine.d.ts
348
370
  declare function renderTemplate(template: string, data: Record<string, unknown>): string;
349
371
  //#endregion
350
- export { BasePlugin, CreateJSDocCommentOptions, DerivedResponseCycleError, DuplicateOperationIdError, DuplicateRouteError, EmptyOperationResponsesError, EmptyResourceOperationsError, EmptySpecResourcesError, GeneratorContext, InvalidDerivedResponseError, InvalidOperationIdError, InvalidRequestSchemaError, InvalidResourceNameError, MissingDerivedResponseParentError, NormalizedCanonicalResponseUsage, NormalizedInlineResponseUsage, NormalizedOperation, NormalizedRequest, NormalizedResource, NormalizedResponse, NormalizedResponseUsage, NormalizedSpec, OperationOutputPaths, PathParameterMismatchError, PluginConfig, PluginConstructor, PluginContext, type PluginContextBuilderApi, PluginDependencyError, PluginLoadError, PluginMetadata, PluginModule, PluginRegistration, type PluginRegistryApi, TypeweaverConfig, TypeweaverPlugin, compareRoutes, createJSDocComment, createPluginContextBuilder, createPluginRegistry, getMethodPriority, getPathParameterNames, isSupportedOperationId, isSupportedResourceName, normalizeRoutePath, normalizeSpec, relative, renderTemplate };
372
+ export { BasePlugin, CreateJSDocCommentOptions, DerivedResponseCycleError, DuplicateOperationIdError, DuplicateRouteError, EmptyOperationResponsesError, EmptyResourceOperationsError, EmptySpecResourcesError, GeneratorContext, InvalidDerivedResponseError, InvalidOperationIdError, InvalidRequestSchemaError, InvalidResourceNameError, MissingDerivedResponseParentError, NormalizedBodyMediaTypeSource, NormalizedBodyTransport, NormalizedCanonicalResponseUsage, NormalizedHttpBody, NormalizedInlineResponseUsage, NormalizedOperation, NormalizedRequest, NormalizedResource, NormalizedResponse, NormalizedResponseUsage, NormalizedSpec, NormalizedSpecWarning, NormalizedSpecWarningCode, NormalizedSpecWarningLocation, OperationOutputPaths, PathParameterMismatchError, PluginConfig, PluginConstructor, PluginContext, type PluginContextBuilderApi, PluginDependencyError, PluginLoadError, PluginMetadata, PluginModule, PluginRegistration, type PluginRegistryApi, TypeweaverConfig, TypeweaverPlugin, compareRoutes, createJSDocComment, createPluginContextBuilder, createPluginRegistry, getMethodPriority, getPathParameterNames, isSupportedOperationId, isSupportedResourceName, normalizeRoutePath, normalizeSpec, relative, renderTemplate };
351
373
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors/DerivedResponseCycleError.ts","../src/errors/DuplicateOperationIdError.ts","../src/errors/DuplicateRouteError.ts","../src/errors/EmptyOperationResponsesError.ts","../src/errors/EmptyResourceOperationsError.ts","../src/errors/EmptySpecResourcesError.ts","../src/errors/InvalidDerivedResponseError.ts","../src/errors/InvalidOperationIdError.ts","../src/NormalizedSpec.ts","../src/errors/InvalidRequestSchemaError.ts","../src/errors/InvalidResourceNameError.ts","../src/errors/MissingDerivedResponseParentError.ts","../src/errors/PathParameterMismatchError.ts","../src/normalizeSpec.ts","../src/plugins/types.ts","../src/plugins/BasePlugin.ts","../src/plugins/pluginRegistry.ts","../src/plugins/pluginContext.ts","../src/helpers/namingUtils.ts","../src/helpers/jsdoc.ts","../src/helpers/path.ts","../src/helpers/routePath.ts","../src/helpers/routeSort.ts","../src/helpers/templateEngine.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors/DerivedResponseCycleError.ts","../src/errors/DuplicateOperationIdError.ts","../src/errors/DuplicateRouteError.ts","../src/errors/EmptyOperationResponsesError.ts","../src/errors/EmptyResourceOperationsError.ts","../src/errors/EmptySpecResourcesError.ts","../src/errors/InvalidDerivedResponseError.ts","../src/errors/InvalidOperationIdError.ts","../src/NormalizedSpec.ts","../src/errors/InvalidRequestSchemaError.ts","../src/errors/InvalidResourceNameError.ts","../src/errors/MissingDerivedResponseParentError.ts","../src/errors/PathParameterMismatchError.ts","../src/normalizeSpec.ts","../src/plugins/types.ts","../src/plugins/BasePlugin.ts","../src/plugins/pluginRegistry.ts","../src/plugins/pluginContext.ts","../src/helpers/namingUtils.ts","../src/helpers/jsdoc.ts","../src/helpers/path.ts","../src/helpers/routePath.ts","../src/helpers/routeSort.ts","../src/helpers/templateEngine.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -44,6 +44,28 @@ declare class InvalidOperationIdError extends Error {
44
44
  type NormalizedSpec = {
45
45
  readonly resources: readonly NormalizedResource[];
46
46
  readonly responses: readonly NormalizedResponse[];
47
+ readonly warnings: readonly NormalizedSpecWarning[];
48
+ };
49
+ type NormalizedBodyMediaTypeSource = "content-type-header" | "body-schema" | "raw-fallback";
50
+ type NormalizedBodyTransport = "json" | "text" | "form-url-encoded" | "multipart" | "raw";
51
+ type NormalizedHttpBody = {
52
+ readonly schema: HttpBodySchema;
53
+ readonly mediaType: string;
54
+ readonly mediaTypeSource: NormalizedBodyMediaTypeSource;
55
+ readonly transport: NormalizedBodyTransport;
56
+ };
57
+ type NormalizedSpecWarningCode = "ambiguous-content-type-header" | "missing-content-type-header" | "raw-body-media-type-fallback";
58
+ type NormalizedSpecWarningLocation = {
59
+ readonly part: "request.body" | "response.body";
60
+ readonly resourceName?: string;
61
+ readonly operationId?: string;
62
+ readonly responseName?: string;
63
+ readonly statusCode?: HttpStatusCode;
64
+ };
65
+ type NormalizedSpecWarning = {
66
+ readonly code: NormalizedSpecWarningCode;
67
+ readonly message: string;
68
+ readonly location: NormalizedSpecWarningLocation;
47
69
  };
48
70
  type NormalizedResource = {
49
71
  readonly name: string;
@@ -61,7 +83,7 @@ type NormalizedRequest = {
61
83
  readonly header?: HttpHeaderSchema;
62
84
  readonly param?: HttpParamSchema;
63
85
  readonly query?: HttpQuerySchema;
64
- readonly body?: HttpBodySchema;
86
+ readonly body?: NormalizedHttpBody;
65
87
  };
66
88
  type NormalizedResponse = {
67
89
  readonly name: string;
@@ -69,7 +91,7 @@ type NormalizedResponse = {
69
91
  readonly statusCodeName: string;
70
92
  readonly description: string;
71
93
  readonly header?: HttpHeaderSchema;
72
- readonly body?: HttpBodySchema;
94
+ readonly body?: NormalizedHttpBody;
73
95
  readonly kind: "response" | "derived-response";
74
96
  readonly derivedFrom?: string;
75
97
  readonly lineage?: readonly string[];
@@ -347,5 +369,5 @@ declare const compareRoutes: (a: {
347
369
  //#region src/helpers/templateEngine.d.ts
348
370
  declare function renderTemplate(template: string, data: Record<string, unknown>): string;
349
371
  //#endregion
350
- export { BasePlugin, CreateJSDocCommentOptions, DerivedResponseCycleError, DuplicateOperationIdError, DuplicateRouteError, EmptyOperationResponsesError, EmptyResourceOperationsError, EmptySpecResourcesError, GeneratorContext, InvalidDerivedResponseError, InvalidOperationIdError, InvalidRequestSchemaError, InvalidResourceNameError, MissingDerivedResponseParentError, NormalizedCanonicalResponseUsage, NormalizedInlineResponseUsage, NormalizedOperation, NormalizedRequest, NormalizedResource, NormalizedResponse, NormalizedResponseUsage, NormalizedSpec, OperationOutputPaths, PathParameterMismatchError, PluginConfig, PluginConstructor, PluginContext, type PluginContextBuilderApi, PluginDependencyError, PluginLoadError, PluginMetadata, PluginModule, PluginRegistration, type PluginRegistryApi, TypeweaverConfig, TypeweaverPlugin, compareRoutes, createJSDocComment, createPluginContextBuilder, createPluginRegistry, getMethodPriority, getPathParameterNames, isSupportedOperationId, isSupportedResourceName, normalizeRoutePath, normalizeSpec, relative, renderTemplate };
372
+ export { BasePlugin, CreateJSDocCommentOptions, DerivedResponseCycleError, DuplicateOperationIdError, DuplicateRouteError, EmptyOperationResponsesError, EmptyResourceOperationsError, EmptySpecResourcesError, GeneratorContext, InvalidDerivedResponseError, InvalidOperationIdError, InvalidRequestSchemaError, InvalidResourceNameError, MissingDerivedResponseParentError, NormalizedBodyMediaTypeSource, NormalizedBodyTransport, NormalizedCanonicalResponseUsage, NormalizedHttpBody, NormalizedInlineResponseUsage, NormalizedOperation, NormalizedRequest, NormalizedResource, NormalizedResponse, NormalizedResponseUsage, NormalizedSpec, NormalizedSpecWarning, NormalizedSpecWarningCode, NormalizedSpecWarningLocation, OperationOutputPaths, PathParameterMismatchError, PluginConfig, PluginConstructor, PluginContext, type PluginContextBuilderApi, PluginDependencyError, PluginLoadError, PluginMetadata, PluginModule, PluginRegistration, type PluginRegistryApi, TypeweaverConfig, TypeweaverPlugin, compareRoutes, createJSDocComment, createPluginContextBuilder, createPluginRegistry, getMethodPriority, getPathParameterNames, isSupportedOperationId, isSupportedResourceName, normalizeRoutePath, normalizeSpec, relative, renderTemplate };
351
373
  //# sourceMappingURL=index.d.mts.map