@boon4681/giri 0.0.1
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/LICENSE +21 -0
- package/README.md +231 -0
- package/dist/adapters/hono.d.ts +7 -0
- package/dist/adapters/hono.js +301 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2070 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +164 -0
- package/dist/index.js +1762 -0
- package/dist/index.js.map +1 -0
- package/dist/types-BrUMxh5u.d.ts +233 -0
- package/dist/typescript-plugin.d.ts +7 -0
- package/dist/typescript-plugin.js +120 -0
- package/dist/typescript-plugin.js.map +1 -0
- package/dist/validators/valibot.d.ts +21 -0
- package/dist/validators/valibot.js +81 -0
- package/dist/validators/valibot.js.map +1 -0
- package/dist/validators/zod.d.ts +26 -0
- package/dist/validators/zod.js +70 -0
- package/dist/validators/zod.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// src/typescript-plugin-core.ts
|
|
4
|
+
var import_node_fs = require("fs");
|
|
5
|
+
var import_node_path = require("path");
|
|
6
|
+
function unique(values) {
|
|
7
|
+
return [...new Set(values.map((value) => (0, import_node_path.normalize)(value)))];
|
|
8
|
+
}
|
|
9
|
+
function isInside(parent, child) {
|
|
10
|
+
const rel = (0, import_node_path.relative)(parent, child);
|
|
11
|
+
return rel === "" || !rel.startsWith("..") && !(0, import_node_path.isAbsolute)(rel);
|
|
12
|
+
}
|
|
13
|
+
function absolutePath(projectDir, value) {
|
|
14
|
+
return (0, import_node_path.isAbsolute)(value) ? value : (0, import_node_path.resolve)(projectDir, value);
|
|
15
|
+
}
|
|
16
|
+
function inferRouteRoot(containingFile) {
|
|
17
|
+
const normalized = (0, import_node_path.normalize)(containingFile);
|
|
18
|
+
const parts = normalized.split(import_node_path.sep);
|
|
19
|
+
for (let index = parts.length - 2; index >= 0; index -= 1) {
|
|
20
|
+
if (parts[index] === "src" && parts[index + 1] === "routes") {
|
|
21
|
+
const projectRoot = parts.slice(0, index).join(import_node_path.sep) || import_node_path.sep;
|
|
22
|
+
return {
|
|
23
|
+
projectRoot,
|
|
24
|
+
routesDir: parts.slice(0, index + 2).join(import_node_path.sep)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
function routeKey(routesDir, routeDir) {
|
|
31
|
+
const rel = (0, import_node_path.relative)(routesDir, routeDir);
|
|
32
|
+
return rel ? rel : "__root";
|
|
33
|
+
}
|
|
34
|
+
function rootDirsByKind(projectDir, rootDirs) {
|
|
35
|
+
const routeRoots = [];
|
|
36
|
+
const generatedRoots = [];
|
|
37
|
+
for (const rootDir of rootDirs ?? []) {
|
|
38
|
+
const absolute = absolutePath(projectDir, rootDir);
|
|
39
|
+
const normalized = (0, import_node_path.normalize)(absolute);
|
|
40
|
+
if (normalized.includes(`${import_node_path.sep}.giri${import_node_path.sep}`) || normalized.endsWith(`${import_node_path.sep}types${import_node_path.sep}routes`)) {
|
|
41
|
+
generatedRoots.push(normalized);
|
|
42
|
+
} else {
|
|
43
|
+
routeRoots.push(normalized);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { routeRoots, generatedRoots };
|
|
47
|
+
}
|
|
48
|
+
function resolveGiriTypesImport(options) {
|
|
49
|
+
if (options.moduleName !== "./$types" && options.moduleName !== "./$types.d.ts") {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
const fileExists = options.fileExists ?? import_node_fs.existsSync;
|
|
53
|
+
const containingDir = (0, import_node_path.dirname)(options.containingFile);
|
|
54
|
+
const inferred = inferRouteRoot(options.containingFile);
|
|
55
|
+
const fromRootDirs = rootDirsByKind(options.projectDir, options.rootDirs);
|
|
56
|
+
const routeRoots = unique([
|
|
57
|
+
...inferred ? [inferred.routesDir] : [],
|
|
58
|
+
(0, import_node_path.join)(options.projectDir, "src", "routes"),
|
|
59
|
+
...fromRootDirs.routeRoots
|
|
60
|
+
]);
|
|
61
|
+
const generatedRoots = unique([
|
|
62
|
+
...inferred ? [(0, import_node_path.join)(inferred.projectRoot, ".giri", "types", "routes")] : [],
|
|
63
|
+
(0, import_node_path.join)(options.projectDir, ".giri", "types", "routes"),
|
|
64
|
+
...fromRootDirs.generatedRoots
|
|
65
|
+
]);
|
|
66
|
+
for (const routesDir of routeRoots) {
|
|
67
|
+
if (!isInside(routesDir, containingDir)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const key = routeKey(routesDir, containingDir);
|
|
71
|
+
for (const generatedRoot of generatedRoots) {
|
|
72
|
+
const candidate = (0, import_node_path.join)(generatedRoot, key, "$types.d.ts");
|
|
73
|
+
if (fileExists(candidate)) {
|
|
74
|
+
return candidate;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/typescript-plugin.ts
|
|
82
|
+
function init(modules) {
|
|
83
|
+
return {
|
|
84
|
+
create(info) {
|
|
85
|
+
const host = info.languageServiceHost;
|
|
86
|
+
const originalResolveModuleNames = host.resolveModuleNames?.bind(host);
|
|
87
|
+
host.resolveModuleNames = (moduleNames, containingFile, ...rest) => {
|
|
88
|
+
const originalResults = originalResolveModuleNames ? originalResolveModuleNames(moduleNames, containingFile, ...rest) : void 0;
|
|
89
|
+
return moduleNames.map((moduleName, index) => {
|
|
90
|
+
const resolved = resolveGiriTypesImport({
|
|
91
|
+
moduleName,
|
|
92
|
+
containingFile,
|
|
93
|
+
projectDir: info.project.getCurrentDirectory(),
|
|
94
|
+
rootDirs: info.project.getCompilerOptions().rootDirs,
|
|
95
|
+
fileExists: info.serverHost.fileExists?.bind(info.serverHost)
|
|
96
|
+
});
|
|
97
|
+
if (resolved) {
|
|
98
|
+
return {
|
|
99
|
+
resolvedFileName: resolved,
|
|
100
|
+
extension: modules.typescript.Extension.Dts,
|
|
101
|
+
isExternalLibraryImport: false
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (originalResults) {
|
|
105
|
+
return originalResults[index];
|
|
106
|
+
}
|
|
107
|
+
return modules.typescript.resolveModuleName(
|
|
108
|
+
moduleName,
|
|
109
|
+
containingFile,
|
|
110
|
+
info.project.getCompilerOptions(),
|
|
111
|
+
modules.typescript.sys
|
|
112
|
+
).resolvedModule;
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
return info.languageService;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
module.exports = init;
|
|
120
|
+
//# sourceMappingURL=typescript-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/typescript-plugin-core.ts","../src/typescript-plugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';\n\nexport interface ResolveGiriTypesImportOptions {\n moduleName: string;\n containingFile: string;\n projectDir: string;\n rootDirs?: readonly string[];\n fileExists?: (path: string) => boolean;\n}\n\ninterface InferredRouteRoot {\n projectRoot: string;\n routesDir: string;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values.map((value) => normalize(value)))];\n}\n\nfunction isInside(parent: string, child: string): boolean {\n const rel = relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));\n}\n\nfunction absolutePath(projectDir: string, value: string): string {\n return isAbsolute(value) ? value : resolve(projectDir, value);\n}\n\nfunction inferRouteRoot(containingFile: string): InferredRouteRoot | undefined {\n const normalized = normalize(containingFile);\n const parts = normalized.split(sep);\n\n for (let index = parts.length - 2; index >= 0; index -= 1) {\n if (parts[index] === 'src' && parts[index + 1] === 'routes') {\n const projectRoot = parts.slice(0, index).join(sep) || sep;\n return {\n projectRoot,\n routesDir: parts.slice(0, index + 2).join(sep),\n };\n }\n }\n\n return undefined;\n}\n\nfunction routeKey(routesDir: string, routeDir: string): string {\n const rel = relative(routesDir, routeDir);\n return rel ? rel : '__root';\n}\n\nfunction rootDirsByKind(projectDir: string, rootDirs: readonly string[] | undefined): { routeRoots: string[]; generatedRoots: string[] } {\n const routeRoots: string[] = [];\n const generatedRoots: string[] = [];\n\n for (const rootDir of rootDirs ?? []) {\n const absolute = absolutePath(projectDir, rootDir);\n const normalized = normalize(absolute);\n if (\n normalized.includes(`${sep}.giri${sep}`) ||\n normalized.endsWith(`${sep}types${sep}routes`)\n ) {\n generatedRoots.push(normalized);\n } else {\n routeRoots.push(normalized);\n }\n }\n\n return { routeRoots, generatedRoots };\n}\n\nexport function resolveGiriTypesImport(options: ResolveGiriTypesImportOptions): string | undefined {\n if (\n options.moduleName !== './$types' &&\n options.moduleName !== './$types.d.ts'\n ) {\n return undefined;\n }\n\n const fileExists = options.fileExists ?? existsSync;\n const containingDir = dirname(options.containingFile);\n const inferred = inferRouteRoot(options.containingFile);\n const fromRootDirs = rootDirsByKind(options.projectDir, options.rootDirs);\n\n const routeRoots = unique([\n ...(inferred ? [inferred.routesDir] : []),\n join(options.projectDir, 'src', 'routes'),\n ...fromRootDirs.routeRoots,\n ]);\n const generatedRoots = unique([\n ...(inferred ? [join(inferred.projectRoot, '.giri', 'types', 'routes')] : []),\n join(options.projectDir, '.giri', 'types', 'routes'),\n ...fromRootDirs.generatedRoots,\n ]);\n\n for (const routesDir of routeRoots) {\n if (!isInside(routesDir, containingDir)) {\n continue;\n }\n\n const key = routeKey(routesDir, containingDir);\n for (const generatedRoot of generatedRoots) {\n const candidate = join(generatedRoot, key, '$types.d.ts');\n if (fileExists(candidate)) {\n return candidate;\n }\n }\n }\n\n return undefined;\n}\n","import type * as ts from 'typescript/lib/tsserverlibrary';\nimport { resolveGiriTypesImport } from './typescript-plugin-core';\n\ntype ResolveModuleNames = NonNullable<ts.LanguageServiceHost['resolveModuleNames']>;\n\nfunction init(modules: { typescript: typeof ts }): ts.server.PluginModule {\n return {\n create(info) {\n const host = info.languageServiceHost as ts.LanguageServiceHost & {\n resolveModuleNames?: ResolveModuleNames;\n };\n const originalResolveModuleNames = host.resolveModuleNames?.bind(host);\n\n host.resolveModuleNames = (moduleNames, containingFile, ...rest) => {\n const originalResults = originalResolveModuleNames\n ? originalResolveModuleNames(moduleNames, containingFile, ...rest)\n : undefined;\n\n return moduleNames.map((moduleName, index) => {\n const resolved = resolveGiriTypesImport({\n moduleName,\n containingFile,\n projectDir: info.project.getCurrentDirectory(),\n rootDirs: info.project.getCompilerOptions().rootDirs,\n fileExists: info.serverHost.fileExists?.bind(info.serverHost),\n });\n\n if (resolved) {\n return {\n resolvedFileName: resolved,\n extension: modules.typescript.Extension.Dts,\n isExternalLibraryImport: false,\n };\n }\n\n if (originalResults) {\n return originalResults[index];\n }\n\n return modules.typescript.resolveModuleName(\n moduleName,\n containingFile,\n info.project.getCompilerOptions(),\n modules.typescript.sys,\n ).resolvedModule;\n });\n };\n\n return info.languageService;\n },\n };\n}\n\nexport = init;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
import { B as BodyContentType, a as GiriBodySchema, b as GiriInputSchema } from '../types-BrUMxh5u.js';
|
|
3
|
+
|
|
4
|
+
type AnySchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>;
|
|
5
|
+
/**
|
|
6
|
+
* Valibot adapter. Peer-depends `valibot` and `@valibot/to-json-schema`.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import * as v from 'valibot';
|
|
10
|
+
* import { valibot } from '@boon4681/giri/validators/valibot';
|
|
11
|
+
*
|
|
12
|
+
* export const body = valibot.body({ json: v.object({ name: v.pipe(v.string(), v.minLength(1)) }) });
|
|
13
|
+
* export const query = valibot.query(v.object({ page: v.string() }));
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare const valibot: {
|
|
17
|
+
body<Map extends Partial<Record<BodyContentType, AnySchema>>>(map: Map): GiriBodySchema<{ [K in keyof Map]: Map[K] extends AnySchema ? v.InferOutput<Map[K]> : never; }>;
|
|
18
|
+
query<Schema extends AnySchema>(schema: Schema): GiriInputSchema<v.InferOutput<Schema>>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { valibot };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/validators/valibot.ts
|
|
31
|
+
var valibot_exports = {};
|
|
32
|
+
__export(valibot_exports, {
|
|
33
|
+
valibot: () => valibot
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(valibot_exports);
|
|
36
|
+
var import_to_json_schema = require("@valibot/to-json-schema");
|
|
37
|
+
var v = __toESM(require("valibot"));
|
|
38
|
+
|
|
39
|
+
// src/types.ts
|
|
40
|
+
var inputSchemaBrand = /* @__PURE__ */ Symbol.for("giri.input-schema");
|
|
41
|
+
var bodySchemaBrand = /* @__PURE__ */ Symbol.for("giri.body-schema");
|
|
42
|
+
|
|
43
|
+
// src/validation.ts
|
|
44
|
+
function defineInputSchema(schema) {
|
|
45
|
+
return { [inputSchemaBrand]: true, ...schema };
|
|
46
|
+
}
|
|
47
|
+
function defineBodySchema(contents) {
|
|
48
|
+
return { [bodySchemaBrand]: true, contents };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/validators/valibot.ts
|
|
52
|
+
function wrap(schema) {
|
|
53
|
+
return defineInputSchema({
|
|
54
|
+
validate(value) {
|
|
55
|
+
const result = v.safeParse(schema, value);
|
|
56
|
+
return result.success ? { ok: true, value: result.output } : { ok: false, issues: result.issues };
|
|
57
|
+
},
|
|
58
|
+
toJsonSchema() {
|
|
59
|
+
return (0, import_to_json_schema.toJsonSchema)(schema);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
var valibot = {
|
|
64
|
+
body(map) {
|
|
65
|
+
const contents = {};
|
|
66
|
+
for (const [contentType, schema] of Object.entries(map)) {
|
|
67
|
+
if (schema) {
|
|
68
|
+
contents[contentType] = wrap(schema);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return defineBodySchema(contents);
|
|
72
|
+
},
|
|
73
|
+
query(schema) {
|
|
74
|
+
return wrap(schema);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
valibot
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=valibot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/validators/valibot.ts","../../src/types.ts","../../src/validation.ts"],"sourcesContent":["import { toJsonSchema } from '@valibot/to-json-schema';\nimport * as v from 'valibot';\nimport { defineBodySchema, defineInputSchema } from '../validation';\nimport type { BodyContentType, GiriBodySchema, GiriInputSchema } from '../types';\n\ntype AnySchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>;\n\n/** Wrap a single Valibot schema as a giri input schema. */\nfunction wrap<Schema extends AnySchema>(schema: Schema): GiriInputSchema<v.InferOutput<Schema>> {\n return defineInputSchema<v.InferOutput<Schema>>({\n validate(value) {\n const result = v.safeParse(schema, value);\n return result.success\n ? { ok: true, value: result.output }\n : { ok: false, issues: result.issues };\n },\n toJsonSchema() {\n return toJsonSchema(schema) as Record<string, unknown>;\n },\n });\n}\n\n/**\n * Valibot adapter. Peer-depends `valibot` and `@valibot/to-json-schema`.\n *\n * ```ts\n * import * as v from 'valibot';\n * import { valibot } from '@boon4681/giri/validators/valibot';\n *\n * export const body = valibot.body({ json: v.object({ name: v.pipe(v.string(), v.minLength(1)) }) });\n * export const query = valibot.query(v.object({ page: v.string() }));\n * ```\n */\nexport const valibot = {\n body<Map extends Partial<Record<BodyContentType, AnySchema>>>(\n map: Map,\n ): GiriBodySchema<{ [K in keyof Map]: Map[K] extends AnySchema ? v.InferOutput<Map[K]> : never }> {\n const contents = {} as Record<BodyContentType, GiriInputSchema>;\n for (const [contentType, schema] of Object.entries(map)) {\n if (schema) {\n contents[contentType as BodyContentType] = wrap(schema);\n }\n }\n return defineBodySchema(contents) as unknown as GiriBodySchema<{\n [K in keyof Map]: Map[K] extends AnySchema ? v.InferOutput<Map[K]> : never;\n }>;\n },\n query<Schema extends AnySchema>(schema: Schema): GiriInputSchema<v.InferOutput<Schema>> {\n return wrap(schema);\n },\n};\n","export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';\n\nexport type StatusCode = number;\n\nexport type ResponseFormat = 'json' | 'text';\n\nexport const typedResponseBrand: unique symbol = Symbol.for('giri.typed-response') as never;\n\nexport interface TypedResponse<\n T,\n S extends StatusCode = StatusCode,\n F extends ResponseFormat = ResponseFormat,\n> {\n readonly [typedResponseBrand]: {\n data: T;\n status: S;\n format: F;\n };\n readonly data: T;\n readonly status: S;\n readonly format: F;\n readonly headers?: HeadersInit;\n}\n\nexport type HandlerResponse = Response | TypedResponse<unknown, StatusCode, ResponseFormat>;\n\nexport interface ValidatedInput {\n /**\n * The validated request body. For a single declared content-type it's that schema's\n * output; for several it's a discriminated union `{ type; data }` (see `ValidBody`).\n */\n body?: unknown;\n query?: unknown;\n}\n\nexport interface GiriRequest<Input extends ValidatedInput = ValidatedInput> {\n raw: Request;\n url: URL;\n method: string;\n header(name: string): string | null;\n json<T = unknown>(): Promise<T>;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n formData(): Promise<FormData>;\n valid<K extends keyof Input & ('body' | 'query')>(key: K): Input[K];\n}\n\ndeclare global {\n /**\n * Global registration surface for app-wide types. `giri sync` augments\n * `Giri.Register[\"app\"]` from `src/main.ts` `init()` return type so `c.app` is\n * typed without per-route generics (the registration pattern).\n */\n namespace Giri {\n interface Register {}\n }\n}\n\n/**\n * The app-wide services container, the type of `c.app`. `giri sync` infers it from\n * `src/main.ts`'s `init()` return type (via the global `Giri.Register` augmentation);\n * until then it falls back to an open record. Leave `init` unannotated (its return is\n * the source of truth) and annotate `teardown`'s parameter with this:\n *\n * ```ts\n * export const init = () => ({ db }); // inferred\n * export const teardown = (services: Services) => services.db.close();\n * ```\n */\nexport type Services = Giri.Register extends { app: infer A }\n ? A\n : Record<string, unknown>;\n\nexport interface Context<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> {\n params: Params;\n /** App-wide services from `src/main.ts`'s `init()`, seeded into every request. */\n app: Services;\n req: GiriRequest<Input>;\n // Context vars (`c.set`/`c.get`). Keys declared by middleware (`Vars`) are typed;\n // any other key stays open (`unknown`) so untracked keys still work.\n set<K extends keyof Vars & string>(key: K, value: Vars[K]): void;\n set<K extends string>(key: K, value: unknown): void;\n get<K extends keyof Vars & string>(key: K): Vars[K];\n get<V = unknown>(key: string): V;\n json<T, S extends StatusCode = 200>(\n data: T,\n status?: S,\n headers?: HeadersInit,\n ): TypedResponse<T, S, 'json'>;\n text<S extends StatusCode = 200>(\n text: string,\n status?: S,\n headers?: HeadersInit,\n ): TypedResponse<string, S, 'text'>;\n}\n\nexport type Handle<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> = (c: Context<Params, Input, Vars>) => HandlerResponse | Promise<HandlerResponse>;\n\nexport type Next = () => Promise<HandlerResponse | void>;\n\n/** An OpenAPI security requirement, e.g. `{ bearerAuth: [] }`. */\nexport type SecurityRequirement = Record<string, string[]>;\n\nexport interface MiddlewareOpenApi {\n /** Security requirements this middleware enforces */\n security?: SecurityRequirement[];\n /** Optional scheme definitions, merged into `components.securitySchemes` so the doc is self-contained. */\n securitySchemes?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface MiddlewareOptions {\n openapi?: MiddlewareOpenApi;\n}\n\nexport interface Middleware<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> {\n (c: Context<Params, Input, Vars>, next: Next): HandlerResponse | void | Promise<HandlerResponse | void>;\n openapi?: MiddlewareOpenApi;\n}\n\n/** The context vars a middleware injects (its `Vars` type parameter). */\nexport type VarsOf<M> = M extends Middleware<Record<string, string>, ValidatedInput, infer V>\n ? V\n : {};\n\n/** Intersect the injected vars of a tuple of middleware (built with `stack(...)`). */\nexport type MergeStack<T> = T extends readonly [infer Head, ...infer Rest]\n ? VarsOf<Head> & MergeStack<Rest>\n : {};\n\n/**\n * Merge the vars from a middleware stack export. A plain `Middleware[]` (not a `stack(...)` tuple)\n */\nexport type InferStackVars<T> = T extends readonly [unknown, ...unknown[]] ? MergeStack<T> : {};\n\n/**\n * The vars injected by a module own `middleware` export (a `stack(...)`). Used by the\n * generated per-method handle so a verb file's own `export const middleware` types\n * `c.get`/`c.set`, on top of the folder's `+shared.ts` chain.\n */\nexport type MiddlewareVarsOf<M> = M extends { middleware: infer Stack }\n ? InferStackVars<Stack>\n : {};\n\n/** A JSON Schema object (JSON Schema 2020-12 / OpenAPI 3.1 dialect). */\nexport type JsonSchema = Record<string, unknown>;\n\nexport const inputSchemaBrand: unique symbol = Symbol.for('giri.input-schema') as never;\n\nexport type InputValidationResult<Output = unknown> =\n | { ok: true; value: Output }\n | { ok: false; issues: unknown };\n\n/**\n * A input schema every wrapper form (`body`/`query`) export takes. A vendor\n * adapter (`@boon4681/giri/validators/zod`, `@boon4681/giri/validators/valibot`, …) returns one; build a\n * custom one with `defineInputSchema`. giri core depends only on this interface, never\n * on a validator library. `validate` is the runtime check; `toJsonSchema` feeds OpenAPI.\n */\nexport interface GiriInputSchema<Output = unknown> {\n readonly [inputSchemaBrand]: true;\n validate(value: unknown): InputValidationResult<Output> | Promise<InputValidationResult<Output>>;\n toJsonSchema(): JsonSchema;\n}\n\n/** Extract the validated output type of a giri input schema: `Infer<typeof body>`. */\nexport type Infer<T> = T extends GiriInputSchema<infer Output> ? Output : never;\n\nexport type BodyContentType = 'json' | 'form' | 'urlencoded' | 'text';\n\nexport const bodySchemaBrand: unique symbol = Symbol.for('giri.body-schema') as never;\n\n/**\n * A request body declared as a set of accepted content-types wrapped form `body`\n * takes (`zod.body({ json, form })`). One key means that encoding only; several mean the\n * endpoint accepts any of them, dispatched at runtime on the request `Content-Type`.\n * Each entry is a plain `GiriInputSchema`, so `validate`/`toJsonSchema` work per content-type.\n */\nexport interface GiriBodySchema<\n Outputs extends Partial<Record<BodyContentType, unknown>> = Partial<Record<BodyContentType, unknown>>,\n> {\n readonly [bodySchemaBrand]: true;\n readonly contents: { [K in keyof Outputs & BodyContentType]: GiriInputSchema<Outputs[K]> };\n}\n\n/** True when `T` is a union of more than one member. */\ntype IsUnion<T, U = T> = T extends unknown ? ([U] extends [T] ? false : true) : never;\n\n/**\n * The validated body a handler receives. A single declared content-type yields that\n * schema's output directly; several yield a discriminated union keyed by content-type.\n */\nexport type ValidBody<B> = B extends GiriBodySchema<infer Outputs>\n ? IsUnion<keyof Outputs> extends true\n ? { [K in keyof Outputs]: { type: K; data: Outputs[K] } }[keyof Outputs]\n : Outputs[keyof Outputs]\n : never;\n\n/** The validated query a handler receives. */\nexport type ValidQuery<Q> = Q extends GiriInputSchema<infer Output> ? Output : never;\n\n/** Drop keys whose value resolved to `never` (an input the route didn't declare). */\ntype PruneNever<T> = { [K in keyof T as [T[K]] extends [never] ? never : K]: T[K] };\n\n/**\n * Derive a route's `ValidatedInput` from a module's `body`/`query` exports. The generated\n * per-method `$types` handle (`POST`, `GET`, …) uses this so handlers infer `c.req.valid`\n * with no manual generic.\n */\nexport type RouteInputOf<M> = PruneNever<{\n body: M extends { body: infer B } ? ValidBody<B> : never;\n query: M extends { query: infer Q } ? ValidQuery<Q> : never;\n}>;\n\nexport interface RouteInput {\n body?: GiriBodySchema;\n query?: GiriInputSchema;\n}\n\nexport interface RouteOpenApi {\n /** Omit this route from the generated `openapi.json` (it still serves normally). */\n hidden?: boolean;\n // Room to grow: summary, description, tags, deprecated, operationId, …\n}\n\nexport type RouteOpenApiConfig = RouteOpenApi | boolean;\n\nexport interface GiriRouteRegistration {\n method: HttpMethod;\n path: string;\n handle: Handle;\n middleware: Middleware[];\n input?: RouteInput;\n /** App-wide services to seed onto `c.app` (same instance for every route). */\n services?: Services;\n}\n\nexport type GiriFetchHandler = (req: Request) => Response | Promise<Response>;\n\nexport interface GiriServeOptions {\n port: number;\n hostname?: string;\n}\n\nexport interface GiriServerInfo {\n address: string;\n port: number;\n}\n\nexport interface GiriServer {\n close(): void | Promise<void>;\n}\n\nexport interface GiriAdapter<App> {\n name?: string;\n createApp(): App;\n register(app: App, route: GiriRouteRegistration): void;\n fetch(app: App, req: Request): Promise<Response>;\n /**\n * Bind the configured backend's runtime to a port and start serving.\n * giri core stays runtime-agnostic: it hands the adapter a request handler\n * (so hot-reload keeps working) and the adapter owns the actual server.\n */\n serve(\n handler: GiriFetchHandler,\n options: GiriServeOptions,\n onListen?: (info: GiriServerInfo) => void,\n ): GiriServer;\n}\n\nexport interface GiriConfig<App = unknown> {\n adapter: GiriAdapter<App>;\n alias?: Record<string, string | string[]>;\n outDir?: string;\n server?: {\n port?: number;\n hostname?: string;\n };\n errorSchema?: unknown;\n}\n\nexport interface GiriPaths {\n cwd: string;\n routesDir: string;\n outDir: string;\n}\n","import {\n type BodyContentType,\n type GiriBodySchema,\n type GiriInputSchema,\n type InputValidationResult,\n type RouteInput,\n type TypedResponse,\n type ValidatedInput,\n bodySchemaBrand,\n inputSchemaBrand,\n} from './types';\nimport { createTypedResponse } from './context';\n\ninterface PreparedInput {\n ok: true;\n validated: ValidatedInput;\n}\n\ninterface FailedInput {\n ok: false;\n response: TypedResponse<{ message: string; issues: unknown }, 400 | 415, 'json'>;\n}\n\nexport type PreparedRequestInput = PreparedInput | FailedInput;\n\n/**\n * Build a giri input schema from a `validate` + `toJsonSchema` pair. Vendor adapters use\n * this; you can call it directly to make a custom validator. The brand is a global symbol,\n * so a hand-rolled `{ [Symbol.for(\"giri.input-schema\")]: true, validate, toJsonSchema }` works too.\n */\nexport function defineInputSchema<Output>(\n schema: Omit<GiriInputSchema<Output>, typeof inputSchemaBrand>,\n): GiriInputSchema<Output> {\n return { [inputSchemaBrand]: true, ...schema };\n}\n\nexport function isGiriInputSchema(value: unknown): value is GiriInputSchema {\n return Boolean(\n value &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[inputSchemaBrand] === true,\n );\n}\n\n/**\n * Build a giri body schema from per-content-type input schemas. Validator adapters use this `zod.body({ json, form })`\n */\nexport function defineBodySchema<Outputs extends Partial<Record<BodyContentType, unknown>>>(\n contents: GiriBodySchema<Outputs>['contents'],\n): GiriBodySchema<Outputs> {\n return { [bodySchemaBrand]: true, contents };\n}\n\nexport function isGiriBodySchema(value: unknown): value is GiriBodySchema {\n return Boolean(\n value &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[bodySchemaBrand] === true,\n );\n}\n\nconst MIME_TO_CONTENT_TYPE: Record<string, BodyContentType> = {\n 'application/json': 'json',\n 'multipart/form-data': 'form',\n 'application/x-www-form-urlencoded': 'urlencoded',\n 'text/plain': 'text',\n};\n\nfunction contentTypeFromHeader(header: string | null): BodyContentType | undefined {\n if (!header) {\n return undefined;\n }\n const mime = header.split(';', 1)[0].trim().toLowerCase();\n return MIME_TO_CONTENT_TYPE[mime];\n}\n\n/** Flatten a `FormData` into a plain object, collapsing repeated fields into arrays. */\nfunction formDataObject(form: FormData): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n form.forEach((value, key) => {\n const current = result[key];\n if (current === undefined) {\n result[key] = value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n result[key] = [current, value];\n }\n });\n return result;\n}\n\nasync function readRawBody(request: Request, contentType: BodyContentType): Promise<unknown> {\n const cloned = request.clone();\n if (contentType === 'json') {\n return cloned.json();\n }\n if (contentType === 'text') {\n return cloned.text();\n }\n return formDataObject(await cloned.formData());\n}\n\nfunction queryObject(url: URL): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of url.searchParams) {\n const current = result[key];\n if (current === undefined) {\n result[key] = value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n result[key] = [current, value];\n }\n }\n return result;\n}\n\nasync function runValidation(\n schema: GiriInputSchema,\n value: unknown,\n label: string,\n): Promise<InputValidationResult> {\n if (!isGiriInputSchema(schema)) {\n throw new Error(\n `giri: ${label} schema must be wrapped with a validator, e.g. \\`export const ${label} = zod(...)\\` from @boon4681/giri/validators/zod.`,\n );\n }\n return schema.validate(value);\n}\n\nexport async function prepareRequestInput(request: Request, input?: RouteInput): Promise<PreparedRequestInput> {\n const validated: ValidatedInput = {};\n\n if (input?.query) {\n const query = queryObject(new URL(request.url));\n const result = await runValidation(input.query, query, 'query');\n if (!result.ok) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid query parameters.', issues: result.issues },\n 400,\n 'json',\n ),\n };\n }\n validated.query = result.value;\n }\n\n if (input?.body) {\n const contents = input.body.contents as Record<BodyContentType, GiriInputSchema>;\n const declared = Object.keys(contents) as BodyContentType[];\n const requested = contentTypeFromHeader(request.headers.get('content-type'));\n // Pick the schema matching the request's content-type; fall back to JSON when the\n // header is missing/unrecognized but JSON is on offer (so header-less posts still work).\n const chosen: BodyContentType | undefined =\n requested && contents[requested] ? requested : contents.json ? 'json' : undefined;\n\n if (!chosen) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Unsupported media type.', issues: { accepted: declared } },\n 415,\n 'json',\n ),\n };\n }\n\n let rawBody: unknown;\n try {\n rawBody = await readRawBody(request, chosen);\n } catch (error) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid request body.', issues: error },\n 400,\n 'json',\n ),\n };\n }\n\n const result = await runValidation(contents[chosen], rawBody, 'body');\n if (!result.ok) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid request body.', issues: result.issues },\n 400,\n 'json',\n ),\n };\n }\n\n validated.body = declared.length > 1 ? { type: chosen, data: result.value } : result.value;\n }\n\n return { ok: true, validated };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAA6B;AAC7B,QAAmB;;;AC8JZ,IAAM,mBAAkC,uBAAO,IAAI,mBAAmB;AAuBtE,IAAM,kBAAiC,uBAAO,IAAI,kBAAkB;;;ACxJpE,SAAS,kBACZ,QACuB;AACvB,SAAO,EAAE,CAAC,gBAAgB,GAAG,MAAM,GAAG,OAAO;AACjD;AAaO,SAAS,iBACZ,UACuB;AACvB,SAAO,EAAE,CAAC,eAAe,GAAG,MAAM,SAAS;AAC/C;;;AF3CA,SAAS,KAA+B,QAAwD;AAC5F,SAAO,kBAAyC;AAAA,IAC5C,SAAS,OAAO;AACZ,YAAM,SAAW,YAAU,QAAQ,KAAK;AACxC,aAAO,OAAO,UACR,EAAE,IAAI,MAAM,OAAO,OAAO,OAAO,IACjC,EAAE,IAAI,OAAO,QAAQ,OAAO,OAAO;AAAA,IAC7C;AAAA,IACA,eAAe;AACX,iBAAO,oCAAa,MAAM;AAAA,IAC9B;AAAA,EACJ,CAAC;AACL;AAaO,IAAM,UAAU;AAAA,EACnB,KACI,KAC8F;AAC9F,UAAM,WAAW,CAAC;AAClB,eAAW,CAAC,aAAa,MAAM,KAAK,OAAO,QAAQ,GAAG,GAAG;AACrD,UAAI,QAAQ;AACR,iBAAS,WAA8B,IAAI,KAAK,MAAM;AAAA,MAC1D;AAAA,IACJ;AACA,WAAO,iBAAiB,QAAQ;AAAA,EAGpC;AAAA,EACA,MAAgC,QAAwD;AACpF,WAAO,KAAK,MAAM;AAAA,EACtB;AACJ;","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { B as BodyContentType, a as GiriBodySchema, b as GiriInputSchema } from '../types-BrUMxh5u.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Zod adapter. Peer-depends `zod`.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { z } from 'zod';
|
|
9
|
+
* import { zod } from '@boon4681/giri/validators/zod';
|
|
10
|
+
*
|
|
11
|
+
* // JSON body
|
|
12
|
+
* export const body = zod.body({ json: z.object({ name: z.string().min(1) }) });
|
|
13
|
+
* // JSON *or* multipart dispatched on Content-Type at runtime
|
|
14
|
+
* export const body = zod.body({
|
|
15
|
+
* json: z.object({ name: z.string() }),
|
|
16
|
+
* form: z.object({ name: z.string(), avatar: z.instanceof(File) }),
|
|
17
|
+
* });
|
|
18
|
+
* export const query = zod.query(z.object({ page: z.coerce.number() }));
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const zod: {
|
|
22
|
+
body<Map extends Partial<Record<BodyContentType, z.ZodType>>>(map: Map): GiriBodySchema<{ [K in keyof Map]: Map[K] extends z.ZodType ? z.infer<Map[K]> : never; }>;
|
|
23
|
+
query<Schema extends z.ZodType>(schema: Schema): GiriInputSchema<z.infer<Schema>>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { zod };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/validators/zod.ts
|
|
21
|
+
var zod_exports = {};
|
|
22
|
+
__export(zod_exports, {
|
|
23
|
+
zod: () => zod
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(zod_exports);
|
|
26
|
+
var import_zod = require("zod");
|
|
27
|
+
|
|
28
|
+
// src/types.ts
|
|
29
|
+
var inputSchemaBrand = /* @__PURE__ */ Symbol.for("giri.input-schema");
|
|
30
|
+
var bodySchemaBrand = /* @__PURE__ */ Symbol.for("giri.body-schema");
|
|
31
|
+
|
|
32
|
+
// src/validation.ts
|
|
33
|
+
function defineInputSchema(schema) {
|
|
34
|
+
return { [inputSchemaBrand]: true, ...schema };
|
|
35
|
+
}
|
|
36
|
+
function defineBodySchema(contents) {
|
|
37
|
+
return { [bodySchemaBrand]: true, contents };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/validators/zod.ts
|
|
41
|
+
function wrap(schema) {
|
|
42
|
+
return defineInputSchema({
|
|
43
|
+
validate(value) {
|
|
44
|
+
const result = schema.safeParse(value);
|
|
45
|
+
return result.success ? { ok: true, value: result.data } : { ok: false, issues: result.error };
|
|
46
|
+
},
|
|
47
|
+
toJsonSchema() {
|
|
48
|
+
return import_zod.z.toJSONSchema(schema);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
var zod = {
|
|
53
|
+
body(map) {
|
|
54
|
+
const contents = {};
|
|
55
|
+
for (const [contentType, schema] of Object.entries(map)) {
|
|
56
|
+
if (schema) {
|
|
57
|
+
contents[contentType] = wrap(schema);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return defineBodySchema(contents);
|
|
61
|
+
},
|
|
62
|
+
query(schema) {
|
|
63
|
+
return wrap(schema);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
67
|
+
0 && (module.exports = {
|
|
68
|
+
zod
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=zod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/validators/zod.ts","../../src/types.ts","../../src/validation.ts"],"sourcesContent":["import { z } from 'zod';\nimport { defineBodySchema, defineInputSchema } from '../validation';\nimport type { BodyContentType, GiriBodySchema, GiriInputSchema } from '../types';\n\n/** Wrap a single Zod schema as a giri input schema (validate via `safeParse`, JSON Schema via Zod 4). */\nfunction wrap<Schema extends z.ZodType>(schema: Schema): GiriInputSchema<z.infer<Schema>> {\n return defineInputSchema<z.infer<Schema>>({\n validate(value) {\n const result = schema.safeParse(value);\n return result.success\n ? { ok: true, value: result.data }\n : { ok: false, issues: result.error };\n },\n toJsonSchema() {\n return z.toJSONSchema(schema) as Record<string, unknown>;\n },\n });\n}\n\n/**\n * Zod adapter. Peer-depends `zod`.\n *\n * ```ts\n * import { z } from 'zod';\n * import { zod } from '@boon4681/giri/validators/zod';\n *\n * // JSON body\n * export const body = zod.body({ json: z.object({ name: z.string().min(1) }) });\n * // JSON *or* multipart dispatched on Content-Type at runtime\n * export const body = zod.body({\n * json: z.object({ name: z.string() }),\n * form: z.object({ name: z.string(), avatar: z.instanceof(File) }),\n * });\n * export const query = zod.query(z.object({ page: z.coerce.number() }));\n * ```\n */\nexport const zod = {\n body<Map extends Partial<Record<BodyContentType, z.ZodType>>>(\n map: Map,\n ): GiriBodySchema<{ [K in keyof Map]: Map[K] extends z.ZodType ? z.infer<Map[K]> : never }> {\n const contents = {} as Record<BodyContentType, GiriInputSchema>;\n for (const [contentType, schema] of Object.entries(map)) {\n if (schema) {\n contents[contentType as BodyContentType] = wrap(schema);\n }\n }\n return defineBodySchema(contents) as unknown as GiriBodySchema<{\n [K in keyof Map]: Map[K] extends z.ZodType ? z.infer<Map[K]> : never;\n }>;\n },\n query<Schema extends z.ZodType>(schema: Schema): GiriInputSchema<z.infer<Schema>> {\n return wrap(schema);\n },\n};\n","export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';\n\nexport type StatusCode = number;\n\nexport type ResponseFormat = 'json' | 'text';\n\nexport const typedResponseBrand: unique symbol = Symbol.for('giri.typed-response') as never;\n\nexport interface TypedResponse<\n T,\n S extends StatusCode = StatusCode,\n F extends ResponseFormat = ResponseFormat,\n> {\n readonly [typedResponseBrand]: {\n data: T;\n status: S;\n format: F;\n };\n readonly data: T;\n readonly status: S;\n readonly format: F;\n readonly headers?: HeadersInit;\n}\n\nexport type HandlerResponse = Response | TypedResponse<unknown, StatusCode, ResponseFormat>;\n\nexport interface ValidatedInput {\n /**\n * The validated request body. For a single declared content-type it's that schema's\n * output; for several it's a discriminated union `{ type; data }` (see `ValidBody`).\n */\n body?: unknown;\n query?: unknown;\n}\n\nexport interface GiriRequest<Input extends ValidatedInput = ValidatedInput> {\n raw: Request;\n url: URL;\n method: string;\n header(name: string): string | null;\n json<T = unknown>(): Promise<T>;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n formData(): Promise<FormData>;\n valid<K extends keyof Input & ('body' | 'query')>(key: K): Input[K];\n}\n\ndeclare global {\n /**\n * Global registration surface for app-wide types. `giri sync` augments\n * `Giri.Register[\"app\"]` from `src/main.ts` `init()` return type so `c.app` is\n * typed without per-route generics (the registration pattern).\n */\n namespace Giri {\n interface Register {}\n }\n}\n\n/**\n * The app-wide services container, the type of `c.app`. `giri sync` infers it from\n * `src/main.ts`'s `init()` return type (via the global `Giri.Register` augmentation);\n * until then it falls back to an open record. Leave `init` unannotated (its return is\n * the source of truth) and annotate `teardown`'s parameter with this:\n *\n * ```ts\n * export const init = () => ({ db }); // inferred\n * export const teardown = (services: Services) => services.db.close();\n * ```\n */\nexport type Services = Giri.Register extends { app: infer A }\n ? A\n : Record<string, unknown>;\n\nexport interface Context<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> {\n params: Params;\n /** App-wide services from `src/main.ts`'s `init()`, seeded into every request. */\n app: Services;\n req: GiriRequest<Input>;\n // Context vars (`c.set`/`c.get`). Keys declared by middleware (`Vars`) are typed;\n // any other key stays open (`unknown`) so untracked keys still work.\n set<K extends keyof Vars & string>(key: K, value: Vars[K]): void;\n set<K extends string>(key: K, value: unknown): void;\n get<K extends keyof Vars & string>(key: K): Vars[K];\n get<V = unknown>(key: string): V;\n json<T, S extends StatusCode = 200>(\n data: T,\n status?: S,\n headers?: HeadersInit,\n ): TypedResponse<T, S, 'json'>;\n text<S extends StatusCode = 200>(\n text: string,\n status?: S,\n headers?: HeadersInit,\n ): TypedResponse<string, S, 'text'>;\n}\n\nexport type Handle<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> = (c: Context<Params, Input, Vars>) => HandlerResponse | Promise<HandlerResponse>;\n\nexport type Next = () => Promise<HandlerResponse | void>;\n\n/** An OpenAPI security requirement, e.g. `{ bearerAuth: [] }`. */\nexport type SecurityRequirement = Record<string, string[]>;\n\nexport interface MiddlewareOpenApi {\n /** Security requirements this middleware enforces */\n security?: SecurityRequirement[];\n /** Optional scheme definitions, merged into `components.securitySchemes` so the doc is self-contained. */\n securitySchemes?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface MiddlewareOptions {\n openapi?: MiddlewareOpenApi;\n}\n\nexport interface Middleware<\n Params extends Record<string, string> = Record<string, string>,\n Input extends ValidatedInput = ValidatedInput,\n Vars extends Record<string, unknown> = {},\n> {\n (c: Context<Params, Input, Vars>, next: Next): HandlerResponse | void | Promise<HandlerResponse | void>;\n openapi?: MiddlewareOpenApi;\n}\n\n/** The context vars a middleware injects (its `Vars` type parameter). */\nexport type VarsOf<M> = M extends Middleware<Record<string, string>, ValidatedInput, infer V>\n ? V\n : {};\n\n/** Intersect the injected vars of a tuple of middleware (built with `stack(...)`). */\nexport type MergeStack<T> = T extends readonly [infer Head, ...infer Rest]\n ? VarsOf<Head> & MergeStack<Rest>\n : {};\n\n/**\n * Merge the vars from a middleware stack export. A plain `Middleware[]` (not a `stack(...)` tuple)\n */\nexport type InferStackVars<T> = T extends readonly [unknown, ...unknown[]] ? MergeStack<T> : {};\n\n/**\n * The vars injected by a module own `middleware` export (a `stack(...)`). Used by the\n * generated per-method handle so a verb file's own `export const middleware` types\n * `c.get`/`c.set`, on top of the folder's `+shared.ts` chain.\n */\nexport type MiddlewareVarsOf<M> = M extends { middleware: infer Stack }\n ? InferStackVars<Stack>\n : {};\n\n/** A JSON Schema object (JSON Schema 2020-12 / OpenAPI 3.1 dialect). */\nexport type JsonSchema = Record<string, unknown>;\n\nexport const inputSchemaBrand: unique symbol = Symbol.for('giri.input-schema') as never;\n\nexport type InputValidationResult<Output = unknown> =\n | { ok: true; value: Output }\n | { ok: false; issues: unknown };\n\n/**\n * A input schema every wrapper form (`body`/`query`) export takes. A vendor\n * adapter (`@boon4681/giri/validators/zod`, `@boon4681/giri/validators/valibot`, …) returns one; build a\n * custom one with `defineInputSchema`. giri core depends only on this interface, never\n * on a validator library. `validate` is the runtime check; `toJsonSchema` feeds OpenAPI.\n */\nexport interface GiriInputSchema<Output = unknown> {\n readonly [inputSchemaBrand]: true;\n validate(value: unknown): InputValidationResult<Output> | Promise<InputValidationResult<Output>>;\n toJsonSchema(): JsonSchema;\n}\n\n/** Extract the validated output type of a giri input schema: `Infer<typeof body>`. */\nexport type Infer<T> = T extends GiriInputSchema<infer Output> ? Output : never;\n\nexport type BodyContentType = 'json' | 'form' | 'urlencoded' | 'text';\n\nexport const bodySchemaBrand: unique symbol = Symbol.for('giri.body-schema') as never;\n\n/**\n * A request body declared as a set of accepted content-types wrapped form `body`\n * takes (`zod.body({ json, form })`). One key means that encoding only; several mean the\n * endpoint accepts any of them, dispatched at runtime on the request `Content-Type`.\n * Each entry is a plain `GiriInputSchema`, so `validate`/`toJsonSchema` work per content-type.\n */\nexport interface GiriBodySchema<\n Outputs extends Partial<Record<BodyContentType, unknown>> = Partial<Record<BodyContentType, unknown>>,\n> {\n readonly [bodySchemaBrand]: true;\n readonly contents: { [K in keyof Outputs & BodyContentType]: GiriInputSchema<Outputs[K]> };\n}\n\n/** True when `T` is a union of more than one member. */\ntype IsUnion<T, U = T> = T extends unknown ? ([U] extends [T] ? false : true) : never;\n\n/**\n * The validated body a handler receives. A single declared content-type yields that\n * schema's output directly; several yield a discriminated union keyed by content-type.\n */\nexport type ValidBody<B> = B extends GiriBodySchema<infer Outputs>\n ? IsUnion<keyof Outputs> extends true\n ? { [K in keyof Outputs]: { type: K; data: Outputs[K] } }[keyof Outputs]\n : Outputs[keyof Outputs]\n : never;\n\n/** The validated query a handler receives. */\nexport type ValidQuery<Q> = Q extends GiriInputSchema<infer Output> ? Output : never;\n\n/** Drop keys whose value resolved to `never` (an input the route didn't declare). */\ntype PruneNever<T> = { [K in keyof T as [T[K]] extends [never] ? never : K]: T[K] };\n\n/**\n * Derive a route's `ValidatedInput` from a module's `body`/`query` exports. The generated\n * per-method `$types` handle (`POST`, `GET`, …) uses this so handlers infer `c.req.valid`\n * with no manual generic.\n */\nexport type RouteInputOf<M> = PruneNever<{\n body: M extends { body: infer B } ? ValidBody<B> : never;\n query: M extends { query: infer Q } ? ValidQuery<Q> : never;\n}>;\n\nexport interface RouteInput {\n body?: GiriBodySchema;\n query?: GiriInputSchema;\n}\n\nexport interface RouteOpenApi {\n /** Omit this route from the generated `openapi.json` (it still serves normally). */\n hidden?: boolean;\n // Room to grow: summary, description, tags, deprecated, operationId, …\n}\n\nexport type RouteOpenApiConfig = RouteOpenApi | boolean;\n\nexport interface GiriRouteRegistration {\n method: HttpMethod;\n path: string;\n handle: Handle;\n middleware: Middleware[];\n input?: RouteInput;\n /** App-wide services to seed onto `c.app` (same instance for every route). */\n services?: Services;\n}\n\nexport type GiriFetchHandler = (req: Request) => Response | Promise<Response>;\n\nexport interface GiriServeOptions {\n port: number;\n hostname?: string;\n}\n\nexport interface GiriServerInfo {\n address: string;\n port: number;\n}\n\nexport interface GiriServer {\n close(): void | Promise<void>;\n}\n\nexport interface GiriAdapter<App> {\n name?: string;\n createApp(): App;\n register(app: App, route: GiriRouteRegistration): void;\n fetch(app: App, req: Request): Promise<Response>;\n /**\n * Bind the configured backend's runtime to a port and start serving.\n * giri core stays runtime-agnostic: it hands the adapter a request handler\n * (so hot-reload keeps working) and the adapter owns the actual server.\n */\n serve(\n handler: GiriFetchHandler,\n options: GiriServeOptions,\n onListen?: (info: GiriServerInfo) => void,\n ): GiriServer;\n}\n\nexport interface GiriConfig<App = unknown> {\n adapter: GiriAdapter<App>;\n alias?: Record<string, string | string[]>;\n outDir?: string;\n server?: {\n port?: number;\n hostname?: string;\n };\n errorSchema?: unknown;\n}\n\nexport interface GiriPaths {\n cwd: string;\n routesDir: string;\n outDir: string;\n}\n","import {\n type BodyContentType,\n type GiriBodySchema,\n type GiriInputSchema,\n type InputValidationResult,\n type RouteInput,\n type TypedResponse,\n type ValidatedInput,\n bodySchemaBrand,\n inputSchemaBrand,\n} from './types';\nimport { createTypedResponse } from './context';\n\ninterface PreparedInput {\n ok: true;\n validated: ValidatedInput;\n}\n\ninterface FailedInput {\n ok: false;\n response: TypedResponse<{ message: string; issues: unknown }, 400 | 415, 'json'>;\n}\n\nexport type PreparedRequestInput = PreparedInput | FailedInput;\n\n/**\n * Build a giri input schema from a `validate` + `toJsonSchema` pair. Vendor adapters use\n * this; you can call it directly to make a custom validator. The brand is a global symbol,\n * so a hand-rolled `{ [Symbol.for(\"giri.input-schema\")]: true, validate, toJsonSchema }` works too.\n */\nexport function defineInputSchema<Output>(\n schema: Omit<GiriInputSchema<Output>, typeof inputSchemaBrand>,\n): GiriInputSchema<Output> {\n return { [inputSchemaBrand]: true, ...schema };\n}\n\nexport function isGiriInputSchema(value: unknown): value is GiriInputSchema {\n return Boolean(\n value &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[inputSchemaBrand] === true,\n );\n}\n\n/**\n * Build a giri body schema from per-content-type input schemas. Validator adapters use this `zod.body({ json, form })`\n */\nexport function defineBodySchema<Outputs extends Partial<Record<BodyContentType, unknown>>>(\n contents: GiriBodySchema<Outputs>['contents'],\n): GiriBodySchema<Outputs> {\n return { [bodySchemaBrand]: true, contents };\n}\n\nexport function isGiriBodySchema(value: unknown): value is GiriBodySchema {\n return Boolean(\n value &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[bodySchemaBrand] === true,\n );\n}\n\nconst MIME_TO_CONTENT_TYPE: Record<string, BodyContentType> = {\n 'application/json': 'json',\n 'multipart/form-data': 'form',\n 'application/x-www-form-urlencoded': 'urlencoded',\n 'text/plain': 'text',\n};\n\nfunction contentTypeFromHeader(header: string | null): BodyContentType | undefined {\n if (!header) {\n return undefined;\n }\n const mime = header.split(';', 1)[0].trim().toLowerCase();\n return MIME_TO_CONTENT_TYPE[mime];\n}\n\n/** Flatten a `FormData` into a plain object, collapsing repeated fields into arrays. */\nfunction formDataObject(form: FormData): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n form.forEach((value, key) => {\n const current = result[key];\n if (current === undefined) {\n result[key] = value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n result[key] = [current, value];\n }\n });\n return result;\n}\n\nasync function readRawBody(request: Request, contentType: BodyContentType): Promise<unknown> {\n const cloned = request.clone();\n if (contentType === 'json') {\n return cloned.json();\n }\n if (contentType === 'text') {\n return cloned.text();\n }\n return formDataObject(await cloned.formData());\n}\n\nfunction queryObject(url: URL): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of url.searchParams) {\n const current = result[key];\n if (current === undefined) {\n result[key] = value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n result[key] = [current, value];\n }\n }\n return result;\n}\n\nasync function runValidation(\n schema: GiriInputSchema,\n value: unknown,\n label: string,\n): Promise<InputValidationResult> {\n if (!isGiriInputSchema(schema)) {\n throw new Error(\n `giri: ${label} schema must be wrapped with a validator, e.g. \\`export const ${label} = zod(...)\\` from @boon4681/giri/validators/zod.`,\n );\n }\n return schema.validate(value);\n}\n\nexport async function prepareRequestInput(request: Request, input?: RouteInput): Promise<PreparedRequestInput> {\n const validated: ValidatedInput = {};\n\n if (input?.query) {\n const query = queryObject(new URL(request.url));\n const result = await runValidation(input.query, query, 'query');\n if (!result.ok) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid query parameters.', issues: result.issues },\n 400,\n 'json',\n ),\n };\n }\n validated.query = result.value;\n }\n\n if (input?.body) {\n const contents = input.body.contents as Record<BodyContentType, GiriInputSchema>;\n const declared = Object.keys(contents) as BodyContentType[];\n const requested = contentTypeFromHeader(request.headers.get('content-type'));\n // Pick the schema matching the request's content-type; fall back to JSON when the\n // header is missing/unrecognized but JSON is on offer (so header-less posts still work).\n const chosen: BodyContentType | undefined =\n requested && contents[requested] ? requested : contents.json ? 'json' : undefined;\n\n if (!chosen) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Unsupported media type.', issues: { accepted: declared } },\n 415,\n 'json',\n ),\n };\n }\n\n let rawBody: unknown;\n try {\n rawBody = await readRawBody(request, chosen);\n } catch (error) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid request body.', issues: error },\n 400,\n 'json',\n ),\n };\n }\n\n const result = await runValidation(contents[chosen], rawBody, 'body');\n if (!result.ok) {\n return {\n ok: false,\n response: createTypedResponse(\n { message: 'Invalid request body.', issues: result.issues },\n 400,\n 'json',\n ),\n };\n }\n\n validated.body = declared.length > 1 ? { type: chosen, data: result.value } : result.value;\n }\n\n return { ok: true, validated };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAkB;;;AC+JX,IAAM,mBAAkC,uBAAO,IAAI,mBAAmB;AAuBtE,IAAM,kBAAiC,uBAAO,IAAI,kBAAkB;;;ACxJpE,SAAS,kBACZ,QACuB;AACvB,SAAO,EAAE,CAAC,gBAAgB,GAAG,MAAM,GAAG,OAAO;AACjD;AAaO,SAAS,iBACZ,UACuB;AACvB,SAAO,EAAE,CAAC,eAAe,GAAG,MAAM,SAAS;AAC/C;;;AF9CA,SAAS,KAA+B,QAAkD;AACtF,SAAO,kBAAmC;AAAA,IACtC,SAAS,OAAO;AACZ,YAAM,SAAS,OAAO,UAAU,KAAK;AACrC,aAAO,OAAO,UACR,EAAE,IAAI,MAAM,OAAO,OAAO,KAAK,IAC/B,EAAE,IAAI,OAAO,QAAQ,OAAO,MAAM;AAAA,IAC5C;AAAA,IACA,eAAe;AACX,aAAO,aAAE,aAAa,MAAM;AAAA,IAChC;AAAA,EACJ,CAAC;AACL;AAmBO,IAAM,MAAM;AAAA,EACf,KACI,KACwF;AACxF,UAAM,WAAW,CAAC;AAClB,eAAW,CAAC,aAAa,MAAM,KAAK,OAAO,QAAQ,GAAG,GAAG;AACrD,UAAI,QAAQ;AACR,iBAAS,WAA8B,IAAI,KAAK,MAAM;AAAA,MAC1D;AAAA,IACJ;AACA,WAAO,iBAAiB,QAAQ;AAAA,EAGpC;AAAA,EACA,MAAgC,QAAkD;AAC9E,WAAO,KAAK,MAAM;AAAA,EACtB;AACJ;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@boon4681/giri",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"giri": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./hono": {
|
|
16
|
+
"types": "./dist/adapters/hono.d.ts",
|
|
17
|
+
"default": "./dist/adapters/hono.js"
|
|
18
|
+
},
|
|
19
|
+
"./adapters/hono": {
|
|
20
|
+
"types": "./dist/adapters/hono.d.ts",
|
|
21
|
+
"default": "./dist/adapters/hono.js"
|
|
22
|
+
},
|
|
23
|
+
"./validators/zod": {
|
|
24
|
+
"types": "./dist/validators/zod.d.ts",
|
|
25
|
+
"default": "./dist/validators/zod.js"
|
|
26
|
+
},
|
|
27
|
+
"./validators/valibot": {
|
|
28
|
+
"types": "./dist/validators/valibot.d.ts",
|
|
29
|
+
"default": "./dist/validators/valibot.js"
|
|
30
|
+
},
|
|
31
|
+
"./tsc": {
|
|
32
|
+
"types": "./dist/typescript-plugin.d.ts",
|
|
33
|
+
"require": "./dist/typescript-plugin.js",
|
|
34
|
+
"default": "./dist/typescript-plugin.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsx ./build.ts",
|
|
42
|
+
"test": "vitest --run",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@clack/prompts": "^1.5.1",
|
|
47
|
+
"@hono/standard-validator": "^0.2.1",
|
|
48
|
+
"@sinclair/typebox": "^0.34.49",
|
|
49
|
+
"esbuild": "^0.27.7",
|
|
50
|
+
"esbuild-register": "^3.6.0",
|
|
51
|
+
"openapi-types": "^12.1.3",
|
|
52
|
+
"tinyglobby": "^0.2.16"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@hono/node-server": "^2.0.3",
|
|
56
|
+
"@types/node": "^25.9.1",
|
|
57
|
+
"@valibot/to-json-schema": "^1.7.0",
|
|
58
|
+
"hono": "^4.12.18",
|
|
59
|
+
"tsup": "^8.4.0",
|
|
60
|
+
"tsx": "^4.22.4",
|
|
61
|
+
"typescript": "^5.8.3",
|
|
62
|
+
"valibot": "^1.4.1",
|
|
63
|
+
"vite-node": "^3.2.4",
|
|
64
|
+
"vitest": "^3.2.0",
|
|
65
|
+
"zod": "^4.4.3"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"@hono/node-server": "^2.0.0",
|
|
69
|
+
"@valibot/to-json-schema": "^1.0.0",
|
|
70
|
+
"hono": "^4.12.0",
|
|
71
|
+
"typescript": ">=5.4",
|
|
72
|
+
"valibot": "^1.0.0",
|
|
73
|
+
"zod": "^4.0.0"
|
|
74
|
+
},
|
|
75
|
+
"peerDependenciesMeta": {
|
|
76
|
+
"@hono/node-server": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@valibot/to-json-schema": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"hono": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"valibot": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"zod": {
|
|
89
|
+
"optional": true
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
|
|
93
|
+
}
|