@lpdjs/firestore-repo-service 2.6.9 → 2.6.10

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.
@@ -989,6 +989,67 @@ declare function buildOpenApiDocument(routes: AnyRouteDef[], basePath: string, c
989
989
  */
990
990
  declare function renderDocsHtml(specUrl: string, title: string): string;
991
991
 
992
+ /**
993
+ * Build a deep link to the GCP Cloud Logging "Logs Explorer", pre-filtered on a
994
+ * correlation id, so a developer can jump straight from an HTTP error response
995
+ * to the matching structured log.
996
+ *
997
+ * Designed as a dev ergonomic: keep it **disabled in production** (the link is
998
+ * meant for engineers, not end users) and enable it locally / in staging. The
999
+ * `errorId` returned by {@link BaseLogger.error} and carried by your `AppError`
1000
+ * is the same value used both in the response body and in the link's query.
1001
+ *
1002
+ * @example
1003
+ * ```ts
1004
+ * // package-level helper
1005
+ * const url = gcpLogsUrl(error.errorId, {
1006
+ * enabled: process.env.NODE_ENV !== "production",
1007
+ * projectId: "my-gcp-project", // or omit to read it from the environment
1008
+ * });
1009
+ *
1010
+ * // inside BaseErrorHandler.mapError
1011
+ * return c.json({ error: msg, errorId, ...(url ? { logsUrl: url } : {}) }, 412);
1012
+ * ```
1013
+ */
1014
+ /** Options controlling {@link gcpLogsUrl}. */
1015
+ interface GcpLogsLinkOptions {
1016
+ /**
1017
+ * Master switch — when falsy, {@link gcpLogsUrl} returns `undefined` and no
1018
+ * link is produced. Default: `false` (opt-in). Wire it to e.g.
1019
+ * `process.env.NODE_ENV !== "production"`.
1020
+ */
1021
+ enabled?: boolean;
1022
+ /**
1023
+ * GCP project id. Defaults to the first non-empty of
1024
+ * `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT`, `GCP_PROJECT` (all auto-set on
1025
+ * Cloud Functions / Cloud Run). When none is resolvable, no link is built.
1026
+ */
1027
+ projectId?: string;
1028
+ /**
1029
+ * Structured-log field that carries the correlation id. Must match what your
1030
+ * logger writes (the package's {@link BaseLogger} writes `errorId`).
1031
+ * Default: `"errorId"`.
1032
+ */
1033
+ field?: string;
1034
+ /**
1035
+ * Optional lookback window appended to the query as an ISO-8601 duration
1036
+ * (e.g. `"PT1H"`, `"PT30M"`, `"P1D"`). Omit to let the Logs Explorer use its
1037
+ * default range.
1038
+ */
1039
+ duration?: string;
1040
+ }
1041
+ /**
1042
+ * Resolve the GCP project id from an explicit value, falling back to the
1043
+ * standard environment variables. Returns `undefined` when none is set.
1044
+ */
1045
+ declare function resolveGcpProjectId(explicit?: string): string | undefined;
1046
+ /**
1047
+ * Build the Logs Explorer URL filtered on `<field>="<errorId>"`, or return
1048
+ * `undefined` when the feature is disabled, the `errorId` is missing, or no
1049
+ * project id can be resolved (so callers can spread it safely).
1050
+ */
1051
+ declare function gcpLogsUrl(errorId: string | undefined, options?: GcpLogsLinkOptions): string | undefined;
1052
+
992
1053
  /**
993
1054
  * `BaseErrorHandler` — the package's ready-to-use {@link ErrorHandler}.
994
1055
  *
@@ -1024,7 +1085,29 @@ declare function renderDocsHtml(specUrl: string, title: string): string;
1024
1085
  * ```
1025
1086
  */
1026
1087
 
1088
+ /** Construction options shared by every {@link BaseErrorHandler}. */
1089
+ interface BaseErrorHandlerOptions {
1090
+ /**
1091
+ * Enable building a GCP Logs Explorer deep link from an error's correlation
1092
+ * id (see {@link BaseErrorHandler.gcpLogsUrl}). Disabled by default — turn it
1093
+ * on in dev/staging to let engineers jump from a response to its log.
1094
+ */
1095
+ gcpLogs?: GcpLogsLinkOptions;
1096
+ }
1027
1097
  declare class BaseErrorHandler<TEnv extends Env = Env, TServices extends AnyServicesContainer = AnyServicesContainer> implements ErrorHandler<TEnv, TServices> {
1098
+ protected readonly options: BaseErrorHandlerOptions;
1099
+ constructor(options?: BaseErrorHandlerOptions);
1100
+ /**
1101
+ * Build a GCP Logs Explorer link for `errorId`, or `undefined` when the
1102
+ * `gcpLogs` option is disabled / unresolved. Spread it into a mapped
1103
+ * response to give developers a one-click jump to the matching log:
1104
+ *
1105
+ * ```ts
1106
+ * const logsUrl = this.gcpLogsUrl(error.errorId);
1107
+ * return c.json({ error, errorId, ...(logsUrl ? { logsUrl } : {}) }, status);
1108
+ * ```
1109
+ */
1110
+ protected gcpLogsUrl(errorId?: string): string | undefined;
1028
1111
  /**
1029
1112
  * Orchestration — not meant to be overridden. Tries the user mapping first,
1030
1113
  * logs it when matched, then falls back to the built-in mapping.
@@ -1287,4 +1370,4 @@ declare function generateRoutesManifest(routes: ScannedRoute[], opts: GeneratorO
1287
1370
  /** Convenience helper used by the CLI — combines scan + generate in one call. */
1288
1371
  declare function generateFromRoot(rootAbs: string, outFileRel: string, derive: PathDeriveOptions, importExtension: string, scan: (root: string) => ScannedRoute[]): GenerationResult;
1289
1372
 
1290
- export { type AnyRouteDef, type AnyServicesContainer, type ApiConfig, type ApiConfigMap, type ApiKeySecurityScheme, type ApiRegistry, type ApiRegistryOptions, BadRequestError, BaseErrorHandler, BaseLogger, type BasicAuthOptions, DEFAULT_DERIVE, DEFAULT_GENERATOR_BANNER, DEFAULT_SCANNER, type DecodedBearerToken, type ErrorHandler, type ErrorHandlerContext, type FirebaseBearerAuthLike, type FirebaseBearerAuthOptions, type GenerationResult, type GeneratorOptions, HonoServer, type HonoServerOptions, type HttpMethod, type HttpSecurityScheme, type InterceptorConfig, type InterceptorErrorResponse, type InterceptorOption, type InterceptorOutput, type LogSeverity, type Logger, type MutualTlsSecurityScheme, type OAuth2SecurityScheme, type OAuthFlowObject, type OAuthFlowsObject, type OpenAPIConfig, type OpenAPIInfo, type OpenIdConnectSecurityScheme, OutputValidationError, type PathDeriveOptions, type PayloadSource, type RequestContext, type RouteDef, type RouteHandler, type RouteInput, type RouteInterceptor, type RouteModuleDefault, type RouteOutput, type RoutesUnion, type ScannedRoute, type ScannerOptions, type SecurityRequirement, type SecurityScheme, type SecuritySchemeBase, type ServiceProvider, type ServiceProviderMap, type ServicesContainer, type ServicesOf, UseCase, type UseCaseClass, type UseCaseRouteMeta, ValidationError, basicAuth, buildOpenApiDocument, createApiRegistry, createRequestContextMiddleware, createServices, defaultErrorResponse, defineRoutes, derivePath, firebaseBearerAuth, generateFromRoot, generateRoutesManifest, renderDocsHtml, scanRoutes, toImportSpecifier, useCaseRoute, withRequestContext };
1373
+ export { type AnyRouteDef, type AnyServicesContainer, type ApiConfig, type ApiConfigMap, type ApiKeySecurityScheme, type ApiRegistry, type ApiRegistryOptions, BadRequestError, BaseErrorHandler, type BaseErrorHandlerOptions, BaseLogger, type BasicAuthOptions, DEFAULT_DERIVE, DEFAULT_GENERATOR_BANNER, DEFAULT_SCANNER, type DecodedBearerToken, type ErrorHandler, type ErrorHandlerContext, type FirebaseBearerAuthLike, type FirebaseBearerAuthOptions, type GcpLogsLinkOptions, type GenerationResult, type GeneratorOptions, HonoServer, type HonoServerOptions, type HttpMethod, type HttpSecurityScheme, type InterceptorConfig, type InterceptorErrorResponse, type InterceptorOption, type InterceptorOutput, type LogSeverity, type Logger, type MutualTlsSecurityScheme, type OAuth2SecurityScheme, type OAuthFlowObject, type OAuthFlowsObject, type OpenAPIConfig, type OpenAPIInfo, type OpenIdConnectSecurityScheme, OutputValidationError, type PathDeriveOptions, type PayloadSource, type RequestContext, type RouteDef, type RouteHandler, type RouteInput, type RouteInterceptor, type RouteModuleDefault, type RouteOutput, type RoutesUnion, type ScannedRoute, type ScannerOptions, type SecurityRequirement, type SecurityScheme, type SecuritySchemeBase, type ServiceProvider, type ServiceProviderMap, type ServicesContainer, type ServicesOf, UseCase, type UseCaseClass, type UseCaseRouteMeta, ValidationError, basicAuth, buildOpenApiDocument, createApiRegistry, createRequestContextMiddleware, createServices, defaultErrorResponse, defineRoutes, derivePath, firebaseBearerAuth, gcpLogsUrl, generateFromRoot, generateRoutesManifest, renderDocsHtml, resolveGcpProjectId, scanRoutes, toImportSpecifier, useCaseRoute, withRequestContext };
@@ -989,6 +989,67 @@ declare function buildOpenApiDocument(routes: AnyRouteDef[], basePath: string, c
989
989
  */
990
990
  declare function renderDocsHtml(specUrl: string, title: string): string;
991
991
 
992
+ /**
993
+ * Build a deep link to the GCP Cloud Logging "Logs Explorer", pre-filtered on a
994
+ * correlation id, so a developer can jump straight from an HTTP error response
995
+ * to the matching structured log.
996
+ *
997
+ * Designed as a dev ergonomic: keep it **disabled in production** (the link is
998
+ * meant for engineers, not end users) and enable it locally / in staging. The
999
+ * `errorId` returned by {@link BaseLogger.error} and carried by your `AppError`
1000
+ * is the same value used both in the response body and in the link's query.
1001
+ *
1002
+ * @example
1003
+ * ```ts
1004
+ * // package-level helper
1005
+ * const url = gcpLogsUrl(error.errorId, {
1006
+ * enabled: process.env.NODE_ENV !== "production",
1007
+ * projectId: "my-gcp-project", // or omit to read it from the environment
1008
+ * });
1009
+ *
1010
+ * // inside BaseErrorHandler.mapError
1011
+ * return c.json({ error: msg, errorId, ...(url ? { logsUrl: url } : {}) }, 412);
1012
+ * ```
1013
+ */
1014
+ /** Options controlling {@link gcpLogsUrl}. */
1015
+ interface GcpLogsLinkOptions {
1016
+ /**
1017
+ * Master switch — when falsy, {@link gcpLogsUrl} returns `undefined` and no
1018
+ * link is produced. Default: `false` (opt-in). Wire it to e.g.
1019
+ * `process.env.NODE_ENV !== "production"`.
1020
+ */
1021
+ enabled?: boolean;
1022
+ /**
1023
+ * GCP project id. Defaults to the first non-empty of
1024
+ * `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT`, `GCP_PROJECT` (all auto-set on
1025
+ * Cloud Functions / Cloud Run). When none is resolvable, no link is built.
1026
+ */
1027
+ projectId?: string;
1028
+ /**
1029
+ * Structured-log field that carries the correlation id. Must match what your
1030
+ * logger writes (the package's {@link BaseLogger} writes `errorId`).
1031
+ * Default: `"errorId"`.
1032
+ */
1033
+ field?: string;
1034
+ /**
1035
+ * Optional lookback window appended to the query as an ISO-8601 duration
1036
+ * (e.g. `"PT1H"`, `"PT30M"`, `"P1D"`). Omit to let the Logs Explorer use its
1037
+ * default range.
1038
+ */
1039
+ duration?: string;
1040
+ }
1041
+ /**
1042
+ * Resolve the GCP project id from an explicit value, falling back to the
1043
+ * standard environment variables. Returns `undefined` when none is set.
1044
+ */
1045
+ declare function resolveGcpProjectId(explicit?: string): string | undefined;
1046
+ /**
1047
+ * Build the Logs Explorer URL filtered on `<field>="<errorId>"`, or return
1048
+ * `undefined` when the feature is disabled, the `errorId` is missing, or no
1049
+ * project id can be resolved (so callers can spread it safely).
1050
+ */
1051
+ declare function gcpLogsUrl(errorId: string | undefined, options?: GcpLogsLinkOptions): string | undefined;
1052
+
992
1053
  /**
993
1054
  * `BaseErrorHandler` — the package's ready-to-use {@link ErrorHandler}.
994
1055
  *
@@ -1024,7 +1085,29 @@ declare function renderDocsHtml(specUrl: string, title: string): string;
1024
1085
  * ```
1025
1086
  */
1026
1087
 
1088
+ /** Construction options shared by every {@link BaseErrorHandler}. */
1089
+ interface BaseErrorHandlerOptions {
1090
+ /**
1091
+ * Enable building a GCP Logs Explorer deep link from an error's correlation
1092
+ * id (see {@link BaseErrorHandler.gcpLogsUrl}). Disabled by default — turn it
1093
+ * on in dev/staging to let engineers jump from a response to its log.
1094
+ */
1095
+ gcpLogs?: GcpLogsLinkOptions;
1096
+ }
1027
1097
  declare class BaseErrorHandler<TEnv extends Env = Env, TServices extends AnyServicesContainer = AnyServicesContainer> implements ErrorHandler<TEnv, TServices> {
1098
+ protected readonly options: BaseErrorHandlerOptions;
1099
+ constructor(options?: BaseErrorHandlerOptions);
1100
+ /**
1101
+ * Build a GCP Logs Explorer link for `errorId`, or `undefined` when the
1102
+ * `gcpLogs` option is disabled / unresolved. Spread it into a mapped
1103
+ * response to give developers a one-click jump to the matching log:
1104
+ *
1105
+ * ```ts
1106
+ * const logsUrl = this.gcpLogsUrl(error.errorId);
1107
+ * return c.json({ error, errorId, ...(logsUrl ? { logsUrl } : {}) }, status);
1108
+ * ```
1109
+ */
1110
+ protected gcpLogsUrl(errorId?: string): string | undefined;
1028
1111
  /**
1029
1112
  * Orchestration — not meant to be overridden. Tries the user mapping first,
1030
1113
  * logs it when matched, then falls back to the built-in mapping.
@@ -1287,4 +1370,4 @@ declare function generateRoutesManifest(routes: ScannedRoute[], opts: GeneratorO
1287
1370
  /** Convenience helper used by the CLI — combines scan + generate in one call. */
1288
1371
  declare function generateFromRoot(rootAbs: string, outFileRel: string, derive: PathDeriveOptions, importExtension: string, scan: (root: string) => ScannedRoute[]): GenerationResult;
1289
1372
 
1290
- export { type AnyRouteDef, type AnyServicesContainer, type ApiConfig, type ApiConfigMap, type ApiKeySecurityScheme, type ApiRegistry, type ApiRegistryOptions, BadRequestError, BaseErrorHandler, BaseLogger, type BasicAuthOptions, DEFAULT_DERIVE, DEFAULT_GENERATOR_BANNER, DEFAULT_SCANNER, type DecodedBearerToken, type ErrorHandler, type ErrorHandlerContext, type FirebaseBearerAuthLike, type FirebaseBearerAuthOptions, type GenerationResult, type GeneratorOptions, HonoServer, type HonoServerOptions, type HttpMethod, type HttpSecurityScheme, type InterceptorConfig, type InterceptorErrorResponse, type InterceptorOption, type InterceptorOutput, type LogSeverity, type Logger, type MutualTlsSecurityScheme, type OAuth2SecurityScheme, type OAuthFlowObject, type OAuthFlowsObject, type OpenAPIConfig, type OpenAPIInfo, type OpenIdConnectSecurityScheme, OutputValidationError, type PathDeriveOptions, type PayloadSource, type RequestContext, type RouteDef, type RouteHandler, type RouteInput, type RouteInterceptor, type RouteModuleDefault, type RouteOutput, type RoutesUnion, type ScannedRoute, type ScannerOptions, type SecurityRequirement, type SecurityScheme, type SecuritySchemeBase, type ServiceProvider, type ServiceProviderMap, type ServicesContainer, type ServicesOf, UseCase, type UseCaseClass, type UseCaseRouteMeta, ValidationError, basicAuth, buildOpenApiDocument, createApiRegistry, createRequestContextMiddleware, createServices, defaultErrorResponse, defineRoutes, derivePath, firebaseBearerAuth, generateFromRoot, generateRoutesManifest, renderDocsHtml, scanRoutes, toImportSpecifier, useCaseRoute, withRequestContext };
1373
+ export { type AnyRouteDef, type AnyServicesContainer, type ApiConfig, type ApiConfigMap, type ApiKeySecurityScheme, type ApiRegistry, type ApiRegistryOptions, BadRequestError, BaseErrorHandler, type BaseErrorHandlerOptions, BaseLogger, type BasicAuthOptions, DEFAULT_DERIVE, DEFAULT_GENERATOR_BANNER, DEFAULT_SCANNER, type DecodedBearerToken, type ErrorHandler, type ErrorHandlerContext, type FirebaseBearerAuthLike, type FirebaseBearerAuthOptions, type GcpLogsLinkOptions, type GenerationResult, type GeneratorOptions, HonoServer, type HonoServerOptions, type HttpMethod, type HttpSecurityScheme, type InterceptorConfig, type InterceptorErrorResponse, type InterceptorOption, type InterceptorOutput, type LogSeverity, type Logger, type MutualTlsSecurityScheme, type OAuth2SecurityScheme, type OAuthFlowObject, type OAuthFlowsObject, type OpenAPIConfig, type OpenAPIInfo, type OpenIdConnectSecurityScheme, OutputValidationError, type PathDeriveOptions, type PayloadSource, type RequestContext, type RouteDef, type RouteHandler, type RouteInput, type RouteInterceptor, type RouteModuleDefault, type RouteOutput, type RoutesUnion, type ScannedRoute, type ScannerOptions, type SecurityRequirement, type SecurityScheme, type SecuritySchemeBase, type ServiceProvider, type ServiceProviderMap, type ServicesContainer, type ServicesOf, UseCase, type UseCaseClass, type UseCaseRouteMeta, ValidationError, basicAuth, buildOpenApiDocument, createApiRegistry, createRequestContextMiddleware, createServices, defaultErrorResponse, defineRoutes, derivePath, firebaseBearerAuth, gcpLogsUrl, generateFromRoot, generateRoutesManifest, renderDocsHtml, resolveGcpProjectId, scanRoutes, toImportSpecifier, useCaseRoute, withRequestContext };
@@ -1,4 +1,4 @@
1
- import {Hono}from'hono';import {getRequestListener}from'@hono/node-server';import {extendZodWithOpenApi,OpenAPIRegistry,OpenApiGeneratorV31}from'@asteasolutions/zod-to-openapi';import {z as z$1}from'zod';import {AsyncLocalStorage}from'async_hooks';import {readdirSync,statSync,mkdirSync,writeFileSync}from'fs';import {join,relative,sep,dirname}from'path';function J(t){return t}var v=class extends Error{constructor(n,r){super("Request validation failed");this.zodError=n;this.source=r;this.statusCode=400;this.name="ValidationError";}};var T=class extends Error{constructor(n){super(n);this.statusCode=400;this.name="BadRequestError";}},S=class extends Error{constructor(n){super("Output validation failed");this.zodError=n;this.statusCode=500;this.name="OutputValidationError";}};function Z(t){return t.issues.map(e=>({path:e.path.join("."),code:e.code,message:e.message}))}function E(t,e){return e instanceof v?t.json({success:false,error:"Validation failed",issues:Z(e.zodError)},400):e instanceof T?t.json({success:false,error:"Bad Request",message:e.message},400):e instanceof S?t.json({success:false,error:"Output validation failed",issues:Z(e.zodError)},500):null}extendZodWithOpenApi(z$1);var _="Successful response",B="Error response";function te(t){return t==="get"?"query":"json"}function ne(t,e){let n=e?.output;return n?typeof n=="function"?n(t):n:t}function re(t){if(typeof t.safeParse=="function")return {description:B,schema:t};let e=t;return {description:e.description??B,schema:e.schema}}function C(t,e,n,r){let s=new OpenAPIRegistry;if(n.securitySchemes)for(let[i,c]of Object.entries(n.securitySchemes))s.registerComponent("securitySchemes",i,c);for(let i of t){let c=i.method,p=i.source??te(c),u=ie(e,i.path??"/"),d=i.status??200,m=oe(c,p,i.input),g=U(p,i.input,"query"),h=U(p,i.input,"param"),f=ae(c,u),l=ne(i.output,r),y={[d]:l?{description:_,content:{"application/json":{schema:l}}}:{description:_}};if(r?.errors)for(let[x,A]of Object.entries(r.errors)){let{description:q,schema:j}=re(A);y[x]=j?{description:q,content:{"application/json":{schema:j}}}:{description:q};}s.registerPath({method:c,path:se(u),operationId:f,summary:i.summary,description:i.description,tags:i.tags,deprecated:i.deprecated,security:i.security,request:{...g?{query:g}:{},...h?{params:h}:{},...m?{body:m}:{}},responses:y});}return new OpenApiGeneratorV31(s.definitions).generateDocument({openapi:"3.1.0",info:n.info,servers:n.servers,security:n.security})}function oe(t,e,n){return !n||t==="get"?null:e==="json"?{content:{"application/json":{schema:n}}}:e==="form"?{content:{"application/x-www-form-urlencoded":{schema:n}}}:null}function U(t,e,n){if(e&&(n==="query"&&t==="query"||n==="param"&&t==="param"))return e}function se(t){return t.replace(/:([A-Za-z0-9_]+)/g,"{$1}")}function ie(t,e){let n=t.endsWith("/")?t.slice(0,-1):t,r=e.startsWith("/")?e:`/${e}`,s=`${n}${r}`;return s===""?"/":s}function ae(t,e){let n=e.replace(/[{}]/g,"").replace(/\/+/g,"_").replace(/[^A-Za-z0-9_]/g,"").replace(/^_+|_+$/g,"");return `${t}_${n||"root"}`}function P(t,e){let n=t.replace(/"/g,"&quot;");return `<!doctype html>
1
+ import {Hono}from'hono';import {getRequestListener}from'@hono/node-server';import {extendZodWithOpenApi,OpenAPIRegistry,OpenApiGeneratorV31}from'@asteasolutions/zod-to-openapi';import {z as z$1}from'zod';import {AsyncLocalStorage}from'async_hooks';import {readdirSync,statSync,mkdirSync,writeFileSync}from'fs';import {join,relative,sep,dirname}from'path';function Q(t){return t}var v=class extends Error{constructor(n,o){super("Request validation failed");this.zodError=n;this.source=o;this.statusCode=400;this.name="ValidationError";}};var T=class extends Error{constructor(n){super(n);this.statusCode=400;this.name="BadRequestError";}},S=class extends Error{constructor(n){super("Output validation failed");this.zodError=n;this.statusCode=500;this.name="OutputValidationError";}};function _(t){return t.issues.map(e=>({path:e.path.join("."),code:e.code,message:e.message}))}function E(t,e){return e instanceof v?t.json({success:false,error:"Validation failed",issues:_(e.zodError)},400):e instanceof T?t.json({success:false,error:"Bad Request",message:e.message},400):e instanceof S?t.json({success:false,error:"Output validation failed",issues:_(e.zodError)},500):null}extendZodWithOpenApi(z$1);var U="Successful response",Z="Error response";function re(t){return t==="get"?"query":"json"}function oe(t,e){let n=e?.output;return n?typeof n=="function"?n(t):n:t}function se(t){if(typeof t.safeParse=="function")return {description:Z,schema:t};let e=t;return {description:e.description??Z,schema:e.schema}}function C(t,e,n,o){let s=new OpenAPIRegistry;if(n.securitySchemes)for(let[i,c]of Object.entries(n.securitySchemes))s.registerComponent("securitySchemes",i,c);for(let i of t){let c=i.method,p=i.source??re(c),u=ce(e,i.path??"/"),d=i.status??200,m=ie(c,p,i.input),g=$(p,i.input,"query"),h=$(p,i.input,"param"),f=pe(c,u),l=oe(i.output,o),y={[d]:l?{description:U,content:{"application/json":{schema:l}}}:{description:U}};if(o?.errors)for(let[x,A]of Object.entries(o.errors)){let{description:q,schema:L}=se(A);y[x]=L?{description:q,content:{"application/json":{schema:L}}}:{description:q};}s.registerPath({method:c,path:ae(u),operationId:f,summary:i.summary,description:i.description,tags:i.tags,deprecated:i.deprecated,security:i.security,request:{...g?{query:g}:{},...h?{params:h}:{},...m?{body:m}:{}},responses:y});}return new OpenApiGeneratorV31(s.definitions).generateDocument({openapi:"3.1.0",info:n.info,servers:n.servers,security:n.security})}function ie(t,e,n){return !n||t==="get"?null:e==="json"?{content:{"application/json":{schema:n}}}:e==="form"?{content:{"application/x-www-form-urlencoded":{schema:n}}}:null}function $(t,e,n){if(e&&(n==="query"&&t==="query"||n==="param"&&t==="param"))return e}function ae(t){return t.replace(/:([A-Za-z0-9_]+)/g,"{$1}")}function ce(t,e){let n=t.endsWith("/")?t.slice(0,-1):t,o=e.startsWith("/")?e:`/${e}`,s=`${n}${o}`;return s===""?"/":s}function pe(t,e){let n=e.replace(/[{}]/g,"").replace(/\/+/g,"_").replace(/[^A-Za-z0-9_]/g,"").replace(/^_+|_+$/g,"");return `${t}_${n||"root"}`}function P(t,e){let n=t.replace(/"/g,"&quot;");return `<!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
@@ -9,7 +9,7 @@ import {Hono}from'hono';import {getRequestListener}from'@hono/node-server';impor
9
9
  <script id="api-reference" data-url="${n}"></script>
10
10
  <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
11
11
  </body>
12
- </html>`}var O=new AsyncLocalStorage,pe=Object.freeze({get c(){let t=O.getStore();if(!t)throw new Error("[services] requestContext.c was accessed outside of a request. Wrap non-HTTP code paths (cron, triggers, scripts, tests) in `withRequestContext({ c }, () => ...)` to supply a Hono Context.");return t.c},get maybeC(){return O.getStore()?.c}});function I(){return async(t,e)=>{await O.run({c:t},async()=>{await e();});}}function ue(t,e){return O.run({c:t.c},async()=>e())}var w="ctx";function de(t){let e=new Map,n=[],r=new Proxy({},{get(s,o){if(typeof o!="string")return;if(o===w)return pe;if(e.has(o))return e.get(o);let a=t[o];if(typeof a!="function")throw new Error(`[services] unknown service "${o}". Registered: ${[w,...Object.keys(t)].join(", ")}`);if(n.includes(o))throw new Error(`[services] circular dependency detected: ${[...n,o].join(" \u2192 ")}`);n.push(o);try{let i=le(a)?new a(r):a(r);return e.set(o,i),i}finally{n.pop();}},has(s,o){return typeof o!="string"?false:o===w||o in t},ownKeys(){return [w,...Object.keys(t)]},getOwnPropertyDescriptor(s,o){if(typeof o=="string"&&(o===w||o in t))return {enumerable:true,configurable:true}}});return r}function le(t){return /^class[\s{]/.test(Function.prototype.toString.call(t))}var ge=Object.freeze({}),R=class{constructor(e){this.cachedSpec=null;this.options=e,this.app=new Hono,this.mountedRoutes=ve(e.routes,e.api),e.services&&this.app.use("*",I());let n=[...e.middlewares??[],...e.globalMiddlewares??[]];for(let r of n)this.app.use("*",r);this.mountRoutes(),this.mountOpenApi(),e.notFound&&this.app.notFound(e.notFound),e.onError&&this.app.onError(e.onError);}get hono(){return this.app}get nodeHandler(){return getRequestListener(this.app.fetch,{overrideGlobalObjects:false})}toFunction(e,n){let r=this.nodeHandler;return n?e(n,r):e(r)}buildOpenApiSpec(){if(this.cachedSpec)return this.cachedSpec;if(!this.options.openapi)throw new Error("[HonoServer] openapi config not set");return this.cachedSpec=C(this.mountedRoutes,this.options.basePath??"",this.options.openapi,me(this.options.interceptor)),this.cachedSpec}mountRoutes(){let e=this.options.basePath??"",n=this.options.validateOutput??false,r=this.options.verbose??false;for(let s of this.mountedRoutes){if(!s.path)throw new Error(`[HonoServer] route "${s.method.toUpperCase()} (no path)" \u2014 missing \`path\`. Run the codegen so the path is derived from the file location, or set it explicitly.`);let o=k(e,s.path),a=s.middlewares??[],i=s.source??(s.method==="get"?"query":"json"),c=Se(s,i,n,he(this.options.interceptor),this.options.services,this.options.errorHandler,this.options.logger),p=s.method.toUpperCase();this.app.on(p,[o],...a,c),r&&console.log(`[HonoServer] ${s.method.toUpperCase().padEnd(6)} ${o}`);}}mountOpenApi(){let e=this.options.openapi;if(!e)return;let n=e.path??"/openapi.json",r=e.docsPath===void 0?"/docs":e.docsPath,s=k(this.options.basePath??"",n),o=r===false?null:k(this.options.basePath??"",r),a=e.docsAuth?Array.isArray(e.docsAuth)?e.docsAuth:[e.docsAuth]:[];if(this.app.on("GET",[s],...a,i=>i.json(this.buildOpenApiSpec())),o){let i=Te(o,s);this.app.on("GET",[o],...a,c=>c.html(P(i,e.info.title)));}}};function $(t){return typeof t=="object"&&t!==null&&typeof t.handler=="function"}function he(t){if(t)return $(t)?t.handler:t}function me(t){return $(t)?t:void 0}function ve(t,e){return e?t.filter(n=>Array.isArray(n.api)?n.api.includes(e):n.api===e):t.slice()}function k(t,e){let n=t.endsWith("/")?t.slice(0,-1):t,r=e.startsWith("/")?e:`/${e}`,s=`${n}${r}`;return s===""?"/":s}function Te(t,e){let n=t.split("/").filter(Boolean),r=e.split("/").filter(Boolean);n.pop();let s=0;for(;s<n.length&&s<r.length&&n[s]===r[s];)s++;let o=n.length-s;return [...Array(o).fill(".."),...r.slice(s)].join("/")||"./"}function Se(t,e,n,r,s,o,a){let i=t.input,c=t.output,p=t.status??200,u=s??ge;return async d=>{let m=async f=>{if(o){let l=await o.handle({error:f,c:d,route:t,services:u,logger:a});if(l)return l}return E(d,f)},g=async()=>{let f;if(i){let y;try{y=await Re(d,e,t.method);}catch(A){throw new T(A instanceof Error?A.message:String(A))}let x=i.safeParse(y);if(!x.success)throw new v(x.error,e);f=x.data;}let l=await t.handler({input:f,c:d,services:u,errorHandler:o,logger:a});if(n&&c&&!(l instanceof Response)){let y=c.safeParse(l);if(!y.success)throw new S(y.error);return y.data}return l},h;if(r)try{h=await r({next:g,route:t,c:d,services:u,errorHandler:o,logger:a});}catch(f){let l=await m(f);if(l)return l;throw f}else try{h=await g();}catch(f){let l=await m(f);if(l)return l;throw f}return h instanceof Response?h:d.json(h,p)}}async function Re(t,e,n){switch(e){case "json":{if(n==="get")return t.req.query();let r=await t.req.text();if(!r)return {};try{return JSON.parse(r)}catch(s){throw new Error(`Invalid JSON body: ${s instanceof Error?s.message:String(s)}`)}}case "query":return t.req.query();case "form":return await t.req.parseBody();case "param":return t.req.param();default:return {}}}var b=class{constructor(e){this.services=e;}};function H(t,e){return {...e,input:t.input,output:t.output,handler:({input:n,services:r})=>new t(r).execute(n)}}function xe(t,e){let n=e?.services,r=e?.errorHandler,s=e?.logger;return {configs:t,defineRoute(o){return o},useCaseRoute(o,a){return H(o,a)},serverFor(o,a){let i=t[o];if(!i)throw new Error(`[ApiRegistry] unknown api "${o}". Registered: ${Object.keys(t).join(", ")}`);return new R({...i,api:o,routes:a,services:n,errorHandler:i.errorHandler??r,logger:i.logger??s})},toFunctions(o,a,i){let c={};for(let p of Object.keys(t)){let u={...i?.defaults??{},...i?.per?.[p]??{}},d=new R({...t[p],api:p,routes:o,services:n,errorHandler:t[p].errorHandler??r,logger:t[p].logger??s});c[p]=Object.keys(u).length?d.toFunction(a,u):d.toFunction(a);}return c}}}var M=class{async handle(e){let n=await this.mapError(e);return n?(this.logError(e,n),n):this.handleBuiltin(e)}mapError(e){return null}logError(e,n){}handleBuiltin(e){return E(e.c,e.error)}};var D=class t{info(e,n){this.write("INFO",this.payload(e,n));}warn(e,n){this.write("WARNING",this.payload(e,n));}debug(e,n){this.write("DEBUG",this.payload(e,n));}error(e,n){let r=t.errorId(e);return this.write("ERROR",{errorId:r,message:e instanceof Error?e.message:String(e),...e instanceof Error&&e.stack?{stack:e.stack}:{},...n!==void 0?{meta:n}:{}}),r}payload(e,n){return n!==void 0?{message:e,meta:n}:{message:e}}write(e,n){let r={severity:e,...n};e==="ERROR"?console.error(r):e==="WARNING"?console.warn(r):console.log(r);}static errorId(e){return e&&typeof e=="object"&&"errorId"in e&&typeof e.errorId=="string"?e.errorId:Math.random().toString(36).slice(2,12)}};function Ae(t){let{getAuth:e,allow:n,checkRevoked:r=false,contextKey:s="docsUser"}=t;return async(o,a)=>{let c=(o.req.header("authorization")??o.req.header("Authorization"))?.match(/^Bearer\s+(.+)$/i);if(!c)return o.json({error:"Unauthorized"},401,{"WWW-Authenticate":"Bearer"});let p;try{p=await e().verifyIdToken(c[1],r);}catch{return o.json({error:"Unauthorized"},401,{"WWW-Authenticate":"Bearer"})}if(n){let u=false;try{u=await n(p);}catch{u=false;}if(!u)return o.json({error:"Forbidden"},403)}return o.set(s,p),a()}}function Ee(t){let{username:e,password:n,realm:r="Docs"}=t,s=`Basic ${btoa(`${e}:${n}`)}`;return async(o,a)=>{let i=o.req.header("authorization")??o.req.header("Authorization")??"";return we(i,s)?a():o.text("Unauthorized",401,{"WWW-Authenticate":`Basic realm="${r}"`})}}function we(t,e){if(t.length!==e.length)return false;let n=0;for(let r=0;r<t.length;r++)n|=t.charCodeAt(r)^e.charCodeAt(r);return n===0}var N={skipSegments:["useCases","useCase","use-cases","use-case"],casing:"preserve"};function z(t,e=N){let n=new Set(e.skipSegments.map(s=>s.toLowerCase()));return "/"+t.split("/").filter(Boolean).filter(s=>!n.has(s.toLowerCase())).map(s=>e.casing==="kebab"?Oe(s):s).join("/")}function Oe(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function F(t,e,n){let r=L(t),s=L(e),o=0;for(;o<r.length&&o<s.length&&r[o]===s[o];)o++;let a=r.length-o,i=s.slice(o),p=(i[i.length-1]??"").replace(/\.[mc]?[tj]sx?$/i,""),u=n===""?p:`${p}${n}`;return i[i.length-1]=u,(a===0?"./":"../".repeat(a))+i.join("/")}function L(t){return t.replace(/\\/g,"/").replace(/\/+$/,"").split("/").filter((n,r)=>!(r===0&&n===""))}var K={routesFile:"routes.ts",excludeSegments:["node_modules","__generated__","tests","__tests__",".turbo","dist","build",".next"]};function He(t,e=K){let n=[];return G(t,t,e,n),n.sort((r,s)=>r.relPath.localeCompare(s.relPath)),n}function G(t,e,n,r){let s;try{s=readdirSync(e);}catch{return}for(let o of s){if(n.excludeSegments.includes(o))continue;let a=join(e,o),i;try{i=statSync(a);}catch{continue}if(i.isDirectory())G(t,a,n,r);else if(i.isFile()&&o===n.routesFile){let c=relative(t,a).split(sep).join("/"),p=c.replace(/\/?[^/]+$/,"");r.push({absPath:a,relPath:c,relDir:p});}}}var W="/**\n * AUTO-GENERATED by `@lpdjs/firestore-repo-service` Hono codegen.\n * Do not edit by hand \u2014 re-run `hono:gen` after adding / removing route files.\n */\n";function V(t,e){let n=dirname(e.outFile);mkdirSync(n,{recursive:true});let r=e.banner??W,s=(e.now??new Date).toISOString(),o=e.importExtension,a=[],i=[],c=[];t.forEach((u,d)=>{let m=F(n,u.absPath,o),g=z(u.relDir,e.derive);a.push(`import mod${d} from ${JSON.stringify(m)};`),i.push(` { __derivedPath: ${JSON.stringify(g)}, mod: mod${d} },`),c.push({source:u.relPath,url:g});});let p=`${r}// Generated at ${s} \u2014 ${t.length} route file${t.length===1?"":"s"}.
12
+ </html>`}var w=new AsyncLocalStorage,de=Object.freeze({get c(){let t=w.getStore();if(!t)throw new Error("[services] requestContext.c was accessed outside of a request. Wrap non-HTTP code paths (cron, triggers, scripts, tests) in `withRequestContext({ c }, () => ...)` to supply a Hono Context.");return t.c},get maybeC(){return w.getStore()?.c}});function I(){return async(t,e)=>{await w.run({c:t},async()=>{await e();});}}function le(t,e){return w.run({c:t.c},async()=>e())}var O="ctx";function fe(t){let e=new Map,n=[],o=new Proxy({},{get(s,r){if(typeof r!="string")return;if(r===O)return de;if(e.has(r))return e.get(r);let a=t[r];if(typeof a!="function")throw new Error(`[services] unknown service "${r}". Registered: ${[O,...Object.keys(t)].join(", ")}`);if(n.includes(r))throw new Error(`[services] circular dependency detected: ${[...n,r].join(" \u2192 ")}`);n.push(r);try{let i=ye(a)?new a(o):a(o);return e.set(r,i),i}finally{n.pop();}},has(s,r){return typeof r!="string"?false:r===O||r in t},ownKeys(){return [O,...Object.keys(t)]},getOwnPropertyDescriptor(s,r){if(typeof r=="string"&&(r===O||r in t))return {enumerable:true,configurable:true}}});return o}function ye(t){return /^class[\s{]/.test(Function.prototype.toString.call(t))}var me=Object.freeze({}),R=class{constructor(e){this.cachedSpec=null;this.options=e,this.app=new Hono,this.mountedRoutes=Se(e.routes,e.api),e.services&&this.app.use("*",I());let n=[...e.middlewares??[],...e.globalMiddlewares??[]];for(let o of n)this.app.use("*",o);this.mountRoutes(),this.mountOpenApi(),e.notFound&&this.app.notFound(e.notFound),e.onError&&this.app.onError(e.onError);}get hono(){return this.app}get nodeHandler(){return getRequestListener(this.app.fetch,{overrideGlobalObjects:false})}toFunction(e,n){let o=this.nodeHandler;return n?e(n,o):e(o)}buildOpenApiSpec(){if(this.cachedSpec)return this.cachedSpec;if(!this.options.openapi)throw new Error("[HonoServer] openapi config not set");return this.cachedSpec=C(this.mountedRoutes,this.options.basePath??"",this.options.openapi,Te(this.options.interceptor)),this.cachedSpec}mountRoutes(){let e=this.options.basePath??"",n=this.options.validateOutput??false,o=this.options.verbose??false;for(let s of this.mountedRoutes){if(!s.path)throw new Error(`[HonoServer] route "${s.method.toUpperCase()} (no path)" \u2014 missing \`path\`. Run the codegen so the path is derived from the file location, or set it explicitly.`);let r=k(e,s.path),a=s.middlewares??[],i=s.source??(s.method==="get"?"query":"json"),c=xe(s,i,n,ve(this.options.interceptor),this.options.services,this.options.errorHandler,this.options.logger),p=s.method.toUpperCase();this.app.on(p,[r],...a,c),o&&console.log(`[HonoServer] ${s.method.toUpperCase().padEnd(6)} ${r}`);}}mountOpenApi(){let e=this.options.openapi;if(!e)return;let n=e.path??"/openapi.json",o=e.docsPath===void 0?"/docs":e.docsPath,s=k(this.options.basePath??"",n),r=o===false?null:k(this.options.basePath??"",o),a=e.docsAuth?Array.isArray(e.docsAuth)?e.docsAuth:[e.docsAuth]:[];if(this.app.on("GET",[s],...a,i=>i.json(this.buildOpenApiSpec())),r){let i=Re(r,s);this.app.on("GET",[r],...a,c=>c.html(P(i,e.info.title)));}}};function B(t){return typeof t=="object"&&t!==null&&typeof t.handler=="function"}function ve(t){if(t)return B(t)?t.handler:t}function Te(t){return B(t)?t:void 0}function Se(t,e){return e?t.filter(n=>Array.isArray(n.api)?n.api.includes(e):n.api===e):t.slice()}function k(t,e){let n=t.endsWith("/")?t.slice(0,-1):t,o=e.startsWith("/")?e:`/${e}`,s=`${n}${o}`;return s===""?"/":s}function Re(t,e){let n=t.split("/").filter(Boolean),o=e.split("/").filter(Boolean);n.pop();let s=0;for(;s<n.length&&s<o.length&&n[s]===o[s];)s++;let r=n.length-s;return [...Array(r).fill(".."),...o.slice(s)].join("/")||"./"}function xe(t,e,n,o,s,r,a){let i=t.input,c=t.output,p=t.status??200,u=s??me;return async d=>{let m=async f=>{if(r){let l=await r.handle({error:f,c:d,route:t,services:u,logger:a});if(l)return l}return E(d,f)},g=async()=>{let f;if(i){let y;try{y=await Ae(d,e,t.method);}catch(A){throw new T(A instanceof Error?A.message:String(A))}let x=i.safeParse(y);if(!x.success)throw new v(x.error,e);f=x.data;}let l=await t.handler({input:f,c:d,services:u,errorHandler:r,logger:a});if(n&&c&&!(l instanceof Response)){let y=c.safeParse(l);if(!y.success)throw new S(y.error);return y.data}return l},h;if(o)try{h=await o({next:g,route:t,c:d,services:u,errorHandler:r,logger:a});}catch(f){let l=await m(f);if(l)return l;throw f}else try{h=await g();}catch(f){let l=await m(f);if(l)return l;throw f}return h instanceof Response?h:d.json(h,p)}}async function Ae(t,e,n){switch(e){case "json":{if(n==="get")return t.req.query();let o=await t.req.text();if(!o)return {};try{return JSON.parse(o)}catch(s){throw new Error(`Invalid JSON body: ${s instanceof Error?s.message:String(s)}`)}}case "query":return t.req.query();case "form":return await t.req.parseBody();case "param":return t.req.param();default:return {}}}var b=class{constructor(e){this.services=e;}};function H(t,e){return {...e,input:t.input,output:t.output,handler:({input:n,services:o})=>new t(o).execute(n)}}function Ee(t,e){let n=e?.services,o=e?.errorHandler,s=e?.logger;return {configs:t,defineRoute(r){return r},useCaseRoute(r,a){return H(r,a)},serverFor(r,a){let i=t[r];if(!i)throw new Error(`[ApiRegistry] unknown api "${r}". Registered: ${Object.keys(t).join(", ")}`);return new R({...i,api:r,routes:a,services:n,errorHandler:i.errorHandler??o,logger:i.logger??s})},toFunctions(r,a,i){let c={};for(let p of Object.keys(t)){let u={...i?.defaults??{},...i?.per?.[p]??{}},d=new R({...t[p],api:p,routes:r,services:n,errorHandler:t[p].errorHandler??o,logger:t[p].logger??s});c[p]=Object.keys(u).length?d.toFunction(a,u):d.toFunction(a);}return c}}}function G(t){return t||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT||process.env.GCP_PROJECT||void 0}function M(t,e={}){if(!e.enabled||!t)return;let n=G(e.projectId);if(!n)return;let s=`jsonPayload.${e.field??"errorId"}="${t}"`,r=[`query=${encodeURIComponent(s)}`];return e.duration&&r.push(`duration=${encodeURIComponent(e.duration)}`),`https://console.cloud.google.com/logs/query;${r.join(";")}?project=${encodeURIComponent(n)}`}var D=class{constructor(e={}){this.options=e;}gcpLogsUrl(e){return M(e,this.options.gcpLogs)}async handle(e){let n=await this.mapError(e);return n?(this.logError(e,n),n):this.handleBuiltin(e)}mapError(e){return null}logError(e,n){}handleBuiltin(e){return E(e.c,e.error)}};var z=class t{info(e,n){this.write("INFO",this.payload(e,n));}warn(e,n){this.write("WARNING",this.payload(e,n));}debug(e,n){this.write("DEBUG",this.payload(e,n));}error(e,n){let o=t.errorId(e);return this.write("ERROR",{errorId:o,message:e instanceof Error?e.message:String(e),...e instanceof Error&&e.stack?{stack:e.stack}:{},...n!==void 0?{meta:n}:{}}),o}payload(e,n){return n!==void 0?{message:e,meta:n}:{message:e}}write(e,n){let o={severity:e,...n};e==="ERROR"?console.error(o):e==="WARNING"?console.warn(o):console.log(o);}static errorId(e){return e&&typeof e=="object"&&"errorId"in e&&typeof e.errorId=="string"?e.errorId:Math.random().toString(36).slice(2,12)}};function Oe(t){let{getAuth:e,allow:n,checkRevoked:o=false,contextKey:s="docsUser"}=t;return async(r,a)=>{let c=(r.req.header("authorization")??r.req.header("Authorization"))?.match(/^Bearer\s+(.+)$/i);if(!c)return r.json({error:"Unauthorized"},401,{"WWW-Authenticate":"Bearer"});let p;try{p=await e().verifyIdToken(c[1],o);}catch{return r.json({error:"Unauthorized"},401,{"WWW-Authenticate":"Bearer"})}if(n){let u=false;try{u=await n(p);}catch{u=false;}if(!u)return r.json({error:"Forbidden"},403)}return r.set(s,p),a()}}function we(t){let{username:e,password:n,realm:o="Docs"}=t,s=`Basic ${btoa(`${e}:${n}`)}`;return async(r,a)=>{let i=r.req.header("authorization")??r.req.header("Authorization")??"";return Ce(i,s)?a():r.text("Unauthorized",401,{"WWW-Authenticate":`Basic realm="${o}"`})}}function Ce(t,e){if(t.length!==e.length)return false;let n=0;for(let o=0;o<t.length;o++)n|=t.charCodeAt(o)^e.charCodeAt(o);return n===0}var K={skipSegments:["useCases","useCase","use-cases","use-case"],casing:"preserve"};function F(t,e=K){let n=new Set(e.skipSegments.map(s=>s.toLowerCase()));return "/"+t.split("/").filter(Boolean).filter(s=>!n.has(s.toLowerCase())).map(s=>e.casing==="kebab"?Pe(s):s).join("/")}function Pe(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function j(t,e,n){let o=N(t),s=N(e),r=0;for(;r<o.length&&r<s.length&&o[r]===s[r];)r++;let a=o.length-r,i=s.slice(r),p=(i[i.length-1]??"").replace(/\.[mc]?[tj]sx?$/i,""),u=n===""?p:`${p}${n}`;return i[i.length-1]=u,(a===0?"./":"../".repeat(a))+i.join("/")}function N(t){return t.replace(/\\/g,"/").replace(/\/+$/,"").split("/").filter((n,o)=>!(o===0&&n===""))}var W={routesFile:"routes.ts",excludeSegments:["node_modules","__generated__","tests","__tests__",".turbo","dist","build",".next"]};function De(t,e=W){let n=[];return V(t,t,e,n),n.sort((o,s)=>o.relPath.localeCompare(s.relPath)),n}function V(t,e,n,o){let s;try{s=readdirSync(e);}catch{return}for(let r of s){if(n.excludeSegments.includes(r))continue;let a=join(e,r),i;try{i=statSync(a);}catch{continue}if(i.isDirectory())V(t,a,n,o);else if(i.isFile()&&r===n.routesFile){let c=relative(t,a).split(sep).join("/"),p=c.replace(/\/?[^/]+$/,"");o.push({absPath:a,relPath:c,relDir:p});}}}var J="/**\n * AUTO-GENERATED by `@lpdjs/firestore-repo-service` Hono codegen.\n * Do not edit by hand \u2014 re-run `hono:gen` after adding / removing route files.\n */\n";function Y(t,e){let n=dirname(e.outFile);mkdirSync(n,{recursive:true});let o=e.banner??J,s=(e.now??new Date).toISOString(),r=e.importExtension,a=[],i=[],c=[];t.forEach((u,d)=>{let m=j(n,u.absPath,r),g=F(u.relDir,e.derive);a.push(`import mod${d} from ${JSON.stringify(m)};`),i.push(` { __derivedPath: ${JSON.stringify(g)}, mod: mod${d} },`),c.push({source:u.relPath,url:g});});let p=`${o}// Generated at ${s} \u2014 ${t.length} route file${t.length===1?"":"s"}.
13
13
 
14
14
  import type { AnyRouteDef, RouteModuleDefault } from "@lpdjs/firestore-repo-service/servers/hono";
15
15
 
@@ -26,5 +26,5 @@ export const routes: AnyRouteDef[] = __defs.flatMap(({ __derivedPath, mod }) =>
26
26
  const list = Array.isArray(mod) ? mod : [mod];
27
27
  return list.map((route) => ({ ...route, path: route.path ?? __derivedPath }));
28
28
  });
29
- `;return writeFileSync(e.outFile,p,"utf8"),{outFile:e.outFile,routeCount:t.length,derivedPaths:c}}function qe(t,e,n,r,s){let o=s(t),a=join(t,e);return V(o,{outFile:a,derive:n,importExtension:r})}export{T as BadRequestError,M as BaseErrorHandler,D as BaseLogger,N as DEFAULT_DERIVE,W as DEFAULT_GENERATOR_BANNER,K as DEFAULT_SCANNER,R as HonoServer,S as OutputValidationError,b as UseCase,v as ValidationError,Ee as basicAuth,C as buildOpenApiDocument,xe as createApiRegistry,I as createRequestContextMiddleware,de as createServices,E as defaultErrorResponse,J as defineRoutes,z as derivePath,Ae as firebaseBearerAuth,qe as generateFromRoot,V as generateRoutesManifest,P as renderDocsHtml,He as scanRoutes,F as toImportSpecifier,H as useCaseRoute,ue as withRequestContext};//# sourceMappingURL=index.js.map
29
+ `;return writeFileSync(e.outFile,p,"utf8"),{outFile:e.outFile,routeCount:t.length,derivedPaths:c}}function Le(t,e,n,o,s){let r=s(t),a=join(t,e);return Y(r,{outFile:a,derive:n,importExtension:o})}export{T as BadRequestError,D as BaseErrorHandler,z as BaseLogger,K as DEFAULT_DERIVE,J as DEFAULT_GENERATOR_BANNER,W as DEFAULT_SCANNER,R as HonoServer,S as OutputValidationError,b as UseCase,v as ValidationError,we as basicAuth,C as buildOpenApiDocument,Ee as createApiRegistry,I as createRequestContextMiddleware,fe as createServices,E as defaultErrorResponse,Q as defineRoutes,F as derivePath,Oe as firebaseBearerAuth,M as gcpLogsUrl,Le as generateFromRoot,Y as generateRoutesManifest,P as renderDocsHtml,G as resolveGcpProjectId,De as scanRoutes,j as toImportSpecifier,H as useCaseRoute,le as withRequestContext};//# sourceMappingURL=index.js.map
30
30
  //# sourceMappingURL=index.js.map