@warlock.js/core 5.35.0 → 5.37.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/esm/cli/commands/migrate.command.mjs +10 -0
  3. package/esm/cli/commands/migrate.command.mjs.map +1 -1
  4. package/esm/cli/commands/release/release-command.action.mjs +245 -0
  5. package/esm/cli/commands/release/release-command.action.mjs.map +1 -0
  6. package/esm/cli/commands/release.command.mjs +66 -0
  7. package/esm/cli/commands/release.command.mjs.map +1 -0
  8. package/esm/cli/framework-cli-commands.mjs +2 -0
  9. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  10. package/esm/database/migrate-action.mjs +24 -2
  11. package/esm/database/migrate-action.mjs.map +1 -1
  12. package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
  13. package/esm/dev-server/loader/load-hook.mjs +6 -0
  14. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  15. package/esm/dev-server/module-loader.mjs +1 -1
  16. package/esm/dev-server/parse-imports.mjs +1 -1
  17. package/esm/dev-server/type-generator.mjs +1 -1
  18. package/esm/e2e/cdp.d.mts.map +1 -1
  19. package/esm/e2e/cdp.mjs +9 -2
  20. package/esm/e2e/cdp.mjs.map +1 -1
  21. package/esm/e2e/page.d.mts +9 -1
  22. package/esm/e2e/page.d.mts.map +1 -1
  23. package/esm/e2e/page.mjs +45 -7
  24. package/esm/e2e/page.mjs.map +1 -1
  25. package/esm/e2e/types.d.mts +18 -0
  26. package/esm/e2e/types.d.mts.map +1 -1
  27. package/esm/e2e/types.mjs.map +1 -1
  28. package/esm/errors/error-codes.d.mts +24 -0
  29. package/esm/errors/error-codes.d.mts.map +1 -1
  30. package/esm/errors/error-codes.mjs +24 -0
  31. package/esm/errors/error-codes.mjs.map +1 -1
  32. package/esm/generations/features/test.feature.mjs +7 -7
  33. package/esm/generations/features/test.feature.mjs.map +1 -1
  34. package/esm/generations/features/web.feature.mjs +3 -3
  35. package/esm/generations/features/web.feature.mjs.map +1 -1
  36. package/esm/index.d.mts +6 -3
  37. package/esm/index.mjs +4 -2
  38. package/esm/localization/index.mjs +3 -1
  39. package/esm/localization/translation-usage-graph.d.mts +49 -0
  40. package/esm/localization/translation-usage-graph.d.mts.map +1 -0
  41. package/esm/localization/translation-usage-graph.mjs +128 -0
  42. package/esm/localization/translation-usage-graph.mjs.map +1 -0
  43. package/esm/localization/translation-usage.d.mts +85 -0
  44. package/esm/localization/translation-usage.d.mts.map +1 -0
  45. package/esm/localization/translation-usage.mjs +307 -0
  46. package/esm/localization/translation-usage.mjs.map +1 -0
  47. package/esm/production/build-budgets.d.mts +18 -0
  48. package/esm/production/build-budgets.d.mts.map +1 -1
  49. package/esm/production/build-budgets.mjs.map +1 -1
  50. package/esm/production/route-registration-snapshot.mjs +12 -3
  51. package/esm/production/route-registration-snapshot.mjs.map +1 -1
  52. package/esm/release/activate.mjs +261 -0
  53. package/esm/release/activate.mjs.map +1 -0
  54. package/esm/release/candidate.mjs +107 -0
  55. package/esm/release/candidate.mjs.map +1 -0
  56. package/esm/release/cascade-migration-provider.mjs +32 -0
  57. package/esm/release/cascade-migration-provider.mjs.map +1 -0
  58. package/esm/release/config.mjs +60 -0
  59. package/esm/release/config.mjs.map +1 -0
  60. package/esm/release/gate.mjs +67 -0
  61. package/esm/release/gate.mjs.map +1 -0
  62. package/esm/release/migrations-proof.mjs +100 -0
  63. package/esm/release/migrations-proof.mjs.map +1 -0
  64. package/esm/release/prune.mjs +42 -0
  65. package/esm/release/prune.mjs.map +1 -0
  66. package/esm/release/report.mjs +25 -0
  67. package/esm/release/report.mjs.map +1 -0
  68. package/esm/release/runner.mjs +55 -0
  69. package/esm/release/runner.mjs.map +1 -0
  70. package/esm/release/semver.mjs +53 -0
  71. package/esm/release/semver.mjs.map +1 -0
  72. package/esm/release/stage.mjs +122 -0
  73. package/esm/release/stage.mjs.map +1 -0
  74. package/esm/release/store.mjs +131 -0
  75. package/esm/release/store.mjs.map +1 -0
  76. package/esm/release/types.d.mts +102 -0
  77. package/esm/release/types.d.mts.map +1 -0
  78. package/esm/release/verify.mjs +94 -0
  79. package/esm/release/verify.mjs.map +1 -0
  80. package/esm/router/index.d.mts +2 -2
  81. package/esm/router/index.mjs +2 -2
  82. package/esm/router/router.d.mts +4 -0
  83. package/esm/router/router.d.mts.map +1 -1
  84. package/esm/router/router.mjs +14 -3
  85. package/esm/router/router.mjs.map +1 -1
  86. package/esm/router/types.d.mts +45 -0
  87. package/esm/router/types.d.mts.map +1 -1
  88. package/esm/router/unguarded-route-diagnostics.d.mts +6 -0
  89. package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -1
  90. package/esm/router/unguarded-route-diagnostics.mjs +10 -2
  91. package/esm/router/unguarded-route-diagnostics.mjs.map +1 -1
  92. package/esm/tooling/check/api-route-references.d.mts +16 -0
  93. package/esm/tooling/check/api-route-references.d.mts.map +1 -0
  94. package/esm/tooling/check/api-route-references.mjs +146 -0
  95. package/esm/tooling/check/api-route-references.mjs.map +1 -0
  96. package/esm/tooling/check/conventions-step.d.mts +6 -3
  97. package/esm/tooling/check/conventions-step.d.mts.map +1 -1
  98. package/esm/tooling/check/conventions-step.mjs +19 -10
  99. package/esm/tooling/check/conventions-step.mjs.map +1 -1
  100. package/esm/tooling/check/run-check.d.mts.map +1 -1
  101. package/esm/tooling/check/run-check.mjs +4 -2
  102. package/esm/tooling/check/run-check.mjs.map +1 -1
  103. package/esm/tooling/check/security-conventions.mjs +19 -1
  104. package/esm/tooling/check/security-conventions.mjs.map +1 -1
  105. package/esm/tooling/check/translation-conventions.mjs +32 -0
  106. package/esm/tooling/check/translation-conventions.mjs.map +1 -0
  107. package/esm/tooling/inspect/collect-files.mjs +1 -1
  108. package/esm/tooling/inspect/collect-routes.mjs +3 -2
  109. package/esm/tooling/inspect/collect-routes.mjs.map +1 -1
  110. package/esm/upgrade/codemods/index.mjs +2 -0
  111. package/esm/upgrade/codemods/index.mjs.map +1 -1
  112. package/esm/upgrade/codemods/vite-vitest.mjs +170 -0
  113. package/esm/upgrade/codemods/vite-vitest.mjs.map +1 -0
  114. package/esm/upgrade/notes.mjs +4 -0
  115. package/esm/upgrade/notes.mjs.map +1 -1
  116. package/esm/validation/init.mjs +11 -4
  117. package/esm/validation/init.mjs.map +1 -1
  118. package/esm/validation/translate-rule.mjs +63 -0
  119. package/esm/validation/translate-rule.mjs.map +1 -0
  120. package/esm/warlock-config/index.d.mts +3 -2
  121. package/esm/warlock-config/types.d.mts +8 -0
  122. package/esm/warlock-config/types.d.mts.map +1 -1
  123. package/llms-full.txt +221 -18
  124. package/llms.txt +1 -0
  125. package/package.json +13 -13
  126. package/skills/deploy-release/SKILL.md +76 -0
  127. package/skills/index.md +1 -1
  128. package/skills/register-route/SKILL.md +25 -0
  129. package/skills/test-service/SKILL.md +8 -8
  130. package/skills/upgrade-from-5-29/SKILL.md +91 -0
  131. package/skills/use-localization/SKILL.md +4 -0
  132. package/skills/warlock-check/SKILL.md +11 -8
  133. package/skills/warlock-conventions/SKILL.md +1 -1
package/esm/index.mjs CHANGED
@@ -73,7 +73,7 @@ import "./image/index.mjs";
73
73
  import { UploadedFile } from "./http/uploaded-file.mjs";
74
74
  import { URL_CREDENTIAL_PARAMS, buildRequestLogSnapshot, redactQueryCredentials, redactUrlCredentials, resolveRequestLoggingOptions } from "./http/request-log-snapshot.mjs";
75
75
  import { Request } from "./http/request.mjs";
76
- import { AUTH_GUARD_MARKER, isAuthGuardMiddleware, isUnguardedMutatingRoute, markAuthGuard, reportUnguardedMutatingRoutes, resetUnguardedRouteReports } from "./router/unguarded-route-diagnostics.mjs";
76
+ import { AUTH_GUARD_MARKER, isAuthGuardMiddleware, isRequiredGuardRoute, isUnguardedMutatingRoute, markAuthGuard, reportUnguardedMutatingRoutes, resetUnguardedRouteReports } from "./router/unguarded-route-diagnostics.mjs";
77
77
  import { Router, router } from "./router/router.mjs";
78
78
  import "./router/index.mjs";
79
79
  import { registerHttpPlugins, resolvePublicRoot } from "./http/plugins.mjs";
@@ -169,6 +169,8 @@ import "./secrets/index.mjs";
169
169
  import { ERROR_CODES, ERROR_CODES_DOCS_URL, errorCodeDocsUrl, errorCodeOf, explainErrorCode, isWarlockErrorCode } from "./errors/error-codes.mjs";
170
170
  import { LocaleDictionaryError, parseLocaleDictionary } from "./localization/parse-locale-dictionary.mjs";
171
171
  import { registerGroupedTranslationKeys, registerLocaleDictionary, unregisterLocaleDictionary } from "./localization/register-locale-dictionary.mjs";
172
+ import { EMPTY_TRANSLATION_USAGE, isTranslationKeyUsed, mergeTranslationUsage, readTranslationDeclarations, scanTranslationSource, translationDeclarationUsage, usageOf } from "./localization/translation-usage.mjs";
173
+ import { analyzePageTranslationUsage, analyzeTranslationGraph, readSourceFile, resolveSourceImport } from "./localization/translation-usage-graph.mjs";
172
174
  import "./localization/index.mjs";
173
175
  import { exampleFromSchema } from "./openapi/postman/example-from-schema.mjs";
174
176
  import { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection } from "./openapi/postman/openapi-to-postman-collection.mjs";
@@ -204,4 +206,4 @@ import { colors } from "@mongez/copper";
204
206
 
205
207
  export * from "@mongez/localization"
206
208
 
207
- export { $registerUseCase, $unregisterUseCase, APP_ROLES, AUTH_GUARD_MARKER, AccessConnector, AiConnector, AppError, Application, BOOT_SIGNAL_ENV_KEY, BOOT_SIGNAL_VERSION, BadRequestError, BadSchemaUseCaseError, BaseConnector, BenchmarkProfiler, BenchmarkSnapshots, CLICommand, CacheConnector, CascadeAdapter, CascadeQueryBuilder, CloudDriver, ConfigSpecialHandlers, ConflictError, ConnectorLifecyclePhase, ConnectorPriority, ConnectorsManager, ConsoleChannel, CookieJarUnavailableError, DEFAULT_CSP_DIRECTIVES, DEFAULT_POSTMAN_BASE_URL, DOSpacesDriver, DatabaseCacheDriver, DatabaseConnector, DatabaseLog, DatabaseLogModel, ERROR_CODES, ERROR_CODES_DOCS_URL, FileValidator, ForbiddenError, HeraldConnector, HttpConnector, HttpError, HttpErrorCodes, Image, ImageVariantsConfigError, InvalidConfigError, InvalidCspDirectiveError, LocalDriver, LocaleDictionaryError, LoggerConnector, MAIL_EVENTS, Mail, MailError, MailerConnector, MemorySecretBackend, MimeTypes, NULLABLE_RESOURCE, NoopChannel, NotAcceptableError, NotAllowedError, NotificationsConnector, OPENAPI_JSON_SCHEMA_DIALECT, POSTMAN_COLLECTION_SCHEMA, Path, PortInUseError, Queue, R2Driver, RegisterResource, RepositoryManager, Request, RequestController, RequestLog, Resource, ResourceFieldBuilder, ResourceNotFoundError, Response, ResponseStatus, Restful, RouteNameTakenError, RouteRegistry, Router, S3Driver, SUPPORTED_RUNTIMES_DOCS_URL, ScopedStorage, SecretStore, SecretStoreError, SeederDependencyCycleError, ServerError, SocketConnector, Storage, StorageCapabilityError, StorageConnector, StorageError, StorageFile, StorageNotInitializedError, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, URL_CREDENTIAL_PARAMS, UnAuthorizedError, UnknownSeederDependencyError, UploadedFile, WarlockConfigManager, WarlockError, addUseCaseHistory, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertNodeOnlyCommand, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assertValidConfigModules, assetsUrl, beginHttpDrain, bootstrap, broadcastSocketEvent, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildOpenApiDocument, buildRequestLogSnapshot, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, clock, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, createUploadedFileController, decrypt, defaultHttpConfigurations, defineConfig, defineConfigSchema, defineResource, deriveTraceId, describeJavaScriptRuntime, describePositionalHandlerSuspect, detectJavaScriptRuntime, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, errorCodeDocsUrl, errorCodeOf, escapeHeaderValue, evaluateConditionalRequest, exampleFromSchema, existsExceptCurrentIdRule, existsExceptCurrentUserRule, explainErrorCode, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, formatConfigIssues, generateImageVariants, generateMailId, getDefaultMailConfig, getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, getExplicitMailMode, getHttpReadyReport, getHttpServer, getLastMail, getLocalized, getMailEventName, getMailMode, getMailboxSize, getMailer, getMailerConfig, getMimeType, getPoolStats, getPublicUrl, getRoles, getSites, getSocketServer, getTestMailbox, getUseCase, getUseCaseHistory, getUseCases, globalEventsCallbacksMap, globalUseCasesEvents, hasRole, hashBody, hashPassword, health, hmacHash, httpConfig, ids, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isAuthGuardMiddleware, isBootSignal, isConfigSchema, isDevelopmentMode, isNewerVersion, isNullableResource, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isSafeRedirect, isTestMode, isTracingEnabled, isUnguardedMutatingRoute, isUnknownTsExtensionError, isUnresolvedConfigImportError, isUnsupportedTypeStrippingError, isValidIdempotencyKey, isWarlockErrorCode, listEndpoint, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, markAuthGuard, matchesDerivedRouteName, matchesIfMatch, matchesIfNoneMatch, measure, mergeCspDirectives, middleware, nodeOnlyCommandError, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, nullable, onHttpServerRebuilt, openApiToPostmanCollection, originOf, ownOrigin, parseEntityTag, parseEntityTagList, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, purgeImageVariants, redactQueryCredentials, redactUrlCredentials, registerAppConfig, registerConfiguredConnectors, registerDevelopmentOpenApiProvider, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, reportUnguardedMutatingRoutes, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetMailMode, resetRolesCacheForTests, resetTracingConfigForTests, resetUnguardedRouteReports, resolveCspConfig, resolveCsrfOriginVerdict, resolveImageVariant, resolveMailConfig, resolvePublicRoot, resolveRequestLoggingOptions, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, safeRedirect, sanitizePath, secrets, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setClockSource, setConfig, setEnvironment, setHttpReadyReport, setIdsSource, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, strongEntityTagMatch, t, tempPath, toJson, toSingleLineSseField, trackConnectionsForDrain, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, unverifiedBuildRuntimeNotice, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateConfigValue, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, weakEntityTagMatch, wrapResponseInDataKey };
209
+ export { $registerUseCase, $unregisterUseCase, APP_ROLES, AUTH_GUARD_MARKER, AccessConnector, AiConnector, AppError, Application, BOOT_SIGNAL_ENV_KEY, BOOT_SIGNAL_VERSION, BadRequestError, BadSchemaUseCaseError, BaseConnector, BenchmarkProfiler, BenchmarkSnapshots, CLICommand, CacheConnector, CascadeAdapter, CascadeQueryBuilder, CloudDriver, ConfigSpecialHandlers, ConflictError, ConnectorLifecyclePhase, ConnectorPriority, ConnectorsManager, ConsoleChannel, CookieJarUnavailableError, DEFAULT_CSP_DIRECTIVES, DEFAULT_POSTMAN_BASE_URL, DOSpacesDriver, DatabaseCacheDriver, DatabaseConnector, DatabaseLog, DatabaseLogModel, EMPTY_TRANSLATION_USAGE, ERROR_CODES, ERROR_CODES_DOCS_URL, FileValidator, ForbiddenError, HeraldConnector, HttpConnector, HttpError, HttpErrorCodes, Image, ImageVariantsConfigError, InvalidConfigError, InvalidCspDirectiveError, LocalDriver, LocaleDictionaryError, LoggerConnector, MAIL_EVENTS, Mail, MailError, MailerConnector, MemorySecretBackend, MimeTypes, NULLABLE_RESOURCE, NoopChannel, NotAcceptableError, NotAllowedError, NotificationsConnector, OPENAPI_JSON_SCHEMA_DIALECT, POSTMAN_COLLECTION_SCHEMA, Path, PortInUseError, Queue, R2Driver, RegisterResource, RepositoryManager, Request, RequestController, RequestLog, Resource, ResourceFieldBuilder, ResourceNotFoundError, Response, ResponseStatus, Restful, RouteNameTakenError, RouteRegistry, Router, S3Driver, SUPPORTED_RUNTIMES_DOCS_URL, ScopedStorage, SecretStore, SecretStoreError, SeederDependencyCycleError, ServerError, SocketConnector, Storage, StorageCapabilityError, StorageConnector, StorageError, StorageFile, StorageNotInitializedError, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, URL_CREDENTIAL_PARAMS, UnAuthorizedError, UnknownSeederDependencyError, UploadedFile, WarlockConfigManager, WarlockError, addUseCaseHistory, analyzePageTranslationUsage, analyzeTranslationGraph, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertNodeOnlyCommand, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assertValidConfigModules, assetsUrl, beginHttpDrain, bootstrap, broadcastSocketEvent, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildOpenApiDocument, buildRequestLogSnapshot, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, clock, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, createUploadedFileController, decrypt, defaultHttpConfigurations, defineConfig, defineConfigSchema, defineResource, deriveTraceId, describeJavaScriptRuntime, describePositionalHandlerSuspect, detectJavaScriptRuntime, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, errorCodeDocsUrl, errorCodeOf, escapeHeaderValue, evaluateConditionalRequest, exampleFromSchema, existsExceptCurrentIdRule, existsExceptCurrentUserRule, explainErrorCode, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, formatConfigIssues, generateImageVariants, generateMailId, getDefaultMailConfig, getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, getExplicitMailMode, getHttpReadyReport, getHttpServer, getLastMail, getLocalized, getMailEventName, getMailMode, getMailboxSize, getMailer, getMailerConfig, getMimeType, getPoolStats, getPublicUrl, getRoles, getSites, getSocketServer, getTestMailbox, getUseCase, getUseCaseHistory, getUseCases, globalEventsCallbacksMap, globalUseCasesEvents, hasRole, hashBody, hashPassword, health, hmacHash, httpConfig, ids, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isAuthGuardMiddleware, isBootSignal, isConfigSchema, isDevelopmentMode, isNewerVersion, isNullableResource, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isRequiredGuardRoute, isSafeRedirect, isTestMode, isTracingEnabled, isTranslationKeyUsed, isUnguardedMutatingRoute, isUnknownTsExtensionError, isUnresolvedConfigImportError, isUnsupportedTypeStrippingError, isValidIdempotencyKey, isWarlockErrorCode, listEndpoint, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, markAuthGuard, matchesDerivedRouteName, matchesIfMatch, matchesIfNoneMatch, measure, mergeCspDirectives, mergeTranslationUsage, middleware, nodeOnlyCommandError, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, nullable, onHttpServerRebuilt, openApiToPostmanCollection, originOf, ownOrigin, parseEntityTag, parseEntityTagList, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, purgeImageVariants, readSourceFile, readTranslationDeclarations, redactQueryCredentials, redactUrlCredentials, registerAppConfig, registerConfiguredConnectors, registerDevelopmentOpenApiProvider, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, reportUnguardedMutatingRoutes, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetMailMode, resetRolesCacheForTests, resetTracingConfigForTests, resetUnguardedRouteReports, resolveCspConfig, resolveCsrfOriginVerdict, resolveImageVariant, resolveMailConfig, resolvePublicRoot, resolveRequestLoggingOptions, resolveSourceImport, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, safeRedirect, sanitizePath, scanTranslationSource, secrets, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setClockSource, setConfig, setEnvironment, setHttpReadyReport, setIdsSource, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, strongEntityTagMatch, t, tempPath, toJson, toSingleLineSseField, trackConnectionsForDrain, translationDeclarationUsage, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, unverifiedBuildRuntimeNotice, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, usageOf, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateConfigValue, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, weakEntityTagMatch, wrapResponseInDataKey };
@@ -1,4 +1,6 @@
1
1
  import { LocaleDictionaryError, parseLocaleDictionary } from "./parse-locale-dictionary.mjs";
2
2
  import { registerGroupedTranslationKeys, registerLocaleDictionary, unregisterLocaleDictionary } from "./register-locale-dictionary.mjs";
3
+ import { EMPTY_TRANSLATION_USAGE, isTranslationKeyUsed, mergeTranslationUsage, readTranslationDeclarations, scanTranslationSource, translationDeclarationUsage, usageOf } from "./translation-usage.mjs";
4
+ import { analyzePageTranslationUsage, analyzeTranslationGraph, readSourceFile, resolveSourceImport } from "./translation-usage-graph.mjs";
3
5
 
4
- export { LocaleDictionaryError, parseLocaleDictionary, registerGroupedTranslationKeys, registerLocaleDictionary, unregisterLocaleDictionary };
6
+ export { EMPTY_TRANSLATION_USAGE, LocaleDictionaryError, analyzePageTranslationUsage, analyzeTranslationGraph, isTranslationKeyUsed, mergeTranslationUsage, parseLocaleDictionary, readSourceFile, readTranslationDeclarations, registerGroupedTranslationKeys, registerLocaleDictionary, resolveSourceImport, scanTranslationSource, translationDeclarationUsage, unregisterLocaleDictionary, usageOf };
@@ -0,0 +1,49 @@
1
+ import { TranslationUsage } from "./translation-usage.mjs";
2
+ //#region ../../packages/core/src/localization/translation-usage-graph.d.ts
3
+ export type TranslationGraphInput = {
4
+ /** The client entry files a render can execute: the page, its layouts, the root and error pages. */
5
+ readonly entries: readonly string[];
6
+ /** Setup files whose `config.translations` declare keys static analysis cannot see. */
7
+ readonly setupFiles?: readonly string[];
8
+ /** Source text of a file, or `undefined` when it cannot be read. */
9
+ readonly readSource: (file: string) => string | undefined;
10
+ /** Resolves a specifier imported by `importer` to a project file, or `undefined` for a package. */
11
+ readonly resolveImport: (specifier: string, importer: string) => string | undefined;
12
+ };
13
+ export type TranslationGraphResult = {
14
+ /** The union of every reachable file's usage and the declared keys. */
15
+ readonly usage: TranslationUsage;
16
+ /** Every project file the walk read, so a caller can tell when the answer may have changed. */
17
+ readonly files: readonly string[];
18
+ };
19
+ /**
20
+ * Walk the client module graph from `entries` and union what every reachable
21
+ * file can look up.
22
+ *
23
+ * The walk follows value imports, re-exports and dynamic `import()` into
24
+ * project files only. A package is not followed: packages do not carry
25
+ * application translation keys. Fail closed: a reachable file that cannot be
26
+ * read or parsed makes the whole graph dynamic, so the caller ships everything
27
+ * rather than a set that might be missing a key.
28
+ */
29
+ export declare function analyzeTranslationGraph(input: TranslationGraphInput): TranslationGraphResult;
30
+ /**
31
+ * Resolve a specifier for the translation graph: relative paths, and the
32
+ * `web/` and `app/` conventions under the source root. Anything else is a
33
+ * package and resolves to `undefined`.
34
+ */
35
+ export declare function resolveSourceImport(specifier: string, importer: string, appSrcRoot: string): string | undefined;
36
+ /** Read a file as UTF-8, or `undefined` when it is missing or unreadable. */
37
+ export declare function readSourceFile(file: string): string | undefined;
38
+ /**
39
+ * Analyze a page's client graph against the filesystem: the convenience the
40
+ * build and the development server both use. `appSrcRoot` is the application's
41
+ * `src` directory, which the `web/` and `app/` specifiers resolve against.
42
+ */
43
+ export declare function analyzePageTranslationUsage(input: {
44
+ readonly appSrcRoot: string;
45
+ readonly entries: readonly string[];
46
+ readonly setupFiles?: readonly string[];
47
+ }): TranslationGraphResult;
48
+ //#endregion
49
+ //# sourceMappingURL=translation-usage-graph.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-usage-graph.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/localization/translation-usage-graph.ts"],"mappings":";;YAkBY;;WAED;;WAEA;;WAEA,aAAa;;WAEb,gBAAgB,mBAAmB;;YAGlC;;WAED,OAAO;;WAEP;;;;;;;;;;;;wBAaK,wBAAwB,OAAO,wBAAwB;;;;;;wBAqEvD,oBACd,mBACA,kBACA;;wBAiCc,eAAe;;;;;;wBAaf,4BAA4B;WACjC;WACA;WACA;IACP"}
@@ -0,0 +1,128 @@
1
+ import { EMPTY_TRANSLATION_USAGE, mergeTranslationUsage, readTranslationDeclarations, scanTranslationSource, translationDeclarationUsage, usageOf } from "./translation-usage.mjs";
2
+ import path from "node:path";
3
+ import fsSync from "node:fs";
4
+
5
+ //#region ../../packages/core/src/localization/translation-usage-graph.ts
6
+ /** Source files the walk reads. */
7
+ const CODE_FILE = /\.[cm]?[jt]sx?$/;
8
+ /** Extensions tried, in order, for an extension-less specifier. */
9
+ const SOURCE_EXTENSIONS = [
10
+ ".ts",
11
+ ".tsx",
12
+ ".mts",
13
+ ".js",
14
+ ".jsx",
15
+ ".mjs"
16
+ ];
17
+ /**
18
+ * Walk the client module graph from `entries` and union what every reachable
19
+ * file can look up.
20
+ *
21
+ * The walk follows value imports, re-exports and dynamic `import()` into
22
+ * project files only. A package is not followed: packages do not carry
23
+ * application translation keys. Fail closed: a reachable file that cannot be
24
+ * read or parsed makes the whole graph dynamic, so the caller ships everything
25
+ * rather than a set that might be missing a key.
26
+ */
27
+ function analyzeTranslationGraph(input) {
28
+ const seen = /* @__PURE__ */ new Set();
29
+ const files = [];
30
+ const usages = [];
31
+ const queue = [...input.entries];
32
+ for (const setupFile of input.setupFiles ?? []) {
33
+ files.push(setupFile);
34
+ usages.push(readDeclarations(input, setupFile));
35
+ }
36
+ for (let file = queue.pop(); file !== void 0; file = queue.pop()) {
37
+ if (seen.has(file)) continue;
38
+ seen.add(file);
39
+ files.push(file);
40
+ const text = input.readSource(file);
41
+ if (text === void 0) {
42
+ usages.push(unreadable(file, "the file could not be read"));
43
+ continue;
44
+ }
45
+ try {
46
+ const scan = scanTranslationSource(file, text);
47
+ usages.push(scan.usage);
48
+ for (const specifier of scan.imports) {
49
+ const resolved = input.resolveImport(specifier, file);
50
+ if (resolved !== void 0 && !seen.has(resolved)) queue.push(resolved);
51
+ }
52
+ } catch (error) {
53
+ usages.push(unreadable(file, `the file could not be parsed (${error instanceof Error ? error.message : String(error)})`));
54
+ }
55
+ }
56
+ return {
57
+ usage: mergeTranslationUsage(usages),
58
+ files
59
+ };
60
+ }
61
+ function readDeclarations(input, setupFile) {
62
+ const text = input.readSource(setupFile);
63
+ if (text === void 0) return unreadable(setupFile, "the setup file could not be read");
64
+ const entries = readTranslationDeclarations(setupFile, text);
65
+ if (entries === void 0) return EMPTY_TRANSLATION_USAGE;
66
+ return mergeTranslationUsage(entries.map((entry) => translationDeclarationUsage(entry, setupFile)));
67
+ }
68
+ /** A dynamic usage that names the file which forced it. */
69
+ function unreadable(file, reason) {
70
+ return usageOf({
71
+ dynamic: true,
72
+ dynamicSites: [{
73
+ file,
74
+ line: 1,
75
+ column: 1,
76
+ text: `<${reason}>`
77
+ }]
78
+ });
79
+ }
80
+ /**
81
+ * Resolve a specifier for the translation graph: relative paths, and the
82
+ * `web/` and `app/` conventions under the source root. Anything else is a
83
+ * package and resolves to `undefined`.
84
+ */
85
+ function resolveSourceImport(specifier, importer, appSrcRoot) {
86
+ let base;
87
+ if (specifier.startsWith(".")) base = path.resolve(path.dirname(importer), specifier);
88
+ else if (specifier.startsWith("web/") || specifier.startsWith("app/")) base = path.join(appSrcRoot, specifier);
89
+ else return;
90
+ const candidates = [
91
+ base,
92
+ ...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`),
93
+ ...SOURCE_EXTENSIONS.map((extension) => path.join(base, `index${extension}`))
94
+ ];
95
+ if (/\.jsx?$/.test(base)) {
96
+ const stripped = base.replace(/\.jsx?$/, "");
97
+ candidates.push(...SOURCE_EXTENSIONS.map((extension) => `${stripped}${extension}`));
98
+ }
99
+ return candidates.find((candidate) => CODE_FILE.test(candidate) && isFile(candidate));
100
+ }
101
+ function isFile(candidate) {
102
+ return fsSync.statSync(candidate, { throwIfNoEntry: false })?.isFile() === true;
103
+ }
104
+ /** Read a file as UTF-8, or `undefined` when it is missing or unreadable. */
105
+ function readSourceFile(file) {
106
+ try {
107
+ return fsSync.readFileSync(file, "utf8");
108
+ } catch {
109
+ return;
110
+ }
111
+ }
112
+ /**
113
+ * Analyze a page's client graph against the filesystem: the convenience the
114
+ * build and the development server both use. `appSrcRoot` is the application's
115
+ * `src` directory, which the `web/` and `app/` specifiers resolve against.
116
+ */
117
+ function analyzePageTranslationUsage(input) {
118
+ return analyzeTranslationGraph({
119
+ entries: input.entries,
120
+ setupFiles: input.setupFiles,
121
+ readSource: readSourceFile,
122
+ resolveImport: (specifier, importer) => resolveSourceImport(specifier, importer, input.appSrcRoot)
123
+ });
124
+ }
125
+
126
+ //#endregion
127
+ export { analyzePageTranslationUsage, analyzeTranslationGraph, readSourceFile, resolveSourceImport };
128
+ //# sourceMappingURL=translation-usage-graph.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-usage-graph.mjs","names":["fs"],"sources":["../../../../../../../../packages/core/src/localization/translation-usage-graph.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n EMPTY_TRANSLATION_USAGE,\n mergeTranslationUsage,\n readTranslationDeclarations,\n scanTranslationSource,\n translationDeclarationUsage,\n usageOf,\n type TranslationUsage,\n} from \"./translation-usage\";\n\n/** Source files the walk reads. */\nconst CODE_FILE = /\\.[cm]?[jt]sx?$/;\n\n/** Extensions tried, in order, for an extension-less specifier. */\nconst SOURCE_EXTENSIONS = [\".ts\", \".tsx\", \".mts\", \".js\", \".jsx\", \".mjs\"];\n\nexport type TranslationGraphInput = {\n /** The client entry files a render can execute: the page, its layouts, the root and error pages. */\n readonly entries: readonly string[];\n /** Setup files whose `config.translations` declare keys static analysis cannot see. */\n readonly setupFiles?: readonly string[];\n /** Source text of a file, or `undefined` when it cannot be read. */\n readonly readSource: (file: string) => string | undefined;\n /** Resolves a specifier imported by `importer` to a project file, or `undefined` for a package. */\n readonly resolveImport: (specifier: string, importer: string) => string | undefined;\n};\n\nexport type TranslationGraphResult = {\n /** The union of every reachable file's usage and the declared keys. */\n readonly usage: TranslationUsage;\n /** Every project file the walk read, so a caller can tell when the answer may have changed. */\n readonly files: readonly string[];\n};\n\n/**\n * Walk the client module graph from `entries` and union what every reachable\n * file can look up.\n *\n * The walk follows value imports, re-exports and dynamic `import()` into\n * project files only. A package is not followed: packages do not carry\n * application translation keys. Fail closed: a reachable file that cannot be\n * read or parsed makes the whole graph dynamic, so the caller ships everything\n * rather than a set that might be missing a key.\n */\nexport function analyzeTranslationGraph(input: TranslationGraphInput): TranslationGraphResult {\n const seen = new Set<string>();\n const files: string[] = [];\n const usages: TranslationUsage[] = [];\n const queue = [...input.entries];\n\n for (const setupFile of input.setupFiles ?? []) {\n files.push(setupFile);\n usages.push(readDeclarations(input, setupFile));\n }\n\n for (let file = queue.pop(); file !== undefined; file = queue.pop()) {\n if (seen.has(file)) continue;\n seen.add(file);\n files.push(file);\n\n const text = input.readSource(file);\n\n if (text === undefined) {\n usages.push(unreadable(file, \"the file could not be read\"));\n continue;\n }\n\n try {\n const scan = scanTranslationSource(file, text);\n usages.push(scan.usage);\n\n for (const specifier of scan.imports) {\n const resolved = input.resolveImport(specifier, file);\n if (resolved !== undefined && !seen.has(resolved)) queue.push(resolved);\n }\n } catch (error) {\n usages.push(\n unreadable(\n file,\n `the file could not be parsed (${error instanceof Error ? error.message : String(error)})`,\n ),\n );\n }\n }\n\n return { usage: mergeTranslationUsage(usages), files };\n}\n\nfunction readDeclarations(input: TranslationGraphInput, setupFile: string): TranslationUsage {\n const text = input.readSource(setupFile);\n if (text === undefined) return unreadable(setupFile, \"the setup file could not be read\");\n\n const entries = readTranslationDeclarations(setupFile, text);\n if (entries === undefined) return EMPTY_TRANSLATION_USAGE;\n\n return mergeTranslationUsage(\n entries.map((entry) => translationDeclarationUsage(entry, setupFile)),\n );\n}\n\n/** A dynamic usage that names the file which forced it. */\nfunction unreadable(file: string, reason: string): TranslationUsage {\n return usageOf({\n dynamic: true,\n dynamicSites: [{ file, line: 1, column: 1, text: `<${reason}>` }],\n });\n}\n\n/**\n * Resolve a specifier for the translation graph: relative paths, and the\n * `web/` and `app/` conventions under the source root. Anything else is a\n * package and resolves to `undefined`.\n */\nexport function resolveSourceImport(\n specifier: string,\n importer: string,\n appSrcRoot: string,\n): string | undefined {\n let base: string;\n\n if (specifier.startsWith(\".\")) {\n base = path.resolve(path.dirname(importer), specifier);\n } else if (specifier.startsWith(\"web/\") || specifier.startsWith(\"app/\")) {\n base = path.join(appSrcRoot, specifier);\n } else {\n return undefined;\n }\n\n const candidates = [\n base,\n ...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`),\n ...SOURCE_EXTENSIONS.map((extension) => path.join(base, `index${extension}`)),\n ];\n\n // TypeScript sources imported with their emitted `.js` extension.\n if (/\\.jsx?$/.test(base)) {\n const stripped = base.replace(/\\.jsx?$/, \"\");\n candidates.push(...SOURCE_EXTENSIONS.map((extension) => `${stripped}${extension}`));\n }\n\n // Only code is walked: a JSON, CSS or asset import carries no translation lookup.\n return candidates.find((candidate) => CODE_FILE.test(candidate) && isFile(candidate));\n}\n\nfunction isFile(candidate: string): boolean {\n return fs.statSync(candidate, { throwIfNoEntry: false })?.isFile() === true;\n}\n\n/** Read a file as UTF-8, or `undefined` when it is missing or unreadable. */\nexport function readSourceFile(file: string): string | undefined {\n try {\n return fs.readFileSync(file, \"utf8\");\n } catch {\n return undefined;\n }\n}\n\n/**\n * Analyze a page's client graph against the filesystem: the convenience the\n * build and the development server both use. `appSrcRoot` is the application's\n * `src` directory, which the `web/` and `app/` specifiers resolve against.\n */\nexport function analyzePageTranslationUsage(input: {\n readonly appSrcRoot: string;\n readonly entries: readonly string[];\n readonly setupFiles?: readonly string[];\n}): TranslationGraphResult {\n return analyzeTranslationGraph({\n entries: input.entries,\n setupFiles: input.setupFiles,\n readSource: readSourceFile,\n resolveImport: (specifier, importer) =>\n resolveSourceImport(specifier, importer, input.appSrcRoot),\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ //#region ../../packages/core/src/localization/translation-usage.d.ts
2
+ /**
3
+ * What one page (or one module) can look up in the translation table, derived
4
+ * from static source. Consumers decide what to ship; this type only says which
5
+ * keys a client render may ask for.
6
+ *
7
+ * - `keys` are exact keys. A key also delivers its whole subtree, so a declared
8
+ * group (`"members"`) and a literal leaf (`"members.title"`) use one matching
9
+ * rule.
10
+ * - `prefixes` come from template keys with a static prefix
11
+ * (`` trans(`statuses.${status}`) `` gives `"statuses."`). Every key that
12
+ * starts with one is reachable.
13
+ * - `dynamic` is set when a lookup key cannot be known before render. The
14
+ * consumer must then assume every key is reachable.
15
+ */
16
+ export type TranslationUsage = {
17
+ readonly keys: readonly string[];
18
+ readonly prefixes: readonly string[];
19
+ /**
20
+ * Key-shaped string literals written anywhere in the walked modules, outside
21
+ * a recognized lookup (a helper's argument, a constant, an object that maps to
22
+ * keys, a prop). A literal counts as used when it equals an existing key,
23
+ * names a group or subtree, or is the base of plural variants
24
+ * (`"cart.items"` reaches `"cart.items_one"` and `"cart.items_other"`).
25
+ */
26
+ readonly literals: readonly string[];
27
+ /** The static heads of template literals with substitutions, which reach every key that starts with one. */
28
+ readonly literalPrefixes: readonly string[];
29
+ readonly dynamic: boolean;
30
+ /** Where each unresolvable lookup was written, for diagnostics. */
31
+ readonly dynamicSites: readonly TranslationDynamicSite[];
32
+ };
33
+ export type TranslationDynamicSite = {
34
+ readonly file: string;
35
+ readonly line: number;
36
+ readonly column: number;
37
+ /** The source text of the lookup's key argument, as written. */
38
+ readonly text: string;
39
+ };
40
+ /** What one source file contributes: its own usage plus the modules it loads at run time. */
41
+ export type TranslationSourceScan = {
42
+ readonly usage: TranslationUsage;
43
+ /** Specifiers of value imports, re-exports and dynamic `import()` calls. */
44
+ readonly imports: readonly string[];
45
+ };
46
+ /** Build a usage value from parts, deduplicated and frozen. */
47
+ export declare function usageOf(parts: {
48
+ readonly keys?: readonly string[];
49
+ readonly prefixes?: readonly string[];
50
+ readonly literals?: readonly string[];
51
+ readonly literalPrefixes?: readonly string[];
52
+ readonly dynamic?: boolean;
53
+ readonly dynamicSites?: readonly TranslationDynamicSite[];
54
+ }): TranslationUsage;
55
+ export declare const EMPTY_TRANSLATION_USAGE: TranslationUsage;
56
+ /**
57
+ * Turn one `config.translations` entry into the usage it declares.
58
+ *
59
+ * `"statuses.*"` declares every key under `statuses.`, `"members"` declares a
60
+ * key and its subtree, and `"*"` declares everything. A wildcard anywhere but
61
+ * the final `.*`, or an empty entry, is refused rather than guessed at.
62
+ */
63
+ export declare function translationDeclarationUsage(entry: string, file: string): TranslationUsage;
64
+ /** The union of several usages: a dynamic lookup anywhere makes the union dynamic. */
65
+ export declare function mergeTranslationUsage(usages: readonly TranslationUsage[]): TranslationUsage;
66
+ /** Whether a usage can reach `key`. A dynamic usage reaches every key. */
67
+ export declare function isTranslationKeyUsed(usage: TranslationUsage, key: string): boolean;
68
+ /**
69
+ * Scan one source file for translation lookups and the modules it loads.
70
+ *
71
+ * Literal keys, static-prefix templates, identifiers bound to a module-level
72
+ * string constant, and choices between those (`a ? "x" : "y"`) all resolve. Any
73
+ * other key expression is `dynamic`, and so is a translator that escapes as a
74
+ * value (passed on, returned, stored): whoever receives it can call it with any
75
+ * key.
76
+ */
77
+ export declare function scanTranslationSource(fileName: string, text: string): TranslationSourceScan;
78
+ /**
79
+ * The `config.translations` declaration of a page's setup file, as its raw
80
+ * entries. Read statically, like `config.route`, so the build never runs the
81
+ * file. `undefined` when the file declares none.
82
+ */
83
+ export declare function readTranslationDeclarations(fileName: string, text: string): readonly string[] | undefined;
84
+ //#endregion
85
+ //# sourceMappingURL=translation-usage.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-usage.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/localization/translation-usage.ts"],"mappings":";;;;;;;;;;;;;;;YAgBY;WACD;WACA;;;;;;;;WAQA;;WAEA;WACA;;WAEA,uBAAuB;;YAGtB;WACD;WACA;WACA;;WAEA;;;YAIC;WACD,OAAO;;WAEP;;;wBA+BK,QAAQ;WACb;WACA;WACA;WACA;WACA;WACA,wBAAwB;IAC/B;qBAWS,yBAAyB;;;;;;;;wBAStB,4BAA4B,eAAe,eAAe;;wBAsB1D,sBAAsB,iBAAiB,qBAAqB;;wBA2B5D,qBAAqB,OAAO,kBAAkB;;;;;;;;;;wBAsK9C,sBAAsB,kBAAkB,eAAe;;;;;;wBAwIvD,4BACd,kBACA"}