@naylence/runtime 0.3.5-test.910 → 0.3.5-test.911
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/browser/index.cjs +1847 -1054
- package/dist/browser/index.mjs +1842 -1049
- package/dist/cjs/naylence/fame/factory-manifest.js +2 -0
- package/dist/cjs/naylence/fame/http/oauth2-token-router.js +751 -88
- package/dist/cjs/naylence/fame/node/admission/admission-profile-factory.js +61 -0
- package/dist/cjs/naylence/fame/security/auth/oauth2-pkce-token-provider-factory.js +171 -0
- package/dist/cjs/naylence/fame/security/auth/oauth2-pkce-token-provider.js +560 -0
- package/dist/cjs/naylence/fame/telemetry/open-telemetry-trace-emitter-factory.js +19 -2
- package/dist/cjs/naylence/fame/telemetry/open-telemetry-trace-emitter.js +19 -9
- package/dist/cjs/naylence/fame/util/register-runtime-factories.js +6 -0
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/factory-manifest.js +2 -0
- package/dist/esm/naylence/fame/http/oauth2-token-router.js +751 -88
- package/dist/esm/naylence/fame/node/admission/admission-profile-factory.js +61 -0
- package/dist/esm/naylence/fame/security/auth/oauth2-pkce-token-provider-factory.js +134 -0
- package/dist/esm/naylence/fame/security/auth/oauth2-pkce-token-provider.js +555 -0
- package/dist/esm/naylence/fame/telemetry/open-telemetry-trace-emitter-factory.js +19 -2
- package/dist/esm/naylence/fame/telemetry/open-telemetry-trace-emitter.js +19 -9
- package/dist/esm/naylence/fame/util/register-runtime-factories.js +6 -0
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +1843 -1050
- package/dist/node/index.mjs +1842 -1049
- package/dist/node/node.cjs +2658 -1202
- package/dist/node/node.mjs +2657 -1201
- package/dist/types/naylence/fame/factory-manifest.d.ts +1 -1
- package/dist/types/naylence/fame/http/oauth2-token-router.d.ts +73 -17
- package/dist/types/naylence/fame/security/auth/oauth2-pkce-token-provider-factory.d.ts +27 -0
- package/dist/types/naylence/fame/security/auth/oauth2-pkce-token-provider.d.ts +42 -0
- package/dist/types/naylence/fame/telemetry/open-telemetry-trace-emitter.d.ts +4 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +3 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Provides the list of runtime factory modules for registration.
|
|
6
6
|
*/
|
|
7
|
-
export declare const MODULES: readonly ["./connector/broadcast-channel-connector-factory.js", "./connector/broadcast-channel-listener-factory.js", "./connector/http-listener-factory.js", "./connector/http-stateless-connector-factory.js", "./connector/inpage-connector-factory.js", "./connector/inpage-listener-factory.js", "./connector/websocket-connector-factory.js", "./connector/websocket-listener-factory.js", "./delivery/at-least-once-delivery-policy-factory.js", "./delivery/at-most-once-delivery-policy-factory.js", "./delivery/delivery-profile-factory.js", "./fabric/in-process-fame-fabric-factory.js", "./node/admission/admission-profile-factory.js", "./node/admission/direct-admission-client-factory.js", "./node/admission/noop-admission-client-factory.js", "./node/admission/welcome-service-client-factory.js", "./node/node-factory.js", "./placement/static-node-placement-strategy-factory.js", "./security/auth/bearer-token-header-auth-injection-strategy-factory.js", "./security/auth/default-authorizer-factory.js", "./security/auth/jwks-jwt-token-verifier-factory.js", "./security/auth/jwt-token-issuer-factory.js", "./security/auth/jwt-token-verifier-factory.js", "./security/auth/no-auth-injection-strategy-factory.js", "./security/auth/none-token-provider-factory.js", "./security/auth/noop-authorizer-factory.js", "./security/auth/noop-token-issuer-factory.js", "./security/auth/noop-token-verifier-factory.js", "./security/auth/oauth2-authorizer-factory.js", "./security/auth/oauth2-client-credentials-token-provider-factory.js", "./security/auth/query-param-auth-injection-strategy-factory.js", "./security/auth/shared-secret-authorizer-factory.js", "./security/auth/shared-secret-token-provider-factory.js", "./security/auth/shared-secret-token-verifier-factory.js", "./security/auth/static-token-provider-factory.js", "./security/auth/websocket-subprotocol-auth-injection-strategy-factory.js", "./security/credential/dev-fixed-key-credential-provider-factory.js", "./security/credential/env-credential-provider-factory.js", "./security/credential/none-credential-provider-factory.js", "./security/credential/prompt-credential-provider-factory.js", "./security/credential/secret-store-credential-provider-factory.js", "./security/credential/session-key-credential-provider-factory.js", "./security/credential/static-credential-provider-factory.js", "./security/default-security-manager-factory.js", "./security/encryption/noop-encryption-manager-factory.js", "./security/encryption/noop-secure-channel-manager-factory.js", "./security/keys/default-key-manager-factory.js", "./security/keys/in-memory-key-store-factory.js", "./security/keys/noop-key-validator-factory.js", "./security/node-security-profile-factory.js", "./security/policy/default-security-policy-factory.js", "./security/policy/no-security-policy-factory.js", "./security/signing/eddsa-envelope-signer-factory.js", "./security/signing/eddsa-envelope-verifier-factory.js", "./sentinel/capability-aware-routing-policy-factory.js", "./sentinel/composite-routing-policy-factory.js", "./sentinel/hybrid-path-routing-policy-factory.js", "./sentinel/load-balancing/composite-load-balancing-strategy-factory.js", "./sentinel/load-balancing/hrw-load-balancing-strategy-factory.js", "./sentinel/load-balancing/load-balancing-profile-factory.js", "./sentinel/load-balancing/random-load-balancing-strategy-factory.js", "./sentinel/load-balancing/round-robin-load-balancing-strategy-factory.js", "./sentinel/load-balancing/sticky-load-balancing-strategy-factory.js", "./sentinel/routing-profile-factory.js", "./sentinel/sentinel-factory.js", "./sentinel/store/route-store-factory.js", "./stickiness/simple-load-balancer-stickiness-manager-factory.js", "./telemetry/noop-trace-emitter-factory.js", "./telemetry/open-telemetry-trace-emitter-factory.js", "./telemetry/trace-emitter-profile-factory.js", "./welcome/default-welcome-service-factory.js"];
|
|
7
|
+
export declare const MODULES: readonly ["./connector/broadcast-channel-connector-factory.js", "./connector/broadcast-channel-listener-factory.js", "./connector/http-listener-factory.js", "./connector/http-stateless-connector-factory.js", "./connector/inpage-connector-factory.js", "./connector/inpage-listener-factory.js", "./connector/websocket-connector-factory.js", "./connector/websocket-listener-factory.js", "./delivery/at-least-once-delivery-policy-factory.js", "./delivery/at-most-once-delivery-policy-factory.js", "./delivery/delivery-profile-factory.js", "./fabric/in-process-fame-fabric-factory.js", "./node/admission/admission-profile-factory.js", "./node/admission/direct-admission-client-factory.js", "./node/admission/noop-admission-client-factory.js", "./node/admission/welcome-service-client-factory.js", "./node/node-factory.js", "./placement/static-node-placement-strategy-factory.js", "./security/auth/bearer-token-header-auth-injection-strategy-factory.js", "./security/auth/default-authorizer-factory.js", "./security/auth/jwks-jwt-token-verifier-factory.js", "./security/auth/jwt-token-issuer-factory.js", "./security/auth/jwt-token-verifier-factory.js", "./security/auth/no-auth-injection-strategy-factory.js", "./security/auth/none-token-provider-factory.js", "./security/auth/noop-authorizer-factory.js", "./security/auth/noop-token-issuer-factory.js", "./security/auth/noop-token-verifier-factory.js", "./security/auth/oauth2-authorizer-factory.js", "./security/auth/oauth2-client-credentials-token-provider-factory.js", "./security/auth/oauth2-pkce-token-provider-factory.js", "./security/auth/query-param-auth-injection-strategy-factory.js", "./security/auth/shared-secret-authorizer-factory.js", "./security/auth/shared-secret-token-provider-factory.js", "./security/auth/shared-secret-token-verifier-factory.js", "./security/auth/static-token-provider-factory.js", "./security/auth/websocket-subprotocol-auth-injection-strategy-factory.js", "./security/credential/dev-fixed-key-credential-provider-factory.js", "./security/credential/env-credential-provider-factory.js", "./security/credential/none-credential-provider-factory.js", "./security/credential/prompt-credential-provider-factory.js", "./security/credential/secret-store-credential-provider-factory.js", "./security/credential/session-key-credential-provider-factory.js", "./security/credential/static-credential-provider-factory.js", "./security/default-security-manager-factory.js", "./security/encryption/noop-encryption-manager-factory.js", "./security/encryption/noop-secure-channel-manager-factory.js", "./security/keys/default-key-manager-factory.js", "./security/keys/in-memory-key-store-factory.js", "./security/keys/noop-key-validator-factory.js", "./security/node-security-profile-factory.js", "./security/policy/default-security-policy-factory.js", "./security/policy/no-security-policy-factory.js", "./security/signing/eddsa-envelope-signer-factory.js", "./security/signing/eddsa-envelope-verifier-factory.js", "./sentinel/capability-aware-routing-policy-factory.js", "./sentinel/composite-routing-policy-factory.js", "./sentinel/hybrid-path-routing-policy-factory.js", "./sentinel/load-balancing/composite-load-balancing-strategy-factory.js", "./sentinel/load-balancing/hrw-load-balancing-strategy-factory.js", "./sentinel/load-balancing/load-balancing-profile-factory.js", "./sentinel/load-balancing/random-load-balancing-strategy-factory.js", "./sentinel/load-balancing/round-robin-load-balancing-strategy-factory.js", "./sentinel/load-balancing/sticky-load-balancing-strategy-factory.js", "./sentinel/routing-profile-factory.js", "./sentinel/sentinel-factory.js", "./sentinel/store/route-store-factory.js", "./stickiness/simple-load-balancer-stickiness-manager-factory.js", "./telemetry/noop-trace-emitter-factory.js", "./telemetry/open-telemetry-trace-emitter-factory.js", "./telemetry/trace-emitter-profile-factory.js", "./welcome/default-welcome-service-factory.js"];
|
|
8
8
|
export type FactoryModuleSpec = (typeof MODULES)[number];
|
|
9
9
|
export type FactoryModuleLoader = () => Promise<Record<string, unknown>>;
|
|
10
10
|
export declare const MODULE_LOADERS: Record<FactoryModuleSpec, FactoryModuleLoader>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OAuth2 client credentials grant
|
|
2
|
+
* OAuth2 client credentials and authorization code (PKCE) grant router for Express
|
|
3
3
|
*
|
|
4
|
-
* Provides /oauth/token
|
|
5
|
-
* Implements OAuth2 client credentials grant with JWT token issuance
|
|
4
|
+
* Provides /oauth/token and /oauth/authorize endpoints for local development and testing.
|
|
5
|
+
* Implements OAuth2 client credentials grant with JWT token issuance and
|
|
6
|
+
* OAuth2 authorization code grant with PKCE verification.
|
|
6
7
|
*/
|
|
7
8
|
import { type Router } from 'express';
|
|
8
9
|
import type { CryptoProvider } from '../security/crypto/providers/crypto-provider.js';
|
|
@@ -44,12 +45,76 @@ export interface CreateOAuth2TokenRouterOptions {
|
|
|
44
45
|
* Default: EdDSA
|
|
45
46
|
*/
|
|
46
47
|
algorithm?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Enable PKCE authorization code grant (default: true)
|
|
50
|
+
*/
|
|
51
|
+
enablePkce?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Allow public clients (no client_secret) for PKCE exchange (default: true)
|
|
54
|
+
*/
|
|
55
|
+
allowPublicClients?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Authorization code TTL in seconds (default: 300)
|
|
58
|
+
*/
|
|
59
|
+
authorizationCodeTtlSec?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Enable developer login experience for authorization flows (default: false)
|
|
62
|
+
*/
|
|
63
|
+
enableDevLogin?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Developer login username (required if enableDevLogin is true and not set via env)
|
|
66
|
+
*/
|
|
67
|
+
devLoginUsername?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Developer login password (required if enableDevLogin is true and not set via env)
|
|
70
|
+
*/
|
|
71
|
+
devLoginPassword?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Developer login session TTL in seconds (default: 3600)
|
|
74
|
+
*/
|
|
75
|
+
devLoginSessionTtlSec?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Cookie name for developer login session (default: naylence_dev_session)
|
|
78
|
+
|
|
79
|
+
if (devLoginEnabled) {
|
|
80
|
+
cleanupLoginSessions(loginSessions, Date.now());
|
|
81
|
+
const activeSession = getActiveSession(
|
|
82
|
+
req,
|
|
83
|
+
loginSessions,
|
|
84
|
+
devLoginCookieName,
|
|
85
|
+
devLoginSessionTtlMs
|
|
86
|
+
);
|
|
87
|
+
if (!activeSession) {
|
|
88
|
+
const returnTo = sanitizeReturnTo(
|
|
89
|
+
req.originalUrl,
|
|
90
|
+
sessionCookiePath,
|
|
91
|
+
authorizationRedirectPath
|
|
92
|
+
);
|
|
93
|
+
const loginLocation = `${prefix}/login?return_to=${encodeURIComponent(
|
|
94
|
+
returnTo
|
|
95
|
+
)}`;
|
|
96
|
+
setNoCacheHeaders(res);
|
|
97
|
+
res.redirect(302, loginLocation);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
*/
|
|
102
|
+
devLoginCookieName?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Whether to mark the developer login cookie as secure (default: false)
|
|
105
|
+
*/
|
|
106
|
+
devLoginSecureCookie?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Custom title for the developer login page (default: Developer Login)
|
|
109
|
+
*/
|
|
110
|
+
devLoginTitle?: string;
|
|
47
111
|
}
|
|
48
112
|
/**
|
|
49
|
-
* Create an Express router that implements OAuth2
|
|
113
|
+
* Create an Express router that implements OAuth2 token and authorization endpoints
|
|
114
|
+
* with support for client credentials and authorization code (PKCE) grants.
|
|
50
115
|
*
|
|
51
116
|
* @param options - Router configuration options
|
|
52
|
-
* @returns Express router with OAuth2 token
|
|
117
|
+
* @returns Express router with OAuth2 token and authorization endpoints
|
|
53
118
|
*
|
|
54
119
|
* Environment Variables:
|
|
55
120
|
* FAME_JWT_CLIENT_ID: OAuth2 client identifier
|
|
@@ -58,17 +123,8 @@ export interface CreateOAuth2TokenRouterOptions {
|
|
|
58
123
|
* FAME_JWT_AUDIENCE: JWT audience claim (optional)
|
|
59
124
|
* FAME_JWT_ALGORITHM: JWT signing algorithm (optional, default: EdDSA)
|
|
60
125
|
* FAME_JWT_ALLOWED_SCOPES: Allowed scopes (optional, default: node.connect)
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* import express from 'express';
|
|
65
|
-
* import { createOAuth2TokenRouter } from '@naylence/runtime';
|
|
66
|
-
*
|
|
67
|
-
* const app = express();
|
|
68
|
-
* app.use(express.urlencoded({ extended: true }));
|
|
69
|
-
*
|
|
70
|
-
* const cryptoProvider = new MyCryptoProvider();
|
|
71
|
-
* app.use(createOAuth2TokenRouter({ cryptoProvider }));
|
|
72
|
-
* ```
|
|
126
|
+
* FAME_OAUTH_ENABLE_PKCE: Enable PKCE authorization endpoints (optional, default: true)
|
|
127
|
+
* FAME_OAUTH_ALLOW_PUBLIC_CLIENTS: Allow PKCE exchanges without client_secret (optional, default: true)
|
|
128
|
+
* FAME_OAUTH_CODE_TTL_SEC: Authorization code TTL in seconds (optional, default: 300)
|
|
73
129
|
*/
|
|
74
130
|
export declare function createOAuth2TokenRouter(options: CreateOAuth2TokenRouterOptions): Router;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type SecretSourceType } from '../credential/secret-source.js';
|
|
2
|
+
import type { TokenProvider } from './token-provider.js';
|
|
3
|
+
import { TokenProviderFactory, type TokenProviderConfig } from './token-provider-factory.js';
|
|
4
|
+
export interface OAuth2PkceTokenProviderConfig extends TokenProviderConfig {
|
|
5
|
+
type: 'OAuth2PkceTokenProvider';
|
|
6
|
+
authorizeUrl: string;
|
|
7
|
+
tokenUrl: string;
|
|
8
|
+
redirectUri: string;
|
|
9
|
+
clientId: string;
|
|
10
|
+
username?: SecretSourceType;
|
|
11
|
+
clientSecret?: SecretSourceType;
|
|
12
|
+
scopes?: string[];
|
|
13
|
+
audience?: string;
|
|
14
|
+
codeChallengeMethod?: string;
|
|
15
|
+
codeVerifierLength?: number;
|
|
16
|
+
clockSkewSeconds?: number;
|
|
17
|
+
loginHintParam?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const FACTORY_META: {
|
|
20
|
+
readonly base: "TokenProviderFactory";
|
|
21
|
+
readonly key: "OAuth2PkceTokenProvider";
|
|
22
|
+
};
|
|
23
|
+
export declare class OAuth2PkceTokenProviderFactory extends TokenProviderFactory<OAuth2PkceTokenProviderConfig> {
|
|
24
|
+
readonly type = "OAuth2PkceTokenProvider";
|
|
25
|
+
create(config?: OAuth2PkceTokenProviderConfig | Record<string, unknown> | null): Promise<TokenProvider>;
|
|
26
|
+
}
|
|
27
|
+
export default OAuth2PkceTokenProviderFactory;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type CredentialProvider } from '../credential/credential-provider.js';
|
|
2
|
+
import type { Token } from './token.js';
|
|
3
|
+
import type { TokenProvider } from './token-provider.js';
|
|
4
|
+
interface FetchLike {
|
|
5
|
+
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
6
|
+
}
|
|
7
|
+
type PkceMethod = 'S256' | 'PLAIN';
|
|
8
|
+
export interface OAuth2PkceTokenProviderOptions {
|
|
9
|
+
authorizeUrl: string;
|
|
10
|
+
tokenUrl: string;
|
|
11
|
+
redirectUri: string;
|
|
12
|
+
clientId: string;
|
|
13
|
+
usernameProvider?: CredentialProvider;
|
|
14
|
+
clientSecretProvider?: CredentialProvider;
|
|
15
|
+
scopes?: string[];
|
|
16
|
+
audience?: string;
|
|
17
|
+
fetchImpl?: FetchLike;
|
|
18
|
+
clockSkewSeconds?: number;
|
|
19
|
+
codeVerifierLength?: number;
|
|
20
|
+
codeChallengeMethod?: PkceMethod;
|
|
21
|
+
loginHintParam?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class OAuth2PkceRedirectInitiatedError extends Error {
|
|
24
|
+
constructor(message?: string);
|
|
25
|
+
}
|
|
26
|
+
export declare class OAuth2PkceTokenProvider implements TokenProvider {
|
|
27
|
+
private cachedToken;
|
|
28
|
+
private readonly options;
|
|
29
|
+
constructor(rawOptions: OAuth2PkceTokenProviderOptions | Record<string, unknown>);
|
|
30
|
+
getToken(): Promise<Token>;
|
|
31
|
+
private isTokenFresh;
|
|
32
|
+
private beginBrowserAuthorization;
|
|
33
|
+
private navigate;
|
|
34
|
+
private tryCompletePendingAuthorization;
|
|
35
|
+
private isTokenCompatible;
|
|
36
|
+
private persistToken;
|
|
37
|
+
private buildAuthorizeUrl;
|
|
38
|
+
private resolveFetch;
|
|
39
|
+
private resolveOptionalSecret;
|
|
40
|
+
private exchangeToken;
|
|
41
|
+
}
|
|
42
|
+
export {};
|
|
@@ -3,8 +3,10 @@ import { BaseTraceEmitter } from './base-trace-emitter.js';
|
|
|
3
3
|
import type { TraceSpanOptions, TraceSpanScope } from './trace-emitter.js';
|
|
4
4
|
import type { OtelLifecycleControl } from './otel-setup.js';
|
|
5
5
|
import type { AuthInjectionStrategy } from '../security/auth/auth-injection-strategy.js';
|
|
6
|
+
type OtelApiBridge = Pick<typeof import('@opentelemetry/api'), 'trace' | 'SpanStatusCode'>;
|
|
6
7
|
export declare class OpenTelemetryTraceEmitter extends BaseTraceEmitter {
|
|
7
8
|
private readonly tracer;
|
|
9
|
+
private readonly otelApi;
|
|
8
10
|
private lifecycle;
|
|
9
11
|
private authStrategy;
|
|
10
12
|
private shutdownInvoked;
|
|
@@ -19,6 +21,8 @@ type OpenTelemetryTraceEmitterOptionsInput = {
|
|
|
19
21
|
serviceName?: string;
|
|
20
22
|
service_name?: string;
|
|
21
23
|
tracer?: Tracer;
|
|
24
|
+
otelApi?: OtelApiBridge;
|
|
25
|
+
otel_api?: OtelApiBridge;
|
|
22
26
|
lifecycle?: OtelLifecycleControl | null;
|
|
23
27
|
lifeCycle?: OtelLifecycleControl | null;
|
|
24
28
|
life_cycle?: OtelLifecycleControl | null;
|
package/dist/types/version.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naylence/runtime",
|
|
3
|
-
"version": "0.3.5-test.
|
|
3
|
+
"version": "0.3.5-test.911",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Naylence Runtime - Complete TypeScript runtime",
|
|
6
6
|
"author": "Naylence Dev <naylencedev@gmail.com>",
|
|
@@ -217,6 +217,7 @@
|
|
|
217
217
|
"@types/better-sqlite3": "^7.6.13",
|
|
218
218
|
"@types/jest": "^29.5.14",
|
|
219
219
|
"@types/node": "^24.6.0",
|
|
220
|
+
"@types/supertest": "^2.0.16",
|
|
220
221
|
"@types/ws": "^8.5.10",
|
|
221
222
|
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
|
222
223
|
"@typescript-eslint/parser": "^8.45.0",
|
|
@@ -233,6 +234,7 @@
|
|
|
233
234
|
"rimraf": "^6.0.1",
|
|
234
235
|
"rollup": "^4.52.3",
|
|
235
236
|
"size-limit": "^11.1.5",
|
|
237
|
+
"supertest": "^7.1.3",
|
|
236
238
|
"ts-jest": "^29.4.5",
|
|
237
239
|
"tslib": "^2.6.2",
|
|
238
240
|
"typescript": "^5.3.2",
|