@zintrust/core 0.4.34 → 0.4.38

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.
Files changed (37) hide show
  1. package/package.json +4 -4
  2. package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
  3. package/src/cache/drivers/RedisDriver.js +1 -1
  4. package/src/cli/OptionalCliExtensions.d.ts.map +1 -1
  5. package/src/cli/OptionalCliExtensions.js +1 -0
  6. package/src/cli/commands/WorkerCommands.d.ts +2 -1
  7. package/src/cli/commands/WorkerCommands.d.ts.map +1 -1
  8. package/src/cli/commands/WorkerCommands.js +111 -62
  9. package/src/cli/services/WorkerStartupDiagnostics.d.ts +41 -0
  10. package/src/cli/services/WorkerStartupDiagnostics.d.ts.map +1 -0
  11. package/src/cli/services/WorkerStartupDiagnostics.js +348 -0
  12. package/src/cli/utils/DistPackager.d.ts.map +1 -1
  13. package/src/cli/utils/DistPackager.js +22 -18
  14. package/src/config/workers.d.ts +2 -1
  15. package/src/config/workers.d.ts.map +1 -1
  16. package/src/config/workers.js +6 -1
  17. package/src/index.d.ts +11 -11
  18. package/src/index.d.ts.map +1 -1
  19. package/src/index.js +13 -13
  20. package/src/proxy/CloudflareProxyShared.d.ts +50 -0
  21. package/src/proxy/CloudflareProxyShared.d.ts.map +1 -0
  22. package/src/proxy/CloudflareProxyShared.js +117 -0
  23. package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
  24. package/src/proxy/d1/ZintrustD1Proxy.js +49 -158
  25. package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -1
  26. package/src/proxy/kv/ZintrustKvProxy.js +41 -142
  27. package/src/security/CsrfTokenManager.d.ts.map +1 -1
  28. package/src/security/CsrfTokenManager.js +1 -1
  29. package/src/security/JwtSessions.d.ts.map +1 -1
  30. package/src/security/JwtSessions.js +1 -1
  31. package/src/security/TokenRevocation.d.ts.map +1 -1
  32. package/src/security/TokenRevocation.js +1 -1
  33. package/src/tools/queue/LockProvider.d.ts.map +1 -1
  34. package/src/tools/queue/LockProvider.js +1 -1
  35. package/src/tools/redis/RedisTransport.d.ts +34 -0
  36. package/src/tools/redis/RedisTransport.d.ts.map +1 -0
  37. package/src/tools/redis/RedisTransport.js +251 -0
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @zintrust/core v0.4.34
2
+ * @zintrust/core v0.4.38
3
3
  *
4
4
  * ZinTrust Framework - Production-Grade TypeScript Backend
5
5
  * Built for performance, type safety, and exceptional developer experience
6
6
  *
7
7
  * Build Information:
8
- * Built: 2026-03-29T19:18:37.838Z
8
+ * Built: 2026-03-30T19:59:14.217Z
9
9
  * Node: >=20.0.0
10
10
  * License: MIT
11
11
  *
@@ -21,13 +21,13 @@
21
21
  * Available at runtime for debugging and health checks
22
22
  */
23
23
  export const ZINTRUST_VERSION = '0.1.41';
24
- export const ZINTRUST_BUILD_DATE = '2026-03-29T19:18:37.802Z'; // Replaced during build
24
+ export const ZINTRUST_BUILD_DATE = '2026-03-30T19:59:14.183Z'; // Replaced during build
25
25
  export { Application } from './boot/Application.js';
26
26
  export { AwsSigV4 } from './common/index.js';
27
27
  export { SignedRequest } from './security/SignedRequest.js';
28
28
  export { Server } from './boot/Server.js';
29
29
  export { ServiceContainer } from './container/ServiceContainer.js';
30
- export { Paginator, createPaginator, getNextPageUrl, getPrevPageUrl } from './database/Paginator.js';
30
+ export { createPaginator, getNextPageUrl, getPrevPageUrl, Paginator } from './database/Paginator.js';
31
31
  export { Controller } from './http/Controller.js';
32
32
  export { FileUpload } from './http/FileUpload.js';
33
33
  export { Kernel } from './http/Kernel.js';
@@ -39,7 +39,7 @@ export { MultipartParserRegistry } from './http/parsers/MultipartParserRegistry.
39
39
  export { Request } from './http/Request.js';
40
40
  export { RequestContext } from './http/RequestContext.js';
41
41
  export { Response } from './http/Response.js';
42
- export { ValidationHelper, getValidatedBody, getValidatedHeaders, getValidatedParams, getValidatedQuery, hasValidatedBody, requireValidatedBody, } from './http/ValidationHelper.js';
42
+ export { getValidatedBody, getValidatedHeaders, getValidatedParams, getValidatedQuery, hasValidatedBody, requireValidatedBody, ValidationHelper, } from './http/ValidationHelper.js';
43
43
  export { CsrfMiddleware } from './middleware/CsrfMiddleware.js';
44
44
  export { ErrorHandlerMiddleware } from './middleware/ErrorHandlerMiddleware.js';
45
45
  export { LoggingMiddleware } from './middleware/LoggingMiddleware.js';
@@ -64,13 +64,13 @@ export { Schema as MigrationSchema } from './migrations/schema/index.js';
64
64
  // Adapter registry (for external adapter packages)
65
65
  export { OpenApiGenerator } from './openapi/OpenApiGenerator.js';
66
66
  export { Router } from './routes/Router.js';
67
- export { RouteRegistry, normalizeRouteMeta } from './routes/RouteRegistry.js';
67
+ export { normalizeRouteMeta, RouteRegistry } from './routes/RouteRegistry.js';
68
68
  export { DatabaseAdapterRegistry } from './orm/DatabaseAdapterRegistry.js';
69
69
  // Common
70
- export { Utilities, generateSecureJobId, generateUuid, getString, } from './common/utility.js';
70
+ export { generateSecureJobId, generateUuid, getString, Utilities, } from './common/utility.js';
71
71
  export { delay, ensureDirSafe } from './common/index.js';
72
72
  // Collections
73
- export { Collection, collect } from './collections/index.js';
73
+ export { collect, Collection } from './collections/index.js';
74
74
  // HTTP Client
75
75
  export { HttpClient } from './tools/http/Http.js';
76
76
  // Profiling
@@ -94,14 +94,14 @@ export { Hash } from './security/Hash.js';
94
94
  export { JwtManager } from './security/JwtManager.js';
95
95
  export { JwtSessions } from './security/JwtSessions.js';
96
96
  export { PasswordResetTokenBroker } from './security/PasswordResetTokenBroker.js';
97
- export { Sanitizer, createSanitizer } from './security/Sanitizer.js';
97
+ export { createSanitizer, Sanitizer } from './security/Sanitizer.js';
98
98
  export { TokenRevocation } from './security/TokenRevocation.js';
99
99
  export { Xss } from './security/Xss.js';
100
100
  export { XssProtection } from './security/XssProtection.js';
101
101
  // Exceptions
102
102
  export { ErrorFactory } from './exceptions/ZintrustError.js';
103
103
  // Runtime services
104
- export { RUNTIME_PLATFORM, RuntimeServices, detectCloudflareWorkers, detectRuntimePlatform, } from './runtime/RuntimeServices.js';
104
+ export { detectCloudflareWorkers, detectRuntimePlatform, RUNTIME_PLATFORM, RuntimeServices, } from './runtime/RuntimeServices.js';
105
105
  // Events
106
106
  export { EventDispatcher } from './events/EventDispatcher.js';
107
107
  // Sessions
@@ -132,7 +132,7 @@ export { ServiceAuthMiddleware } from './microservices/ServiceAuthMiddleware.js'
132
132
  export { HealthCheckHandler, ServiceHealthMonitor } from './microservices/ServiceHealthMonitor.js';
133
133
  export { getServiceId, isCanonicalServiceId, normalizeServiceManifest, } from './microservices/ServiceManifest.js';
134
134
  export { ProjectRuntime } from './runtime/ProjectRuntime.js';
135
- export { MiddlewareKeys, clearMiddlewareConfigCache, middlewareConfig } from './config/middleware.js';
135
+ export { clearMiddlewareConfigCache, middlewareConfig, MiddlewareKeys } from './config/middleware.js';
136
136
  export { createBaseDrivers, queueConfig } from './config/queue.js';
137
137
  export { default as broadcastConfig } from './config/broadcast.js';
138
138
  export { default as notificationConfig } from './config/notification.js';
@@ -143,7 +143,7 @@ export { startupConfig } from './config/startup.js';
143
143
  export { Constants, DEFAULTS, ENV_KEYS, HTTP_HEADERS, MIME_TYPES } from './config/constants.js';
144
144
  export { FeatureFlags } from './config/features.js';
145
145
  export { Cloudflare } from './config/cloudflare.js';
146
- export { SECRETS, SecretsManager, getDatabaseCredentials, getJwtSecrets, } from './config/SecretsManager.js';
146
+ export { getDatabaseCredentials, getJwtSecrets, SECRETS, SecretsManager, } from './config/SecretsManager.js';
147
147
  // Config (validation)
148
148
  export { StartupConfigValidator } from './config/StartupConfigValidator.js';
149
149
  export { Mail } from './tools/mail/index.js';
@@ -225,7 +225,7 @@ export { ZintrustLang } from './lang/lang.js';
225
225
  // Workers config
226
226
  export { createRedisConnection, workersConfig } from './config/workers.js';
227
227
  // Redis config key - Singleton exports
228
- export { RedisKeys, createRedisKey, extractOriginalKey, getBullMQSafeQueueName, getPrefix, isAppKey, } from './tools/redis/RedisKeyManager.js';
228
+ export { createRedisKey, extractOriginalKey, getBullMQSafeQueueName, getPrefix, isAppKey, RedisKeys, } from './tools/redis/RedisKeyManager.js';
229
229
  export { CloudflareSocket } from './sockets/CloudflareSocket.js';
230
230
  export { detectRuntime } from './runtime/detectRuntime.js';
231
231
  // NOTE: Node-only exports (like FileLogWriter, process) are intentionally not
@@ -0,0 +1,50 @@
1
+ export type ProxyNoncePutOptions = {
2
+ expirationTtl?: number;
3
+ };
4
+ export type ProxyNonceNamespace = {
5
+ get: (key: string) => Promise<string | null>;
6
+ put: (key: string, value: string, options?: ProxyNoncePutOptions) => Promise<void>;
7
+ };
8
+ type SignedRequestOptions = Readonly<{
9
+ secretEnvVar: string;
10
+ missingSecretStatus: number;
11
+ missingSecretMessage: string;
12
+ defaultSigningWindowMs: number;
13
+ }>;
14
+ type ReadAndVerifyJsonOptions = SignedRequestOptions & Readonly<{
15
+ defaultMaxBodyBytes: number;
16
+ }>;
17
+ type ProxyRequestEnv = object;
18
+ export declare const json: (status: number, body: unknown) => Response;
19
+ export declare const toErrorResponse: (status: number, code: string, message: string) => Response;
20
+ export declare const getEnvInt: (env: ProxyRequestEnv, name: string, fallback: number) => number;
21
+ export declare const normalizeBindingName: (value: unknown) => string | null;
22
+ export declare const readBodyBytes: (request: Request, maxBytes: number) => Promise<{
23
+ ok: true;
24
+ bytes: Uint8Array;
25
+ text: string;
26
+ } | {
27
+ ok: false;
28
+ response: Response;
29
+ }>;
30
+ export declare const parseOptionalJson: (text: string) => {
31
+ ok: true;
32
+ payload: Record<string, unknown> | null;
33
+ } | {
34
+ ok: false;
35
+ response: Response;
36
+ };
37
+ export declare const verifyNonceKv: (kv: ProxyNonceNamespace, keyId: string, nonce: string, ttlMs: number) => Promise<boolean>;
38
+ export declare const verifySignedRequest: (request: Request, env: ProxyRequestEnv, bodyBytes: Uint8Array, options: SignedRequestOptions) => Promise<Response | {
39
+ ok: true;
40
+ }>;
41
+ export declare const readAndVerifyJson: (request: Request, env: ProxyRequestEnv, options: ReadAndVerifyJsonOptions) => Promise<{
42
+ ok: true;
43
+ payload: Record<string, unknown> | null;
44
+ bodyBytes: Uint8Array;
45
+ } | {
46
+ ok: false;
47
+ response: Response;
48
+ }>;
49
+ export {};
50
+ //# sourceMappingURL=CloudflareProxyShared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareProxyShared.d.ts","sourceRoot":"","sources":["../../../src/proxy/CloudflareProxyShared.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAEF,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC,CAAC;AAEH,KAAK,wBAAwB,GAAG,oBAAoB,GAClD,QAAQ,CAAC;IACP,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEL,KAAK,eAAe,GAAG,MAAM,CAAC;AAE9B,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,MAAM,OAAO,KAAG,QAQpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,QAG/E,CAAC;AAMF,eAAO,MAAM,SAAS,GAAI,KAAK,eAAe,EAAE,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MAKhF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,IAI9D,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,OAAO,EAChB,UAAU,MAAM,KACf,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAY3F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,KACX;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAezF,CAAC;AAcF,eAAO,MAAM,aAAa,GACxB,IAAI,mBAAmB,EACvB,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,OAAO,CAAC,OAAO,CAOjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,WAAW,UAAU,EACrB,SAAS,oBAAoB,KAC5B,OAAO,CAAC,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CA+BjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,OAAO,EAChB,KAAK,eAAe,EACpB,SAAS,wBAAwB,KAChC,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAE,GAC5E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAapC,CAAC"}
@@ -0,0 +1,117 @@
1
+ import { isString } from '../helper/index.js';
2
+ import { ErrorHandler } from './ErrorHandler.js';
3
+ import { RequestValidator } from './RequestValidator.js';
4
+ import { SigningService } from './SigningService.js';
5
+ export const json = (status, body) => {
6
+ return new Response(JSON.stringify(body), {
7
+ status,
8
+ headers: {
9
+ 'Content-Type': 'application/json; charset=utf-8',
10
+ 'Cache-Control': 'no-store',
11
+ },
12
+ });
13
+ };
14
+ export const toErrorResponse = (status, code, message) => {
15
+ const error = ErrorHandler.toProxyError(status, code, message);
16
+ return json(error.status, error.body);
17
+ };
18
+ const getEnvValue = (env, name) => {
19
+ return env[name];
20
+ };
21
+ export const getEnvInt = (env, name, fallback) => {
22
+ const raw = getEnvValue(env, name);
23
+ if (!isString(raw))
24
+ return fallback;
25
+ const parsed = Number.parseInt(raw, 10);
26
+ return Number.isFinite(parsed) ? parsed : fallback;
27
+ };
28
+ export const normalizeBindingName = (value) => {
29
+ if (!isString(value))
30
+ return null;
31
+ const trimmed = value.trim();
32
+ return trimmed === '' ? null : trimmed;
33
+ };
34
+ export const readBodyBytes = async (request, maxBytes) => {
35
+ const buf = await request.arrayBuffer();
36
+ if (buf.byteLength > maxBytes) {
37
+ return {
38
+ ok: false,
39
+ response: toErrorResponse(413, 'PAYLOAD_TOO_LARGE', 'Body too large'),
40
+ };
41
+ }
42
+ const bytes = new Uint8Array(buf);
43
+ const text = new TextDecoder().decode(bytes);
44
+ return { ok: true, bytes, text };
45
+ };
46
+ export const parseOptionalJson = (text) => {
47
+ if (text.trim() === '')
48
+ return { ok: true, payload: null };
49
+ const parsed = RequestValidator.parseJson(text);
50
+ if (!parsed.ok) {
51
+ let message = parsed.error.message;
52
+ if (parsed.error.code === 'INVALID_JSON') {
53
+ message = 'Invalid JSON body';
54
+ }
55
+ else if (parsed.error.code === 'VALIDATION_ERROR') {
56
+ message = 'Invalid body';
57
+ }
58
+ return { ok: false, response: toErrorResponse(400, parsed.error.code, message) };
59
+ }
60
+ return { ok: true, payload: parsed.value };
61
+ };
62
+ const loadSigningSecret = (env, secretEnvVar) => {
63
+ const directValue = getEnvValue(env, secretEnvVar);
64
+ const direct = isString(directValue) ? directValue.trim() : '';
65
+ if (direct !== '')
66
+ return direct;
67
+ const fallbackValue = getEnvValue(env, 'APP_KEY');
68
+ const fallback = isString(fallbackValue) ? fallbackValue.trim() : '';
69
+ if (fallback !== '')
70
+ return fallback;
71
+ return null;
72
+ };
73
+ export const verifyNonceKv = async (kv, keyId, nonce, ttlMs) => {
74
+ const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1000));
75
+ const storageKey = `nonce:${keyId}:${nonce}`;
76
+ const existing = await kv.get(storageKey);
77
+ if (existing !== null)
78
+ return false;
79
+ await kv.put(storageKey, '1', { expirationTtl: ttlSeconds });
80
+ return true;
81
+ };
82
+ export const verifySignedRequest = async (request, env, bodyBytes, options) => {
83
+ const secret = loadSigningSecret(env, options.secretEnvVar);
84
+ if (secret === null) {
85
+ return toErrorResponse(options.missingSecretStatus, 'CONFIG_ERROR', options.missingSecretMessage);
86
+ }
87
+ const windowMs = getEnvInt(env, 'ZT_PROXY_SIGNING_WINDOW_MS', options.defaultSigningWindowMs);
88
+ const nonceStore = getEnvValue(env, 'ZT_NONCES');
89
+ const verifyResult = await SigningService.verifyWithKeyProvider({
90
+ method: request.method,
91
+ url: request.url,
92
+ body: bodyBytes,
93
+ headers: request.headers,
94
+ windowMs,
95
+ getSecretForKeyId: (_keyId) => secret,
96
+ verifyNonce: nonceStore === undefined || nonceStore === null
97
+ ? undefined
98
+ : async (keyId, nonce, ttlMs) => verifyNonceKv(nonceStore, keyId, nonce, ttlMs),
99
+ });
100
+ if (!verifyResult.ok) {
101
+ return toErrorResponse(verifyResult.status, verifyResult.code, verifyResult.message);
102
+ }
103
+ return { ok: true };
104
+ };
105
+ export const readAndVerifyJson = async (request, env, options) => {
106
+ const maxBodyBytes = getEnvInt(env, 'ZT_MAX_BODY_BYTES', options.defaultMaxBodyBytes);
107
+ const bodyResult = await readBodyBytes(request, maxBodyBytes);
108
+ if (!bodyResult.ok)
109
+ return { ok: false, response: bodyResult.response };
110
+ const auth = await verifySignedRequest(request, env, bodyResult.bytes, options);
111
+ if (auth instanceof Response)
112
+ return { ok: false, response: auth };
113
+ const parsed = parseOptionalJson(bodyResult.text);
114
+ if (!parsed.ok)
115
+ return { ok: false, response: parsed.response };
116
+ return { ok: true, payload: parsed.payload, bodyBytes: bodyResult.bytes };
117
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"AAMA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,mBAAmB,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC/C,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAkZF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"AAWA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,mBAAmB,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC/C,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AA6QF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -1,30 +1,11 @@
1
1
  import { Logger } from '../../config/logger.js';
2
2
  import { isArray, isObject, isString } from '../../helper/index.js';
3
- import { ErrorHandler } from '../ErrorHandler.js';
3
+ import { getEnvInt, json, normalizeBindingName, readAndVerifyJson, toErrorResponse, } from '../CloudflareProxyShared.js';
4
4
  import { RequestValidator } from '../RequestValidator.js';
5
- import { SigningService } from '../SigningService.js';
6
5
  const DEFAULT_SIGNING_WINDOW_MS = 60_000;
7
6
  const DEFAULT_MAX_BODY_BYTES = 128 * 1024;
8
7
  const DEFAULT_MAX_SQL_BYTES = 32 * 1024;
9
8
  const DEFAULT_MAX_PARAMS = 256;
10
- const json = (status, body) => new Response(JSON.stringify(body), {
11
- status,
12
- headers: {
13
- 'Content-Type': 'application/json; charset=utf-8',
14
- 'Cache-Control': 'no-store',
15
- },
16
- });
17
- const toErrorResponse = (status, code, message) => {
18
- const error = ErrorHandler.toProxyError(status, code, message);
19
- return json(error.status, error.body);
20
- };
21
- const getEnvInt = (env, name, fallback) => {
22
- const raw = env[name];
23
- if (!isString(raw))
24
- return fallback;
25
- const parsed = Number.parseInt(raw, 10);
26
- return Number.isFinite(parsed) ? parsed : fallback;
27
- };
28
9
  const isDebugEnabled = (env) => {
29
10
  const raw = env.ZT_PROXY_DEBUG;
30
11
  if (!isString(raw))
@@ -52,12 +33,6 @@ const logProxyError = (env, context, error) => {
52
33
  message: safeErrorMessage(error).slice(0, 800),
53
34
  });
54
35
  };
55
- const normalizeBindingName = (value) => {
56
- if (!isString(value))
57
- return null;
58
- const trimmed = value.trim();
59
- return trimmed === '' ? null : trimmed;
60
- };
61
36
  const resolveD1Binding = (env) => {
62
37
  const candidates = ['DB', 'zintrust_db', normalizeBindingName(env.D1_BINDING)].filter((value, index, values) => isString(value) && value.trim() !== '' && values.indexOf(value) === index);
63
38
  const record = env;
@@ -69,43 +44,6 @@ const resolveD1Binding = (env) => {
69
44
  }
70
45
  return null;
71
46
  };
72
- const readBodyBytes = async (request, maxBytes) => {
73
- const buf = await request.arrayBuffer();
74
- if (buf.byteLength > maxBytes) {
75
- return {
76
- ok: false,
77
- response: toErrorResponse(413, 'PAYLOAD_TOO_LARGE', 'Body too large'),
78
- };
79
- }
80
- const bytes = new Uint8Array(buf);
81
- const text = new TextDecoder().decode(bytes);
82
- return { ok: true, bytes, text };
83
- };
84
- const parseOptionalJson = (text) => {
85
- if (text.trim() === '')
86
- return { ok: true, payload: null };
87
- const parsed = RequestValidator.parseJson(text);
88
- if (!parsed.ok) {
89
- let message = parsed.error.message;
90
- if (parsed.error.code === 'INVALID_JSON') {
91
- message = 'Invalid JSON body';
92
- }
93
- else if (parsed.error.code === 'VALIDATION_ERROR') {
94
- message = 'Invalid body';
95
- }
96
- return { ok: false, response: toErrorResponse(400, parsed.error.code, message) };
97
- }
98
- return { ok: true, payload: parsed.value };
99
- };
100
- const loadSigningSecret = (env) => {
101
- const direct = isString(env.D1_REMOTE_SECRET) ? env.D1_REMOTE_SECRET.trim() : '';
102
- if (direct !== '')
103
- return direct;
104
- const fallback = isString(env.APP_KEY) ? env.APP_KEY.trim() : '';
105
- if (fallback !== '')
106
- return fallback;
107
- return null;
108
- };
109
47
  const loadStatements = (env) => {
110
48
  const raw = env.ZT_D1_STATEMENTS_JSON;
111
49
  if (!isString(raw) || raw.trim() === '')
@@ -130,37 +68,6 @@ const isMutatingSql = (sql) => {
130
68
  normalized.startsWith('alter') ||
131
69
  normalized.startsWith('replace'));
132
70
  };
133
- const verifyNonceKv = async (kv, keyId, nonce, ttlMs) => {
134
- const ttlSeconds = Math.max(1, Math.ceil(ttlMs / 1000));
135
- const storageKey = `nonce:${keyId}:${nonce}`;
136
- const existing = await kv.get(storageKey);
137
- if (existing !== null)
138
- return false;
139
- await kv.put(storageKey, '1', { expirationTtl: ttlSeconds });
140
- return true;
141
- };
142
- const verifySignedRequest = async (request, env, bodyBytes) => {
143
- const secret = loadSigningSecret(env);
144
- if (secret === null) {
145
- return toErrorResponse(401, 'CONFIG_ERROR', 'Missing signing secret (D1_REMOTE_SECRET or APP_KEY)');
146
- }
147
- const windowMs = getEnvInt(env, 'ZT_PROXY_SIGNING_WINDOW_MS', DEFAULT_SIGNING_WINDOW_MS);
148
- const verifyResult = await SigningService.verifyWithKeyProvider({
149
- method: request.method,
150
- url: request.url,
151
- body: bodyBytes,
152
- headers: request.headers,
153
- windowMs,
154
- getSecretForKeyId: (_keyId) => secret,
155
- verifyNonce: env.ZT_NONCES === undefined
156
- ? undefined
157
- : async (keyId, nonce, ttlMs) => verifyNonceKv(env.ZT_NONCES, keyId, nonce, ttlMs),
158
- });
159
- if (!verifyResult.ok) {
160
- return toErrorResponse(verifyResult.status, verifyResult.code, verifyResult.message);
161
- }
162
- return { ok: true };
163
- };
164
71
  const requireDb = (env) => {
165
72
  const db = resolveD1Binding(env);
166
73
  if (db === null) {
@@ -197,36 +104,41 @@ const enforceSqlLimits = (env, sql, params) => {
197
104
  }
198
105
  return null;
199
106
  };
200
- const readAndVerifyJson = async (request, env) => {
201
- const maxBodyBytes = getEnvInt(env, 'ZT_MAX_BODY_BYTES', DEFAULT_MAX_BODY_BYTES);
202
- const bodyResult = await readBodyBytes(request, maxBodyBytes);
203
- if (!bodyResult.ok)
204
- return { ok: false, response: bodyResult.response };
205
- const auth = await verifySignedRequest(request, env, bodyResult.bytes);
206
- if (auth instanceof Response)
207
- return { ok: false, response: auth };
208
- const parsed = parseOptionalJson(bodyResult.text);
107
+ const resolveDbRequest = async (request, env) => {
108
+ const check = await readAndVerifyJson(request, env, {
109
+ secretEnvVar: 'D1_REMOTE_SECRET',
110
+ missingSecretStatus: 401,
111
+ missingSecretMessage: 'Missing signing secret (D1_REMOTE_SECRET or APP_KEY)',
112
+ defaultSigningWindowMs: DEFAULT_SIGNING_WINDOW_MS,
113
+ defaultMaxBodyBytes: DEFAULT_MAX_BODY_BYTES,
114
+ });
115
+ if (!check.ok)
116
+ return { ok: false, response: check.response };
117
+ const db = requireDb(env);
118
+ if (db instanceof Response)
119
+ return { ok: false, response: db };
120
+ return { ok: true, db, payload: check.payload };
121
+ };
122
+ const resolveSqlRequest = async (request, env) => {
123
+ const resolved = await resolveDbRequest(request, env);
124
+ if (!resolved.ok)
125
+ return { ok: false, response: resolved.response };
126
+ const parsed = parseSqlPayload(resolved.payload);
209
127
  if (!parsed.ok)
210
128
  return { ok: false, response: parsed.response };
211
- return { ok: true, payload: parsed.payload, bodyBytes: bodyResult.bytes };
129
+ const limit = enforceSqlLimits(env, parsed.sql, parsed.params);
130
+ if (limit !== null)
131
+ return { ok: false, response: limit };
132
+ return { ok: true, db: resolved.db, sql: parsed.sql, params: parsed.params };
212
133
  };
213
134
  const handleQuery = async (request, env) => {
214
135
  try {
215
- const check = await readAndVerifyJson(request, env);
216
- if (!check.ok)
217
- return check.response;
218
- const db = requireDb(env);
219
- if (db instanceof Response)
220
- return db;
221
- const parsed = parseSqlPayload(check.payload);
222
- if (!parsed.ok)
223
- return parsed.response;
224
- const limit = enforceSqlLimits(env, parsed.sql, parsed.params);
225
- if (limit !== null)
226
- return limit;
227
- const result = await db
228
- .prepare(parsed.sql)
229
- .bind(...parsed.params)
136
+ const resolved = await resolveSqlRequest(request, env);
137
+ if (!resolved.ok)
138
+ return resolved.response;
139
+ const result = await resolved.db
140
+ .prepare(resolved.sql)
141
+ .bind(...resolved.params)
230
142
  .all();
231
143
  const rows = result.results ?? [];
232
144
  return json(200, { rows, rowCount: rows.length });
@@ -238,21 +150,12 @@ const handleQuery = async (request, env) => {
238
150
  };
239
151
  const handleQueryOne = async (request, env) => {
240
152
  try {
241
- const check = await readAndVerifyJson(request, env);
242
- if (!check.ok)
243
- return check.response;
244
- const db = requireDb(env);
245
- if (db instanceof Response)
246
- return db;
247
- const parsed = parseSqlPayload(check.payload);
248
- if (!parsed.ok)
249
- return parsed.response;
250
- const limit = enforceSqlLimits(env, parsed.sql, parsed.params);
251
- if (limit !== null)
252
- return limit;
253
- const row = await db
254
- .prepare(parsed.sql)
255
- .bind(...parsed.params)
153
+ const resolved = await resolveSqlRequest(request, env);
154
+ if (!resolved.ok)
155
+ return resolved.response;
156
+ const row = await resolved.db
157
+ .prepare(resolved.sql)
158
+ .bind(...resolved.params)
256
159
  .first();
257
160
  return json(200, { row: row ?? null });
258
161
  }
@@ -263,21 +166,12 @@ const handleQueryOne = async (request, env) => {
263
166
  };
264
167
  const handleExec = async (request, env) => {
265
168
  try {
266
- const check = await readAndVerifyJson(request, env);
267
- if (!check.ok)
268
- return check.response;
269
- const db = requireDb(env);
270
- if (db instanceof Response)
271
- return db;
272
- const parsed = parseSqlPayload(check.payload);
273
- if (!parsed.ok)
274
- return parsed.response;
275
- const limit = enforceSqlLimits(env, parsed.sql, parsed.params);
276
- if (limit !== null)
277
- return limit;
278
- const out = await db
279
- .prepare(parsed.sql)
280
- .bind(...parsed.params)
169
+ const resolved = await resolveSqlRequest(request, env);
170
+ if (!resolved.ok)
171
+ return resolved.response;
172
+ const out = await resolved.db
173
+ .prepare(resolved.sql)
174
+ .bind(...resolved.params)
281
175
  .run();
282
176
  return json(200, { ok: true, meta: out.meta });
283
177
  }
@@ -302,17 +196,14 @@ const parseStatementPayload = (payload) => {
302
196
  };
303
197
  const handleStatement = async (request, env) => {
304
198
  try {
305
- const check = await readAndVerifyJson(request, env);
306
- if (!check.ok)
307
- return check.response;
308
- const db = requireDb(env);
309
- if (db instanceof Response)
310
- return db;
199
+ const resolved = await resolveDbRequest(request, env);
200
+ if (!resolved.ok)
201
+ return resolved.response;
311
202
  const statements = loadStatements(env);
312
203
  if (statements === null) {
313
204
  return toErrorResponse(400, 'CONFIG_ERROR', 'Missing or invalid ZT_D1_STATEMENTS_JSON');
314
205
  }
315
- const parsed = parseStatementPayload(check.payload);
206
+ const parsed = parseStatementPayload(resolved.payload);
316
207
  if (!parsed.ok)
317
208
  return parsed.response;
318
209
  const sql = statements[parsed.statementId];
@@ -320,13 +211,13 @@ const handleStatement = async (request, env) => {
320
211
  return toErrorResponse(404, 'NOT_FOUND', 'Unknown statementId');
321
212
  }
322
213
  if (isMutatingSql(sql)) {
323
- const out = await db
214
+ const out = await resolved.db
324
215
  .prepare(sql)
325
216
  .bind(...parsed.params)
326
217
  .run();
327
218
  return json(200, { ok: true, meta: out.meta });
328
219
  }
329
- const out = await db
220
+ const out = await resolved.db
330
221
  .prepare(sql)
331
222
  .bind(...parsed.params)
332
223
  .all();
@@ -1 +1 @@
1
- {"version":3,"file":"ZintrustKvProxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/kv/ZintrustKvProxy.ts"],"names":[],"mappings":"AAKA,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAChG,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AA0WF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ZintrustKvProxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/kv/ZintrustKvProxy.ts"],"names":[],"mappings":"AAUA,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAChG,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAwOF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}