@stackwright-pro/openapi 0.3.0-alpha.4 → 0.3.0-alpha.6
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.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +73 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -33,8 +33,18 @@ var OpenAPIParser = class {
|
|
|
33
33
|
await SwaggerParser.validate(api);
|
|
34
34
|
}
|
|
35
35
|
let document;
|
|
36
|
+
let dereferenced = false;
|
|
36
37
|
if (dereference) {
|
|
37
|
-
|
|
38
|
+
try {
|
|
39
|
+
document = await SwaggerParser.dereference(api);
|
|
40
|
+
dereferenced = true;
|
|
41
|
+
} catch {
|
|
42
|
+
console.warn(
|
|
43
|
+
`[OpenAPIParser] Warning: Could not fully dereference "${specPath}" (dangling $ref or circular ref). Proceeding without full dereferencing \u2014 some schema references may not resolve.`
|
|
44
|
+
);
|
|
45
|
+
document = api;
|
|
46
|
+
dereferenced = false;
|
|
47
|
+
}
|
|
38
48
|
} else {
|
|
39
49
|
document = api;
|
|
40
50
|
}
|
|
@@ -42,7 +52,7 @@ var OpenAPIParser = class {
|
|
|
42
52
|
return {
|
|
43
53
|
document,
|
|
44
54
|
version,
|
|
45
|
-
dereferenced
|
|
55
|
+
dereferenced
|
|
46
56
|
};
|
|
47
57
|
} catch (error) {
|
|
48
58
|
throw this.enhanceError(error, specPath);
|
|
@@ -92,6 +102,19 @@ var OpenAPIParser = class {
|
|
|
92
102
|
};
|
|
93
103
|
|
|
94
104
|
// src/parser/SchemaResolver.ts
|
|
105
|
+
var SUPPORTED_CONTENT_TYPES = [
|
|
106
|
+
"application/json",
|
|
107
|
+
"application/geo+json",
|
|
108
|
+
// GeoJSON (ORS, mapping APIs)
|
|
109
|
+
"application/vnd.api+json",
|
|
110
|
+
// JSON:API
|
|
111
|
+
"application/ld+json",
|
|
112
|
+
// JSON-LD
|
|
113
|
+
"application/problem+json",
|
|
114
|
+
// RFC 7807 problem details
|
|
115
|
+
"*/*"
|
|
116
|
+
// wildcard fallback
|
|
117
|
+
];
|
|
95
118
|
var SchemaResolver = class {
|
|
96
119
|
/**
|
|
97
120
|
* @param document - Fully dereferenced OpenAPI document. Pass the result of
|
|
@@ -124,16 +147,19 @@ var SchemaResolver = class {
|
|
|
124
147
|
const extractSchema = (responseCode) => {
|
|
125
148
|
const response = responses[responseCode];
|
|
126
149
|
if (!response) return void 0;
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
150
|
+
for (const contentType of SUPPORTED_CONTENT_TYPES) {
|
|
151
|
+
const content = response.content?.[contentType];
|
|
152
|
+
if (!content?.schema) continue;
|
|
153
|
+
const schema = content.schema;
|
|
154
|
+
if ("$ref" in schema) {
|
|
155
|
+
console.warn(
|
|
156
|
+
`[SchemaResolver] Unresolved $ref in schema for ${path3}. Ensure the document is fully dereferenced before passing to SchemaResolver.`
|
|
157
|
+
);
|
|
158
|
+
return schema;
|
|
159
|
+
}
|
|
134
160
|
return schema;
|
|
135
161
|
}
|
|
136
|
-
return
|
|
162
|
+
return void 0;
|
|
137
163
|
};
|
|
138
164
|
const preferred = extractSchema(preferredResponseCode);
|
|
139
165
|
if (preferred) return preferred;
|
|
@@ -544,9 +570,12 @@ var CollectionProviderGenerator = class {
|
|
|
544
570
|
const resolver = new SchemaResolver(this.document);
|
|
545
571
|
const schema = resolver.getResponseSchema(endpoint, method);
|
|
546
572
|
if (!schema) {
|
|
547
|
-
|
|
573
|
+
console.warn(
|
|
574
|
+
` > No response schema found for ${method.toUpperCase()} ${endpoint} \u2014 falling back to z.unknown()`
|
|
575
|
+
);
|
|
548
576
|
}
|
|
549
|
-
const isArray = schema.type === "array";
|
|
577
|
+
const isArray = schema != null ? schema.type === "array" : false;
|
|
578
|
+
const unknownFallback = schema == null;
|
|
550
579
|
const schemaName = `${this.capitalize(collectionName)}Schema`;
|
|
551
580
|
const params = {
|
|
552
581
|
providerName,
|
|
@@ -557,6 +586,7 @@ var CollectionProviderGenerator = class {
|
|
|
557
586
|
baseUrl,
|
|
558
587
|
schemaName,
|
|
559
588
|
isArray,
|
|
589
|
+
unknownFallback,
|
|
560
590
|
bare
|
|
561
591
|
};
|
|
562
592
|
if (auth !== void 0) {
|
|
@@ -578,13 +608,17 @@ var CollectionProviderGenerator = class {
|
|
|
578
608
|
auth,
|
|
579
609
|
schemaName,
|
|
580
610
|
isArray,
|
|
611
|
+
unknownFallback,
|
|
581
612
|
bare
|
|
582
613
|
} = params;
|
|
583
614
|
const authHeader = this.generateAuthHeader(auth);
|
|
584
615
|
const arraySchemaName = `${schemaName.replace(/Schema$/, "")}ArraySchema`;
|
|
585
|
-
const validationSchema = isArray ? arraySchemaName : schemaName;
|
|
586
|
-
const imports = bare ? "" : `import type { CollectionProvider, CollectionItem } from '@stackwright/collections';
|
|
587
|
-
import {
|
|
616
|
+
const validationSchema = unknownFallback ? "z.unknown()" : isArray ? arraySchemaName : schemaName;
|
|
617
|
+
const imports = bare ? "" : unknownFallback ? `import type { CollectionProvider, CollectionItem } from '@stackwright/collections';
|
|
618
|
+
import { z } from 'zod';
|
|
619
|
+
|
|
620
|
+
` : `import type { CollectionProvider, CollectionItem } from '@stackwright/collections';
|
|
621
|
+
import { ${isArray ? arraySchemaName : schemaName} } from './schemas';
|
|
588
622
|
|
|
589
623
|
`;
|
|
590
624
|
return `${imports}/**
|
|
@@ -648,7 +682,7 @@ export class ${providerName} implements CollectionProvider {
|
|
|
648
682
|
* Get a single item by slug
|
|
649
683
|
*/
|
|
650
684
|
async get(slug: string): Promise<CollectionItem | null> {
|
|
651
|
-
${this.generateGetMethod(endpoint, slugField, isArray, collectionName, schemaName)}
|
|
685
|
+
${this.generateGetMethod(endpoint, slugField, isArray, collectionName, schemaName, unknownFallback)}
|
|
652
686
|
}
|
|
653
687
|
|
|
654
688
|
/**
|
|
@@ -684,7 +718,8 @@ export class ${providerName} implements CollectionProvider {
|
|
|
684
718
|
/**
|
|
685
719
|
* Generate get method implementation
|
|
686
720
|
*/
|
|
687
|
-
generateGetMethod(endpoint, slugField, isArray, collectionName, schemaName) {
|
|
721
|
+
generateGetMethod(endpoint, slugField, isArray, collectionName, schemaName, unknownFallback = false) {
|
|
722
|
+
const validationExpr = unknownFallback ? "z.unknown()" : schemaName;
|
|
688
723
|
if (endpoint.includes("{id}") || endpoint.includes(":id")) {
|
|
689
724
|
const detailEndpoint = endpoint.replace("{id}", "${slug}").replace(":id", "${slug}");
|
|
690
725
|
return `const url = \`\${this.baseUrl}${detailEndpoint}\`;
|
|
@@ -702,7 +737,7 @@ export class ${providerName} implements CollectionProvider {
|
|
|
702
737
|
}
|
|
703
738
|
|
|
704
739
|
const data = await response.json();
|
|
705
|
-
const validated = ${
|
|
740
|
+
const validated = ${validationExpr}.parse(data);
|
|
706
741
|
|
|
707
742
|
return this.toCollectionItem(validated);`;
|
|
708
743
|
} else {
|
|
@@ -2804,6 +2839,23 @@ var OpenAPIPlugin = class {
|
|
|
2804
2839
|
async processIntegration(config, projectRoot) {
|
|
2805
2840
|
const { name, spec, auth, mockUrl, collections, endpoints, actions } = config;
|
|
2806
2841
|
console.log(` - Processing integration: ${name}`);
|
|
2842
|
+
const httpCollections = (collections || []).filter((c) => {
|
|
2843
|
+
if (c.transport === "websocket") {
|
|
2844
|
+
console.warn(
|
|
2845
|
+
` > Skipping collection "${c.endpoint}" (transport: websocket \u2014 not yet supported)`
|
|
2846
|
+
);
|
|
2847
|
+
return false;
|
|
2848
|
+
}
|
|
2849
|
+
return true;
|
|
2850
|
+
});
|
|
2851
|
+
const hasEndpoints = endpoints && (endpoints.include?.length || endpoints.exclude?.length);
|
|
2852
|
+
const hasActions = actions && actions.length > 0;
|
|
2853
|
+
if (httpCollections.length === 0 && !hasEndpoints && !hasActions) {
|
|
2854
|
+
console.log(
|
|
2855
|
+
" > No HTTP endpoints or REST collections found \u2014 skipping (WebSocket-only integration not yet supported)"
|
|
2856
|
+
);
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2807
2859
|
const specPath = spec.startsWith("http") ? spec : path2.resolve(projectRoot, spec);
|
|
2808
2860
|
const parser = new OpenAPIParser();
|
|
2809
2861
|
const { document } = await parser.parse(specPath);
|
|
@@ -2822,13 +2874,13 @@ var OpenAPIPlugin = class {
|
|
|
2822
2874
|
fs2.mkdirSync(outputDir, { recursive: true });
|
|
2823
2875
|
const schemaMapping = await this.generateSchemas(
|
|
2824
2876
|
document,
|
|
2825
|
-
|
|
2877
|
+
httpCollections,
|
|
2826
2878
|
outputDir,
|
|
2827
2879
|
name,
|
|
2828
2880
|
endpointFilter
|
|
2829
2881
|
);
|
|
2830
|
-
await this.generateTypes(document,
|
|
2831
|
-
if (
|
|
2882
|
+
await this.generateTypes(document, httpCollections, outputDir, name);
|
|
2883
|
+
if (httpCollections.length > 0) {
|
|
2832
2884
|
await this.generateProvider(document, config, outputDir, name);
|
|
2833
2885
|
}
|
|
2834
2886
|
await this.generateClient(document, outputDir, name, schemaMapping, endpointFilter);
|