@analogjs/router 3.0.0-alpha.6 → 3.0.0-alpha.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/package.json +4 -0
- package/fesm2022/analogjs-router-content.mjs +63 -0
- package/fesm2022/analogjs-router-content.mjs.map +1 -0
- package/fesm2022/analogjs-router-i18n.mjs +156 -0
- package/fesm2022/analogjs-router-i18n.mjs.map +1 -0
- package/fesm2022/analogjs-router-server-actions.mjs +2 -27
- package/fesm2022/analogjs-router-server.mjs +60 -3
- package/fesm2022/analogjs-router-server.mjs.map +1 -0
- package/fesm2022/analogjs-router-tanstack-query-server.mjs +71 -0
- package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
- package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
- package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
- package/fesm2022/analogjs-router-tokens.mjs +7 -2
- package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
- package/fesm2022/analogjs-router.mjs +559 -61
- package/fesm2022/analogjs-router.mjs.map +1 -0
- package/fesm2022/debug.page.mjs +53 -31
- package/fesm2022/debug.page.mjs.map +1 -0
- package/fesm2022/provide-analog-query.mjs +72 -0
- package/fesm2022/provide-analog-query.mjs.map +1 -0
- package/fesm2022/route-files.mjs +361 -0
- package/fesm2022/route-files.mjs.map +1 -0
- package/fesm2022/routes.mjs +5 -278
- package/fesm2022/routes.mjs.map +1 -0
- package/fesm2022/src.mjs +335 -0
- package/fesm2022/src.mjs.map +1 -0
- package/i18n/package.json +4 -0
- package/package.json +77 -26
- package/tanstack-query/package.json +4 -0
- package/tanstack-query/server/package.json +4 -0
- package/types/content/src/index.d.ts +4 -0
- package/types/content/src/lib/debug/routes.d.ts +10 -0
- package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
- package/types/content/src/lib/routes.d.ts +8 -0
- package/types/content/src/lib/with-content-routes.d.ts +2 -0
- package/types/i18n/src/index.d.ts +1 -0
- package/types/i18n/src/provide-i18n.d.ts +92 -0
- package/types/server/actions/src/define-action.d.ts +54 -0
- package/types/server/actions/src/define-api-route.d.ts +57 -0
- package/types/server/actions/src/define-page-load.d.ts +55 -0
- package/types/server/actions/src/define-server-route.d.ts +68 -0
- package/types/server/actions/src/index.d.ts +9 -1
- package/types/server/actions/src/parse-request-data.d.ts +9 -0
- package/types/server/actions/src/validate.d.ts +8 -0
- package/types/server/src/provide-server-context.d.ts +15 -1
- package/types/server/src/render.d.ts +1 -1
- package/types/server/src/server-component-render.d.ts +1 -1
- package/types/src/index.d.ts +16 -5
- package/types/src/lib/cache-key.d.ts +1 -1
- package/types/src/lib/cookie-interceptor.d.ts +1 -1
- package/types/src/lib/debug/debug.page.d.ts +4 -2
- package/types/src/lib/define-route.d.ts +6 -1
- package/types/src/lib/endpoints.d.ts +1 -1
- package/types/src/lib/experimental.d.ts +140 -0
- package/types/src/lib/form-action.directive.d.ts +12 -5
- package/types/src/lib/inject-load.d.ts +5 -2
- package/types/src/lib/inject-navigate.d.ts +23 -0
- package/types/src/lib/inject-route-context.d.ts +32 -0
- package/types/src/lib/inject-typed-params.d.ts +63 -0
- package/types/src/lib/json-ld.d.ts +32 -0
- package/types/src/lib/meta-tags.d.ts +3 -1
- package/types/src/lib/models.d.ts +3 -0
- package/types/src/lib/provide-file-router-base.d.ts +4 -0
- package/types/src/lib/provide-file-router.d.ts +2 -8
- package/types/src/lib/route-builder.d.ts +5 -0
- package/types/src/lib/route-files.d.ts +18 -0
- package/types/src/lib/route-path.d.ts +124 -0
- package/types/src/lib/route-types.d.ts +2 -1
- package/types/src/lib/routes.d.ts +2 -10
- package/types/src/lib/validation-errors.d.ts +7 -0
- package/types/tanstack-query/server/src/define-page-load-queries.d.ts +66 -0
- package/types/tanstack-query/server/src/index.d.ts +3 -0
- package/types/tanstack-query/src/constants.d.ts +9 -0
- package/types/tanstack-query/src/index.d.ts +2 -0
- package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
- package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
- package/types/tanstack-query/src/server-query.d.ts +16 -0
- package/types/tokens/src/index.d.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src.mjs","names":[],"sources":["../../server/actions/src/actions.ts","../../server/actions/src/parse-request-data.ts","../../server/actions/src/validate.ts","../../server/actions/src/define-action.ts","../../server/actions/src/define-server-route.ts","../../server/actions/src/define-page-load.ts"],"sourcesContent":["import type { H3Event, H3EventContext } from 'nitro/h3';\nimport type { $Fetch } from 'nitro/types';\nimport type { NodeContext } from '../../../src/lib/route-types.js';\n\nexport type PageServerAction = {\n params: H3EventContext['params'];\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n};\n\nexport function fail<T = object>(status: number, errors: T): Response {\n return new Response(JSON.stringify(errors), {\n status,\n headers: {\n 'X-Analog-Errors': 'true',\n },\n });\n}\n\nexport function json<T = object>(data: T, config?: ResponseInit): Response {\n return new Response(JSON.stringify(data), {\n headers: {\n 'Content-Type': 'application/json; charset=utf-8',\n },\n ...config,\n });\n}\n\nexport function redirect(\n url: string,\n config: number | ResponseInit = 302,\n): Response {\n if (typeof config === 'number') {\n return new Response(null, {\n status: config,\n headers: {\n Location: `${url}`,\n },\n });\n }\n\n return new Response(null, {\n headers: {\n Location: `${url}`,\n },\n ...config,\n });\n}\n","import { readBody, readFormData, toRequest as h3ToRequest } from 'nitro/h3';\n\ntype RequestEntryValue = string | File;\ntype ParsedRequestValue = RequestEntryValue | RequestEntryValue[];\n\nfunction appendEntry(\n target: Record<string, ParsedRequestValue>,\n key: string,\n value: RequestEntryValue,\n) {\n const existingValue = target[key];\n\n if (existingValue === undefined) {\n target[key] = value;\n return;\n }\n\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n return;\n }\n\n target[key] = [existingValue, value];\n}\n\nfunction getRequest(event: { method: string; headers: Headers }): Request {\n const maybeRequest = (event as unknown as { request?: Request }).request;\n if (maybeRequest) {\n return maybeRequest;\n }\n return h3ToRequest(event as Parameters<typeof h3ToRequest>[0]);\n}\n\nfunction getContentType(event: { method: string; headers: Headers }): string {\n const request = getRequest(event);\n\n return (\n request.headers.get('content-type') ??\n event.headers.get('content-type') ??\n event.headers.get('Content-Type') ??\n ''\n );\n}\n\nfunction isJsonContentType(contentType: string): boolean {\n const mimeType = contentType.split(';', 1)[0]?.trim().toLowerCase() ?? '';\n return mimeType === 'application/json' || mimeType.endsWith('+json');\n}\n\nfunction isFormContentType(contentType: string): boolean {\n return (\n contentType.includes('multipart/form-data') ||\n contentType.includes('application/x-www-form-urlencoded')\n );\n}\n\nexport function parseSearchParams(\n searchParams: URLSearchParams,\n): Record<string, ParsedRequestValue> {\n const result: Record<string, ParsedRequestValue> = {};\n searchParams.forEach((value, key) => {\n appendEntry(result, key, value);\n });\n return result;\n}\n\nexport function parseFormData(\n formData: FormData,\n): Record<string, ParsedRequestValue> {\n const result: Record<string, ParsedRequestValue> = {};\n formData.forEach((value, key) => {\n appendEntry(result, key, value as RequestEntryValue);\n });\n return result;\n}\n\nexport async function parseRequestData(event: {\n method: string;\n headers: Headers;\n}): Promise<unknown> {\n const request = getRequest(event);\n const httpEvent = event as unknown as Parameters<typeof readBody>[0];\n const h3Event = event as unknown as Parameters<typeof readFormData>[0];\n const method = event.method.toUpperCase();\n\n if (method === 'GET' || method === 'HEAD') {\n const url = new URL(request.url, 'http://localhost');\n return parseSearchParams(url.searchParams);\n }\n\n const contentType = getContentType(event);\n\n if (isJsonContentType(contentType)) {\n try {\n return (await readBody(httpEvent)) ?? {};\n } catch {\n try {\n return await request.json();\n } catch {\n return {};\n }\n }\n }\n\n if (isFormContentType(contentType)) {\n try {\n return parseFormData(await readFormData(h3Event));\n } catch {\n if (typeof request.formData === 'function') {\n return parseFormData(await request.formData());\n }\n\n return {};\n }\n }\n\n try {\n return (await readBody(httpEvent)) ?? {};\n } catch {\n try {\n return await request.json();\n } catch {\n return {};\n }\n }\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\n\n/**\n * Validates unknown input against a Standard Schema.\n *\n * Handles both sync and async `validate` implementations — the Standard\n * Schema spec allows either return shape.\n */\nexport async function validateWithSchema<T extends StandardSchemaV1>(\n schema: T,\n data: unknown,\n): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<T>>> {\n return schema['~standard'].validate(data);\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { H3Event, H3EventContext } from 'nitro/h3';\nimport type { $Fetch } from 'nitro/types';\nimport { fail } from './actions';\nimport { parseRequestData } from './parse-request-data';\nimport { validateWithSchema } from './validate';\n\ntype NodeContext = NonNullable<H3Event['node']>;\ntype OptionalSchema = StandardSchemaV1 | undefined;\ntype InferSchema<\n TSchema extends OptionalSchema,\n TFallback,\n> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TSchema>\n : TFallback;\n\nexport interface DefineActionContext<\n TSchema extends OptionalSchema = undefined,\n TParamsSchema extends OptionalSchema = undefined,\n> {\n data: InferSchema<TSchema, Record<string, unknown>>;\n params: InferSchema<TParamsSchema, H3EventContext['params']>;\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n}\n\nexport interface DefineActionOptions<\n TSchema extends OptionalSchema = undefined,\n TParamsSchema extends OptionalSchema = undefined,\n> {\n schema?: TSchema;\n params?: TParamsSchema;\n handler: (\n context: DefineActionContext<TSchema, TParamsSchema>,\n ) => Promise<Response> | Response;\n}\n\n/**\n * Creates a server action handler with Standard Schema input validation.\n *\n * Parses the request body (JSON or FormData) and validates it against the\n * provided schema before invoking the handler. On validation failure,\n * returns `fail(422, issues)` with `StandardSchemaV1.Issue[]`.\n * Repeated form fields are preserved as arrays instead of being collapsed\n * to the last value.\n *\n * @example\n * ```typescript\n * import { defineAction, json } from '@analogjs/router/server/actions';\n * import * as v from 'valibot';\n *\n * const Schema = v.object({\n * email: v.pipe(v.string(), v.email()),\n * });\n *\n * export const action = defineAction({\n * schema: Schema,\n * handler: async ({ data }) => {\n * // data is typed as { email: string }\n * return json({ ok: true });\n * },\n * });\n * ```\n */\nexport function defineAction<\n TSchema extends OptionalSchema = undefined,\n TParamsSchema extends OptionalSchema = undefined,\n>(options: DefineActionOptions<TSchema, TParamsSchema>) {\n type Params = InferSchema<TParamsSchema, H3EventContext['params']>;\n\n function getParams(\n params: H3EventContext['params'],\n ): Params | Record<string, never> {\n return (params ?? {}) as Params | Record<string, never>;\n }\n\n return async (ctx: {\n params: H3EventContext['params'];\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n }): Promise<Response> => {\n const rawParams = getParams(ctx.params);\n\n if (options.params) {\n const paramsResult = await validateWithSchema(options.params, rawParams);\n if (paramsResult.issues) {\n return fail(422, paramsResult.issues);\n }\n return handleValidatedRequest(ctx, options, paramsResult.value as Params);\n }\n\n return handleValidatedRequest(ctx, options, rawParams as Params);\n };\n}\n\nasync function handleValidatedRequest<\n TSchema extends OptionalSchema = undefined,\n TParamsSchema extends OptionalSchema = undefined,\n>(\n ctx: {\n params: H3EventContext['params'];\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n },\n options: DefineActionOptions<TSchema, TParamsSchema>,\n params: InferSchema<TParamsSchema, H3EventContext['params']>,\n) {\n type Data = InferSchema<TSchema, Record<string, unknown>>;\n const body = await parseRequestData(ctx.event);\n\n let data: unknown = body;\n\n if (options.schema) {\n const result = await validateWithSchema(options.schema, body);\n if (result.issues) {\n return fail(422, result.issues);\n }\n data = result.value;\n }\n\n return options.handler({\n data: data as Data,\n params,\n req: ctx.req,\n res: ctx.res,\n fetch: ctx.fetch,\n event: ctx.event,\n });\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { H3Event } from 'nitro/h3';\nimport { getRequestURL } from 'nitro/h3';\nimport { fail, json } from './actions';\nimport { parseRequestData, parseSearchParams } from './parse-request-data';\nimport { validateWithSchema } from './validate';\n\nexport type DefineServerRouteResult = Response | unknown;\n\nexport interface ServerRouteHandler<\n TQuery = unknown,\n TBody = unknown,\n TResult = unknown,\n> {\n (event: H3Event): Promise<Response>;\n readonly _types: {\n readonly query: TQuery;\n readonly body: TBody;\n readonly result: TResult;\n };\n}\n\nexport type InferRouteQuery<T> =\n T extends ServerRouteHandler<infer Q, any, any> ? Q : never;\nexport type InferRouteBody<T> =\n T extends ServerRouteHandler<any, infer B, any> ? B : never;\nexport type InferRouteResult<T> =\n T extends ServerRouteHandler<any, any, infer R>\n ? Exclude<R, Response>\n : never;\n\ntype OptionalSchema = StandardSchemaV1 | undefined;\ntype InferSchema<\n TSchema extends OptionalSchema,\n TFallback = unknown,\n> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TSchema>\n : TFallback;\ntype ResolveDataSchema<\n TInput extends OptionalSchema,\n TQuery extends OptionalSchema,\n TBody extends OptionalSchema,\n> = TInput extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TInput>\n : TQuery extends StandardSchemaV1\n ? TBody extends StandardSchemaV1\n ?\n | StandardSchemaV1.InferOutput<TQuery>\n | StandardSchemaV1.InferOutput<TBody>\n : StandardSchemaV1.InferOutput<TQuery>\n : TBody extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TBody>\n : unknown;\n\nexport interface DefineServerRouteContext<\n TInput extends StandardSchemaV1 | undefined = undefined,\n TQuery extends StandardSchemaV1 | undefined = undefined,\n TBody extends StandardSchemaV1 | undefined = undefined,\n TParams extends StandardSchemaV1 | undefined = undefined,\n> {\n data: ResolveDataSchema<TInput, TQuery, TBody>;\n query: InferSchema<TQuery, undefined>;\n body: InferSchema<TBody, undefined>;\n params: InferSchema<TParams, H3Event['context']['params']>;\n event: H3Event;\n}\n\nexport interface DefineServerRouteOptions<\n TInput extends StandardSchemaV1 | undefined = undefined,\n TOutput extends StandardSchemaV1 | undefined = undefined,\n TQuery extends StandardSchemaV1 | undefined = undefined,\n TBody extends StandardSchemaV1 | undefined = undefined,\n TParams extends StandardSchemaV1 | undefined = undefined,\n TResult extends DefineServerRouteResult = DefineServerRouteResult,\n> {\n input?: TInput;\n query?: TQuery;\n body?: TBody;\n params?: TParams;\n output?: TOutput;\n handler: (\n context: DefineServerRouteContext<TInput, TQuery, TBody, TParams>,\n ) => Promise<TResult> | TResult;\n}\n\nfunction isDevEnvironment() {\n return (\n typeof process !== 'undefined' &&\n (process.env['NODE_ENV'] === 'development' ||\n process.env['NODE_ENV'] === 'test')\n );\n}\n\nfunction warnOnOutputIssues(issues: ReadonlyArray<StandardSchemaV1.Issue>) {\n console.warn(\n `[analog] Server route output validation failed:\\n` +\n issues\n .map((i) => {\n const path = i.path\n ? ` at \"${i.path.map((p) => (typeof p === 'object' ? (p as { key: string }).key : p)).join('.')}\"`\n : '';\n return ` - ${i.message}${path}`;\n })\n .join('\\n'),\n );\n}\n\nfunction getRequestUrl(event: H3Event): string {\n try {\n return getRequestURL(event).href;\n } catch {\n return (event as H3Event & { request: Request }).request.url;\n }\n}\n\n/**\n * Creates an h3-compatible event handler with Standard Schema validation.\n *\n * - `input` schema validates the request body (POST/PUT/PATCH) or query\n * params (GET). Returns 422 with `StandardSchemaV1.Issue[]` on failure.\n * - `output` schema validates the response in development only (stripped\n * in production for zero overhead). Logs a warning on mismatch.\n * - Plain return values are serialized with `json(...)`; raw `Response`\n * objects are returned unchanged.\n *\n * @example\n * ```typescript\n * import { defineServerRoute } from '@analogjs/router/server/actions';\n * import * as v from 'valibot';\n *\n * const Input = v.object({\n * name: v.pipe(v.string(), v.minLength(1)),\n * email: v.pipe(v.string(), v.email()),\n * });\n * const Output = v.object({\n * id: v.string(),\n * name: v.string(),\n * });\n *\n * export default defineServerRoute({\n * input: Input,\n * output: Output,\n * handler: async ({ data }) => {\n * const user = await db.users.create(data);\n * return user;\n * },\n * });\n * ```\n */\nexport function defineServerRoute<\n TInput extends StandardSchemaV1 | undefined = undefined,\n TOutput extends StandardSchemaV1 | undefined = undefined,\n TQuery extends StandardSchemaV1 | undefined = undefined,\n TBody extends StandardSchemaV1 | undefined = undefined,\n TParams extends StandardSchemaV1 | undefined = undefined,\n TResult extends DefineServerRouteResult = DefineServerRouteResult,\n>(\n options: DefineServerRouteOptions<\n TInput,\n TOutput,\n TQuery,\n TBody,\n TParams,\n TResult\n >,\n): ServerRouteHandler<\n InferSchema<TQuery, undefined>,\n InferSchema<TBody, undefined>,\n TResult\n> {\n return (async (event: H3Event): Promise<Response> => {\n const method = event.method.toUpperCase();\n let data: unknown;\n let query: unknown;\n let body: unknown;\n let params: unknown = event.context?.params ?? {};\n\n if (options.params) {\n const paramsResult = await validateWithSchema(options.params, params);\n if (paramsResult.issues) {\n return fail(422, paramsResult.issues);\n }\n params = paramsResult.value;\n }\n\n if (options.input) {\n data = await parseRequestData(event);\n\n const inputResult = await validateWithSchema(options.input, data);\n if (inputResult.issues) {\n return fail(422, inputResult.issues);\n }\n data = inputResult.value;\n } else {\n if (options.query) {\n const url = new URL(getRequestUrl(event), 'http://localhost');\n const queryResult = await validateWithSchema(\n options.query,\n parseSearchParams(url.searchParams),\n );\n if (queryResult.issues) {\n return fail(422, queryResult.issues);\n }\n query = queryResult.value;\n }\n\n if (options.body && method !== 'GET' && method !== 'HEAD') {\n body = await parseRequestData(event);\n const bodyResult = await validateWithSchema(options.body, body);\n if (bodyResult.issues) {\n return fail(422, bodyResult.issues);\n }\n body = bodyResult.value;\n }\n\n if (method === 'GET' || method === 'HEAD') {\n data = query;\n } else if (body !== undefined) {\n data = body;\n } else {\n data = query;\n }\n }\n\n const result = await options.handler({\n data: data as ResolveDataSchema<TInput, TQuery, TBody>,\n query: query as InferSchema<TQuery, undefined>,\n body: body as InferSchema<TBody, undefined>,\n params: params as InferSchema<TParams, H3Event['context']['params']>,\n event,\n });\n\n if (result instanceof Response) {\n return result;\n }\n\n if (options.output && isDevEnvironment()) {\n const outputResult = await validateWithSchema(options.output, result);\n if (outputResult.issues) {\n warnOnOutputIssues(outputResult.issues);\n }\n }\n\n return json(result);\n }) as ServerRouteHandler<\n InferSchema<TQuery, undefined>,\n InferSchema<TBody, undefined>,\n TResult\n >;\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { H3Event, H3EventContext } from 'nitro/h3';\nimport { getRequestURL } from 'nitro/h3';\nimport type { $Fetch } from 'nitro/types';\nimport { fail } from './actions';\nimport { parseSearchParams } from './parse-request-data';\nimport { validateWithSchema } from './validate';\n\ntype NodeContext = NonNullable<H3Event['node']>;\ntype OptionalSchema = StandardSchemaV1 | undefined;\ntype InferSchema<\n TSchema extends OptionalSchema,\n TFallback,\n> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TSchema>\n : TFallback;\n\nexport interface PageLoadContext<\n TParamsSchema extends OptionalSchema = undefined,\n TQuerySchema extends OptionalSchema = undefined,\n> {\n params: InferSchema<TParamsSchema, H3EventContext['params']>;\n query: InferSchema<\n TQuerySchema,\n Record<string, string | string[] | undefined>\n >;\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n}\n\nexport interface DefinePageLoadOptions<\n TParamsSchema extends OptionalSchema = undefined,\n TQuerySchema extends OptionalSchema = undefined,\n TResult = unknown,\n> {\n params?: TParamsSchema;\n query?: TQuerySchema;\n handler: (\n context: PageLoadContext<TParamsSchema, TQuerySchema>,\n ) => Promise<TResult> | TResult;\n}\n\n/**\n * Creates a typed page server load function with optional\n * Standard Schema validation for route params and query.\n *\n * Follows the same validation patterns as `defineAction` and\n * `defineServerRoute`: validates before invoking the handler,\n * returns `fail(422, issues)` on validation failure.\n *\n * @example\n * ```typescript\n * // src/app/pages/users/[id].server.ts\n * import { definePageLoad } from '@analogjs/router/server/actions';\n * import * as v from 'valibot';\n *\n * export const routeParamsSchema = v.object({\n * id: v.pipe(v.string(), v.regex(/^\\d+$/)),\n * });\n *\n * export const load = definePageLoad({\n * params: routeParamsSchema,\n * handler: async ({ params, fetch }) => {\n * // params.id is typed as string (validated)\n * const user = await fetch(`/api/users/${params.id}`);\n * return user;\n * },\n * });\n * ```\n */\nexport function definePageLoad<\n TParamsSchema extends OptionalSchema = undefined,\n TQuerySchema extends OptionalSchema = undefined,\n TResult = unknown,\n>(\n options: DefinePageLoadOptions<TParamsSchema, TQuerySchema, TResult>,\n): (ctx: {\n params: H3EventContext['params'];\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n}) => Promise<TResult | Response> {\n type Params = InferSchema<TParamsSchema, H3EventContext['params']>;\n type Query = InferSchema<\n TQuerySchema,\n Record<string, string | string[] | undefined>\n >;\n\n return async (ctx: {\n params: H3EventContext['params'];\n req: NodeContext['req'];\n res: NonNullable<NodeContext['res']>;\n fetch: $Fetch;\n event: H3Event;\n }) => {\n let params: unknown = ctx.params ?? {};\n\n let requestUrl: string;\n try {\n requestUrl = getRequestURL(ctx.event).href;\n } catch {\n requestUrl = (ctx.event as H3Event & { request: Request }).request.url;\n }\n const url = new URL(requestUrl, 'http://localhost');\n let query: unknown = parseSearchParams(url.searchParams);\n\n // Validate params\n if (options.params) {\n const result = await validateWithSchema(options.params, params);\n if (result.issues) {\n return fail(422, result.issues);\n }\n params = result.value;\n }\n\n // Validate query\n if (options.query) {\n const result = await validateWithSchema(options.query, query);\n if (result.issues) {\n return fail(422, result.issues);\n }\n query = result.value;\n }\n\n return options.handler({\n params: params as Params,\n query: query as Query,\n req: ctx.req,\n res: ctx.res,\n fetch: ctx.fetch,\n event: ctx.event,\n });\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analogjs/router",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.60",
|
|
4
4
|
"description": "Filesystem-based routing for Angular",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Brandon Roberts <robertsbt@gmail.com>",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./package.json": {
|
|
9
|
+
"default": "./package.json"
|
|
10
|
+
},
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./types/src/index.d.ts",
|
|
13
|
+
"import": "./fesm2022/analogjs-router.mjs",
|
|
14
|
+
"default": "./fesm2022/analogjs-router.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./content": {
|
|
17
|
+
"types": "./types/content/src/index.d.ts",
|
|
18
|
+
"import": "./fesm2022/analogjs-router-content.mjs",
|
|
19
|
+
"default": "./fesm2022/analogjs-router-content.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./i18n": {
|
|
22
|
+
"types": "./types/i18n/src/index.d.ts",
|
|
23
|
+
"import": "./fesm2022/analogjs-router-i18n.mjs",
|
|
24
|
+
"default": "./fesm2022/analogjs-router-i18n.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./server": {
|
|
27
|
+
"types": "./types/server/src/index.d.ts",
|
|
28
|
+
"import": "./fesm2022/analogjs-router-server.mjs",
|
|
29
|
+
"default": "./fesm2022/analogjs-router-server.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./server/actions": {
|
|
32
|
+
"types": "./types/server/actions/src/index.d.ts",
|
|
33
|
+
"import": "./fesm2022/analogjs-router-server-actions.mjs",
|
|
34
|
+
"default": "./fesm2022/analogjs-router-server-actions.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./tanstack-query": {
|
|
37
|
+
"types": "./types/tanstack-query/src/index.d.ts",
|
|
38
|
+
"import": "./fesm2022/analogjs-router-tanstack-query.mjs",
|
|
39
|
+
"default": "./fesm2022/analogjs-router-tanstack-query.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./tanstack-query/server": {
|
|
42
|
+
"types": "./types/tanstack-query/server/src/index.d.ts",
|
|
43
|
+
"import": "./fesm2022/analogjs-router-tanstack-query-server.mjs",
|
|
44
|
+
"default": "./fesm2022/analogjs-router-tanstack-query-server.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./tokens": {
|
|
47
|
+
"types": "./types/tokens/src/index.d.ts",
|
|
48
|
+
"import": "./fesm2022/analogjs-router-tokens.mjs",
|
|
49
|
+
"default": "./fesm2022/analogjs-router-tokens.mjs"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
7
52
|
"keywords": [
|
|
8
53
|
"angular",
|
|
9
54
|
"router",
|
|
@@ -24,12 +69,39 @@
|
|
|
24
69
|
"url": "https://github.com/sponsors/brandonroberts"
|
|
25
70
|
},
|
|
26
71
|
"peerDependencies": {
|
|
27
|
-
"@analogjs/content": "
|
|
28
|
-
"@
|
|
29
|
-
"@angular/
|
|
72
|
+
"@analogjs/content": "3.0.0-alpha.60",
|
|
73
|
+
"@standard-schema/spec": "^1.1.0",
|
|
74
|
+
"@angular/core": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
|
|
75
|
+
"@angular/platform-server": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
|
|
76
|
+
"@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
|
|
77
|
+
"@tanstack/angular-query-experimental": ">=5.95.0",
|
|
78
|
+
"schema-dts": "^2.0.0"
|
|
79
|
+
},
|
|
80
|
+
"peerDependenciesMeta": {
|
|
81
|
+
"@analogjs/content": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"@standard-schema/spec": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"@angular/platform-server": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
90
|
+
"@tanstack/angular-query-experimental": {
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
93
|
+
"schema-dts": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
30
96
|
},
|
|
31
97
|
"dependencies": {
|
|
32
|
-
"
|
|
98
|
+
"@standard-schema/spec": "^1.1.0",
|
|
99
|
+
"es-toolkit": "^1.45.1",
|
|
100
|
+
"tslib": "^2.3.0"
|
|
101
|
+
},
|
|
102
|
+
"devDependencies": {
|
|
103
|
+
"@analogjs/vite-plugin-angular": "3.0.0-alpha.60",
|
|
104
|
+
"@analogjs/vitest-angular": "3.0.0-alpha.60"
|
|
33
105
|
},
|
|
34
106
|
"ng-update": {
|
|
35
107
|
"packageGroup": [
|
|
@@ -49,26 +121,5 @@
|
|
|
49
121
|
},
|
|
50
122
|
"module": "fesm2022/analogjs-router.mjs",
|
|
51
123
|
"typings": "types/src/index.d.ts",
|
|
52
|
-
"exports": {
|
|
53
|
-
"./package.json": {
|
|
54
|
-
"default": "./package.json"
|
|
55
|
-
},
|
|
56
|
-
".": {
|
|
57
|
-
"types": "./types/src/index.d.ts",
|
|
58
|
-
"default": "./fesm2022/analogjs-router.mjs"
|
|
59
|
-
},
|
|
60
|
-
"./server": {
|
|
61
|
-
"types": "./types/server/src/index.d.ts",
|
|
62
|
-
"default": "./fesm2022/analogjs-router-server.mjs"
|
|
63
|
-
},
|
|
64
|
-
"./server/actions": {
|
|
65
|
-
"types": "./types/server/actions/src/index.d.ts",
|
|
66
|
-
"default": "./fesm2022/analogjs-router-server-actions.mjs"
|
|
67
|
-
},
|
|
68
|
-
"./tokens": {
|
|
69
|
-
"types": "./types/tokens/src/index.d.ts",
|
|
70
|
-
"default": "./fesm2022/analogjs-router-tokens.mjs"
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
124
|
"sideEffects": false
|
|
74
125
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Route } from '@angular/router';
|
|
3
|
+
export declare const DEBUG_CONTENT_ROUTES: InjectionToken<(Route & DebugRoute)[]>;
|
|
4
|
+
export type DebugRoute = {
|
|
5
|
+
path: string;
|
|
6
|
+
filename: string;
|
|
7
|
+
isLayout: boolean;
|
|
8
|
+
children?: DebugRoute[];
|
|
9
|
+
};
|
|
10
|
+
export declare function injectDebugContentRoutes(): (Route & DebugRoute)[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RouteExport } from '
|
|
1
|
+
import type { RouteExport } from '../../../src/lib/models';
|
|
2
2
|
export declare function toMarkdownModule(markdownFileFactory: () => Promise<string>): () => Promise<RouteExport>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Route } from '@angular/router';
|
|
2
|
+
import type { RouteExport } from '../../../src/lib/models';
|
|
3
|
+
/**
|
|
4
|
+
* This variable reference is replaced with a glob of all content routes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ANALOG_CONTENT_ROUTE_FILES: {};
|
|
7
|
+
export type Files = Record<string, () => Promise<RouteExport | string>>;
|
|
8
|
+
export declare function createContentRoutes(files: Files, debug?: boolean): Route[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { provideI18n, I18nConfig, injectSwitchLocale, loadTranslationsRuntime, } from './provide-i18n';
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { EnvironmentProviders, Type } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for runtime i18n support.
|
|
4
|
+
*
|
|
5
|
+
* `defaultLocale` and `locales` are optional when the platform plugin
|
|
6
|
+
* is configured with `i18n` in `vite.config.ts` — the values are
|
|
7
|
+
* injected as build-time globals automatically.
|
|
8
|
+
*/
|
|
9
|
+
export interface I18nConfig {
|
|
10
|
+
/**
|
|
11
|
+
* The default locale to use when no locale is detected.
|
|
12
|
+
* If omitted, reads from the platform plugin's `i18n.defaultLocale`.
|
|
13
|
+
*/
|
|
14
|
+
defaultLocale?: string;
|
|
15
|
+
/**
|
|
16
|
+
* List of supported locale identifiers.
|
|
17
|
+
* If omitted, reads from the platform plugin's `i18n.locales`.
|
|
18
|
+
*/
|
|
19
|
+
locales?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* A function that returns translations for a given locale.
|
|
22
|
+
* The returned record maps message IDs to translated strings.
|
|
23
|
+
*/
|
|
24
|
+
loader: (locale: string) => Promise<Record<string, string>> | Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Fully resolved i18n config with all required fields.
|
|
28
|
+
*/
|
|
29
|
+
export type ResolvedI18nConfig = Required<I18nConfig>;
|
|
30
|
+
/**
|
|
31
|
+
* Resolves the full i18n config by merging explicit values with
|
|
32
|
+
* build-time globals injected by the platform plugin.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveI18nConfig(config: I18nConfig): Required<I18nConfig>;
|
|
35
|
+
/**
|
|
36
|
+
* Provides runtime i18n support using Angular's $localize.
|
|
37
|
+
*
|
|
38
|
+
* This provider:
|
|
39
|
+
* 1. Detects the active locale from the URL or falls back to the default.
|
|
40
|
+
* 2. Makes the current locale available via the LOCALE injection token.
|
|
41
|
+
* 3. Loads translations for the active locale at startup using $localize.
|
|
42
|
+
*
|
|
43
|
+
* Works in both SSR and client-only modes. On the client, locale is detected
|
|
44
|
+
* from `window.location.pathname`. On the server, locale is detected from
|
|
45
|
+
* the request in `provideServerContext()` and provided at the platform level;
|
|
46
|
+
* this function does not shadow it.
|
|
47
|
+
*
|
|
48
|
+
* When the platform plugin is configured with `i18n` in `vite.config.ts`,
|
|
49
|
+
* `defaultLocale` and `locales` are injected automatically — only
|
|
50
|
+
* `loader` is required:
|
|
51
|
+
*
|
|
52
|
+
* ```typescript
|
|
53
|
+
* provideI18n({
|
|
54
|
+
* loader: (locale) => import(`./i18n/${locale}.json`),
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function provideI18n(config: I18nConfig): EnvironmentProviders;
|
|
59
|
+
export declare function detectClientLocale(config: ResolvedI18nConfig): string;
|
|
60
|
+
/**
|
|
61
|
+
* Loads translations for the given locale and registers them with $localize.
|
|
62
|
+
*
|
|
63
|
+
* Always clears any previously loaded translations first so that switching
|
|
64
|
+
* between locales in a single SSR process does not mix translation maps.
|
|
65
|
+
*/
|
|
66
|
+
export declare function initI18n(config: ResolvedI18nConfig, locale?: string): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Loads translations into the global $localize translation map.
|
|
69
|
+
*
|
|
70
|
+
* Uses `@angular/localize`'s `loadTranslations` when available so that
|
|
71
|
+
* each translation string is parsed into the `{text, messageParts,
|
|
72
|
+
* placeholderNames}` shape that `$localize.translate` expects. Falls back
|
|
73
|
+
* to writing raw strings only as a last resort (in which case lookups
|
|
74
|
+
* will not succeed — the fallback exists to keep error messages useful
|
|
75
|
+
* for users who have not installed `@angular/localize`).
|
|
76
|
+
*
|
|
77
|
+
* Requires `@angular/localize/init` to be imported in the application
|
|
78
|
+
* entry point so that `globalThis.$localize` is defined.
|
|
79
|
+
*/
|
|
80
|
+
export declare function loadTranslationsRuntime(translations: Record<string, string>): Promise<void>;
|
|
81
|
+
/** @internal — exported for tests; not re-exported from the package entry. */
|
|
82
|
+
export declare function clearTranslationsRuntime(): Promise<void>;
|
|
83
|
+
/** @internal */
|
|
84
|
+
export declare function ɵregisterI18nComponentDef(typeOrDef: Type<any> | any): void;
|
|
85
|
+
/** @internal */
|
|
86
|
+
export declare function ɵresetI18nComponentDefCache(): void;
|
|
87
|
+
/** @internal */
|
|
88
|
+
export declare function getI18nComponentDefRegistrySize(): number;
|
|
89
|
+
/** @internal */
|
|
90
|
+
export declare function clearI18nComponentDefRegistry(): void;
|
|
91
|
+
export declare function injectSwitchLocale(): (targetLocale: string) => void;
|
|
92
|
+
export declare function replaceLocaleInPath(pathname: string, targetLocale: string, locales: string[]): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { H3Event, H3EventContext } from 'nitro/h3';
|
|
3
|
+
import type { $Fetch } from 'nitro/types';
|
|
4
|
+
type NodeContext = NonNullable<H3Event['node']>;
|
|
5
|
+
type OptionalSchema = StandardSchemaV1 | undefined;
|
|
6
|
+
type InferSchema<TSchema extends OptionalSchema, TFallback> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
|
|
7
|
+
export interface DefineActionContext<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined> {
|
|
8
|
+
data: InferSchema<TSchema, Record<string, unknown>>;
|
|
9
|
+
params: InferSchema<TParamsSchema, H3EventContext['params']>;
|
|
10
|
+
req: NodeContext['req'];
|
|
11
|
+
res: NonNullable<NodeContext['res']>;
|
|
12
|
+
fetch: $Fetch;
|
|
13
|
+
event: H3Event;
|
|
14
|
+
}
|
|
15
|
+
export interface DefineActionOptions<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined> {
|
|
16
|
+
schema?: TSchema;
|
|
17
|
+
params?: TParamsSchema;
|
|
18
|
+
handler: (context: DefineActionContext<TSchema, TParamsSchema>) => Promise<Response> | Response;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a server action handler with Standard Schema input validation.
|
|
22
|
+
*
|
|
23
|
+
* Parses the request body (JSON or FormData) and validates it against the
|
|
24
|
+
* provided schema before invoking the handler. On validation failure,
|
|
25
|
+
* returns `fail(422, issues)` with `StandardSchemaV1.Issue[]`.
|
|
26
|
+
* Repeated form fields are preserved as arrays instead of being collapsed
|
|
27
|
+
* to the last value.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { defineAction, json } from '@analogjs/router/server/actions';
|
|
32
|
+
* import * as v from 'valibot';
|
|
33
|
+
*
|
|
34
|
+
* const Schema = v.object({
|
|
35
|
+
* email: v.pipe(v.string(), v.email()),
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* export const action = defineAction({
|
|
39
|
+
* schema: Schema,
|
|
40
|
+
* handler: async ({ data }) => {
|
|
41
|
+
* // data is typed as { email: string }
|
|
42
|
+
* return json({ ok: true });
|
|
43
|
+
* },
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function defineAction<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined>(options: DefineActionOptions<TSchema, TParamsSchema>): (ctx: {
|
|
48
|
+
params: H3EventContext["params"];
|
|
49
|
+
req: NodeContext["req"];
|
|
50
|
+
res: NonNullable<NodeContext["res"]>;
|
|
51
|
+
fetch: $Fetch;
|
|
52
|
+
event: H3Event;
|
|
53
|
+
}) => Promise<Response>;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { H3Event } from 'nitro/h3';
|
|
3
|
+
export type DefineApiRouteResult = Response | unknown;
|
|
4
|
+
type OptionalSchema = StandardSchemaV1 | undefined;
|
|
5
|
+
type InferSchema<TSchema extends OptionalSchema, TFallback = unknown> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
|
|
6
|
+
type ResolveDataSchema<TInput extends OptionalSchema, TQuery extends OptionalSchema, TBody extends OptionalSchema> = TInput extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TInput> : TQuery extends StandardSchemaV1 ? TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TQuery> | StandardSchemaV1.InferOutput<TBody> : StandardSchemaV1.InferOutput<TQuery> : TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TBody> : unknown;
|
|
7
|
+
export interface DefineApiRouteContext<TInput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined> {
|
|
8
|
+
data: ResolveDataSchema<TInput, TQuery, TBody>;
|
|
9
|
+
query: InferSchema<TQuery, undefined>;
|
|
10
|
+
body: InferSchema<TBody, undefined>;
|
|
11
|
+
params: InferSchema<TParams, H3Event['context']['params']>;
|
|
12
|
+
event: H3Event;
|
|
13
|
+
}
|
|
14
|
+
export interface DefineApiRouteOptions<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineApiRouteResult = DefineApiRouteResult> {
|
|
15
|
+
input?: TInput;
|
|
16
|
+
query?: TQuery;
|
|
17
|
+
body?: TBody;
|
|
18
|
+
params?: TParams;
|
|
19
|
+
output?: TOutput;
|
|
20
|
+
handler: (context: DefineApiRouteContext<TInput, TQuery, TBody, TParams>) => Promise<TResult> | TResult;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates an h3-compatible event handler with Standard Schema validation.
|
|
24
|
+
*
|
|
25
|
+
* - `input` schema validates the request body (POST/PUT/PATCH) or query
|
|
26
|
+
* params (GET). Returns 422 with `StandardSchemaV1.Issue[]` on failure.
|
|
27
|
+
* - `output` schema validates the response in development only (stripped
|
|
28
|
+
* in production for zero overhead). Logs a warning on mismatch.
|
|
29
|
+
* - Plain return values are serialized with `json(...)`; raw `Response`
|
|
30
|
+
* objects are returned unchanged.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* import { defineApiRoute } from '@analogjs/router/server/actions';
|
|
35
|
+
* import * as v from 'valibot';
|
|
36
|
+
*
|
|
37
|
+
* const Input = v.object({
|
|
38
|
+
* name: v.pipe(v.string(), v.minLength(1)),
|
|
39
|
+
* email: v.pipe(v.string(), v.email()),
|
|
40
|
+
* });
|
|
41
|
+
* const Output = v.object({
|
|
42
|
+
* id: v.string(),
|
|
43
|
+
* name: v.string(),
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* export default defineApiRoute({
|
|
47
|
+
* input: Input,
|
|
48
|
+
* output: Output,
|
|
49
|
+
* handler: async ({ data }) => {
|
|
50
|
+
* const user = await db.users.create(data);
|
|
51
|
+
* return user;
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function defineApiRoute<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineApiRouteResult = DefineApiRouteResult>(options: DefineApiRouteOptions<TInput, TOutput, TQuery, TBody, TParams, TResult>): (event: H3Event) => Promise<Response>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { H3Event, H3EventContext } from 'nitro/h3';
|
|
3
|
+
import type { $Fetch } from 'nitro/types';
|
|
4
|
+
type NodeContext = NonNullable<H3Event['node']>;
|
|
5
|
+
type OptionalSchema = StandardSchemaV1 | undefined;
|
|
6
|
+
type InferSchema<TSchema extends OptionalSchema, TFallback> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
|
|
7
|
+
export interface PageLoadContext<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined> {
|
|
8
|
+
params: InferSchema<TParamsSchema, H3EventContext['params']>;
|
|
9
|
+
query: InferSchema<TQuerySchema, Record<string, string | string[] | undefined>>;
|
|
10
|
+
req: NodeContext['req'];
|
|
11
|
+
res: NonNullable<NodeContext['res']>;
|
|
12
|
+
fetch: $Fetch;
|
|
13
|
+
event: H3Event;
|
|
14
|
+
}
|
|
15
|
+
export interface DefinePageLoadOptions<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined, TResult = unknown> {
|
|
16
|
+
params?: TParamsSchema;
|
|
17
|
+
query?: TQuerySchema;
|
|
18
|
+
handler: (context: PageLoadContext<TParamsSchema, TQuerySchema>) => Promise<TResult> | TResult;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a typed page server load function with optional
|
|
22
|
+
* Standard Schema validation for route params and query.
|
|
23
|
+
*
|
|
24
|
+
* Follows the same validation patterns as `defineAction` and
|
|
25
|
+
* `defineServerRoute`: validates before invoking the handler,
|
|
26
|
+
* returns `fail(422, issues)` on validation failure.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // src/app/pages/users/[id].server.ts
|
|
31
|
+
* import { definePageLoad } from '@analogjs/router/server/actions';
|
|
32
|
+
* import * as v from 'valibot';
|
|
33
|
+
*
|
|
34
|
+
* export const routeParamsSchema = v.object({
|
|
35
|
+
* id: v.pipe(v.string(), v.regex(/^\d+$/)),
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* export const load = definePageLoad({
|
|
39
|
+
* params: routeParamsSchema,
|
|
40
|
+
* handler: async ({ params, fetch }) => {
|
|
41
|
+
* // params.id is typed as string (validated)
|
|
42
|
+
* const user = await fetch(`/api/users/${params.id}`);
|
|
43
|
+
* return user;
|
|
44
|
+
* },
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function definePageLoad<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined, TResult = unknown>(options: DefinePageLoadOptions<TParamsSchema, TQuerySchema, TResult>): (ctx: {
|
|
49
|
+
params: H3EventContext['params'];
|
|
50
|
+
req: NodeContext['req'];
|
|
51
|
+
res: NonNullable<NodeContext['res']>;
|
|
52
|
+
fetch: $Fetch;
|
|
53
|
+
event: H3Event;
|
|
54
|
+
}) => Promise<TResult | Response>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { H3Event } from 'nitro/h3';
|
|
3
|
+
export type DefineServerRouteResult = Response | unknown;
|
|
4
|
+
export interface ServerRouteHandler<TQuery = unknown, TBody = unknown, TResult = unknown> {
|
|
5
|
+
(event: H3Event): Promise<Response>;
|
|
6
|
+
readonly _types: {
|
|
7
|
+
readonly query: TQuery;
|
|
8
|
+
readonly body: TBody;
|
|
9
|
+
readonly result: TResult;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export type InferRouteQuery<T> = T extends ServerRouteHandler<infer Q, any, any> ? Q : never;
|
|
13
|
+
export type InferRouteBody<T> = T extends ServerRouteHandler<any, infer B, any> ? B : never;
|
|
14
|
+
export type InferRouteResult<T> = T extends ServerRouteHandler<any, any, infer R> ? Exclude<R, Response> : never;
|
|
15
|
+
type OptionalSchema = StandardSchemaV1 | undefined;
|
|
16
|
+
type InferSchema<TSchema extends OptionalSchema, TFallback = unknown> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
|
|
17
|
+
type ResolveDataSchema<TInput extends OptionalSchema, TQuery extends OptionalSchema, TBody extends OptionalSchema> = TInput extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TInput> : TQuery extends StandardSchemaV1 ? TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TQuery> | StandardSchemaV1.InferOutput<TBody> : StandardSchemaV1.InferOutput<TQuery> : TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TBody> : unknown;
|
|
18
|
+
export interface DefineServerRouteContext<TInput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined> {
|
|
19
|
+
data: ResolveDataSchema<TInput, TQuery, TBody>;
|
|
20
|
+
query: InferSchema<TQuery, undefined>;
|
|
21
|
+
body: InferSchema<TBody, undefined>;
|
|
22
|
+
params: InferSchema<TParams, H3Event['context']['params']>;
|
|
23
|
+
event: H3Event;
|
|
24
|
+
}
|
|
25
|
+
export interface DefineServerRouteOptions<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineServerRouteResult = DefineServerRouteResult> {
|
|
26
|
+
input?: TInput;
|
|
27
|
+
query?: TQuery;
|
|
28
|
+
body?: TBody;
|
|
29
|
+
params?: TParams;
|
|
30
|
+
output?: TOutput;
|
|
31
|
+
handler: (context: DefineServerRouteContext<TInput, TQuery, TBody, TParams>) => Promise<TResult> | TResult;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates an h3-compatible event handler with Standard Schema validation.
|
|
35
|
+
*
|
|
36
|
+
* - `input` schema validates the request body (POST/PUT/PATCH) or query
|
|
37
|
+
* params (GET). Returns 422 with `StandardSchemaV1.Issue[]` on failure.
|
|
38
|
+
* - `output` schema validates the response in development only (stripped
|
|
39
|
+
* in production for zero overhead). Logs a warning on mismatch.
|
|
40
|
+
* - Plain return values are serialized with `json(...)`; raw `Response`
|
|
41
|
+
* objects are returned unchanged.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* import { defineServerRoute } from '@analogjs/router/server/actions';
|
|
46
|
+
* import * as v from 'valibot';
|
|
47
|
+
*
|
|
48
|
+
* const Input = v.object({
|
|
49
|
+
* name: v.pipe(v.string(), v.minLength(1)),
|
|
50
|
+
* email: v.pipe(v.string(), v.email()),
|
|
51
|
+
* });
|
|
52
|
+
* const Output = v.object({
|
|
53
|
+
* id: v.string(),
|
|
54
|
+
* name: v.string(),
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* export default defineServerRoute({
|
|
58
|
+
* input: Input,
|
|
59
|
+
* output: Output,
|
|
60
|
+
* handler: async ({ data }) => {
|
|
61
|
+
* const user = await db.users.create(data);
|
|
62
|
+
* return user;
|
|
63
|
+
* },
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function defineServerRoute<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineServerRouteResult = DefineServerRouteResult>(options: DefineServerRouteOptions<TInput, TOutput, TQuery, TBody, TParams, TResult>): ServerRouteHandler<InferSchema<TQuery, undefined>, InferSchema<TBody, undefined>, TResult>;
|
|
68
|
+
export {};
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
export { PageServerAction
|
|
1
|
+
export type { PageServerAction } from './actions';
|
|
2
|
+
export { json, redirect, fail } from './actions';
|
|
3
|
+
export { defineAction } from './define-action';
|
|
4
|
+
export type { DefineActionContext, DefineActionOptions } from './define-action';
|
|
5
|
+
export { defineServerRoute } from './define-server-route';
|
|
6
|
+
export type { DefineServerRouteContext, DefineServerRouteOptions, DefineServerRouteResult, ServerRouteHandler, InferRouteQuery, InferRouteBody, InferRouteResult, } from './define-server-route';
|
|
7
|
+
export { definePageLoad } from './define-page-load';
|
|
8
|
+
export type { PageLoadContext, DefinePageLoadOptions, } from './define-page-load';
|
|
9
|
+
export { validateWithSchema } from './validate';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type RequestEntryValue = string | File;
|
|
2
|
+
type ParsedRequestValue = RequestEntryValue | RequestEntryValue[];
|
|
3
|
+
export declare function parseSearchParams(searchParams: URLSearchParams): Record<string, ParsedRequestValue>;
|
|
4
|
+
export declare function parseFormData(formData: FormData): Record<string, ParsedRequestValue>;
|
|
5
|
+
export declare function parseRequestData(event: {
|
|
6
|
+
method: string;
|
|
7
|
+
headers: Headers;
|
|
8
|
+
}): Promise<unknown>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
/**
|
|
3
|
+
* Validates unknown input against a Standard Schema.
|
|
4
|
+
*
|
|
5
|
+
* Handles both sync and async `validate` implementations — the Standard
|
|
6
|
+
* Schema spec allows either return shape.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateWithSchema<T extends StandardSchemaV1>(schema: T, data: unknown): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<T>>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StaticProvider } from '@angular/core';
|
|
2
|
-
import { ServerInternalFetch, ServerRequest, ServerResponse } from '
|
|
2
|
+
import { ServerInternalFetch, ServerRequest, ServerResponse } from '../../tokens/src/index.js';
|
|
3
3
|
export declare function provideServerContext({ req, res, fetch, }: {
|
|
4
4
|
req: ServerRequest;
|
|
5
5
|
res: ServerResponse;
|
|
@@ -9,3 +9,17 @@ export declare function getBaseUrl(req: ServerRequest): string;
|
|
|
9
9
|
export declare function getRequestProtocol(req: ServerRequest, opts?: {
|
|
10
10
|
xForwardedProto?: boolean;
|
|
11
11
|
}): string;
|
|
12
|
+
/**
|
|
13
|
+
* Detects the locale from the request URL path prefix or Accept-Language header.
|
|
14
|
+
* URL prefix takes priority (e.g. /fr/about -> 'fr').
|
|
15
|
+
*/
|
|
16
|
+
export declare function detectLocale(req: ServerRequest): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a locale from the first URL path segment if it matches
|
|
19
|
+
* a BCP 47-like pattern (e.g. 'en', 'en-US', 'zh-Hans-CN').
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractLocaleFromUrl(url: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Parses the Accept-Language header and returns the most preferred language.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseAcceptLanguage(header: string | undefined): string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApplicationConfig, Provider, Type } from '@angular/core';
|
|
2
|
-
import type { ServerContext } from '
|
|
2
|
+
import type { ServerContext } from '../../tokens/src/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Returns a function that accepts the navigation URL,
|
|
5
5
|
* the root HTML, and server context.
|