@warlock.js/core 5.26.0 → 5.28.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 (129) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/esm/cli/commands/openapi-generator.action.mjs +43 -0
  3. package/esm/cli/commands/openapi-generator.action.mjs.map +1 -0
  4. package/esm/cli/commands/openapi-generator.command.mjs +44 -0
  5. package/esm/cli/commands/openapi-generator.command.mjs.map +1 -0
  6. package/esm/cli/commands/postman-generator.action.mjs +47 -0
  7. package/esm/cli/commands/postman-generator.action.mjs.map +1 -0
  8. package/esm/cli/commands/postman-generator.command.mjs +43 -0
  9. package/esm/cli/commands/postman-generator.command.mjs.map +1 -0
  10. package/esm/cli/framework-cli-commands.mjs +4 -0
  11. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  12. package/esm/dev-server/build-development-openapi-document.mjs +36 -0
  13. package/esm/dev-server/build-development-openapi-document.mjs.map +1 -0
  14. package/esm/dev-server/collect-development-api-routes.mjs +27 -0
  15. package/esm/dev-server/collect-development-api-routes.mjs.map +1 -0
  16. package/esm/dev-server/dev-logger.mjs +9 -1
  17. package/esm/dev-server/dev-logger.mjs.map +1 -1
  18. package/esm/dev-server/development-server.mjs +6 -3
  19. package/esm/dev-server/development-server.mjs.map +1 -1
  20. package/esm/dev-server/files-orchestrator.mjs +17 -1
  21. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  22. package/esm/dev-server/model-resource-typings.mjs +246 -0
  23. package/esm/dev-server/model-resource-typings.mjs.map +1 -0
  24. package/esm/dev-server/type-generator.mjs +46 -2
  25. package/esm/dev-server/type-generator.mjs.map +1 -1
  26. package/esm/http/index.d.mts +2 -1
  27. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  28. package/esm/http/middleware/inject-request-context.mjs +29 -3
  29. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  30. package/esm/http/serialized.d.mts +114 -0
  31. package/esm/http/serialized.d.mts.map +1 -0
  32. package/esm/index.d.mts +11 -3
  33. package/esm/index.mjs +6 -1
  34. package/esm/openapi/build-openapi-document.d.mts +17 -0
  35. package/esm/openapi/build-openapi-document.d.mts.map +1 -0
  36. package/esm/openapi/build-openapi-document.mjs +124 -0
  37. package/esm/openapi/build-openapi-document.mjs.map +1 -0
  38. package/esm/openapi/cast-schema.mjs +89 -0
  39. package/esm/openapi/cast-schema.mjs.map +1 -0
  40. package/esm/openapi/collect-openapi-document.mjs +40 -0
  41. package/esm/openapi/collect-openapi-document.mjs.map +1 -0
  42. package/esm/openapi/development-openapi-provider.d.mts +28 -0
  43. package/esm/openapi/development-openapi-provider.d.mts.map +1 -0
  44. package/esm/openapi/development-openapi-provider.mjs +35 -0
  45. package/esm/openapi/development-openapi-provider.mjs.map +1 -0
  46. package/esm/openapi/error-responses.mjs +67 -0
  47. package/esm/openapi/error-responses.mjs.map +1 -0
  48. package/esm/openapi/index.d.mts +6 -0
  49. package/esm/openapi/index.mjs +6 -0
  50. package/esm/openapi/openapi-child-output.mjs +57 -0
  51. package/esm/openapi/openapi-child-output.mjs.map +1 -0
  52. package/esm/openapi/openapi-protocol.mjs +30 -0
  53. package/esm/openapi/openapi-protocol.mjs.map +1 -0
  54. package/esm/openapi/paths.mjs +63 -0
  55. package/esm/openapi/paths.mjs.map +1 -0
  56. package/esm/openapi/postman/build-request-body.mjs +86 -0
  57. package/esm/openapi/postman/build-request-body.mjs.map +1 -0
  58. package/esm/openapi/postman/build-request-url.mjs +85 -0
  59. package/esm/openapi/postman/build-request-url.mjs.map +1 -0
  60. package/esm/openapi/postman/build-saved-responses.mjs +60 -0
  61. package/esm/openapi/postman/build-saved-responses.mjs.map +1 -0
  62. package/esm/openapi/postman/example-from-schema.d.mts +17 -0
  63. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -0
  64. package/esm/openapi/postman/example-from-schema.mjs +92 -0
  65. package/esm/openapi/postman/example-from-schema.mjs.map +1 -0
  66. package/esm/openapi/postman/http-status-text.mjs +31 -0
  67. package/esm/openapi/postman/http-status-text.mjs.map +1 -0
  68. package/esm/openapi/postman/index.d.mts +3 -0
  69. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +22 -0
  70. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -0
  71. package/esm/openapi/postman/openapi-to-postman-collection.mjs +109 -0
  72. package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -0
  73. package/esm/openapi/postman/postman-types.d.mts +119 -0
  74. package/esm/openapi/postman/postman-types.d.mts.map +1 -0
  75. package/esm/openapi/postman/resolve-operation-auth.mjs +51 -0
  76. package/esm/openapi/postman/resolve-operation-auth.mjs.map +1 -0
  77. package/esm/openapi/postman/schema-refs.d.mts +7 -0
  78. package/esm/openapi/postman/schema-refs.d.mts.map +1 -0
  79. package/esm/openapi/postman/schema-refs.mjs +41 -0
  80. package/esm/openapi/postman/schema-refs.mjs.map +1 -0
  81. package/esm/openapi/postman/uuid-v5.mjs +29 -0
  82. package/esm/openapi/postman/uuid-v5.mjs.map +1 -0
  83. package/esm/openapi/request-schemas.mjs +138 -0
  84. package/esm/openapi/request-schemas.mjs.map +1 -0
  85. package/esm/openapi/response-schemas.mjs +85 -0
  86. package/esm/openapi/response-schemas.mjs.map +1 -0
  87. package/esm/openapi/schema-registry.mjs +143 -0
  88. package/esm/openapi/schema-registry.mjs.map +1 -0
  89. package/esm/openapi/security.mjs +98 -0
  90. package/esm/openapi/security.mjs.map +1 -0
  91. package/esm/openapi/types.d.mts +119 -0
  92. package/esm/openapi/types.d.mts.map +1 -0
  93. package/esm/production/registration-child-runner.mjs +139 -0
  94. package/esm/production/registration-child-runner.mjs.map +1 -0
  95. package/esm/production/route-registration-child.mjs +30 -2
  96. package/esm/production/route-registration-child.mjs.map +1 -1
  97. package/esm/production/route-registration-snapshot.mjs +22 -119
  98. package/esm/production/route-registration-snapshot.mjs.map +1 -1
  99. package/esm/resource/define-resource.d.mts +44 -14
  100. package/esm/resource/define-resource.d.mts.map +1 -1
  101. package/esm/resource/define-resource.mjs +0 -40
  102. package/esm/resource/define-resource.mjs.map +1 -1
  103. package/esm/resource/index.d.mts +1 -1
  104. package/esm/resource/resource.d.mts +4 -4
  105. package/esm/resource/resource.d.mts.map +1 -1
  106. package/esm/resource/resource.mjs +2 -4
  107. package/esm/resource/resource.mjs.map +1 -1
  108. package/esm/resource/types.d.mts +89 -4
  109. package/esm/resource/types.d.mts.map +1 -1
  110. package/esm/router/index.d.mts +1 -1
  111. package/esm/router/named-api-routes-with-responses.mjs +59 -0
  112. package/esm/router/named-api-routes-with-responses.mjs.map +1 -0
  113. package/esm/router/response-schema-types.mjs +100 -0
  114. package/esm/router/response-schema-types.mjs.map +1 -0
  115. package/esm/router/router.d.mts +2 -2
  116. package/esm/router/router.d.mts.map +1 -1
  117. package/esm/router/router.mjs +38 -11
  118. package/esm/router/router.mjs.map +1 -1
  119. package/esm/router/types.d.mts +16 -1
  120. package/esm/router/types.d.mts.map +1 -1
  121. package/llms-full.txt +293 -5
  122. package/llms.txt +3 -2
  123. package/package.json +13 -13
  124. package/skills/README.md +3 -2
  125. package/skills/create-controller/SKILL.md +39 -2
  126. package/skills/define-resource/SKILL.md +100 -1
  127. package/skills/generate-openapi/SKILL.md +148 -0
  128. package/skills/index.md +3 -3
  129. package/skills/validate-input/SKILL.md +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"type-generator.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/type-generator.ts"],"sourcesContent":["import { ensureDirectoryAsync } from \"@warlock.js/fs\";\nimport { constants } from \"fs\";\nimport { access, readFile, writeFile } from \"fs/promises\";\nimport { moduleResolve } from \"import-meta-resolve\";\nimport { join, resolve } from \"path\";\nimport { pathToFileURL } from \"node:url\";\nimport ts from \"typescript\";\nimport { warlockPath } from \"../utils\";\nimport { devLogError, devLogInfo, devLogSuccess, devServeLog } from \"./dev-logger\";\nimport { readConfigAst } from \"./read-config-ast\";\nimport { runTypingsGeneration, type TypingsGenerationPorts } from \"./run-typings-generation\";\nimport { filesOrchestrator } from \"./files-orchestrator\";\nimport { Path } from \"../utils/normalized-path\";\nimport { extractTranslationKeys } from \"./extract-translation-keys\";\nimport {\n isModuleLocaleDictionaryPath,\n isTranslationRegisteringSource,\n} from \"./translation-keys-sources\";\nimport { parseLocaleDictionary } from \"../localization\";\nimport { getFilesFromDirectory } from \"./utils\";\n\ntype RouteLocaleBuildModule = {\n listRouteLocaleKeys?: (options: {\n appRoot?: string;\n }) => readonly string[] | Promise<readonly string[]>;\n};\n\nconst WEB_PACKAGE = \"@warlock.js/web\";\nconst WEB_BUILD_PACKAGE = \"@warlock.js/web/build\";\n\nfunction isAbsentOptionalWebPackage(thrown: unknown): boolean {\n return (\n typeof thrown === \"object\" &&\n thrown !== null &&\n \"code\" in thrown &&\n (thrown as { code?: unknown }).code === \"ERR_MODULE_NOT_FOUND\" &&\n thrown instanceof Error &&\n thrown.message.includes(`Cannot find package '${WEB_PACKAGE}'`)\n );\n}\n\n/** Load the build-only web key lister without creating a core-to-web static edge. */\nexport async function listRouteLocaleKeysForTypeGeneration(\n appRoot = process.cwd(),\n): Promise<readonly string[]> {\n // Published web entries are import-only. Resolve with ESM conditions from\n // the consuming project; require.resolve rejects those installed exports.\n const projectUrl = pathToFileURL(resolve(appRoot, \"package.json\"));\n\n try {\n moduleResolve(WEB_PACKAGE, projectUrl);\n } catch (thrown) {\n if (isAbsentOptionalWebPackage(thrown)) return [];\n throw thrown;\n }\n\n const buildModuleUrl = moduleResolve(WEB_BUILD_PACKAGE, projectUrl);\n const buildModule = (await import(buildModuleUrl.href)) as RouteLocaleBuildModule;\n\n if (typeof buildModule.listRouteLocaleKeys !== \"function\") {\n throw new Error(\n `${WEB_BUILD_PACKAGE} does not export listRouteLocaleKeys. Upgrade @warlock.js/web to a compatible version.`,\n );\n }\n\n return buildModule.listRouteLocaleKeys({ appRoot });\n}\n\n/** True only for the route-locales convention under the canonical web root. */\nexport function isRouteLocalesJsonPath(path: string): boolean {\n const normalized = Path.normalize(path);\n const relativePath = normalized.startsWith(\"src/\") ? normalized : Path.toRelative(normalized);\n return /^src\\/web(?:\\/.*)?\\/locales\\.json$/.test(relativePath);\n}\n\n/**\n * Typings manifest structure for tracking file hashes\n */\ntype TypingsManifest = {\n version: string;\n lastBuildTime: number;\n storage: {\n sourceHash: string;\n drivers: string[];\n } | null;\n config: Record<\n string,\n {\n sourceHash: string;\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }\n >;\n};\n\n/**\n * TypeGenerator - Generates TypeScript type definitions from config files\n *\n * Parses source config files using the TypeScript Compiler API to extract\n * keys and generate module augmentation types for IDE autocomplete.\n *\n * Uses manifest-based reconciliation to only regenerate when source files change.\n */\nexport class TypeGenerator {\n /**\n * Output directory for generated typings\n */\n private outputDir = warlockPath(\"typings\");\n\n /**\n * Path to typings manifest file\n */\n private manifestPath = join(this.outputDir, \"typings-manifest.json\");\n\n /**\n * Cached manifest data\n */\n private manifest: TypingsManifest | null = null;\n\n /**\n * Cache for config type info and keys\n */\n private configCache = new Map<\n string,\n {\n sourceHash: string;\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }\n >();\n\n /**\n * Generate all framework type definitions\n *\n * Uses manifest-based reconciliation:\n * - If output files don't exist: full regeneration\n * - If files exist: only regenerate changed configs\n */\n public async generateAll(): Promise<void> {\n await this.ensureOutputDir();\n\n const storageFile = join(this.outputDir, \"storage.d.ts\");\n const configFile = join(this.outputDir, \"config.d.ts\");\n const translationsFile = join(this.outputDir, \"translations.d.ts\");\n\n const [manifestExists, storageExists, configExists, translationsExist] = await Promise.all([\n this.exists(this.manifestPath),\n this.exists(storageFile),\n this.exists(configFile),\n this.exists(translationsFile),\n ]);\n\n if (!manifestExists || !storageExists || !configExists || !translationsExist) {\n // Full regeneration (first run or files deleted)\n await this.fullGeneration();\n } else {\n // Load manifest for hash comparison\n await this.loadManifest();\n // Reconciliation: only regenerate changed files\n await this.reconcile();\n }\n\n await this.generateTranslationTypes();\n\n await this.saveManifest();\n }\n\n /**\n * Full regeneration of all type files\n */\n private async fullGeneration(): Promise<void> {\n // Generate storage types\n const storageConfigPath = await this.findConfigFile(\"storage\");\n if (storageConfigPath) {\n this.generateStorageTypes(storageConfigPath);\n }\n\n // Generate config types\n await this.generateConfigTypes();\n }\n\n /**\n * Reconcile: only regenerate changed files\n */\n private async reconcile(): Promise<void> {\n const files = filesOrchestrator.getFiles();\n let storageChanged = false;\n let configChanged = false;\n let unchangedCount = 0;\n\n this.configCache.clear();\n\n // Check storage config\n for (const [path, fileManager] of files) {\n if (path.startsWith(\"src/config/storage\")) {\n const manifestEntry = this.manifest?.storage;\n if (!manifestEntry || manifestEntry.sourceHash !== fileManager.hash) {\n storageChanged = true;\n await this.generateStorageTypes(path);\n }\n break;\n }\n }\n\n // Check config files\n for (const [path, fileManager] of files) {\n if (!path.startsWith(\"src/config/\")) continue;\n if (\n path\n .split(\"/\")\n .pop()\n ?.replace(/[.][^.]+$/, \"\") === \"index\"\n )\n continue;\n\n // Extract config name (remove dir prefix and extension)\n const configName = path.replace(\"src/config/\", \"\").replace(/\\.[^.]+$/, \"\");\n\n const manifestEntry = this.manifest?.config[configName];\n\n if (!manifestEntry || manifestEntry.sourceHash !== fileManager.hash) {\n // File changed or new - regenerate\n configChanged = true;\n const info = await this.extractConfigInfo(fileManager.absolutePath, configName);\n\n this.configCache.set(configName, {\n sourceHash: fileManager.hash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n } else {\n // Unchanged - load from manifest\n unchangedCount++;\n this.configCache.set(configName, manifestEntry);\n }\n }\n\n if (configChanged) {\n await this.writeConfigTypesFromCache();\n } else {\n devLogInfo(`Config types unchanged (${unchangedCount} configs cached)`);\n }\n }\n\n /**\n * Generate storage driver name types\n */\n public async generateStorageTypes(configPath: string): Promise<void> {\n try {\n const driverKeys = await this.extractStorageDriverKeys(configPath);\n\n if (driverKeys.length === 0) {\n devServeLog(\"⚠️ No storage drivers found in config\");\n return;\n }\n\n // Get file hash from filesOrchestrator\n const fileManager = filesOrchestrator.getFiles().get(configPath);\n const sourceHash = fileManager?.hash || \"\";\n\n // Update manifest\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.storage = {\n sourceHash,\n drivers: driverKeys,\n };\n\n const interfaceContent = driverKeys\n .map((k) => ` ${this.toInterfaceKey(k)}: true;`)\n .join(\"\\n\");\n\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Generated from: ${configPath}\n// Regenerates on dev-server start and when storage config changes\n\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface StorageDriverRegistry {\n${interfaceContent}\n }\n}\n`;\n\n const outputPath = join(this.outputDir, \"storage.d.ts\");\n await writeFile(outputPath, content, \"utf-8\");\n\n devLogSuccess(`Generated storage types: ${driverKeys.join(\", \")}`);\n } catch (error) {\n devServeLog(`⚠️ Failed to generate storage types: ${error}`);\n }\n }\n\n /**\n * Check if a file change should trigger type regeneration\n */\n public shouldRegenerateTypes(changedPath: string): boolean {\n return (\n changedPath.includes(\"src/config/\") ||\n changedPath.includes(\"config/\") ||\n this.isLocalesFile(changedPath) ||\n isRouteLocalesJsonPath(changedPath)\n );\n }\n\n /**\n * Handle file change - uses incremental update via cache\n */\n public async handleFileChange(changedPath: string): Promise<void> {\n if (!this.shouldRegenerateTypes(changedPath)) {\n return;\n }\n\n // Regenerate storage types if storage config changed\n if (changedPath.includes(\"config/storage\")) {\n await this.generateStorageTypes(changedPath);\n await this.saveManifest();\n return;\n }\n\n if (this.isLocalesFile(changedPath) || isRouteLocalesJsonPath(changedPath)) {\n await this.generateTranslationTypes();\n return;\n }\n\n // Extract config name from path\n const match = changedPath.match(/config\\/([^/]+)\\.[^.]+$/);\n if (!match) {\n return;\n }\n\n const configName = match[1];\n if (!configName || configName === \"index\") return;\n\n devLogInfo(`Config changed: ${configName}, updating...`);\n\n // Get file manager for hash\n const fileManager = filesOrchestrator.getFiles().get(changedPath);\n const sourceHash = fileManager?.hash || Date.now().toString();\n\n // Update only the changed config in cache (use optimized combined extraction)\n const configDir = join(process.cwd(), \"src/config\");\n const configPath = join(configDir, `${configName}.ts`);\n\n const info = await this.extractConfigInfo(configPath, configName);\n\n this.configCache.set(configName, {\n sourceHash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n\n // Regenerate config.d.ts from cache\n await this.writeConfigTypesFromCache();\n await this.saveManifest();\n }\n\n /**\n * Generate config types - populates cache and writes file\n */\n public async generateConfigTypes(): Promise<void> {\n try {\n const files = filesOrchestrator.getFiles();\n\n // Clear and repopulate cache\n this.configCache.clear();\n\n for (const [path, fileManager] of files) {\n if (!path.startsWith(\"src/config/\")) continue;\n if (\n path\n .split(\"/\")\n .pop()\n ?.replace(/[.][^.]+$/, \"\") === \"index\"\n )\n continue;\n\n // Extract config name\n const configName = path.replace(\"src/config/\", \"\").replace(/\\.[^.]+$/, \"\");\n\n // One parse per config, both extractions off it — see `read-config-ast.ts`.\n const info = await this.extractConfigInfo(fileManager.absolutePath, configName);\n\n this.configCache.set(configName, {\n sourceHash: fileManager.hash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n }\n\n await this.writeConfigTypesFromCache();\n } catch (error) {\n devServeLog(`⚠️ Failed to generate config types: ${error}`);\n }\n }\n\n /**\n * Files (relative paths) that contributed to the last generated registry —\n * used to notice a registering file being deleted, since by the time a\n * delete event reaches {@link executeTypingsGenerator} the file is already\n * gone from `filesOrchestrator`'s map and its content can no longer be\n * inspected.\n */\n private translationSourceFiles = new Set<string>();\n\n /**\n * Generate web's app-augmented translation-key registry.\n *\n * Scans every discovered app source file — not only dedicated\n * `utils/locales.*` files — for `groupedTranslations` calls, both the\n * named-group and object forms, at any nesting depth. Dynamic group names,\n * dictionaries, or keys cannot be resolved statically and are skipped; an\n * app relying on those must document them itself.\n */\n private async generateTranslationTypes(): Promise<void> {\n const keys = new Set<string>();\n const sourceFiles = new Set<string>();\n\n for (const [path, fileManager] of filesOrchestrator.getFiles()) {\n if (!isTranslationRegisteringSource(path, fileManager.source)) {\n continue;\n }\n\n sourceFiles.add(path);\n\n if (isModuleLocaleDictionaryPath(path)) {\n const dictionary = parseLocaleDictionary({\n sourceFile: path,\n source: fileManager.source,\n defaultNamespace: path.split(\"/\")[2]!,\n });\n for (const key of Object.keys(dictionary.entries)) {\n keys.add(key);\n }\n continue;\n }\n\n const sourceFile = await readConfigAst(fileManager.absolutePath);\n if (sourceFile) {\n for (const key of extractTranslationKeys(sourceFile)) {\n keys.add(key);\n }\n }\n }\n\n // The dev source map intentionally tracks executable TypeScript only. Module\n // dictionaries are JSON data, so discover them directly without loading app\n // code; use the runtime parser to keep `$group` and flattening identical.\n for (const absolutePath of await getFilesFromDirectory(\n join(process.cwd(), \"src\", \"app\"),\n \"**/utils/locales.json\",\n )) {\n const path = Path.toRelative(absolutePath);\n sourceFiles.add(path);\n const dictionary = parseLocaleDictionary({\n sourceFile: path,\n source: await readFile(absolutePath, \"utf-8\"),\n defaultNamespace: path.split(\"/\")[2]!,\n });\n for (const key of Object.keys(dictionary.entries)) {\n keys.add(key);\n }\n }\n\n for (const key of await listRouteLocaleKeysForTypeGeneration()) {\n keys.add(key);\n }\n\n this.translationSourceFiles = sourceFiles;\n\n const entries = Array.from(keys)\n .sort()\n .map((key) => ` ${JSON.stringify(key)}: true;`)\n .join(\"\\n\");\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Generated from groupedTranslations calls and route-locales JSON in discovered\n// app source. Dynamic group names/keys cannot be resolved statically and are\n// not included here — document those yourself.\n\nimport \"@warlock.js/web\";\n\ndeclare module \"@warlock.js/web\" {\n interface TranslationKeyRegistry {\n${entries}\n }\n}\n`;\n\n await writeFile(join(this.outputDir, \"translations.d.ts\"), content, \"utf-8\");\n devLogSuccess(`Generated translation types: ${keys.size} keys`);\n }\n\n private isLocalesFile(path: string): boolean {\n return Path.normalize(path).includes(\"/utils/locales.\");\n }\n\n /**\n * Quote an interface key that isn't a valid JS identifier (e.g. a config\n * named `use-cases` or a storage driver `do-spaces`) so the generated\n * `.d.ts` stays syntactically valid. Identifier-safe names are left bare\n * to keep the output clean.\n */\n private toInterfaceKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n }\n\n /**\n * Write config.d.ts from cached data\n */\n private async writeConfigTypesFromCache(): Promise<void> {\n const configTypeInfos: Array<{\n name: string;\n typeName: string | null;\n importSource: string | null;\n }> = [];\n const allKeys: string[] = [];\n\n // Update manifest config section\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.config = {};\n\n for (const [name, data] of this.configCache) {\n configTypeInfos.push({\n name,\n typeName: data.typeName,\n importSource: data.importSource,\n });\n allKeys.push(...data.keys);\n\n // Store in manifest\n this.manifest.config[name] = data;\n }\n\n // Group imports by source\n const imports = new Map<string, Set<string>>();\n for (const info of configTypeInfos) {\n if (info.typeName && info.importSource) {\n if (!imports.has(info.importSource)) {\n imports.set(info.importSource, new Set());\n }\n imports.get(info.importSource)!.add(info.typeName);\n }\n }\n\n const importStatements = Array.from(imports.entries())\n .map(([source, types]) => `import type { ${Array.from(types).join(\", \")} } from \"${source}\";`)\n .join(\"\\n\");\n\n const configEntries = configTypeInfos\n .map((info) => ` ${this.toInterfaceKey(info.name)}: ${info.typeName || \"unknown\"};`)\n .join(\"\\n\");\n\n const keyEntries = allKeys.map((key) => ` \"${key}\": true;`).join(\"\\n\");\n\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Regenerates on dev-server start and when config files change\n\n${importStatements}\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface ConfigRegistry {\n${configEntries}\n }\n\n interface ConfigKeyRegistry {\n${keyEntries}\n }\n}\n`;\n\n const outputPath = join(this.outputDir, \"config.d.ts\");\n await writeFile(outputPath, content, \"utf-8\");\n\n devLogSuccess(\n `Generated config types: ${this.configCache.size} configs, ${allKeys.length} keys`,\n );\n }\n\n // ============================================================\n // Manifest Management\n // ============================================================\n\n /**\n * Load manifest from disk\n */\n private async loadManifest(): Promise<boolean> {\n try {\n if (await this.exists(this.manifestPath)) {\n const content = await readFile(this.manifestPath, \"utf-8\");\n this.manifest = JSON.parse(content);\n return true;\n }\n } catch {\n // Manifest corrupted or missing\n }\n this.manifest = null;\n return false;\n }\n\n /**\n * Save manifest to disk\n */\n private async saveManifest(): Promise<void> {\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.lastBuildTime = Date.now();\n\n await writeFile(this.manifestPath, JSON.stringify(this.manifest, null, 2), \"utf-8\");\n }\n\n /**\n * Create empty manifest structure\n */\n private createEmptyManifest(): TypingsManifest {\n return {\n version: \"1.0.0\",\n lastBuildTime: Date.now(),\n storage: null,\n config: {},\n };\n }\n\n // ============================================================\n // Type Extraction Methods\n // ============================================================\n\n /**\n * Extract BOTH type info AND keys in a single pass\n *\n * One parse serves both extractions. It used to be one whole TypeScript\n * Program per file — halved from two by an earlier pass, which optimised\n * inside a premise that did not need to hold. `read-config-ast.ts` has the\n * numbers.\n *\n * @param configPath Absolute path to the config file\n * @param configName Config name (e.g., \"auth\", \"notifications\")\n * @returns Combined result with type info and keys\n */\n private async extractConfigInfo(\n configPath: string,\n configName: string,\n ): Promise<{\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }> {\n if (!(await this.exists(configPath))) {\n return { typeName: null, importSource: null, keys: [] };\n }\n\n // Parse, do not resolve — `read-config-ast.ts` explains why, with numbers.\n const sourceFile = await readConfigAst(configPath);\n\n if (!sourceFile) {\n return { typeName: null, importSource: null, keys: [] };\n }\n\n // === Type Info Extraction ===\n const importedTypes = new Map<string, string>();\n const localExportedTypes = new Set<string>();\n let foundTypeName: string | null = null;\n\n // === Keys Extraction ===\n const keys: string[] = [];\n\n const visitForTypes = (node: ts.Node): void => {\n // Collect imported types\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = node.moduleSpecifier;\n if (ts.isStringLiteral(moduleSpecifier)) {\n const source = moduleSpecifier.text;\n const importClause = node.importClause;\n if (importClause?.namedBindings && ts.isNamedImports(importClause.namedBindings)) {\n for (const element of importClause.namedBindings.elements) {\n importedTypes.set(element.name.text, source);\n }\n }\n }\n }\n\n // Collect locally exported types\n if (ts.isTypeAliasDeclaration(node)) {\n const modifiers = ts.getModifiers(node);\n if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {\n localExportedTypes.add(node.name.text);\n }\n }\n\n // Collect locally exported interfaces\n if (ts.isInterfaceDeclaration(node)) {\n const modifiers = ts.getModifiers(node);\n if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {\n localExportedTypes.add(node.name.text);\n }\n }\n\n // Find type used on config variable + extract keys\n if (ts.isVariableDeclaration(node)) {\n // Type info\n if (node.type && ts.isTypeReferenceNode(node.type)) {\n foundTypeName = node.type.typeName.getText(sourceFile);\n }\n\n // Keys extraction\n if (node.initializer && ts.isObjectLiteralExpression(node.initializer)) {\n const visitKeys = (objNode: ts.ObjectLiteralExpression, prefix: string): void => {\n for (const prop of objNode.properties) {\n if (ts.isPropertyAssignment(prop) && prop.name) {\n const keyName = prop.name.getText(sourceFile);\n const fullKey = prefix ? `${prefix}.${keyName}` : keyName;\n keys.push(fullKey);\n if (ts.isObjectLiteralExpression(prop.initializer)) {\n visitKeys(prop.initializer, fullKey);\n }\n }\n }\n };\n visitKeys(node.initializer, configName);\n }\n }\n\n ts.forEachChild(node, visitForTypes);\n };\n\n ts.forEachChild(sourceFile, visitForTypes);\n\n // Resolve type info\n let typeName: string | null = null;\n let importSource: string | null = null;\n\n if (foundTypeName) {\n if (importedTypes.has(foundTypeName)) {\n typeName = foundTypeName;\n importSource = importedTypes.get(foundTypeName)!;\n } else if (localExportedTypes.has(foundTypeName)) {\n typeName = foundTypeName;\n const relativePath = Path.toRelative(configPath).replace(/\\.(ts|tsx)$/, \"\");\n importSource = `../../${relativePath}`;\n }\n }\n\n return { typeName, importSource, keys };\n }\n\n /**\n * Extract driver keys from storage config\n */\n private async extractStorageDriverKeys(configPath: string): Promise<string[]> {\n const absolutePath = resolve(configPath);\n\n if (!(await this.exists(absolutePath))) {\n devServeLog(`⚠️ Storage config not found: ${absolutePath}`);\n return [];\n }\n\n const sourceFile = await readConfigAst(absolutePath);\n\n if (!sourceFile) {\n devServeLog(`⚠️ Could not parse storage config: ${absolutePath}`);\n return [];\n }\n\n const keys: string[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node)) {\n const propName = node.name.getText(sourceFile);\n\n if (propName === \"drivers\" && ts.isObjectLiteralExpression(node.initializer)) {\n for (const prop of node.initializer.properties) {\n if (ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop)) {\n const keyName = prop.name?.getText(sourceFile);\n\n if (keyName) {\n keys.push(keyName);\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n ts.forEachChild(sourceFile, visit);\n\n return keys;\n }\n\n /**\n * Find a config file by name\n */\n private async findConfigFile(configName: string): Promise<string | undefined> {\n const possiblePaths = [`src/config/${configName}.ts`, `config/${configName}.ts`];\n\n for (const path of possiblePaths) {\n const fullPath = join(process.cwd(), path);\n\n if (await this.exists(fullPath)) {\n return path;\n }\n }\n\n try {\n const files = filesOrchestrator.getFiles();\n\n for (const [filePath] of files) {\n if (filePath.includes(`config/${configName}`)) {\n return filePath;\n }\n }\n } catch {\n // Files orchestrator not initialized yet\n }\n\n return undefined;\n }\n\n /**\n * Ensure output directory exists\n */\n private async ensureOutputDir(): Promise<void> {\n await ensureDirectoryAsync(this.outputDir);\n }\n\n /**\n * Check if a path exists (async wrapper)\n */\n private async exists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * The ports `runTypingsGeneration` needs, bound to this instance and this\n * package's dev logger.\n */\n private get typingsGenerationPorts(): TypingsGenerationPorts {\n return {\n generate: () => this.generateAll(),\n info: (message) => devLogInfo(message),\n success: (message) => devLogSuccess(message),\n error: (message) => devLogError(message),\n };\n }\n\n /**\n * Generate every config's typings.\n *\n * Runs IN THIS PROCESS. It used to spawn `npx warlock generate.typings`,\n * which could not resolve in a source checkout — see\n * `run-typings-generation.ts` for the whole story.\n */\n public async executeGenerateAllCommand(): Promise<void> {\n await runTypingsGeneration(this.typingsGenerationPorts);\n }\n\n /**\n * Regenerate typings after a batch reload — but only when the batch\n * plausibly touched something the typings depend on: a config file, a file\n * that registers translation keys, or a registering file that was deleted.\n *\n * A deleted file is already gone from `filesOrchestrator` by the time this\n * runs (deletes are processed before `dev-server:batch-complete` fires), so\n * its content can't be re-checked here — `translationSourceFiles` is the\n * set from the last generation, kept for exactly this comparison.\n */\n public async executeTypingsGenerator(upcomingFiles: string[]): Promise<void> {\n const files = filesOrchestrator.getFiles();\n\n const aKnownTranslationSourceVanished = Array.from(this.translationSourceFiles).some(\n (path) => !files.has(path),\n );\n\n const touchedAConfig =\n aKnownTranslationSourceVanished ||\n Array.from(new Set(upcomingFiles)).some((file) => {\n const normalizedPath = Path.normalize(file);\n if (normalizedPath.includes(\"src/config/\")) return true;\n if (isRouteLocalesJsonPath(normalizedPath)) return true;\n if (isModuleLocaleDictionaryPath(normalizedPath)) return true;\n if (this.translationSourceFiles.has(normalizedPath)) return true;\n\n const fileManager = files.get(normalizedPath);\n return (\n fileManager !== undefined &&\n isTranslationRegisteringSource(normalizedPath, fileManager.source)\n );\n });\n\n if (!touchedAConfig) return;\n\n /*\n The changed paths are deliberately NOT passed along. The previous version\n built a `files` array here and then threw it away, spawning the same\n whole-project command as the branch above — so \"incremental\" was a name,\n not a behaviour. `generateAll()` reads the orchestrator, which the batch\n reload has already updated, so the full pass is both correct and the only\n pass that ever actually ran.\n */\n await runTypingsGeneration(this.typingsGenerationPorts);\n }\n}\n\n/**\n * Singleton instance for use throughout dev-server\n */\nexport const typeGenerator = new TypeGenerator();\n"],"mappings":"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"}
1
+ {"version":3,"file":"type-generator.mjs","names":[],"sources":["../../../../../../../core/src/dev-server/type-generator.ts"],"sourcesContent":["import { ensureDirectoryAsync } from \"@warlock.js/fs\";\nimport { constants } from \"fs\";\nimport { access, readFile, writeFile } from \"fs/promises\";\nimport { moduleResolve } from \"import-meta-resolve\";\nimport { join, resolve } from \"path\";\nimport { pathToFileURL } from \"node:url\";\nimport ts from \"typescript\";\nimport { warlockPath } from \"../utils\";\nimport { devLogDim, devLogError, devLogInfo, devLogSuccess, devServeLog } from \"./dev-logger\";\nimport { readConfigAst } from \"./read-config-ast\";\nimport { runTypingsGeneration, type TypingsGenerationPorts } from \"./run-typings-generation\";\nimport { filesOrchestrator } from \"./files-orchestrator\";\nimport { Path } from \"../utils/normalized-path\";\nimport { extractTranslationKeys } from \"./extract-translation-keys\";\nimport {\n isModuleLocaleDictionaryPath,\n isTranslationRegisteringSource,\n} from \"./translation-keys-sources\";\nimport { parseLocaleDictionary } from \"../localization\";\nimport { getFilesFromDirectory } from \"./utils\";\nimport {\n extractModelResourceEntries,\n renderModelResourceRegistry,\n writeFileIfChanged,\n type ModelResourceEntry,\n} from \"./model-resource-typings\";\nimport { parseImports } from \"./parse-imports\";\n\ntype RouteLocaleBuildModule = {\n listRouteLocaleKeys?: (options: {\n appRoot?: string;\n }) => readonly string[] | Promise<readonly string[]>;\n};\n\nconst WEB_PACKAGE = \"@warlock.js/web\";\nconst WEB_BUILD_PACKAGE = \"@warlock.js/web/build\";\n\nfunction isAbsentOptionalWebPackage(thrown: unknown): boolean {\n return (\n typeof thrown === \"object\" &&\n thrown !== null &&\n \"code\" in thrown &&\n (thrown as { code?: unknown }).code === \"ERR_MODULE_NOT_FOUND\" &&\n thrown instanceof Error &&\n thrown.message.includes(`Cannot find package '${WEB_PACKAGE}'`)\n );\n}\n\n/** Load the build-only web key lister without creating a core-to-web static edge. */\nexport async function listRouteLocaleKeysForTypeGeneration(\n appRoot = process.cwd(),\n): Promise<readonly string[]> {\n // Published web entries are import-only. Resolve with ESM conditions from\n // the consuming project; require.resolve rejects those installed exports.\n const projectUrl = pathToFileURL(resolve(appRoot, \"package.json\"));\n\n try {\n moduleResolve(WEB_PACKAGE, projectUrl);\n } catch (thrown) {\n if (isAbsentOptionalWebPackage(thrown)) return [];\n throw thrown;\n }\n\n const buildModuleUrl = moduleResolve(WEB_BUILD_PACKAGE, projectUrl);\n const buildModule = (await import(buildModuleUrl.href)) as RouteLocaleBuildModule;\n\n if (typeof buildModule.listRouteLocaleKeys !== \"function\") {\n throw new Error(\n `${WEB_BUILD_PACKAGE} does not export listRouteLocaleKeys. Upgrade @warlock.js/web to a compatible version.`,\n );\n }\n\n return buildModule.listRouteLocaleKeys({ appRoot });\n}\n\n/** True only for the route-locales convention under the canonical web root. */\nexport function isRouteLocalesJsonPath(path: string): boolean {\n const normalized = Path.normalize(path);\n const relativePath = normalized.startsWith(\"src/\") ? normalized : Path.toRelative(normalized);\n return /^src\\/web(?:\\/.*)?\\/locales\\.json$/.test(relativePath);\n}\n\n/**\n * Typings manifest structure for tracking file hashes\n */\ntype TypingsManifest = {\n version: string;\n lastBuildTime: number;\n storage: {\n sourceHash: string;\n drivers: string[];\n } | null;\n config: Record<\n string,\n {\n sourceHash: string;\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }\n >;\n};\n\n/**\n * TypeGenerator - Generates TypeScript type definitions from config files\n *\n * Parses source config files using the TypeScript Compiler API to extract\n * keys and generate module augmentation types for IDE autocomplete.\n *\n * Uses manifest-based reconciliation to only regenerate when source files change.\n */\nexport class TypeGenerator {\n /**\n * Output directory for generated typings\n */\n private outputDir = warlockPath(\"typings\");\n\n /**\n * Path to typings manifest file\n */\n private manifestPath = join(this.outputDir, \"typings-manifest.json\");\n\n /**\n * Cached manifest data\n */\n private manifest: TypingsManifest | null = null;\n\n /**\n * Cache for config type info and keys\n */\n private configCache = new Map<\n string,\n {\n sourceHash: string;\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }\n >();\n\n /**\n * Generate all framework type definitions\n *\n * Uses manifest-based reconciliation:\n * - If output files don't exist: full regeneration\n * - If files exist: only regenerate changed configs\n */\n public async generateAll(): Promise<void> {\n await this.ensureOutputDir();\n\n const storageFile = join(this.outputDir, \"storage.d.ts\");\n const configFile = join(this.outputDir, \"config.d.ts\");\n const translationsFile = join(this.outputDir, \"translations.d.ts\");\n\n const [manifestExists, storageExists, configExists, translationsExist] = await Promise.all([\n this.exists(this.manifestPath),\n this.exists(storageFile),\n this.exists(configFile),\n this.exists(translationsFile),\n ]);\n\n if (!manifestExists || !storageExists || !configExists || !translationsExist) {\n // Full regeneration (first run or files deleted)\n await this.fullGeneration();\n } else {\n // Load manifest for hash comparison\n await this.loadManifest();\n // Reconciliation: only regenerate changed files\n await this.reconcile();\n }\n\n await this.generateTranslationTypes();\n await this.generateModelResourceTypes();\n\n await this.saveManifest();\n }\n\n /**\n * Full regeneration of all type files\n */\n private async fullGeneration(): Promise<void> {\n // Generate storage types\n const storageConfigPath = await this.findConfigFile(\"storage\");\n if (storageConfigPath) {\n this.generateStorageTypes(storageConfigPath);\n }\n\n // Generate config types\n await this.generateConfigTypes();\n }\n\n /**\n * Reconcile: only regenerate changed files\n */\n private async reconcile(): Promise<void> {\n const files = filesOrchestrator.getFiles();\n let storageChanged = false;\n let configChanged = false;\n let unchangedCount = 0;\n\n this.configCache.clear();\n\n // Check storage config\n for (const [path, fileManager] of files) {\n if (path.startsWith(\"src/config/storage\")) {\n const manifestEntry = this.manifest?.storage;\n if (!manifestEntry || manifestEntry.sourceHash !== fileManager.hash) {\n storageChanged = true;\n await this.generateStorageTypes(path);\n }\n break;\n }\n }\n\n // Check config files\n for (const [path, fileManager] of files) {\n if (!path.startsWith(\"src/config/\")) continue;\n if (\n path\n .split(\"/\")\n .pop()\n ?.replace(/[.][^.]+$/, \"\") === \"index\"\n )\n continue;\n\n // Extract config name (remove dir prefix and extension)\n const configName = path.replace(\"src/config/\", \"\").replace(/\\.[^.]+$/, \"\");\n\n const manifestEntry = this.manifest?.config[configName];\n\n if (!manifestEntry || manifestEntry.sourceHash !== fileManager.hash) {\n // File changed or new - regenerate\n configChanged = true;\n const info = await this.extractConfigInfo(fileManager.absolutePath, configName);\n\n this.configCache.set(configName, {\n sourceHash: fileManager.hash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n } else {\n // Unchanged - load from manifest\n unchangedCount++;\n this.configCache.set(configName, manifestEntry);\n }\n }\n\n if (configChanged) {\n await this.writeConfigTypesFromCache();\n } else {\n devLogInfo(`Config types unchanged (${unchangedCount} configs cached)`);\n }\n }\n\n /**\n * Generate storage driver name types\n */\n public async generateStorageTypes(configPath: string): Promise<void> {\n try {\n const driverKeys = await this.extractStorageDriverKeys(configPath);\n\n if (driverKeys.length === 0) {\n devServeLog(\"⚠️ No storage drivers found in config\");\n return;\n }\n\n // Get file hash from filesOrchestrator\n const fileManager = filesOrchestrator.getFiles().get(configPath);\n const sourceHash = fileManager?.hash || \"\";\n\n // Update manifest\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.storage = {\n sourceHash,\n drivers: driverKeys,\n };\n\n const interfaceContent = driverKeys\n .map((k) => ` ${this.toInterfaceKey(k)}: true;`)\n .join(\"\\n\");\n\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Generated from: ${configPath}\n// Regenerates on dev-server start and when storage config changes\n\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface StorageDriverRegistry {\n${interfaceContent}\n }\n}\n`;\n\n const outputPath = join(this.outputDir, \"storage.d.ts\");\n await writeFile(outputPath, content, \"utf-8\");\n\n devLogSuccess(`Generated storage types: ${driverKeys.join(\", \")}`);\n } catch (error) {\n devServeLog(`⚠️ Failed to generate storage types: ${error}`);\n }\n }\n\n /**\n * Check if a file change should trigger type regeneration\n */\n public shouldRegenerateTypes(changedPath: string): boolean {\n return (\n changedPath.includes(\"src/config/\") ||\n changedPath.includes(\"config/\") ||\n this.isLocalesFile(changedPath) ||\n isRouteLocalesJsonPath(changedPath)\n );\n }\n\n /**\n * Handle file change - uses incremental update via cache\n */\n public async handleFileChange(changedPath: string): Promise<void> {\n if (!this.shouldRegenerateTypes(changedPath)) {\n return;\n }\n\n // Regenerate storage types if storage config changed\n if (changedPath.includes(\"config/storage\")) {\n await this.generateStorageTypes(changedPath);\n await this.saveManifest();\n return;\n }\n\n if (this.isLocalesFile(changedPath) || isRouteLocalesJsonPath(changedPath)) {\n await this.generateTranslationTypes();\n return;\n }\n\n // Extract config name from path\n const match = changedPath.match(/config\\/([^/]+)\\.[^.]+$/);\n if (!match) {\n return;\n }\n\n const configName = match[1];\n if (!configName || configName === \"index\") return;\n\n devLogInfo(`Config changed: ${configName}, updating...`);\n\n // Get file manager for hash\n const fileManager = filesOrchestrator.getFiles().get(changedPath);\n const sourceHash = fileManager?.hash || Date.now().toString();\n\n // Update only the changed config in cache (use optimized combined extraction)\n const configDir = join(process.cwd(), \"src/config\");\n const configPath = join(configDir, `${configName}.ts`);\n\n const info = await this.extractConfigInfo(configPath, configName);\n\n this.configCache.set(configName, {\n sourceHash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n\n // Regenerate config.d.ts from cache\n await this.writeConfigTypesFromCache();\n await this.saveManifest();\n }\n\n /**\n * Generate config types - populates cache and writes file\n */\n public async generateConfigTypes(): Promise<void> {\n try {\n const files = filesOrchestrator.getFiles();\n\n // Clear and repopulate cache\n this.configCache.clear();\n\n for (const [path, fileManager] of files) {\n if (!path.startsWith(\"src/config/\")) continue;\n if (\n path\n .split(\"/\")\n .pop()\n ?.replace(/[.][^.]+$/, \"\") === \"index\"\n )\n continue;\n\n // Extract config name\n const configName = path.replace(\"src/config/\", \"\").replace(/\\.[^.]+$/, \"\");\n\n // One parse per config, both extractions off it — see `read-config-ast.ts`.\n const info = await this.extractConfigInfo(fileManager.absolutePath, configName);\n\n this.configCache.set(configName, {\n sourceHash: fileManager.hash,\n typeName: info.typeName,\n importSource: info.importSource,\n keys: info.keys,\n });\n }\n\n await this.writeConfigTypesFromCache();\n } catch (error) {\n devServeLog(`⚠️ Failed to generate config types: ${error}`);\n }\n }\n\n /**\n * Files (relative paths) that contributed to the last generated registry —\n * used to notice a registering file being deleted, since by the time a\n * delete event reaches {@link executeTypingsGenerator} the file is already\n * gone from `filesOrchestrator`'s map and its content can no longer be\n * inspected.\n */\n private translationSourceFiles = new Set<string>();\n\n /**\n * Generate web's app-augmented translation-key registry.\n *\n * Scans every discovered app source file — not only dedicated\n * `utils/locales.*` files — for `groupedTranslations` calls, both the\n * named-group and object forms, at any nesting depth. Dynamic group names,\n * dictionaries, or keys cannot be resolved statically and are skipped; an\n * app relying on those must document them itself.\n */\n private async generateTranslationTypes(): Promise<void> {\n const keys = new Set<string>();\n const sourceFiles = new Set<string>();\n\n for (const [path, fileManager] of filesOrchestrator.getFiles()) {\n if (!isTranslationRegisteringSource(path, fileManager.source)) {\n continue;\n }\n\n sourceFiles.add(path);\n\n if (isModuleLocaleDictionaryPath(path)) {\n const dictionary = parseLocaleDictionary({\n sourceFile: path,\n source: fileManager.source,\n defaultNamespace: path.split(\"/\")[2]!,\n });\n for (const key of Object.keys(dictionary.entries)) {\n keys.add(key);\n }\n continue;\n }\n\n const sourceFile = await readConfigAst(fileManager.absolutePath);\n if (sourceFile) {\n for (const key of extractTranslationKeys(sourceFile)) {\n keys.add(key);\n }\n }\n }\n\n // The dev source map intentionally tracks executable TypeScript only. Module\n // dictionaries are JSON data, so discover them directly without loading app\n // code; use the runtime parser to keep `$group` and flattening identical.\n for (const absolutePath of await getFilesFromDirectory(\n join(process.cwd(), \"src\", \"app\"),\n \"**/utils/locales.json\",\n )) {\n const path = Path.toRelative(absolutePath);\n sourceFiles.add(path);\n const dictionary = parseLocaleDictionary({\n sourceFile: path,\n source: await readFile(absolutePath, \"utf-8\"),\n defaultNamespace: path.split(\"/\")[2]!,\n });\n for (const key of Object.keys(dictionary.entries)) {\n keys.add(key);\n }\n }\n\n for (const key of await listRouteLocaleKeysForTypeGeneration()) {\n keys.add(key);\n }\n\n this.translationSourceFiles = sourceFiles;\n\n const entries = Array.from(keys)\n .sort()\n .map((key) => ` ${JSON.stringify(key)}: true;`)\n .join(\"\\n\");\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Generated from groupedTranslations calls and route-locales JSON in discovered\n// app source. Dynamic group names/keys cannot be resolved statically and are\n// not included here — document those yourself.\n\nimport \"@warlock.js/web\";\n\ndeclare module \"@warlock.js/web\" {\n interface TranslationKeyRegistry {\n${entries}\n }\n}\n`;\n\n await writeFile(join(this.outputDir, \"translations.d.ts\"), content, \"utf-8\");\n devLogSuccess(`Generated translation types: ${keys.size} keys`);\n }\n\n /**\n * Files that contributed to the last `model-resources.d.ts`: the model files\n * and the modules their resources were resolved to. Kept for the same reason\n * as {@link translationSourceFiles}: a deleted file is already gone from the\n * orchestrator when the batch reaches {@link executeTypingsGenerator}.\n */\n private modelResourceSourceFiles = new Set<string>();\n\n /**\n * Generate `model-resources.d.ts`: the `ModelResourceRegistry` augmentation\n * behind `Serialized<Model>`.\n *\n * Reads every discovered model file (`*.model.ts`) and records the ones that\n * declare `static resource = <Identifier>`. Static AST read only, no app\n * module is imported; see `model-resource-typings.ts` for what is skipped.\n * The file is rewritten only when its text changes.\n */\n private async generateModelResourceTypes(): Promise<void> {\n try {\n const entries: ModelResourceEntry[] = [];\n const sourceFiles = new Set<string>();\n const skippedModels: string[] = [];\n\n for (const [path, fileManager] of filesOrchestrator.getFiles()) {\n if (fileManager.type !== \"model\" || !fileManager.source.includes(\"resource\")) continue;\n\n const imports = await parseImports(fileManager.source, fileManager.absolutePath);\n const extraction = extractModelResourceEntries({\n source: fileManager.source,\n absolutePath: fileManager.absolutePath,\n resolveImport: (specifier) => imports.get(specifier)?.absolutePath,\n });\n\n if (extraction.entries.length > 0) sourceFiles.add(path);\n\n for (const entry of extraction.entries) {\n entries.push(entry);\n sourceFiles.add(Path.toRelative(entry.resourceFile));\n }\n\n for (const skipped of extraction.skipped) {\n skippedModels.push(`${skipped.className} (${skipped.reason})`);\n }\n }\n\n this.modelResourceSourceFiles = sourceFiles;\n\n const written = await writeFileIfChanged(\n join(this.outputDir, \"model-resources.d.ts\"),\n renderModelResourceRegistry(entries, this.outputDir),\n );\n\n if (written) devLogSuccess(`Generated model resource types: ${entries.length} models`);\n\n if (skippedModels.length > 0) {\n devLogDim(\n `Model resources not typed (not statically resolvable): ${skippedModels.join(\", \")}`,\n );\n }\n } catch (error) {\n devServeLog(`⚠️ Failed to generate model resource types: ${error}`);\n }\n }\n\n private isLocalesFile(path: string): boolean {\n return Path.normalize(path).includes(\"/utils/locales.\");\n }\n\n /**\n * Quote an interface key that isn't a valid JS identifier (e.g. a config\n * named `use-cases` or a storage driver `do-spaces`) so the generated\n * `.d.ts` stays syntactically valid. Identifier-safe names are left bare\n * to keep the output clean.\n */\n private toInterfaceKey(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n }\n\n /**\n * Write config.d.ts from cached data\n */\n private async writeConfigTypesFromCache(): Promise<void> {\n const configTypeInfos: Array<{\n name: string;\n typeName: string | null;\n importSource: string | null;\n }> = [];\n const allKeys: string[] = [];\n\n // Update manifest config section\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.config = {};\n\n for (const [name, data] of this.configCache) {\n configTypeInfos.push({\n name,\n typeName: data.typeName,\n importSource: data.importSource,\n });\n allKeys.push(...data.keys);\n\n // Store in manifest\n this.manifest.config[name] = data;\n }\n\n // Group imports by source\n const imports = new Map<string, Set<string>>();\n for (const info of configTypeInfos) {\n if (info.typeName && info.importSource) {\n if (!imports.has(info.importSource)) {\n imports.set(info.importSource, new Set());\n }\n imports.get(info.importSource)!.add(info.typeName);\n }\n }\n\n const importStatements = Array.from(imports.entries())\n .map(([source, types]) => `import type { ${Array.from(types).join(\", \")} } from \"${source}\";`)\n .join(\"\\n\");\n\n const configEntries = configTypeInfos\n .map((info) => ` ${this.toInterfaceKey(info.name)}: ${info.typeName || \"unknown\"};`)\n .join(\"\\n\");\n\n const keyEntries = allKeys.map((key) => ` \"${key}\": true;`).join(\"\\n\");\n\n const content = `// Auto-generated by Warlock.js - DO NOT EDIT\n// Regenerates on dev-server start and when config files change\n\n${importStatements}\nimport \"@warlock.js/core\";\n\ndeclare module \"@warlock.js/core\" {\n interface ConfigRegistry {\n${configEntries}\n }\n\n interface ConfigKeyRegistry {\n${keyEntries}\n }\n}\n`;\n\n const outputPath = join(this.outputDir, \"config.d.ts\");\n await writeFile(outputPath, content, \"utf-8\");\n\n devLogSuccess(\n `Generated config types: ${this.configCache.size} configs, ${allKeys.length} keys`,\n );\n }\n\n // ============================================================\n // Manifest Management\n // ============================================================\n\n /**\n * Load manifest from disk\n */\n private async loadManifest(): Promise<boolean> {\n try {\n if (await this.exists(this.manifestPath)) {\n const content = await readFile(this.manifestPath, \"utf-8\");\n this.manifest = JSON.parse(content);\n return true;\n }\n } catch {\n // Manifest corrupted or missing\n }\n this.manifest = null;\n return false;\n }\n\n /**\n * Save manifest to disk\n */\n private async saveManifest(): Promise<void> {\n if (!this.manifest) {\n this.manifest = this.createEmptyManifest();\n }\n this.manifest.lastBuildTime = Date.now();\n\n await writeFile(this.manifestPath, JSON.stringify(this.manifest, null, 2), \"utf-8\");\n }\n\n /**\n * Create empty manifest structure\n */\n private createEmptyManifest(): TypingsManifest {\n return {\n version: \"1.0.0\",\n lastBuildTime: Date.now(),\n storage: null,\n config: {},\n };\n }\n\n // ============================================================\n // Type Extraction Methods\n // ============================================================\n\n /**\n * Extract BOTH type info AND keys in a single pass\n *\n * One parse serves both extractions. It used to be one whole TypeScript\n * Program per file — halved from two by an earlier pass, which optimised\n * inside a premise that did not need to hold. `read-config-ast.ts` has the\n * numbers.\n *\n * @param configPath Absolute path to the config file\n * @param configName Config name (e.g., \"auth\", \"notifications\")\n * @returns Combined result with type info and keys\n */\n private async extractConfigInfo(\n configPath: string,\n configName: string,\n ): Promise<{\n typeName: string | null;\n importSource: string | null;\n keys: string[];\n }> {\n if (!(await this.exists(configPath))) {\n return { typeName: null, importSource: null, keys: [] };\n }\n\n // Parse, do not resolve — `read-config-ast.ts` explains why, with numbers.\n const sourceFile = await readConfigAst(configPath);\n\n if (!sourceFile) {\n return { typeName: null, importSource: null, keys: [] };\n }\n\n // === Type Info Extraction ===\n const importedTypes = new Map<string, string>();\n const localExportedTypes = new Set<string>();\n let foundTypeName: string | null = null;\n\n // === Keys Extraction ===\n const keys: string[] = [];\n\n const visitForTypes = (node: ts.Node): void => {\n // Collect imported types\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = node.moduleSpecifier;\n if (ts.isStringLiteral(moduleSpecifier)) {\n const source = moduleSpecifier.text;\n const importClause = node.importClause;\n if (importClause?.namedBindings && ts.isNamedImports(importClause.namedBindings)) {\n for (const element of importClause.namedBindings.elements) {\n importedTypes.set(element.name.text, source);\n }\n }\n }\n }\n\n // Collect locally exported types\n if (ts.isTypeAliasDeclaration(node)) {\n const modifiers = ts.getModifiers(node);\n if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {\n localExportedTypes.add(node.name.text);\n }\n }\n\n // Collect locally exported interfaces\n if (ts.isInterfaceDeclaration(node)) {\n const modifiers = ts.getModifiers(node);\n if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {\n localExportedTypes.add(node.name.text);\n }\n }\n\n // Find type used on config variable + extract keys\n if (ts.isVariableDeclaration(node)) {\n // Type info\n if (node.type && ts.isTypeReferenceNode(node.type)) {\n foundTypeName = node.type.typeName.getText(sourceFile);\n }\n\n // Keys extraction\n if (node.initializer && ts.isObjectLiteralExpression(node.initializer)) {\n const visitKeys = (objNode: ts.ObjectLiteralExpression, prefix: string): void => {\n for (const prop of objNode.properties) {\n if (ts.isPropertyAssignment(prop) && prop.name) {\n const keyName = prop.name.getText(sourceFile);\n const fullKey = prefix ? `${prefix}.${keyName}` : keyName;\n keys.push(fullKey);\n if (ts.isObjectLiteralExpression(prop.initializer)) {\n visitKeys(prop.initializer, fullKey);\n }\n }\n }\n };\n visitKeys(node.initializer, configName);\n }\n }\n\n ts.forEachChild(node, visitForTypes);\n };\n\n ts.forEachChild(sourceFile, visitForTypes);\n\n // Resolve type info\n let typeName: string | null = null;\n let importSource: string | null = null;\n\n if (foundTypeName) {\n if (importedTypes.has(foundTypeName)) {\n typeName = foundTypeName;\n importSource = importedTypes.get(foundTypeName)!;\n } else if (localExportedTypes.has(foundTypeName)) {\n typeName = foundTypeName;\n const relativePath = Path.toRelative(configPath).replace(/\\.(ts|tsx)$/, \"\");\n importSource = `../../${relativePath}`;\n }\n }\n\n return { typeName, importSource, keys };\n }\n\n /**\n * Extract driver keys from storage config\n */\n private async extractStorageDriverKeys(configPath: string): Promise<string[]> {\n const absolutePath = resolve(configPath);\n\n if (!(await this.exists(absolutePath))) {\n devServeLog(`⚠️ Storage config not found: ${absolutePath}`);\n return [];\n }\n\n const sourceFile = await readConfigAst(absolutePath);\n\n if (!sourceFile) {\n devServeLog(`⚠️ Could not parse storage config: ${absolutePath}`);\n return [];\n }\n\n const keys: string[] = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isPropertyAssignment(node)) {\n const propName = node.name.getText(sourceFile);\n\n if (propName === \"drivers\" && ts.isObjectLiteralExpression(node.initializer)) {\n for (const prop of node.initializer.properties) {\n if (ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop)) {\n const keyName = prop.name?.getText(sourceFile);\n\n if (keyName) {\n keys.push(keyName);\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n ts.forEachChild(sourceFile, visit);\n\n return keys;\n }\n\n /**\n * Find a config file by name\n */\n private async findConfigFile(configName: string): Promise<string | undefined> {\n const possiblePaths = [`src/config/${configName}.ts`, `config/${configName}.ts`];\n\n for (const path of possiblePaths) {\n const fullPath = join(process.cwd(), path);\n\n if (await this.exists(fullPath)) {\n return path;\n }\n }\n\n try {\n const files = filesOrchestrator.getFiles();\n\n for (const [filePath] of files) {\n if (filePath.includes(`config/${configName}`)) {\n return filePath;\n }\n }\n } catch {\n // Files orchestrator not initialized yet\n }\n\n return undefined;\n }\n\n /**\n * Ensure output directory exists\n */\n private async ensureOutputDir(): Promise<void> {\n await ensureDirectoryAsync(this.outputDir);\n }\n\n /**\n * Check if a path exists (async wrapper)\n */\n private async exists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * The ports `runTypingsGeneration` needs, bound to this instance and this\n * package's dev logger.\n */\n private get typingsGenerationPorts(): TypingsGenerationPorts {\n return {\n generate: () => this.generateAll(),\n info: (message) => devLogInfo(message),\n success: (message) => devLogSuccess(message),\n error: (message) => devLogError(message),\n };\n }\n\n /**\n * Generate every config's typings.\n *\n * Runs IN THIS PROCESS. It used to spawn `npx warlock generate.typings`,\n * which could not resolve in a source checkout — see\n * `run-typings-generation.ts` for the whole story.\n */\n public async executeGenerateAllCommand(): Promise<void> {\n await runTypingsGeneration(this.typingsGenerationPorts);\n }\n\n /**\n * Regenerate typings after a batch reload — but only when the batch\n * plausibly touched something the typings depend on: a config file, a file\n * that registers translation keys, or a registering file that was deleted.\n *\n * A deleted file is already gone from `filesOrchestrator` by the time this\n * runs (deletes are processed before `dev-server:batch-complete` fires), so\n * its content can't be re-checked here — `translationSourceFiles` is the\n * set from the last generation, kept for exactly this comparison.\n */\n public async executeTypingsGenerator(upcomingFiles: string[]): Promise<void> {\n const files = filesOrchestrator.getFiles();\n\n const aKnownTranslationSourceVanished = Array.from(this.translationSourceFiles).some(\n (path) => !files.has(path),\n );\n\n const aKnownModelResourceSourceVanished = Array.from(this.modelResourceSourceFiles).some(\n (path) => !files.has(path),\n );\n\n const touchedAConfig =\n aKnownTranslationSourceVanished ||\n aKnownModelResourceSourceVanished ||\n Array.from(new Set(upcomingFiles)).some((file) => {\n const normalizedPath = Path.normalize(file);\n if (normalizedPath.includes(\"src/config/\")) return true;\n if (isRouteLocalesJsonPath(normalizedPath)) return true;\n if (isModuleLocaleDictionaryPath(normalizedPath)) return true;\n if (this.translationSourceFiles.has(normalizedPath)) return true;\n if (this.modelResourceSourceFiles.has(normalizedPath)) return true;\n if (files.get(normalizedPath)?.type === \"model\") return true;\n\n const fileManager = files.get(normalizedPath);\n return (\n fileManager !== undefined &&\n isTranslationRegisteringSource(normalizedPath, fileManager.source)\n );\n });\n\n if (!touchedAConfig) return;\n\n /*\n The changed paths are deliberately NOT passed along. The previous version\n built a `files` array here and then threw it away, spawning the same\n whole-project command as the branch above — so \"incremental\" was a name,\n not a behaviour. `generateAll()` reads the orchestrator, which the batch\n reload has already updated, so the full pass is both correct and the only\n pass that ever actually ran.\n */\n await runTypingsGeneration(this.typingsGenerationPorts);\n }\n}\n\n/**\n * Singleton instance for use throughout dev-server\n */\nexport const typeGenerator = new TypeGenerator();\n"],"mappings":"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"}
@@ -42,4 +42,5 @@ import { HttpServerRebuiltListener, notifyHttpServerRebuilt, onHttpServerRebuilt
42
42
  import { deriveTraceId, parseTraceparentTraceId } from "./tracing/trace-id.mjs";
43
43
  import { TracingContextSource, buildTracingContext, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, isTracingEnabled, registerTracingHooks, resetTracingConfigForTests, resolveTracingConfig } from "./tracing/tracing-dispatcher.mjs";
44
44
  import { RequestContextStore, requestContext, useCurrentUser, useRequest, useRequestStore } from "./context/request-context.mjs";
45
- import { requestMemo } from "./context/request-memo.mjs";
45
+ import { requestMemo } from "./context/request-memo.mjs";
46
+ import { ModelResourceRegistry, Serialized, SerializedWire } from "./serialized.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"inject-request-context.d.mts","names":[],"sources":["../../../../../../../../core/src/http/middleware/inject-request-context.ts"],"mappings":";;;;;;;AA8CA;;;iBAAgB,kBAAA,CACd,OAAA,EAAS,OAAA,OACT,QAAA,EAAU,QAAA,GACT,OAAA,CAAQ,gBAAA;;;;iBA2KK,CAAA,CAAE,OAAA,UAAiB,YAAA,GAAe,MAAM"}
1
+ {"version":3,"file":"inject-request-context.d.mts","names":[],"sources":["../../../../../../../../core/src/http/middleware/inject-request-context.ts"],"mappings":";;;;;;;AA8CA;;;iBAAgB,kBAAA,CACd,OAAA,EAAS,OAAA,OACT,QAAA,EAAU,QAAA,GACT,OAAA,CAAQ,gBAAA;;;;iBAqNK,CAAA,CAAE,OAAA,UAAiB,YAAA,GAAe,MAAM"}
@@ -69,12 +69,38 @@ function createRequestStore(request, response) {
69
69
  request.trigger("executedAction", request.route);
70
70
  return output;
71
71
  } catch (error) {
72
- request.log(error, "error");
72
+ logRequestError(error, request);
73
73
  return handleRequestError(error, response, request);
74
74
  }
75
75
  });
76
76
  }
77
77
  /**
78
+ * The HTTP status an error will be answered with, or `undefined` when it is not
79
+ * one of the known HTTP-answerable shapes (those fall through to the opaque 500).
80
+ *
81
+ * Single source for `handleRequestError` and the request logger, so the rule
82
+ * that decides the response status is the same rule that decides the log level.
83
+ * @internal
84
+ */
85
+ function resolveRequestErrorStatus(error) {
86
+ if (error instanceof HttpError) return error.status;
87
+ if (error instanceof DatabaseWriterValidationError) return config.get("http.modelValidationErrorStatus", 500);
88
+ }
89
+ /**
90
+ * Log a request error at the right severity. An error answered with a 4xx is an
91
+ * expected client error (a thrown 404/409/422): one `warn` line, no stack.
92
+ * Everything else (5xx, unknown errors) keeps the error-level entry with its stack.
93
+ * @internal
94
+ */
95
+ function logRequestError(error, request) {
96
+ const status = resolveRequestErrorStatus(error);
97
+ if (status !== void 0 && status < 500 && error instanceof Error) {
98
+ request.log(`${error.name}: ${error.message} (${status})`, "warn");
99
+ return;
100
+ }
101
+ request.log(error, "error");
102
+ }
103
+ /**
78
104
  * Unconditional floor for an unhandled request error (canon 8d3c13a8): route it
79
105
  * through the logger, and when no logger channel is configured (nothing would
80
106
  * record it) fall back to `console.error` so the only copy is never lost.
@@ -98,11 +124,11 @@ function handleRequestError(error, response, request) {
98
124
  return response.setStatusCode(error.status).send(payload);
99
125
  }
100
126
  if (error instanceof DatabaseWriterValidationError) {
101
- log.error("http", "model-write-validation-error", error, {
127
+ const status = resolveRequestErrorStatus(error);
128
+ if (status >= 500) log.error("http", "model-write-validation-error", error, {
102
129
  requestId: request.id,
103
130
  errors: error.errors
104
131
  });
105
- const status = config.get("http.modelValidationErrorStatus", 500);
106
132
  if (status < 500) return response.setStatusCode(status).send({ errors: error.errors });
107
133
  return response.setStatusCode(status).send({ error: "Internal server error." });
108
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inject-request-context.mjs","names":["requestContextInstance"],"sources":["../../../../../../../../core/src/http/middleware/inject-request-context.ts"],"sourcesContent":["/**\n * Request Context Middleware\n *\n * Creates a unified context for each request using the ContextManager.\n * All framework contexts (request, storage, database) are available throughout the request lifecycle.\n */\nimport { trans } from \"@mongez/localization\";\nimport { type GenericObject } from \"@mongez/reinforcements\";\nimport { DatabaseWriterValidationError } from \"@warlock.js/cascade\";\nimport { contextManager } from \"@warlock.js/context\";\nimport { log } from \"@warlock.js/logger\";\nimport config from \"@mongez/config\";\nimport { environment } from \"../../utils\";\nimport { requestContext as requestContextInstance } from \"../context/request-context\";\nimport { applyCspHeader } from \"../csp\";\nimport { runDefaultCsrfGuard } from \"../csrf-default-guard\";\nimport { HttpError } from \"../errors\";\nimport { type Request } from \"../request\";\nimport { type Response } from \"../response\";\nimport { buildTracingContext, dispatchPhase, isTracingEnabled } from \"../tracing\";\nimport { type ReturnedResponse } from \"./../types\";\n\n// Contexts are now registered in core/context/init-contexts.ts via initializeContexts()\n\n/**\n * Echo `request.id` back as a response header so the FE / proxies / log\n * aggregators can correlate by the same value the server logs against.\n *\n * Reads the header name from `http.requestId.header` (default `X-Request-Id`).\n * Skip when `http.requestId.enabled` is explicitly false.\n */\nfunction stampRequestIdHeader(request: Request, response: Response) {\n const requestIdConfig = config.get(\"http.requestId\", {} as Record<string, any>);\n\n if (requestIdConfig.enabled === false) return;\n\n const headerName = requestIdConfig.header || \"X-Request-Id\";\n\n response.header(headerName, request.id);\n}\n\n/**\n * Create request store and execute middleware + handler\n *\n * Runs all registered contexts together using ContextManager.\n */\nexport function createRequestStore(\n request: Request<any>,\n response: Response,\n): Promise<ReturnedResponse> {\n stampRequestIdHeader(request, response);\n\n // Stamped this early — before any middleware or handler runs — so the\n // header carries the SAME nonce the web layer later reads off\n // `request.nonce` for its `<script>` tags: `request.nonce` caches on first\n // read, and this is deliberately the first read. A no-op when the app\n // hasn't opted into `http.csp` (see `csp.ts`).\n applyCspHeader(request, response);\n\n // Build all context stores using the immutable API\n // Each context defines its own store initialization via buildStore()\n const httpContextStore = contextManager.buildStores({ request, response });\n\n // Run all contexts together!\n return contextManager.runAll(httpContextStore, async () => {\n try {\n // Default CSRF-Origin guard (SECURITY, card 8a752ab2) — the earliest\n // seam common to every request, BEFORE the route's own middleware\n // (`request.runMiddleware()` below) and before any app handler, so it\n // applies even to a route that never attaches\n // `authMiddleware(\"cookie:*\")`. See `../csrf-default-guard.ts` for the\n // full scope rule and `{ csrf: false }` exemption.\n const csrfGuardResponse = await runDefaultCsrfGuard(request, response, t, (reason) => {\n log.error(\n \"http\",\n \"csrf-default-guard\",\n new Error(`Default CSRF Origin guard refused request: ${reason}`),\n );\n });\n\n if (csrfGuardResponse) {\n return csrfGuardResponse as ReturnedResponse;\n }\n\n // Run middleware chain\n const result = await request.runMiddleware();\n\n if (result) {\n return result as ReturnedResponse;\n }\n\n // Execute route handler\n request.trigger(\"executingAction\", request.route);\n\n const handler = request.getHandler();\n\n request.log(\"Executing Handler\", \"info\");\n\n const tracingEnabled = isTracingEnabled();\n const handlerStartedAt = tracingEnabled ? performance.now() : 0;\n\n const output = await handler({ request, response });\n\n if (tracingEnabled) {\n dispatchPhase(buildTracingContext(request), {\n name: \"handler\",\n durationMs: performance.now() - handlerStartedAt,\n });\n }\n\n request.log(\"Handler Executed Successfully\", \"success\");\n\n request.trigger(\"executedAction\", request.route);\n\n return output as ReturnedResponse;\n } catch (error) {\n request.log(error, \"error\");\n return handleRequestError(error, response, request);\n }\n });\n}\n\n/**\n * Unconditional floor for an unhandled request error (canon 8d3c13a8): route it\n * through the logger, and when no logger channel is configured (nothing would\n * record it) fall back to `console.error` so the only copy is never lost.\n * @internal\n */\nfunction reportUnhandledRequestError(error: unknown, request: Request<any>) {\n log.error(\"http\", \"unhandled-request-error\", error, { requestId: request.id });\n\n if (log.channels.length === 0) {\n console.error(`[http] unhandled-request-error (requestId: ${request.id})`, error);\n }\n}\n\n/**\n * Handle request errors\n * @internal\n */\nfunction handleRequestError(\n error: unknown,\n response: Response,\n request: Request<any>,\n): ReturnedResponse {\n // Availability floor, not a cache-policy nit: `handleRequestError` is the\n // single funnel every unhandled error in every Warlock app passes through\n // (`createRequestStore`'s catch above), and none of the branches below set\n // a `Cache-Control` header. Without this, an error response — a 500 as\n // much as a 401/403/404 carrying per-request/-user state — can be stored\n // by a shared cache or CDN and replayed to other requests/users long after\n // the condition that caused it is gone: a cached 500 becomes an outage\n // that outlives its cause; a cached 401/403 becomes a leak across users.\n // Set once, here, before any branch runs — not per branch — because the\n // branches below do not partition by status. `ResourceNotFoundError`,\n // `UnAuthorizedError`, `ForbiddenError`, `BadRequestError` and `ServerError`\n // all extend `HttpError`, so the `HttpError` branch answers for every one of\n // them, and a raw `HttpError` can carry any caller-chosen status, 4xx or 5xx.\n // Gating the floor on the eventual status would mean re-deriving that status\n // per branch — one rule meeting one form while others reach the same output.\n // Applying it once, unconditionally, is both simpler and safer.\n response.header(\"Cache-Control\", \"private, no-store\");\n\n if (error instanceof HttpError) {\n // 5xx HttpErrors (e.g. `ServerError`) are server faults: send them to the\n // logger channels too, tagged with the request id.\n if (error.status >= 500) {\n log.error(\"http\", \"request-error\", error, { requestId: request.id });\n }\n\n const payload: GenericObject = {\n error: error.message,\n };\n if (error.payload) {\n payload.payload = error.payload;\n }\n\n if (environment() === \"development\") {\n payload.stack = error.stack;\n }\n\n return response.setStatusCode(error.status).send(payload);\n }\n\n if (error instanceof DatabaseWriterValidationError) {\n log.error(\"http\", \"model-write-validation-error\", error, {\n requestId: request.id,\n errors: error.errors,\n });\n\n const status = config.get(\"http.modelValidationErrorStatus\", 500);\n\n // A 4xx status means the app treats this as the client's fault, so the\n // field errors are useful to it; a 5xx stays opaque.\n if (status < 500) {\n return response.setStatusCode(status).send({\n errors: error.errors,\n });\n }\n\n return response.setStatusCode(status).send({\n error: \"Internal server error.\",\n });\n }\n\n // Last resort: the error matched none of the known shapes above, so the\n // client gets a deliberately opaque message. Without this line the error\n // itself is discarded here — no stack, no message, nothing in any log — and\n // an unrecognised failure becomes indistinguishable from a working server\n // returning 500. Never swallow the only copy of an error (`65e476ee`).\n reportUnhandledRequestError(error, request);\n\n return response.serverError({\n error: \"Internal server error.\",\n });\n}\n\n/**\n * Translate a keyword (uses request context for locale)\n */\nexport function t(keyword: string, placeholders?: Record<string, unknown>): string {\n return (\n requestContextInstance.getRequest()?.trans(keyword, placeholders) ||\n trans(keyword, placeholders)\n );\n}\n\n// `fromRequest` was removed in v5. It cached computed values as dynamic\n// properties on the Request instance, which only compiled because of the\n// `[key: string]: any` index signature that v5 deletes (eed20184). Use\n// `requestMemo(key, fn)` from `../context/request-memo` instead — same\n// per-request lifetime, single-flight, and it never touches the Request object.\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAS,qBAAqB,SAAkB,UAAoB;CAClE,MAAM,kBAAkB,OAAO,IAAI,kBAAkB,CAAC,CAAwB;CAE9E,IAAI,gBAAgB,YAAY,OAAO;CAEvC,MAAM,aAAa,gBAAgB,UAAU;CAE7C,SAAS,OAAO,YAAY,QAAQ,EAAE;AACxC;;;;;;AAOA,SAAgB,mBACd,SACA,UAC2B;CAC3B,qBAAqB,SAAS,QAAQ;CAOtC,eAAe,SAAS,QAAQ;CAIhC,MAAM,mBAAmB,eAAe,YAAY;EAAE;EAAS;CAAS,CAAC;CAGzE,OAAO,eAAe,OAAO,kBAAkB,YAAY;EACzD,IAAI;GAOF,MAAM,oBAAoB,MAAM,oBAAoB,SAAS,UAAU,IAAI,WAAW;IACpF,IAAI,MACF,QACA,sCACA,IAAI,MAAM,8CAA8C,QAAQ,CAClE;GACF,CAAC;GAED,IAAI,mBACF,OAAO;GAIT,MAAM,SAAS,MAAM,QAAQ,cAAc;GAE3C,IAAI,QACF,OAAO;GAIT,QAAQ,QAAQ,mBAAmB,QAAQ,KAAK;GAEhD,MAAM,UAAU,QAAQ,WAAW;GAEnC,QAAQ,IAAI,qBAAqB,MAAM;GAEvC,MAAM,iBAAiB,iBAAiB;GACxC,MAAM,mBAAmB,iBAAiB,YAAY,IAAI,IAAI;GAE9D,MAAM,SAAS,MAAM,QAAQ;IAAE;IAAS;GAAS,CAAC;GAElD,IAAI,gBACF,cAAc,oBAAoB,OAAO,GAAG;IAC1C,MAAM;IACN,YAAY,YAAY,IAAI,IAAI;GAClC,CAAC;GAGH,QAAQ,IAAI,iCAAiC,SAAS;GAEtD,QAAQ,QAAQ,kBAAkB,QAAQ,KAAK;GAE/C,OAAO;EACT,SAAS,OAAO;GACd,QAAQ,IAAI,OAAO,OAAO;GAC1B,OAAO,mBAAmB,OAAO,UAAU,OAAO;EACpD;CACF,CAAC;AACH;;;;;;;AAQA,SAAS,4BAA4B,OAAgB,SAAuB;CAC1E,IAAI,MAAM,QAAQ,2BAA2B,OAAO,EAAE,WAAW,QAAQ,GAAG,CAAC;CAE7E,IAAI,IAAI,SAAS,WAAW,GAC1B,QAAQ,MAAM,8CAA8C,QAAQ,GAAG,IAAI,KAAK;AAEpF;;;;;AAMA,SAAS,mBACP,OACA,UACA,SACkB;CAiBlB,SAAS,OAAO,iBAAiB,mBAAmB;CAEpD,IAAI,iBAAiB,WAAW;EAG9B,IAAI,MAAM,UAAU,KAClB,IAAI,MAAM,QAAQ,iBAAiB,OAAO,EAAE,WAAW,QAAQ,GAAG,CAAC;EAGrE,MAAM,UAAyB,EAC7B,OAAO,MAAM,QACf;EACA,IAAI,MAAM,SACR,QAAQ,UAAU,MAAM;EAG1B,IAAI,YAAY,MAAM,eACpB,QAAQ,QAAQ,MAAM;EAGxB,OAAO,SAAS,cAAc,MAAM,MAAM,CAAC,CAAC,KAAK,OAAO;CAC1D;CAEA,IAAI,iBAAiB,+BAA+B;EAClD,IAAI,MAAM,QAAQ,gCAAgC,OAAO;GACvD,WAAW,QAAQ;GACnB,QAAQ,MAAM;EAChB,CAAC;EAED,MAAM,SAAS,OAAO,IAAI,mCAAmC,GAAG;EAIhE,IAAI,SAAS,KACX,OAAO,SAAS,cAAc,MAAM,CAAC,CAAC,KAAK,EACzC,QAAQ,MAAM,OAChB,CAAC;EAGH,OAAO,SAAS,cAAc,MAAM,CAAC,CAAC,KAAK,EACzC,OAAO,yBACT,CAAC;CACH;CAOA,4BAA4B,OAAO,OAAO;CAE1C,OAAO,SAAS,YAAY,EAC1B,OAAO,yBACT,CAAC;AACH;;;;AAKA,SAAgB,EAAE,SAAiB,cAAgD;CACjF,OACEA,eAAuB,WAAW,CAAC,EAAE,MAAM,SAAS,YAAY,KAChE,MAAM,SAAS,YAAY;AAE/B"}
1
+ {"version":3,"file":"inject-request-context.mjs","names":["requestContextInstance"],"sources":["../../../../../../../../core/src/http/middleware/inject-request-context.ts"],"sourcesContent":["/**\n * Request Context Middleware\n *\n * Creates a unified context for each request using the ContextManager.\n * All framework contexts (request, storage, database) are available throughout the request lifecycle.\n */\nimport { trans } from \"@mongez/localization\";\nimport { type GenericObject } from \"@mongez/reinforcements\";\nimport { DatabaseWriterValidationError } from \"@warlock.js/cascade\";\nimport { contextManager } from \"@warlock.js/context\";\nimport { log } from \"@warlock.js/logger\";\nimport config from \"@mongez/config\";\nimport { environment } from \"../../utils\";\nimport { requestContext as requestContextInstance } from \"../context/request-context\";\nimport { applyCspHeader } from \"../csp\";\nimport { runDefaultCsrfGuard } from \"../csrf-default-guard\";\nimport { HttpError } from \"../errors\";\nimport { type Request } from \"../request\";\nimport { type Response } from \"../response\";\nimport { buildTracingContext, dispatchPhase, isTracingEnabled } from \"../tracing\";\nimport { type ReturnedResponse } from \"./../types\";\n\n// Contexts are now registered in core/context/init-contexts.ts via initializeContexts()\n\n/**\n * Echo `request.id` back as a response header so the FE / proxies / log\n * aggregators can correlate by the same value the server logs against.\n *\n * Reads the header name from `http.requestId.header` (default `X-Request-Id`).\n * Skip when `http.requestId.enabled` is explicitly false.\n */\nfunction stampRequestIdHeader(request: Request, response: Response) {\n const requestIdConfig = config.get(\"http.requestId\", {} as Record<string, any>);\n\n if (requestIdConfig.enabled === false) return;\n\n const headerName = requestIdConfig.header || \"X-Request-Id\";\n\n response.header(headerName, request.id);\n}\n\n/**\n * Create request store and execute middleware + handler\n *\n * Runs all registered contexts together using ContextManager.\n */\nexport function createRequestStore(\n request: Request<any>,\n response: Response,\n): Promise<ReturnedResponse> {\n stampRequestIdHeader(request, response);\n\n // Stamped this early — before any middleware or handler runs — so the\n // header carries the SAME nonce the web layer later reads off\n // `request.nonce` for its `<script>` tags: `request.nonce` caches on first\n // read, and this is deliberately the first read. A no-op when the app\n // hasn't opted into `http.csp` (see `csp.ts`).\n applyCspHeader(request, response);\n\n // Build all context stores using the immutable API\n // Each context defines its own store initialization via buildStore()\n const httpContextStore = contextManager.buildStores({ request, response });\n\n // Run all contexts together!\n return contextManager.runAll(httpContextStore, async () => {\n try {\n // Default CSRF-Origin guard (SECURITY, card 8a752ab2) — the earliest\n // seam common to every request, BEFORE the route's own middleware\n // (`request.runMiddleware()` below) and before any app handler, so it\n // applies even to a route that never attaches\n // `authMiddleware(\"cookie:*\")`. See `../csrf-default-guard.ts` for the\n // full scope rule and `{ csrf: false }` exemption.\n const csrfGuardResponse = await runDefaultCsrfGuard(request, response, t, (reason) => {\n log.error(\n \"http\",\n \"csrf-default-guard\",\n new Error(`Default CSRF Origin guard refused request: ${reason}`),\n );\n });\n\n if (csrfGuardResponse) {\n return csrfGuardResponse as ReturnedResponse;\n }\n\n // Run middleware chain\n const result = await request.runMiddleware();\n\n if (result) {\n return result as ReturnedResponse;\n }\n\n // Execute route handler\n request.trigger(\"executingAction\", request.route);\n\n const handler = request.getHandler();\n\n request.log(\"Executing Handler\", \"info\");\n\n const tracingEnabled = isTracingEnabled();\n const handlerStartedAt = tracingEnabled ? performance.now() : 0;\n\n const output = await handler({ request, response });\n\n if (tracingEnabled) {\n dispatchPhase(buildTracingContext(request), {\n name: \"handler\",\n durationMs: performance.now() - handlerStartedAt,\n });\n }\n\n request.log(\"Handler Executed Successfully\", \"success\");\n\n request.trigger(\"executedAction\", request.route);\n\n return output as ReturnedResponse;\n } catch (error) {\n logRequestError(error, request);\n return handleRequestError(error, response, request);\n }\n });\n}\n\n/**\n * The HTTP status an error will be answered with, or `undefined` when it is not\n * one of the known HTTP-answerable shapes (those fall through to the opaque 500).\n *\n * Single source for `handleRequestError` and the request logger, so the rule\n * that decides the response status is the same rule that decides the log level.\n * @internal\n */\nfunction resolveRequestErrorStatus(error: unknown): number | undefined {\n if (error instanceof HttpError) {\n return error.status;\n }\n\n if (error instanceof DatabaseWriterValidationError) {\n return config.get(\"http.modelValidationErrorStatus\", 500);\n }\n\n return undefined;\n}\n\n/**\n * Log a request error at the right severity. An error answered with a 4xx is an\n * expected client error (a thrown 404/409/422): one `warn` line, no stack.\n * Everything else (5xx, unknown errors) keeps the error-level entry with its stack.\n * @internal\n */\nfunction logRequestError(error: unknown, request: Request<any>) {\n const status = resolveRequestErrorStatus(error);\n\n if (status !== undefined && status < 500 && error instanceof Error) {\n request.log(`${error.name}: ${error.message} (${status})`, \"warn\");\n\n return;\n }\n\n request.log(error, \"error\");\n}\n\n/**\n * Unconditional floor for an unhandled request error (canon 8d3c13a8): route it\n * through the logger, and when no logger channel is configured (nothing would\n * record it) fall back to `console.error` so the only copy is never lost.\n * @internal\n */\nfunction reportUnhandledRequestError(error: unknown, request: Request<any>) {\n log.error(\"http\", \"unhandled-request-error\", error, { requestId: request.id });\n\n if (log.channels.length === 0) {\n console.error(`[http] unhandled-request-error (requestId: ${request.id})`, error);\n }\n}\n\n/**\n * Handle request errors\n * @internal\n */\nfunction handleRequestError(\n error: unknown,\n response: Response,\n request: Request<any>,\n): ReturnedResponse {\n // Availability floor, not a cache-policy nit: `handleRequestError` is the\n // single funnel every unhandled error in every Warlock app passes through\n // (`createRequestStore`'s catch above), and none of the branches below set\n // a `Cache-Control` header. Without this, an error response — a 500 as\n // much as a 401/403/404 carrying per-request/-user state — can be stored\n // by a shared cache or CDN and replayed to other requests/users long after\n // the condition that caused it is gone: a cached 500 becomes an outage\n // that outlives its cause; a cached 401/403 becomes a leak across users.\n // Set once, here, before any branch runs — not per branch — because the\n // branches below do not partition by status. `ResourceNotFoundError`,\n // `UnAuthorizedError`, `ForbiddenError`, `BadRequestError` and `ServerError`\n // all extend `HttpError`, so the `HttpError` branch answers for every one of\n // them, and a raw `HttpError` can carry any caller-chosen status, 4xx or 5xx.\n // Gating the floor on the eventual status would mean re-deriving that status\n // per branch — one rule meeting one form while others reach the same output.\n // Applying it once, unconditionally, is both simpler and safer.\n response.header(\"Cache-Control\", \"private, no-store\");\n\n if (error instanceof HttpError) {\n // 5xx HttpErrors (e.g. `ServerError`) are server faults: send them to the\n // logger channels too, tagged with the request id.\n if (error.status >= 500) {\n log.error(\"http\", \"request-error\", error, { requestId: request.id });\n }\n\n const payload: GenericObject = {\n error: error.message,\n };\n if (error.payload) {\n payload.payload = error.payload;\n }\n\n if (environment() === \"development\") {\n payload.stack = error.stack;\n }\n\n return response.setStatusCode(error.status).send(payload);\n }\n\n if (error instanceof DatabaseWriterValidationError) {\n const status = resolveRequestErrorStatus(error) as number;\n\n // A 4xx is an expected client error, already logged as a one-line warn by\n // `logRequestError`; only a 5xx gets the error-level entry with its stack.\n if (status >= 500) {\n log.error(\"http\", \"model-write-validation-error\", error, {\n requestId: request.id,\n errors: error.errors,\n });\n }\n\n // A 4xx status means the app treats this as the client's fault, so the\n // field errors are useful to it; a 5xx stays opaque.\n if (status < 500) {\n return response.setStatusCode(status).send({\n errors: error.errors,\n });\n }\n\n return response.setStatusCode(status).send({\n error: \"Internal server error.\",\n });\n }\n\n // Last resort: the error matched none of the known shapes above, so the\n // client gets a deliberately opaque message. Without this line the error\n // itself is discarded here — no stack, no message, nothing in any log — and\n // an unrecognised failure becomes indistinguishable from a working server\n // returning 500. Never swallow the only copy of an error (`65e476ee`).\n reportUnhandledRequestError(error, request);\n\n return response.serverError({\n error: \"Internal server error.\",\n });\n}\n\n/**\n * Translate a keyword (uses request context for locale)\n */\nexport function t(keyword: string, placeholders?: Record<string, unknown>): string {\n return (\n requestContextInstance.getRequest()?.trans(keyword, placeholders) ||\n trans(keyword, placeholders)\n );\n}\n\n// `fromRequest` was removed in v5. It cached computed values as dynamic\n// properties on the Request instance, which only compiled because of the\n// `[key: string]: any` index signature that v5 deletes (eed20184). Use\n// `requestMemo(key, fn)` from `../context/request-memo` instead — same\n// per-request lifetime, single-flight, and it never touches the Request object.\n"],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { Model } from "@warlock.js/cascade";
2
+
3
+ //#region ../core/src/http/serialized.d.ts
4
+ /**
5
+ * The two wire formats Warlock serializes a value into.
6
+ *
7
+ * - `"json"`: an API response. `Response.parse` walks the value, then the body
8
+ * is `JSON.stringify`-ed. `Date` becomes a string, `Map` an object, `Set` an
9
+ * array.
10
+ * - `"devalue"`: page loader data. `serializeLoaderData` walks the value, then
11
+ * `devalue` encodes it. `Date`, `Map`, `Set`, `RegExp` and `URL` survive as
12
+ * native values.
13
+ */
14
+ type SerializedWire = "json" | "devalue";
15
+ /**
16
+ * Maps cascade models to the resource that serializes them.
17
+ *
18
+ * Empty on purpose: `Model.resource` is a static typed `any`, so a model
19
+ * instance type cannot reveal its resource. A code generator (or the app)
20
+ * augments this interface instead, one entry per model:
21
+ *
22
+ * @example
23
+ * declare module "@warlock.js/core" {
24
+ * interface ModelResourceRegistry {
25
+ * User: { model: User; resource: typeof UserResource };
26
+ * }
27
+ * }
28
+ *
29
+ * `Serialized<User>` then resolves to the output of `UserResource`. A model
30
+ * with no entry resolves to its serialized `data` type instead.
31
+ */
32
+ interface ModelResourceRegistry {}
33
+ /** Deepest level `Serialized` walks before giving up with `unknown`. */
34
+ type MaxSerializedDepth = 8;
35
+ type IsAny<T> = 0 extends 1 & T ? true : false;
36
+ type Primitive = string | number | boolean | bigint | symbol | null | undefined;
37
+ /** Passes through untouched on both wires (`Buffer` has a `toJSON`, so it must be caught first). */
38
+ type Binary = Buffer | Uint8Array;
39
+ /** Returned whole by `serializeLoaderData` before `toJSON` is considered. */
40
+ type DevalueNative = Date | RegExp | URL | Map<any, any> | Set<any>;
41
+ /**
42
+ * Built-in classes that are not plain objects and have no `toJSON`. JSON emits
43
+ * `{}` for them (their state is not enumerable); devalue cannot encode them.
44
+ */
45
+ type OpaqueBuiltin = Error | WeakMap<any, any> | WeakSet<any> | WeakRef<any>;
46
+ type IsFunctionValued<V> = IsAny<V> extends true ? false : [Exclude<V, undefined>] extends [never] ? false : [Exclude<V, undefined>] extends [(...args: any[]) => any] ? true : false;
47
+ type IsUndefinable<V> = IsAny<V> extends true ? false : unknown extends V ? false : undefined extends V ? true : false;
48
+ /** Keys whose value is not a function: functions are dropped by JSON and by the key-removal rule. */
49
+ type DataKeys<T> = { [K in keyof T]-?: IsFunctionValued<T[K]> extends true ? never : K }[keyof T];
50
+ /** Keys that JSON omits when their value is `undefined`, so they become optional on the json wire. */
51
+ type UndefinableKeys<T> = { [K in keyof T]-?: K extends DataKeys<T> ? (IsUndefinable<T[K]> extends true ? K : never) : never }[keyof T];
52
+ type Flatten<T> = { [K in keyof T]: T[K] };
53
+ /**
54
+ * Whether `T` has members a mapped copy cannot carry (private, protected or
55
+ * `#private`). Only such a class is detectable as a class at the type level; a
56
+ * class with public members only is structurally an interface, so it is treated
57
+ * as a plain object. Mapping `keyof T` drops the non-public members, which makes
58
+ * the copy unassignable back to `T`.
59
+ */
60
+ type HasNonPublicMembers<T> = { [K in keyof T]: T[K] } extends T ? false : true;
61
+ /** Resource registered for the model type `T`, or `never` when `T` has no entry. */
62
+ type RegisteredResource<T> = { [K in keyof ModelResourceRegistry]: ModelResourceRegistry[K] extends {
63
+ model: infer M;
64
+ resource: infer R;
65
+ } ? [T] extends [M] ? [M] extends [T] ? R : never : never : never }[keyof ModelResourceRegistry];
66
+ /** What a resource class emits from `toJSON()`, serialized for the wire. */
67
+ type SerializedResource<R, W extends SerializedWire, D extends unknown[]> = R extends (new (...args: any[]) => {
68
+ toJSON(): infer O;
69
+ }) ? Serialized<O, W, D> : unknown;
70
+ type SerializedModel<T, W extends SerializedWire, D extends unknown[]> = [RegisteredResource<T>] extends [never] ? T extends {
71
+ data: infer Data;
72
+ } ? Serialized<Data, W, [...D, 0]> : never : SerializedResource<RegisteredResource<T>, W, [...D, 0]>;
73
+ type SerializedJsonObject<T, D extends unknown[]> = Flatten<{ [K in keyof T as K extends Exclude<DataKeys<T>, UndefinableKeys<T>> ? K : never]-?: Serialized<T[K], "json", [...D, 0]> } & { [K in keyof T as K extends UndefinableKeys<T> ? K : never]+?: Serialized<Exclude<T[K], undefined>, "json", [...D, 0]> }>;
74
+ type SerializedDevalueObject<T, D extends unknown[]> = { -readonly [K in keyof T as K extends DataKeys<T> ? K : never]: Serialized<T[K], "devalue", [...D, 0]> };
75
+ type SerializedObject<T, W extends SerializedWire, D extends unknown[]> = W extends "json" ? SerializedJsonObject<T, D> : SerializedDevalueObject<T, D>;
76
+ /**
77
+ * The type of what a client receives after Warlock serializes a value of type
78
+ * `T`. It mirrors `Response.parse` (`"json"`, the default) and
79
+ * `serializeLoaderData` (`"devalue"`), branch for branch and in the same order:
80
+ *
81
+ * 1. `any` stays `any`; `unknown` stays `unknown`; primitives pass through.
82
+ * 2. `Buffer` / `Uint8Array` pass through on both wires.
83
+ * 3. devalue: `Date`, `RegExp`, `URL`, `Map`, `Set` stay native.
84
+ * json: `Map<K, V>` becomes `Record<K, V'>`.
85
+ * 4. A cascade `Model`: the output of its registered resource (see
86
+ * {@link ModelResourceRegistry}), else its serialized `data` type.
87
+ * 5. Anything with `toJSON()`: the serialized (awaited) result. This is where a
88
+ * `Date` becomes a `string` on json.
89
+ * 6. Arrays and tuples map item by item; other iterables (a `Set` on json,
90
+ * generators) become arrays.
91
+ * 7. Functions are removed from objects (and are `never` on their own).
92
+ * 8. Objects are mapped key by key. On json a key whose value can be
93
+ * `undefined` becomes optional, because `JSON.stringify` omits it.
94
+ *
95
+ * Plain object vs class instance cannot be decided by the type system in
96
+ * general. The rule used: only a class with non-public (private, protected or
97
+ * `#private`) members, or a built-in such as `Error`, is treated as a class
98
+ * instance without `toJSON`. It maps to its public data properties on json
99
+ * (`Error` to `{}`) and to `never` on devalue, where devalue throws at render
100
+ * time. Any other object type is treated as plain.
101
+ *
102
+ * Nesting is walked up to a fixed depth, then the result is `unknown`.
103
+ *
104
+ * @example
105
+ * type UserPayload = Serialized<User>; // resource output or serialized data
106
+ * type PageData = Serialized<LoaderReturn, "devalue">;
107
+ */
108
+ type Serialized<T, W extends SerializedWire = "json", D extends unknown[] = []> = IsAny<T> extends true ? any : unknown extends T ? unknown : D["length"] extends MaxSerializedDepth ? unknown : T extends Primitive ? T : T extends Binary ? T : W extends "devalue" ? T extends DevalueNative ? T : T extends PromiseLike<infer V> ? Serialized<V, W, D> : SerializedStructure<T, W, D> : T extends Map<infer K, infer V> ? Record<Extract<K, PropertyKey>, Serialized<V, W, D>> : SerializedStructure<T, W, D>;
109
+ type SerializedStructure<T, W extends SerializedWire, D extends unknown[]> = T extends Model<any> ? SerializedModel<T, W, D> : T extends {
110
+ toJSON(...args: any[]): infer R;
111
+ } ? Serialized<Awaited<R>, W, [...D, 0]> : T extends readonly unknown[] ? { -readonly [K in keyof T]: Serialized<T[K], W, D> } : T extends Iterable<infer I> ? Serialized<I, W, D>[] : T extends ((...args: any[]) => any) ? never : T extends OpaqueBuiltin ? W extends "json" ? {} : never : HasNonPublicMembers<T> extends true ? W extends "json" ? SerializedObject<T, W, D> : never : SerializedObject<T, W, D>;
112
+ //#endregion
113
+ export { ModelResourceRegistry, Serialized, SerializedWire };
114
+ //# sourceMappingURL=serialized.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialized.d.mts","names":[],"sources":["../../../../../../../core/src/http/serialized.ts"],"mappings":"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"}
package/esm/index.d.mts CHANGED
@@ -64,11 +64,12 @@ import { deriveTraceId, parseTraceparentTraceId } from "./http/tracing/trace-id.
64
64
  import { TracingContextSource, buildTracingContext, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, isTracingEnabled, registerTracingHooks, resetTracingConfigForTests, resolveTracingConfig } from "./http/tracing/tracing-dispatcher.mjs";
65
65
  import { RequestContextStore, requestContext, useCurrentUser, useRequest, useRequestStore } from "./http/context/request-context.mjs";
66
66
  import { requestMemo } from "./http/context/request-memo.mjs";
67
+ import { ModelResourceRegistry, Serialized, SerializedWire } from "./http/serialized.mjs";
67
68
  import { LocalizedObject, getLocalized } from "./utils/get-localized.mjs";
68
69
  import { ResourceFieldBuilder } from "./resource/resource-field-builder.mjs";
69
70
  import { Resource, ResourceConstructor, ResourceContract } from "./resource/resource.mjs";
70
- import { ResourceArraySchema, ResourceCastType, ResourceFieldBuilderDateOutputOptions, ResourceFieldConfig, ResourceOutputValueCastType, ResourceSchema, ResourceSelfReference, ResponseBodyValue, ResponseSchema } from "./resource/types.mjs";
71
- import { GroupedRoutesOptions, HttpContext, Middleware, MiddlewareResponse, NamedApiRoute, PartialPick, RequestControllerContract, RequestHandler, RequestHandlerType, RequestHandlerValidation, RequestMethod, ResourceMethod, RestfulMiddleware, Route, RouteOptions, RouteResource, RouterGroupCallback, RouterStacks } from "./router/types.mjs";
71
+ import { BaseCastOutput, CastOutput, FieldOutput, ResourceArraySchema, ResourceCastType, ResourceFieldBuilderDateOutputOptions, ResourceFieldConfig, ResourceOutput, ResourceOutputOf, ResourceOutputValueCastType, ResourceSchema, ResourceSelfReference, ResponseBodyOutput, ResponseBodyValue, ResponseSchema, ResponseSchemaOutput } from "./resource/types.mjs";
72
+ import { GroupedRoutesOptions, HttpContext, Middleware, MiddlewareResponse, NamedApiRoute, NamedApiRoutesOptions, PartialPick, RequestControllerContract, RequestHandler, RequestHandlerType, RequestHandlerValidation, RequestMethod, ResourceMethod, RestfulMiddleware, Route, RouteOptions, RouteResource, RouterGroupCallback, RouterStacks } from "./router/types.mjs";
72
73
  import { PositionalHandlerSuspect, clearPositionalHandlerSuspects, describePositionalHandlerSuspect, forgetPositionalHandlerSuspects, inspectHandlerSignature, listPositionalHandlerSuspects, looksLikePositionalHandler, reportPositionalHandlerSuspects } from "./router/positional-handler-diagnostics.mjs";
73
74
  import { matchesDerivedRouteName, routeNameMethodSuffix } from "./router/route-name-method-suffix.mjs";
74
75
  import { RouteRegistry } from "./router/route-registry.mjs";
@@ -138,6 +139,12 @@ import { renderReactMail } from "./mail/react-mail.mjs";
138
139
  import { sendMail } from "./mail/send-mail.mjs";
139
140
  import { Mail } from "./mail/mail.mjs";
140
141
  import { assertMailCount, assertMailSent, captureMail, clearTestMailbox, findMailsBySubject, findMailsTo, getLastMail, getMailboxSize, getTestMailbox, wasMailSentTo, wasMailSentWithSubject } from "./mail/test-mailbox.mjs";
142
+ import { PostmanAuth, PostmanAuthEntry, PostmanBody, PostmanCollection, PostmanCollectionOptions, PostmanFolder, PostmanFormParam, PostmanHeader, PostmanItem, PostmanOriginalRequest, PostmanQueryParam, PostmanRequest, PostmanRequestItem, PostmanResponse, PostmanUrl, PostmanVariable } from "./openapi/postman/postman-types.mjs";
143
+ import { AuthDescriptor, OpenApiBuildResult, OpenApiComponents, OpenApiContext, OpenApiDocument, OpenApiOperation, OpenApiParameter, OpenApiRequestBody, OpenApiResponse, OpenApiRouteInput, OpenApiSchema, OpenApiSecurityRequirement, OpenApiSecurityScheme, OpenApiValidationResponseConfig, WarningSink } from "./openapi/types.mjs";
144
+ import { DevelopmentPostmanResult, getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, registerDevelopmentOpenApiProvider } from "./openapi/development-openapi-provider.mjs";
145
+ import { OPENAPI_JSON_SCHEMA_DIALECT, buildOpenApiDocument } from "./openapi/build-openapi-document.mjs";
146
+ import { exampleFromSchema } from "./openapi/postman/example-from-schema.mjs";
147
+ import { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection } from "./openapi/postman/openapi-to-postman-collection.mjs";
141
148
  import { renderReact } from "./react/index.mjs";
142
149
  import { RepositoryManager } from "./repositories/repository.manager.mjs";
143
150
  import { RepositoryAdapterContract } from "./repositories/contracts/repository-adapter.contract.mjs";
@@ -182,9 +189,10 @@ import { WarlockConfigManager, isUnknownTsExtensionError, warlockConfigManager }
182
189
  import { env } from "@mongez/dotenv";
183
190
  import { colors } from "@mongez/copper";
184
191
  export * from "@mongez/localization";
185
- export { $registerUseCase, $unregisterUseCase, APP_ROLES, AccessConnector, AggregateExpressionInput, AggregateExpressions, AiConnector, AllRepositoryOptions, AppConfigurations, AppRole, Application, BOOT_SIGNAL_ENV_KEY, BOOT_SIGNAL_VERSION, BadRequestError, BadSchemaUseCaseError, BaseConnector, type BenchmarkChannel, type BenchmarkConfigurations, type BenchmarkErrorResult, type BenchmarkOptions, BenchmarkProfiler, type BenchmarkProfilerOptions, type BenchmarkResult, BenchmarkSnapshots, type BenchmarkSnapshotsOptions, type BenchmarkStats, type BenchmarkSuccessResult, BootContext, BootListener, BootSignal, BootSignalType, BootValidator, CLICommand, type CLICommandAction, type CLICommandOption, type CLICommandOptions, type CLICommandPreload, type CLICommandSource, CacheConnector, type CacheMiddlewareOptions, CachedRepositoryOptions, type CapturedMail, CascadeAdapter, CascadeQueryBuilder, ChunkCallback, ClosableServer, CloudDriver, CloudStorageDriverContract, CloudStorageDriverOptions, CloudStorageFileData, type CommandActionData, type ConcurrencyLimitOptions, ConfigKey, ConfigKeyRegistry, ConfigName, ConfigRegistry, ConfigSpecialHandlers, ConflictError, Connector, ConnectorBuildContext, ConnectorBuildContribution, ConnectorBuildGenerateResult, ConnectorEsbuildPatch, ConnectorLifecyclePhase, ConnectorName, ConnectorPriority, ConnectorsManager, ConsoleChannel, ContainerTypes, CookieJarUnavailableError, CookieOptions, CspConfig, CsrfOriginCheckReason, CsrfOriginVerdict, CursorPaginationOptions, CursorPaginationResult, DEFAULT_CSP_DIRECTIVES, DOSpacesDriver, DatabaseCacheDriver, type DatabaseCacheOptions, DatabaseConnector, DatabaseLog, DatabaseLogModel, DatabaseLogOptions, DecodedAccessToken, DefineResourceOptions, DeleteManyResult, DetectedImageFormat, type DevelopmentModelModuleEntry, type DevelopmentModelModuleState, type DevelopmentModelModules, EncryptionConfigurations, EncryptionPasswordConfigurations, Environment, EventSubscription, ExistsExceptCurrentIdRuleOptions, ExistsExceptCurrentUserRuleOptions, FastifyInstance, FileNamingStrategy, FileValidationOptions, FileValidator, FileVisibility, FilterFunction, FilterOperator, FilterOptions, FilterRule, FilterRules, ForbiddenError, GenerateImageVariantsOptions, GeneratedImageDescriptor, GeneratedImageVariant, GroupByFields, GroupedRoutesOptions, HealthCheck, HealthStatus, HeraldConnector, HttpConfigurations, HttpConnector, HttpContext, HttpError, HttpErrorCodes, HttpReadyReport, HttpServerRebuiltListener, HttpTracingConfig, type IdempotencyOptions, Image, ImageFormat, ImageInput, ImageTransformCallback, ImageTransformConfig, ImageTransformOptions, ImageVariantDefinition, ImageVariantFit, ImageVariantOutputFormat, ImageVariantsConfigError, InvalidCspDirectiveError, type IpFilterOptions, ListOptions, LocalDriver, LocalStorageDriverOptions, LocaleDictionaryEntries, LocaleDictionaryError, LocalizedObject, LogConfigurations, LoggerConnector, MAIL_EVENTS, Mail, type MailAddress, type MailAttachment, type MailConfigurations, MailError, type MailErrorCode, type MailEvents, type MailMode, type MailOptions, type MailPriority, type MailResult, MailerConnector, type MailersConfig, type MaintenanceOptions, Middleware, MiddlewareResponse, MimeTypes, NamedApiRoute, NoopChannel, type NormalizedMail, NotAcceptableError, NotAllowedError, NotificationsConnector, PaginationMode, PaginationResult, ParsedLocaleDictionary, PartialMiddleware, PartialPick, Path, PipeableReactStream, PipelineOptions, PortInUseError, PositionalHandlerSuspect, PrefixConfig, PrefixOptions, PresignedOptions, PresignedUploadOptions, PutDirectoryOptions, PutDirectoryResult, PutFromUrlOptions, PutOptions, QueryBuilderContract, Queue, R2Driver, R2StorageDriverOptions, type RateLimitOptions, RegisterConfiguredConnectorsOptions, RegisterResource, RegisteredUseCase, RepositoryAdapterContract, RepositoryConfigurations, RepositoryEvent, RepositoryManager, RepositoryOptions, RepositoryOptionsWithCursor, RepositoryOptionsWithPages, Request, RequestContextStore, RequestController, RequestControllerContract, RequestEvent, RequestHandler, RequestHandlerType, RequestHandlerValidation, RequestLocals, RequestLog, RequestMethod, RequestTranslator, type ResolvedCLICommandOption, ResolvedImageVariantsConfig, Resource, ResourceArraySchema, ResourceCastType, ResourceConstructor, ResourceContract, ResourceFieldBuilder, ResourceFieldBuilderDateOutputOptions, ResourceFieldConfig, ResourceMethod, ResourceNotFoundError, ResourceOutputValueCastType, ResourceSchema, ResourceSelfReference, Response, ResponseBodyValue, ResponseEvent, ResponseSSEController, ResponseSchema, ResponseStatus, ResponseStreamController, Restful, RestfulMiddleware, ReturnedResponse, Route, RouteOptions, RouteRegistry, RouteResource, Router, RouterGroupCallback, RouterStacks, RuntimeStrategy, S3Driver, type SESConfigurations, type SMTPConfigurations, SafeFetchOptions, SafeFetchResult, SaveAsOptions, SaveMode, SaveOptions, ScopedStorage, ScopedStorageContract, SeedClock, SeedContext, SeedRecordRef, SeedResult, Seeder, SeederDependencyCycleError, SeederMetadata, SendBufferOptions, SendFileOptions, ServerError, ShutdownListener, SocketAdapterFactory, SocketConnector, SocketOptions, Storage, StorageCapabilityError, StorageConfigurations, StorageConnector, StorageCopyEventPayload, StorageDriverConfig, StorageDriverContextStore, StorageDriverContract, StorageDriverName, StorageDriverRegistry, StorageDriverType, StorageError, StorageErrorOptions, StorageEventHandler, StorageEventPayload, StorageEventType, StorageFile, StorageFileData, StorageFileInfo, StorageManagerContract, StorageNotInitializedError, StoragePutEventPayload, StreamReactResponseOptions, TemporaryTokenError, TemporaryTokenPayload, TemporaryTokenValidation, TracingContext, TracingContextSource, TracingHooks, TracingPhaseInfo, TracingRequestEndInfo, Track, TrackableModel, TypedAllRepositoryOptions, TypedRepositoryOptions, TypedRepositoryOptionsWithCursor, TypedRepositoryOptionsWithPages, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, UnAuthorizedError, UniqueExceptCurrentIdRuleOptions, UniqueExceptCurrentUserRuleOptions, UnknownSeederDependencyError, UploadedFile, UploadedFileImageOptions, UploadedFileJson, UploadedFileQuery, UploadsConfigurations, UploadsImagesConfigurations, UseCase, UseCaseAfterMiddleware, UseCaseBeforeMiddleware, UseCaseBroadcastChannel, UseCaseBroadcastEvent, UseCaseBroadcastOption, UseCaseConfigurations, UseCaseContext, UseCaseErrorResult, UseCaseEventsCallbacksMap, UseCaseGuard, UseCaseHandler, UseCaseOnExecutingContext, UseCaseResult, UseCaseRuntimeOptions, UseCaseWithSchema, ValidationConfiguration, VariantOutputFormat, VariantSourceFormat, WarlockConfig, WarlockConfigManager, WatermarkConfig, WhereOperator, XMLable, addUseCaseHistory, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assetsUrl, bootstrap, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, decrypt, defaultHttpConfigurations, defineConfig, defineResource, deriveTraceId, describePositionalHandlerSuspect, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, existsExceptCurrentIdRule, existsExceptCurrentUserRule, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, generateImageVariants, generateMailId, getDefaultMailConfig, 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, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isBootSignal, isDevelopmentMode, isNewerVersion, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isTestMode, isTracingEnabled, isUnknownTsExtensionError, isValidIdempotencyKey, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, matchesDerivedRouteName, measure, mergeCspDirectives, middleware, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, onHttpServerRebuilt, originOf, ownOrigin, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, registerAppConfig, registerConfiguredConnectors, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetRolesCacheForTests, resetTracingConfigForTests, resolveCspConfig, resolveCsrfOriginVerdict, resolveMailConfig, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, sanitizePath, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setConfig, setEnvironment, setHttpReadyReport, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, t, tempPath, toJson, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, wrapResponseInDataKey };
192
+ export { $registerUseCase, $unregisterUseCase, APP_ROLES, AccessConnector, AggregateExpressionInput, AggregateExpressions, AiConnector, AllRepositoryOptions, AppConfigurations, AppRole, Application, AuthDescriptor, BOOT_SIGNAL_ENV_KEY, BOOT_SIGNAL_VERSION, BadRequestError, BadSchemaUseCaseError, BaseCastOutput, BaseConnector, type BenchmarkChannel, type BenchmarkConfigurations, type BenchmarkErrorResult, type BenchmarkOptions, BenchmarkProfiler, type BenchmarkProfilerOptions, type BenchmarkResult, BenchmarkSnapshots, type BenchmarkSnapshotsOptions, type BenchmarkStats, type BenchmarkSuccessResult, BootContext, BootListener, BootSignal, BootSignalType, BootValidator, CLICommand, type CLICommandAction, type CLICommandOption, type CLICommandOptions, type CLICommandPreload, type CLICommandSource, CacheConnector, type CacheMiddlewareOptions, CachedRepositoryOptions, type CapturedMail, CascadeAdapter, CascadeQueryBuilder, CastOutput, ChunkCallback, ClosableServer, CloudDriver, CloudStorageDriverContract, CloudStorageDriverOptions, CloudStorageFileData, type CommandActionData, type ConcurrencyLimitOptions, ConfigKey, ConfigKeyRegistry, ConfigName, ConfigRegistry, ConfigSpecialHandlers, ConflictError, Connector, ConnectorBuildContext, ConnectorBuildContribution, ConnectorBuildGenerateResult, ConnectorEsbuildPatch, ConnectorLifecyclePhase, ConnectorName, ConnectorPriority, ConnectorsManager, ConsoleChannel, ContainerTypes, CookieJarUnavailableError, CookieOptions, CspConfig, CsrfOriginCheckReason, CsrfOriginVerdict, CursorPaginationOptions, CursorPaginationResult, DEFAULT_CSP_DIRECTIVES, DEFAULT_POSTMAN_BASE_URL, DOSpacesDriver, DatabaseCacheDriver, type DatabaseCacheOptions, DatabaseConnector, DatabaseLog, DatabaseLogModel, DatabaseLogOptions, DecodedAccessToken, DefineResourceOptions, DeleteManyResult, DetectedImageFormat, type DevelopmentModelModuleEntry, type DevelopmentModelModuleState, type DevelopmentModelModules, DevelopmentPostmanResult, EncryptionConfigurations, EncryptionPasswordConfigurations, Environment, EventSubscription, ExistsExceptCurrentIdRuleOptions, ExistsExceptCurrentUserRuleOptions, FastifyInstance, FieldOutput, FileNamingStrategy, FileValidationOptions, FileValidator, FileVisibility, FilterFunction, FilterOperator, FilterOptions, FilterRule, FilterRules, ForbiddenError, GenerateImageVariantsOptions, GeneratedImageDescriptor, GeneratedImageVariant, GroupByFields, GroupedRoutesOptions, HealthCheck, HealthStatus, HeraldConnector, HttpConfigurations, HttpConnector, HttpContext, HttpError, HttpErrorCodes, HttpReadyReport, HttpServerRebuiltListener, HttpTracingConfig, type IdempotencyOptions, Image, ImageFormat, ImageInput, ImageTransformCallback, ImageTransformConfig, ImageTransformOptions, ImageVariantDefinition, ImageVariantFit, ImageVariantOutputFormat, ImageVariantsConfigError, InvalidCspDirectiveError, type IpFilterOptions, ListOptions, LocalDriver, LocalStorageDriverOptions, LocaleDictionaryEntries, LocaleDictionaryError, LocalizedObject, LogConfigurations, LoggerConnector, MAIL_EVENTS, Mail, type MailAddress, type MailAttachment, type MailConfigurations, MailError, type MailErrorCode, type MailEvents, type MailMode, type MailOptions, type MailPriority, type MailResult, MailerConnector, type MailersConfig, type MaintenanceOptions, Middleware, MiddlewareResponse, MimeTypes, ModelResourceRegistry, NamedApiRoute, NamedApiRoutesOptions, NoopChannel, type NormalizedMail, NotAcceptableError, NotAllowedError, NotificationsConnector, OPENAPI_JSON_SCHEMA_DIALECT, OpenApiBuildResult, OpenApiComponents, OpenApiContext, OpenApiDocument, OpenApiOperation, OpenApiParameter, OpenApiRequestBody, OpenApiResponse, OpenApiRouteInput, OpenApiSchema, OpenApiSecurityRequirement, OpenApiSecurityScheme, OpenApiValidationResponseConfig, POSTMAN_COLLECTION_SCHEMA, PaginationMode, PaginationResult, ParsedLocaleDictionary, PartialMiddleware, PartialPick, Path, PipeableReactStream, PipelineOptions, PortInUseError, PositionalHandlerSuspect, PostmanAuth, PostmanAuthEntry, PostmanBody, PostmanCollection, PostmanCollectionOptions, PostmanFolder, PostmanFormParam, PostmanHeader, PostmanItem, PostmanOriginalRequest, PostmanQueryParam, PostmanRequest, PostmanRequestItem, PostmanResponse, PostmanUrl, PostmanVariable, PrefixConfig, PrefixOptions, PresignedOptions, PresignedUploadOptions, PutDirectoryOptions, PutDirectoryResult, PutFromUrlOptions, PutOptions, QueryBuilderContract, Queue, R2Driver, R2StorageDriverOptions, type RateLimitOptions, RegisterConfiguredConnectorsOptions, RegisterResource, RegisteredUseCase, RepositoryAdapterContract, RepositoryConfigurations, RepositoryEvent, RepositoryManager, RepositoryOptions, RepositoryOptionsWithCursor, RepositoryOptionsWithPages, Request, RequestContextStore, RequestController, RequestControllerContract, RequestEvent, RequestHandler, RequestHandlerType, RequestHandlerValidation, RequestLocals, RequestLog, RequestMethod, RequestTranslator, type ResolvedCLICommandOption, ResolvedImageVariantsConfig, Resource, ResourceArraySchema, ResourceCastType, ResourceConstructor, ResourceContract, ResourceFieldBuilder, ResourceFieldBuilderDateOutputOptions, ResourceFieldConfig, ResourceMethod, ResourceNotFoundError, ResourceOutput, ResourceOutputOf, ResourceOutputValueCastType, ResourceSchema, ResourceSelfReference, Response, ResponseBodyOutput, ResponseBodyValue, ResponseEvent, ResponseSSEController, ResponseSchema, ResponseSchemaOutput, ResponseStatus, ResponseStreamController, Restful, RestfulMiddleware, ReturnedResponse, Route, RouteOptions, RouteRegistry, RouteResource, Router, RouterGroupCallback, RouterStacks, RuntimeStrategy, S3Driver, type SESConfigurations, type SMTPConfigurations, SafeFetchOptions, SafeFetchResult, SaveAsOptions, SaveMode, SaveOptions, ScopedStorage, ScopedStorageContract, SeedClock, SeedContext, SeedRecordRef, SeedResult, Seeder, SeederDependencyCycleError, SeederMetadata, SendBufferOptions, SendFileOptions, Serialized, SerializedWire, ServerError, ShutdownListener, SocketAdapterFactory, SocketConnector, SocketOptions, Storage, StorageCapabilityError, StorageConfigurations, StorageConnector, StorageCopyEventPayload, StorageDriverConfig, StorageDriverContextStore, StorageDriverContract, StorageDriverName, StorageDriverRegistry, StorageDriverType, StorageError, StorageErrorOptions, StorageEventHandler, StorageEventPayload, StorageEventType, StorageFile, StorageFileData, StorageFileInfo, StorageManagerContract, StorageNotInitializedError, StoragePutEventPayload, StreamReactResponseOptions, TemporaryTokenError, TemporaryTokenPayload, TemporaryTokenValidation, TracingContext, TracingContextSource, TracingHooks, TracingPhaseInfo, TracingRequestEndInfo, Track, TrackableModel, TypedAllRepositoryOptions, TypedRepositoryOptions, TypedRepositoryOptionsWithCursor, TypedRepositoryOptionsWithPages, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, UnAuthorizedError, UniqueExceptCurrentIdRuleOptions, UniqueExceptCurrentUserRuleOptions, UnknownSeederDependencyError, UploadedFile, UploadedFileImageOptions, UploadedFileJson, UploadedFileQuery, UploadsConfigurations, UploadsImagesConfigurations, UseCase, UseCaseAfterMiddleware, UseCaseBeforeMiddleware, UseCaseBroadcastChannel, UseCaseBroadcastEvent, UseCaseBroadcastOption, UseCaseConfigurations, UseCaseContext, UseCaseErrorResult, UseCaseEventsCallbacksMap, UseCaseGuard, UseCaseHandler, UseCaseOnExecutingContext, UseCaseResult, UseCaseRuntimeOptions, UseCaseWithSchema, ValidationConfiguration, VariantOutputFormat, VariantSourceFormat, WarlockConfig, WarlockConfigManager, WarningSink, WatermarkConfig, WhereOperator, XMLable, addUseCaseHistory, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assetsUrl, bootstrap, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildOpenApiDocument, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, decrypt, defaultHttpConfigurations, defineConfig, defineResource, deriveTraceId, describePositionalHandlerSuspect, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, exampleFromSchema, existsExceptCurrentIdRule, existsExceptCurrentUserRule, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, generateImageVariants, generateMailId, getDefaultMailConfig, getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, 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, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isBootSignal, isDevelopmentMode, isNewerVersion, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isTestMode, isTracingEnabled, isUnknownTsExtensionError, isValidIdempotencyKey, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, matchesDerivedRouteName, measure, mergeCspDirectives, middleware, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, onHttpServerRebuilt, openApiToPostmanCollection, originOf, ownOrigin, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, registerAppConfig, registerConfiguredConnectors, registerDevelopmentOpenApiProvider, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetRolesCacheForTests, resetTracingConfigForTests, resolveCspConfig, resolveCsrfOriginVerdict, resolveMailConfig, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, sanitizePath, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setConfig, setEnvironment, setHttpReadyReport, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, t, tempPath, toJson, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, wrapResponseInDataKey };
186
193
  import "./config/types.mjs";
187
194
  import "./http/request.mjs";
195
+ import "./http/serialized.mjs";
188
196
  import "./http/types.mjs";
189
197
  import "./storage/types.mjs";
190
198
  import "./validation/types.mjs";
package/esm/index.mjs CHANGED
@@ -150,6 +150,11 @@ import "./encryption/index.mjs";
150
150
  import { LocaleDictionaryError, parseLocaleDictionary } from "./localization/parse-locale-dictionary.mjs";
151
151
  import { registerGroupedTranslationKeys, registerLocaleDictionary, unregisterLocaleDictionary } from "./localization/register-locale-dictionary.mjs";
152
152
  import "./localization/index.mjs";
153
+ import { exampleFromSchema } from "./openapi/postman/example-from-schema.mjs";
154
+ import { DEFAULT_POSTMAN_BASE_URL, POSTMAN_COLLECTION_SCHEMA, openApiToPostmanCollection } from "./openapi/postman/openapi-to-postman-collection.mjs";
155
+ import { getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, registerDevelopmentOpenApiProvider } from "./openapi/development-openapi-provider.mjs";
156
+ import { OPENAPI_JSON_SCHEMA_DIALECT, buildOpenApiDocument } from "./openapi/build-openapi-document.mjs";
157
+ import "./openapi/index.mjs";
153
158
  import { CascadeQueryBuilder } from "./repositories/adapters/cascade/cascade-query-builder.mjs";
154
159
  import { CascadeAdapter, UPDATE_MANY_BATCH_SIZE } from "./repositories/adapters/cascade/cascade-adapter.mjs";
155
160
  import { RepositoryManager } from "./repositories/repository.manager.mjs";
@@ -178,4 +183,4 @@ import { colors } from "@mongez/copper";
178
183
 
179
184
  export * from "@mongez/localization"
180
185
 
181
- export { $registerUseCase, $unregisterUseCase, APP_ROLES, AccessConnector, AiConnector, 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, DOSpacesDriver, DatabaseCacheDriver, DatabaseConnector, DatabaseLog, DatabaseLogModel, FileValidator, ForbiddenError, HeraldConnector, HttpConnector, HttpError, HttpErrorCodes, Image, ImageVariantsConfigError, InvalidCspDirectiveError, LocalDriver, LocaleDictionaryError, LoggerConnector, MAIL_EVENTS, Mail, MailError, MailerConnector, MimeTypes, NoopChannel, NotAcceptableError, NotAllowedError, NotificationsConnector, Path, PortInUseError, Queue, R2Driver, RegisterResource, RepositoryManager, Request, RequestController, RequestLog, Resource, ResourceFieldBuilder, ResourceNotFoundError, Response, ResponseStatus, Restful, RouteRegistry, Router, S3Driver, ScopedStorage, SeederDependencyCycleError, ServerError, SocketConnector, Storage, StorageCapabilityError, StorageConnector, StorageError, StorageFile, StorageNotInitializedError, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, UnAuthorizedError, UnknownSeederDependencyError, UploadedFile, WarlockConfigManager, addUseCaseHistory, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assetsUrl, bootstrap, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, decrypt, defaultHttpConfigurations, defineConfig, defineResource, deriveTraceId, describePositionalHandlerSuspect, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, existsExceptCurrentIdRule, existsExceptCurrentUserRule, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, generateImageVariants, generateMailId, getDefaultMailConfig, 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, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isBootSignal, isDevelopmentMode, isNewerVersion, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isTestMode, isTracingEnabled, isUnknownTsExtensionError, isValidIdempotencyKey, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, matchesDerivedRouteName, measure, mergeCspDirectives, middleware, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, onHttpServerRebuilt, originOf, ownOrigin, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, registerAppConfig, registerConfiguredConnectors, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetRolesCacheForTests, resetTracingConfigForTests, resolveCspConfig, resolveCsrfOriginVerdict, resolveMailConfig, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, sanitizePath, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setConfig, setEnvironment, setHttpReadyReport, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, t, tempPath, toJson, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, wrapResponseInDataKey };
186
+ export { $registerUseCase, $unregisterUseCase, APP_ROLES, AccessConnector, AiConnector, 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, FileValidator, ForbiddenError, HeraldConnector, HttpConnector, HttpError, HttpErrorCodes, Image, ImageVariantsConfigError, InvalidCspDirectiveError, LocalDriver, LocaleDictionaryError, LoggerConnector, MAIL_EVENTS, Mail, MailError, MailerConnector, MimeTypes, 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, RouteRegistry, Router, S3Driver, ScopedStorage, SeederDependencyCycleError, ServerError, SocketConnector, Storage, StorageCapabilityError, StorageConnector, StorageError, StorageFile, StorageNotInitializedError, UPDATE_MANY_BATCH_SIZE, UPLOADS_DEFAULTS, UnAuthorizedError, UnknownSeederDependencyError, UploadedFile, WarlockConfigManager, addUseCaseHistory, anyMatch, app, appLog, appPath, applyCspHeader, assertConfiguredHttpPortIsFree, assertMailCount, assertMailSent, assertNoReservedConnectorNames, assertPortIsAvailable, assertSitesRequireWebRole, assertUniqueConnectorNames, assetsUrl, bootstrap, broadcastUseCaseResult, buildCspHeaderValue, buildIdempotencyCacheKey, buildOpenApiDocument, buildTracingContext, cachePath, captureMail, clearPositionalHandlerSuspects, clearTestMailbox, closeAllMailers, closeMailer, closeServerWithTimeout, colors, command, config, configPath, configSpecialHandlers, connectorsManager, container, createHttpApplication, createRequestStore, decrypt, defaultHttpConfigurations, defineConfig, defineResource, deriveTraceId, describePositionalHandlerSuspect, dispatchPhase, dispatchRequestEnd, dispatchRequestStart, displayEnvironmentMode, encrypt, ensureFatalIsVisible, env, environment, exampleFromSchema, existsExceptCurrentIdRule, existsExceptCurrentUserRule, fetchLatestVersion, fileExtensionRule, fileRule, fileTypeRule, findMailsBySubject, findMailsTo, fireLifecycleEvent, forgetPositionalHandlerSuspects, generateImageVariants, generateMailId, getDefaultMailConfig, getDevelopmentOpenApiDocument, getDevelopmentPostmanCollection, 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, imageRule, increaseUseCaseFailedCalls, increaseUseCaseSuccessCalls, inspectHandlerSignature, ipMatches, isAllowedCsrfOrigin, isBootSignal, isDevelopmentMode, isNewerVersion, isPortAvailable, isPrivateOrReservedIp, isProductionMode, isTestMode, isTracingEnabled, isUnknownTsExtensionError, isValidIdempotencyKey, listPositionalHandlerSuspects, loadS3, logResponse, logsPath, looksLikePositionalHandler, mailEvents, matchesDerivedRouteName, measure, mergeCspDirectives, middleware, normalizeOrigin, normalizeRequestPath, normalizeRoutePath, notifyHttpServerRebuilt, onHttpServerRebuilt, openApiToPostmanCollection, originOf, ownOrigin, parseLocaleDictionary, parseRoles, parseSites, parseSize, parseTraceparentTraceId, paths, preflightConfiguredHttpPort, promiseAllObject, publicPath, publicUrl, registerAppConfig, registerConfiguredConnectors, registerDevelopmentOpenApiProvider, registerGroupedTranslationKeys, registerHttpPlugins, registerLocaleDictionary, registerTracingHooks, remedyLines, renderReact, renderReactMail, reportPositionalHandlerSuspects, requestContext, requestMemo, requiresDefaultCsrfGuard, resetHttpReadyReport, resetMailConfig, resetRolesCacheForTests, resetTracingConfigForTests, resolveCspConfig, resolveCsrfOriginVerdict, resolveMailConfig, resolveTracingConfig, resolveWithinRoot, rootPath, routeNameMethodSuffix, router, runDefaultCsrfGuard, runPipeline, safeFetchToBuffer, sanitizePath, seeder, sendBootSignal, sendMail, serializeCspDirectives, servesHttp, setBaseUrl, setConfig, setEnvironment, setHttpReadyReport, setLogConfigurations, setMailConfigurations, setMailMode, shouldPreflightHttpPort, sleep, sluggable, srcPath, startHttpServer, stopHttpApplication, storage, storageConfig, storageConfigurations, storageDriverContext, storagePath, streamReactResponse, t, tempPath, toJson, uniqueExceptCurrentIdRule, uniqueExceptCurrentUserRule, unregisterLocaleDictionary, uploadedFileController, uploadedFileMetadataSchema, uploadsConfig, uploadsPath, uploadsUrl, url, useCase, useComputedModel, useComputedSlug, useCurrentUser, useHashedPassword, useRequest, useRequestStore, validateCspConfigAtBoot, validateCspDirectives, verifyMailer, verifyPassword, warlockConfigManager, warlockPath, wasMailSentTo, wasMailSentWithSubject, wrapResponseInDataKey };