@stackwright-pro/openapi 0.1.0 → 0.1.1
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 +331 -2
- package/dist/index.d.ts +331 -2
- package/dist/index.js +1025 -201
- package/dist/index.mjs +1022 -201
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,65 @@
|
|
|
1
1
|
import { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
-
import { z } from 'zod';
|
|
2
|
+
import { z, ZodSchema } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Supported OpenAPI versions
|
|
6
6
|
*/
|
|
7
7
|
type OpenAPIDocument = OpenAPIV3.Document | OpenAPIV3_1.Document;
|
|
8
|
+
/**
|
|
9
|
+
* An approved API specification.
|
|
10
|
+
* Used by enterprise customers to whitelist specific OpenAPI specs.
|
|
11
|
+
*/
|
|
12
|
+
interface ApprovedSpec {
|
|
13
|
+
/** Human-readable name for the spec */
|
|
14
|
+
name: string;
|
|
15
|
+
/** URL or file path to the approved spec */
|
|
16
|
+
url: string;
|
|
17
|
+
/** Expected SHA-256 hash of the spec content */
|
|
18
|
+
sha256: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Security configuration for approved specs enforcement.
|
|
22
|
+
* Configured in stackwright.yml under `prebuild.security`.
|
|
23
|
+
*/
|
|
24
|
+
interface PrebuildSecurityConfig {
|
|
25
|
+
/** Enable approved-specs enforcement */
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
/** List of approved specifications */
|
|
28
|
+
allowlist: ApprovedSpec[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Result of validating a spec against the approved list.
|
|
32
|
+
*/
|
|
33
|
+
interface ValidationResult {
|
|
34
|
+
/** Whether the spec is approved */
|
|
35
|
+
valid: boolean;
|
|
36
|
+
/** Error code if not valid */
|
|
37
|
+
errorCode?: 'SPEC_NOT_ON_ALLOWLIST' | 'SPEC_MODIFIED' | 'DOWNLOAD_FAILED';
|
|
38
|
+
/** Human-readable error message */
|
|
39
|
+
error?: string;
|
|
40
|
+
/** URL of the spec that was validated */
|
|
41
|
+
specUrl?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extended site config with prebuild security.
|
|
45
|
+
* Users can add this to stackwright.yml.
|
|
46
|
+
*/
|
|
47
|
+
interface SiteConfig {
|
|
48
|
+
/** Prebuild configuration */
|
|
49
|
+
prebuild?: {
|
|
50
|
+
/** Security settings for approved-specs enforcement */
|
|
51
|
+
security?: PrebuildSecurityConfig;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Endpoint filter configuration
|
|
56
|
+
*/
|
|
57
|
+
interface EndpointFilter$1 {
|
|
58
|
+
/** Endpoints/patterns to include (default: all) */
|
|
59
|
+
include?: string[];
|
|
60
|
+
/** Endpoints/patterns to exclude */
|
|
61
|
+
exclude?: string[];
|
|
62
|
+
}
|
|
8
63
|
/**
|
|
9
64
|
* Configuration for OpenAPI integration in stackwright.yml
|
|
10
65
|
*/
|
|
@@ -13,6 +68,8 @@ interface OpenAPIConfig {
|
|
|
13
68
|
name: string;
|
|
14
69
|
/** OpenAPI spec (URL or local file path) */
|
|
15
70
|
spec: string;
|
|
71
|
+
/** Mock server URL for development (e.g., http://localhost:4010) */
|
|
72
|
+
mockUrl?: string;
|
|
16
73
|
/** Authentication configuration */
|
|
17
74
|
auth?: {
|
|
18
75
|
type: 'bearer' | 'apiKey' | 'oauth2';
|
|
@@ -28,6 +85,8 @@ interface OpenAPIConfig {
|
|
|
28
85
|
/** Optional filters */
|
|
29
86
|
filters?: Record<string, unknown>;
|
|
30
87
|
}>;
|
|
88
|
+
/** Endpoint filter - only generate code for matching endpoints */
|
|
89
|
+
endpoints?: EndpointFilter$1;
|
|
31
90
|
}
|
|
32
91
|
/**
|
|
33
92
|
* Result of OpenAPI compilation
|
|
@@ -141,6 +200,8 @@ interface ZodGenerationOptions {
|
|
|
141
200
|
optionalByDefault?: boolean;
|
|
142
201
|
/** Custom name for the generated schema */
|
|
143
202
|
schemaName?: string;
|
|
203
|
+
/** If true, emit only the schema + type — no import statements */
|
|
204
|
+
bare?: boolean;
|
|
144
205
|
}
|
|
145
206
|
/**
|
|
146
207
|
* Generates Zod schemas from OpenAPI schema objects
|
|
@@ -263,6 +324,8 @@ interface ProviderGenerationOptions {
|
|
|
263
324
|
type: 'bearer' | 'apiKey';
|
|
264
325
|
headerName?: string;
|
|
265
326
|
};
|
|
327
|
+
/** If true, emit only the class code without import statements */
|
|
328
|
+
bare?: boolean;
|
|
266
329
|
}
|
|
267
330
|
/**
|
|
268
331
|
* Generates CollectionProvider implementations from OpenAPI specs
|
|
@@ -359,6 +422,7 @@ declare class ClientGenerator {
|
|
|
359
422
|
private resolver;
|
|
360
423
|
private schemaMapping?;
|
|
361
424
|
private requiredSchemas;
|
|
425
|
+
private generatedRequestSchemas;
|
|
362
426
|
constructor(document: OpenAPIDocument, schemaMapping?: SchemaMapping);
|
|
363
427
|
/**
|
|
364
428
|
* Generate typed API client code from OpenAPI document
|
|
@@ -510,6 +574,19 @@ declare class ClientGenerator {
|
|
|
510
574
|
* Get all endpoints from the document
|
|
511
575
|
*/
|
|
512
576
|
private getAllEndpoints;
|
|
577
|
+
/**
|
|
578
|
+
* Deduplicate colliding operationIds by appending a path-based suffix.
|
|
579
|
+
*
|
|
580
|
+
* Real-world specs (e.g. SAM.gov) reuse the same operationId across
|
|
581
|
+
* versioned paths. We make each one unique so the generated client
|
|
582
|
+
* has no duplicate method names.
|
|
583
|
+
*/
|
|
584
|
+
private deduplicateOperationIds;
|
|
585
|
+
/**
|
|
586
|
+
* Turn an API path into a valid, readable identifier suffix.
|
|
587
|
+
* e.g. '/entity-information/v4/download-entities' -> 'entityInformationV4DownloadEntities'
|
|
588
|
+
*/
|
|
589
|
+
private sanitizePath;
|
|
513
590
|
/**
|
|
514
591
|
* Get parameters for an operation
|
|
515
592
|
*/
|
|
@@ -604,10 +681,30 @@ interface PrebuildPlugin {
|
|
|
604
681
|
* - Typed API client functions
|
|
605
682
|
*
|
|
606
683
|
* All generated code is written to src/generated/{integrationName}/
|
|
684
|
+
*
|
|
685
|
+
* === Phase 2: Approved-Specs Enforcement ===
|
|
686
|
+
*
|
|
687
|
+
* Enterprise customers can enable security enforcement via stackwright.yml:
|
|
688
|
+
*
|
|
689
|
+
* ```yaml
|
|
690
|
+
* prebuild:
|
|
691
|
+
* security:
|
|
692
|
+
* enabled: true
|
|
693
|
+
* allowlist:
|
|
694
|
+
* - name: logistics-api
|
|
695
|
+
* url: https://api.gov.mil/logistics/v1/openapi.yaml
|
|
696
|
+
* sha256: a1b2c3d4e5f6...
|
|
697
|
+
* ```
|
|
698
|
+
*
|
|
699
|
+
* This ensures only approved API specs can generate code.
|
|
607
700
|
*/
|
|
608
701
|
declare class OpenAPIPlugin implements PrebuildPlugin {
|
|
609
702
|
name: string;
|
|
610
703
|
beforeBuild(context: PrebuildPluginContext): Promise<void>;
|
|
704
|
+
/**
|
|
705
|
+
* Print a security rejection error in a formatted box
|
|
706
|
+
*/
|
|
707
|
+
private printSecurityRejection;
|
|
611
708
|
private processIntegration;
|
|
612
709
|
private generateSchemas;
|
|
613
710
|
private generateTypes;
|
|
@@ -631,4 +728,236 @@ declare class OpenAPIPlugin implements PrebuildPlugin {
|
|
|
631
728
|
*/
|
|
632
729
|
declare function createOpenAPIPlugin(): PrebuildPlugin;
|
|
633
730
|
|
|
634
|
-
|
|
731
|
+
/**
|
|
732
|
+
* Configuration for OpenAPI source adapter
|
|
733
|
+
*/
|
|
734
|
+
interface OpenAPISourceConfig<T = unknown> {
|
|
735
|
+
/** Base URL of the API */
|
|
736
|
+
baseUrl: string;
|
|
737
|
+
/** API endpoint path */
|
|
738
|
+
endpoint: string;
|
|
739
|
+
/** HTTP method (default: 'get') */
|
|
740
|
+
method?: 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
741
|
+
/** Optional query parameters */
|
|
742
|
+
params?: Record<string, string | number | boolean>;
|
|
743
|
+
/** Optional request body */
|
|
744
|
+
body?: unknown;
|
|
745
|
+
/** Optional headers */
|
|
746
|
+
headers?: Record<string, string>;
|
|
747
|
+
/** Optional Zod schema for validation */
|
|
748
|
+
schema?: ZodSchema<T>;
|
|
749
|
+
/** Authentication config */
|
|
750
|
+
auth?: {
|
|
751
|
+
type: 'bearer' | 'apiKey';
|
|
752
|
+
token?: string;
|
|
753
|
+
apiKey?: string;
|
|
754
|
+
headerName?: string;
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Creates a fetcher function from OpenAPI configuration
|
|
759
|
+
*
|
|
760
|
+
* @example
|
|
761
|
+
* ```typescript
|
|
762
|
+
* const fetcher = createOpenAPIFetcher({
|
|
763
|
+
* baseUrl: 'https://api.example.com',
|
|
764
|
+
* endpoint: '/equipment',
|
|
765
|
+
* auth: { type: 'bearer', token: process.env.API_TOKEN }
|
|
766
|
+
* });
|
|
767
|
+
*
|
|
768
|
+
* // Use with Pulse
|
|
769
|
+
* <Pulse fetcher={fetcher} interval={5000} />
|
|
770
|
+
* ```
|
|
771
|
+
*/
|
|
772
|
+
declare function createOpenAPIFetcher<T = unknown>(config: OpenAPISourceConfig<T>): () => Promise<T>;
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Filters endpoints based on include/exclude patterns.
|
|
776
|
+
*
|
|
777
|
+
* Supports:
|
|
778
|
+
* - Exact match: /equipment
|
|
779
|
+
* - Path prefix (includes subpaths): /equipment matches /equipment and /equipment/123
|
|
780
|
+
* - Path with params: /equipment/{id}
|
|
781
|
+
* - Single wildcard: /admin/* matches /admin/users (not /admin itself)
|
|
782
|
+
* - Double wildcard: /admin/** matches /admin/users and /admin/nested/deep
|
|
783
|
+
* - Root path: / matches all paths
|
|
784
|
+
*/
|
|
785
|
+
declare class EndpointFilter {
|
|
786
|
+
private include;
|
|
787
|
+
private exclude;
|
|
788
|
+
constructor(filter?: EndpointFilter$1);
|
|
789
|
+
/**
|
|
790
|
+
* Check if a path should be included in code generation.
|
|
791
|
+
*
|
|
792
|
+
* Logic:
|
|
793
|
+
* 1. If path matches any exclude pattern → excluded
|
|
794
|
+
* 2. If path matches any include pattern → included
|
|
795
|
+
* 3. Otherwise → excluded (default deny)
|
|
796
|
+
*/
|
|
797
|
+
matches(path: string): boolean;
|
|
798
|
+
/**
|
|
799
|
+
* Match path against a pattern.
|
|
800
|
+
*/
|
|
801
|
+
private matchPattern;
|
|
802
|
+
/**
|
|
803
|
+
* Convert a glob-like pattern to a RegExp.
|
|
804
|
+
*
|
|
805
|
+
* Pattern semantics:
|
|
806
|
+
* - `*` = single path segment (no slashes), minimum 1 character
|
|
807
|
+
* - `**` = multiple path segments (includes slashes), zero or more segments
|
|
808
|
+
* - `{param}` = single path segment parameter
|
|
809
|
+
* - Exact match segments are literal strings
|
|
810
|
+
*/
|
|
811
|
+
private globToRegex;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Validates that OpenAPI specs are on the approved list
|
|
816
|
+
* and haven't been modified since approval.
|
|
817
|
+
*
|
|
818
|
+
* @example
|
|
819
|
+
* ```typescript
|
|
820
|
+
* const config: PrebuildSecurityConfig = {
|
|
821
|
+
* enabled: true,
|
|
822
|
+
* allowlist: [
|
|
823
|
+
* {
|
|
824
|
+
* name: 'Government Logistics API',
|
|
825
|
+
* url: 'https://api.gov.mil/logistics/v1/openapi.yaml',
|
|
826
|
+
* sha256: 'a1b2c3d4e5f6...'
|
|
827
|
+
* }
|
|
828
|
+
* ]
|
|
829
|
+
* };
|
|
830
|
+
*
|
|
831
|
+
* const validator = new ApprovedSpecsValidator(config);
|
|
832
|
+
* const result = await validator.validate('https://api.gov.mil/logistics/v1/openapi.yaml');
|
|
833
|
+
*
|
|
834
|
+
* if (!result.valid) {
|
|
835
|
+
* console.error('Security rejection:', result.error);
|
|
836
|
+
* process.exit(1);
|
|
837
|
+
* }
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
840
|
+
declare class ApprovedSpecsValidator {
|
|
841
|
+
private allowlist;
|
|
842
|
+
private cache;
|
|
843
|
+
private skipHashVerification;
|
|
844
|
+
private readonly ALLOWED_DIRS;
|
|
845
|
+
private readonly MAX_RESPONSE_SIZE;
|
|
846
|
+
/**
|
|
847
|
+
* Create a new ApprovedSpecsValidator
|
|
848
|
+
*
|
|
849
|
+
* @param config - Security configuration from stackwright.yml
|
|
850
|
+
* @param skipHashVerification - Skip hash check (for testing/development)
|
|
851
|
+
*/
|
|
852
|
+
constructor(config: PrebuildSecurityConfig, skipHashVerification?: boolean);
|
|
853
|
+
/**
|
|
854
|
+
* Build list of allowed directories for path traversal prevention.
|
|
855
|
+
* Defaults to cwd, specs subdir, and .stackwright cache dir.
|
|
856
|
+
*/
|
|
857
|
+
private buildAllowedDirs;
|
|
858
|
+
/**
|
|
859
|
+
* Validate that a file path is within allowed directories (path traversal prevention).
|
|
860
|
+
* Uses realpathSync to resolve symlinks and prevent symlink traversal attacks.
|
|
861
|
+
*
|
|
862
|
+
* @param filePath - File path to validate
|
|
863
|
+
* @returns true if path is allowed, false otherwise
|
|
864
|
+
*/
|
|
865
|
+
private isPathAllowed;
|
|
866
|
+
/**
|
|
867
|
+
* Check if a URL/path is a path traversal attempt.
|
|
868
|
+
* This is checked BEFORE the allowlist to prevent bypassing path security.
|
|
869
|
+
*
|
|
870
|
+
* @param specUrl - URL or path to check
|
|
871
|
+
* @returns true if this is a path traversal attempt
|
|
872
|
+
*/
|
|
873
|
+
private isPathTraversalAttempt;
|
|
874
|
+
/**
|
|
875
|
+
* Validate that a hex string is a valid SHA-256 hash (64 hex characters).
|
|
876
|
+
*
|
|
877
|
+
* @param hash - String to validate
|
|
878
|
+
* @returns true if valid SHA-256 hex format
|
|
879
|
+
*/
|
|
880
|
+
private isValidHex;
|
|
881
|
+
/**
|
|
882
|
+
* Validate that a redirect URL is safe (SSRF protection).
|
|
883
|
+
* Blocks:
|
|
884
|
+
* - HTTPS → HTTP downgrades
|
|
885
|
+
* - Private IP ranges (10.x.x.x, 172.16-31.x.x, 192.168.x.x, 127.x.x.x)
|
|
886
|
+
* - Localhost and loopback addresses
|
|
887
|
+
* - Cloud metadata endpoints
|
|
888
|
+
* - IPv6 private/link-local addresses
|
|
889
|
+
*
|
|
890
|
+
* @param location - Redirect location URL
|
|
891
|
+
* @param originalProtocol - Protocol of the original request
|
|
892
|
+
* @returns true if redirect is safe, false if it should be blocked
|
|
893
|
+
*/
|
|
894
|
+
private isRedirectSafe;
|
|
895
|
+
/**
|
|
896
|
+
* Atomically check if path is allowed and read content if so.
|
|
897
|
+
* Prevents TOCTOU race conditions by combining existence check,
|
|
898
|
+
* symlink resolution, path validation, and file read in a single operation.
|
|
899
|
+
*
|
|
900
|
+
* @param filePath - File path to check and read
|
|
901
|
+
* @returns Object with content if successful, or error message
|
|
902
|
+
*/
|
|
903
|
+
private readAllowedFile;
|
|
904
|
+
/**
|
|
905
|
+
* Check if security enforcement is enabled
|
|
906
|
+
*/
|
|
907
|
+
isEnabled(): boolean;
|
|
908
|
+
/**
|
|
909
|
+
* Get the allowlist count
|
|
910
|
+
*/
|
|
911
|
+
getAllowlistCount(): number;
|
|
912
|
+
/**
|
|
913
|
+
* Validate that a spec is on the approved list and matches expected hash.
|
|
914
|
+
*
|
|
915
|
+
* @param specUrl - URL or file path to the spec to validate
|
|
916
|
+
* @returns ValidationResult indicating if the spec is approved
|
|
917
|
+
*/
|
|
918
|
+
validate(specUrl: string): Promise<ValidationResult>;
|
|
919
|
+
/**
|
|
920
|
+
* Validate multiple specs at once (batch validation).
|
|
921
|
+
* Fails fast on first error.
|
|
922
|
+
*
|
|
923
|
+
* @param specUrls - Array of URLs/paths to validate
|
|
924
|
+
* @returns Map of URL to ValidationResult
|
|
925
|
+
*/
|
|
926
|
+
validateAll(specUrls: string[]): Promise<Map<string, ValidationResult>>;
|
|
927
|
+
/**
|
|
928
|
+
* Validate all specs and return all results (non-fail-fast).
|
|
929
|
+
*
|
|
930
|
+
* @param specUrls - Array of URLs/paths to validate
|
|
931
|
+
* @returns Map of URL to ValidationResult
|
|
932
|
+
*/
|
|
933
|
+
validateAllComplete(specUrls: string[]): Promise<Map<string, ValidationResult>>;
|
|
934
|
+
/**
|
|
935
|
+
* Get content hash from cache or download.
|
|
936
|
+
*/
|
|
937
|
+
private getHash;
|
|
938
|
+
/**
|
|
939
|
+
* Download content from URL or file.
|
|
940
|
+
* Includes path traversal and SSRF protection.
|
|
941
|
+
*/
|
|
942
|
+
private download;
|
|
943
|
+
/**
|
|
944
|
+
* Check if two URLs match (handles trailing slashes, case sensitivity, etc.).
|
|
945
|
+
* Strips credentials and hash to prevent bypass via @ symbol.
|
|
946
|
+
*/
|
|
947
|
+
private urlsMatch;
|
|
948
|
+
/**
|
|
949
|
+
* Format error message for spec not on allowlist
|
|
950
|
+
*/
|
|
951
|
+
private formatAllowlistError;
|
|
952
|
+
/**
|
|
953
|
+
* Format error message for hash mismatch
|
|
954
|
+
*/
|
|
955
|
+
private formatHashMismatchError;
|
|
956
|
+
/**
|
|
957
|
+
* Clear the download cache.
|
|
958
|
+
* Useful for long-running processes.
|
|
959
|
+
*/
|
|
960
|
+
clearCache(): void;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
export { type ApprovedSpec, ApprovedSpecsValidator, type ClientGenerationOptions, ClientGenerator, type CollectionConfig, CollectionProviderGenerator, EndpointFilter, OpenAPICollectionProvider, type OpenAPICompilationResult, type OpenAPIConfig, type OpenAPIDocument, OpenAPIParser, OpenAPIPlugin, type OpenAPISourceConfig, type ParseOptions, type ParseResult, type PrebuildSecurityConfig, type ProviderGenerationOptions, type SchemaMapping, SchemaResolver, type SiteConfig, type TypeGenerationOptions, TypeGenerator, type ValidationResult, type ZodGenerationOptions, ZodSchemaGenerator, createOpenAPIFetcher, createOpenAPIPlugin };
|