@nooh-ts/nooh 0.1.1 → 0.2.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/dist/index.d.mts CHANGED
@@ -1,21 +1,118 @@
1
+ import { Context, Env } from "hono";
2
+ import { HTTPResponseError, HandlerResponse } from "hono/types";
3
+ //#region src/errors.d.ts
4
+ type ErrorConstructor = new (...args: any[]) => Error;
5
+ type ErrorFactory<Constructor extends ErrorConstructor> = (...args: ConstructorParameters<Constructor>) => InstanceType<Constructor>;
6
+ type ErrorContext<Errors extends Record<string, ErrorConstructor>> = { readonly [Name in keyof Errors]: ErrorFactory<Errors[Name]>; };
7
+ type NoohErrorHandler<Environment extends Env = Env, Path extends string = string> = (error: Error | HTTPResponseError, c: Context<Environment, Path>) => HandlerResponse<unknown>;
8
+ //#endregion
9
+ //#region src/validation.d.ts
10
+ type NoohRequestValidationTarget = "json" | "form" | "query" | "param" | "header" | "cookie";
11
+ type NoohValidationTarget = NoohRequestValidationTarget | "response";
12
+ interface NoohStandardSchema {
13
+ readonly "~standard": {
14
+ readonly validate: (value: never, ...args: never[]) => unknown;
15
+ readonly types?: {
16
+ readonly input?: unknown;
17
+ readonly output?: unknown;
18
+ };
19
+ };
20
+ }
21
+ type NoohStandardSchemaInput<Schema extends NoohStandardSchema> = Schema["~standard"]["types"] extends {
22
+ readonly input?: infer Input;
23
+ } ? Input : unknown;
24
+ type NoohStandardSchemaOutput<Schema extends NoohStandardSchema> = Schema["~standard"]["types"] extends {
25
+ readonly output?: infer Output;
26
+ } ? Output : NoohStandardSchemaInput<Schema>;
27
+ type NoohValidatorEngine = (...args: never[]) => unknown;
28
+ interface NoohValidatorOptions {
29
+ readonly engine?: NoohValidatorEngine;
30
+ }
31
+ //#endregion
1
32
  //#region src/config.d.ts
2
- interface NoohConfigOptions {
33
+ interface NoohConfigOptions<Environment extends Env = Env> {
34
+ readonly dependencies?: string;
35
+ readonly onError?: NoohErrorHandler<Environment>;
3
36
  readonly routes?: string;
37
+ readonly validator?: NoohValidatorOptions;
4
38
  }
5
- interface NoohConfig<Environment> extends NoohConfigOptions {
39
+ interface NoohConfig<Environment extends Env = Env> extends NoohConfigOptions<Environment> {
6
40
  readonly __nooh_env: Environment;
7
41
  }
8
42
  type ConfigEnvironment<T> = T extends {
9
43
  readonly __nooh_env: infer Environment;
10
44
  } ? Environment : never;
11
- interface NoohGroupOptions<Middleware = unknown> {
45
+ interface NoohGroupOptions<Environment extends Env = Env, Middleware = unknown> {
12
46
  readonly middleware?: readonly Middleware[];
47
+ readonly onError?: NoohErrorHandler<Environment>;
13
48
  }
14
- interface NoohGroup<Middleware = unknown> {
49
+ interface NoohGroup<Environment extends Env = Env, Middleware = unknown> {
15
50
  readonly middleware?: readonly Middleware[];
51
+ readonly onError?: NoohErrorHandler<Environment>;
52
+ }
53
+ export declare const config: <Environment extends Env>(options?: NoohConfigOptions<Environment>) => NoohConfig<Environment>;
54
+ export declare const group: <Environment extends Env = Env, Middleware = unknown>(options?: NoohGroupOptions<Environment, Middleware>) => NoohGroup<Environment, Middleware>;
55
+ //#endregion
56
+ //#region src/di.d.ts
57
+ type DependencyScope = "singleton" | "request" | "transient" | "value";
58
+ interface DependencyResolutionContext {
59
+ readonly cache: Map<object, unknown>;
60
+ readonly resolving: Set<object>;
61
+ readonly stack: string[];
62
+ }
63
+ export declare class DependencyCycleError extends Error {
64
+ readonly path: readonly string[];
65
+ constructor(path: readonly string[]);
66
+ }
67
+ interface DependencyDefinition<Value, Scope extends DependencyScope = DependencyScope, Dependencies extends readonly AnyDependencyReference[] = readonly []> {
68
+ readonly __nooh_definition: true;
69
+ readonly dependencies: Dependencies;
70
+ readonly factory: (dependencies: DependencyContext<Dependencies>) => Value;
71
+ readonly scope: Scope;
72
+ }
73
+ interface DependencyReference<Name extends string, Value, Scope extends DependencyScope = DependencyScope, Dependencies extends readonly AnyDependencyReference[] = readonly []> {
74
+ readonly __nooh_dependency: true;
75
+ readonly dependencies: Dependencies;
76
+ readonly name: Name;
77
+ readonly resolve: (context: DependencyResolutionContext) => Value;
78
+ readonly scope: Scope;
79
+ }
80
+ type AnyDependencyReference = DependencyReference<string, unknown, DependencyScope, readonly AnyDependencyReference[]>;
81
+ type AnyDependencyDefinition = DependencyDefinition<unknown, DependencyScope, readonly AnyDependencyReference[]>;
82
+ type DependencyEntry = AnyDependencyDefinition | (() => unknown);
83
+ type DefinitionValue<T> = T extends DependencyDefinition<infer Value, DependencyScope, readonly AnyDependencyReference[]> ? Value : T extends (() => infer Value) ? Value : never;
84
+ type DefinitionScope<T> = T extends DependencyDefinition<unknown, infer Scope, readonly AnyDependencyReference[]> ? Scope : T extends (() => unknown) ? "singleton" : never;
85
+ type DefinitionDependencies<T> = T extends DependencyDefinition<unknown, DependencyScope, infer Dependencies> ? Dependencies : T extends (() => unknown) ? readonly [] : never;
86
+ type Container<Entries extends Record<string, DependencyEntry>> = { readonly [Key in keyof Entries & string]: DependencyReference<Key, DefinitionValue<Entries[Key]>, DefinitionScope<Entries[Key]>, DefinitionDependencies<Entries[Key]>>; };
87
+ interface DependencyFactoryOptions<Scope extends DependencyScope, Dependencies extends readonly AnyDependencyReference[], Value> {
88
+ readonly deps: Dependencies & ValidateDependencyScopes<Scope, Dependencies>;
89
+ readonly factory: (dependencies: DependencyContext<Dependencies>) => Value;
90
+ }
91
+ type CanDependOn<Parent extends DependencyScope, Child extends DependencyScope> = Parent extends "singleton" ? Child extends "singleton" | "value" ? true : false : Parent extends "request" ? Child extends "singleton" | "request" | "transient" | "value" ? true : false : Parent extends "transient" ? true : Child extends "value" ? true : false;
92
+ interface InvalidDependencyScope<Parent extends DependencyScope, Child extends DependencyScope> {
93
+ readonly __nooh_dependency_error__: `A ${Parent} dependency cannot depend on a ${Child} dependency.`;
94
+ }
95
+ type ValidateDependencyScopesImpl<Parent extends DependencyScope, Dependencies extends readonly AnyDependencyReference[]> = Dependencies extends readonly [infer Head, ...infer Tail] ? Head extends AnyDependencyReference ? Head extends DependencyReference<string, unknown, infer ChildScope, readonly AnyDependencyReference[]> ? CanDependOn<Parent, ChildScope> extends true ? readonly [Head, ...ValidateDependencyScopesImpl<Parent, Tail extends readonly AnyDependencyReference[] ? Tail : []>] : readonly [Head & InvalidDependencyScope<Parent, ChildScope>, ...ValidateDependencyScopesImpl<Parent, Tail extends readonly AnyDependencyReference[] ? Tail : []>] : Dependencies : Dependencies : Dependencies;
96
+ type ValidateDependencyScopes<Parent extends DependencyScope, Dependencies extends readonly AnyDependencyReference[]> = ValidateDependencyScopesImpl<Parent, Dependencies>;
97
+ export declare function singleton<Value>(factory: () => Value): DependencyDefinition<Value, "singleton", readonly []>;
98
+ export declare function singleton<const Dependencies extends readonly AnyDependencyReference[], Value>(options: DependencyFactoryOptions<"singleton", Dependencies, Value>): DependencyDefinition<Value, "singleton", Dependencies>;
99
+ export declare function request<Value>(factory: () => Value): DependencyDefinition<Value, "request", readonly []>;
100
+ export declare function request<const Dependencies extends readonly AnyDependencyReference[], Value>(options: DependencyFactoryOptions<"request", Dependencies, Value>): DependencyDefinition<Value, "request", Dependencies>;
101
+ export declare function transient<Value>(factory: () => Value): DependencyDefinition<Value, "transient", readonly []>;
102
+ export declare function transient<const Dependencies extends readonly AnyDependencyReference[], Value>(options: DependencyFactoryOptions<"transient", Dependencies, Value>): DependencyDefinition<Value, "transient", Dependencies>;
103
+ export declare const value: <Value>(input: Value) => DependencyDefinition<Value, "value", readonly []>;
104
+ export declare const container: <const Entries extends Record<string, DependencyEntry>>(entries: Entries) => Container<Entries>;
105
+ type DependencyName<Dependency> = Dependency extends DependencyReference<infer Name, unknown, DependencyScope, readonly AnyDependencyReference[]> ? Name : never;
106
+ type DependencyValue<Dependency> = Dependency extends DependencyReference<string, infer Value, DependencyScope, readonly AnyDependencyReference[]> ? Value : never;
107
+ type DependencyContext<Dependencies extends readonly AnyDependencyReference[]> = { [Dependency in Dependencies[number] as DependencyName<Dependency>]: DependencyValue<Dependency>; };
108
+ interface DuplicateDependency<Name extends string> {
109
+ readonly __nooh_dependency_error__: `Duplicate dependency name "${Name}".`;
110
+ }
111
+ interface ReservedDependencyName<Name extends string> {
112
+ readonly __nooh_dependency_error__: `Dependency name "${Name}" is reserved by the handler context.`;
16
113
  }
17
- export declare const config: <Environment>(options?: NoohConfigOptions) => NoohConfig<Environment>;
18
- export declare const group: <Middleware = unknown>(options?: NoohGroupOptions<Middleware>) => NoohGroup<Middleware>;
114
+ type ValidateDependenciesImpl<Dependencies extends readonly AnyDependencyReference[], Reserved extends string, Seen extends string = never> = Dependencies extends readonly [infer Head, ...infer Tail] ? Head extends AnyDependencyReference ? DependencyName<Head> extends (infer Name) ? Name extends string ? Name extends Reserved ? readonly [Head & ReservedDependencyName<Name>, ...ValidateDependenciesImpl<Tail extends readonly AnyDependencyReference[] ? Tail : [], Reserved, Seen>] : Name extends Seen ? readonly [Head & DuplicateDependency<Name>, ...ValidateDependenciesImpl<Tail extends readonly AnyDependencyReference[] ? Tail : [], Reserved, Seen>] : readonly [Head, ...ValidateDependenciesImpl<Tail extends readonly AnyDependencyReference[] ? Tail : [], Reserved, Seen | Name>] : Dependencies : Dependencies : Dependencies : Dependencies;
115
+ type ValidateDependencies<Dependencies extends readonly AnyDependencyReference[], Reserved extends string = never> = ValidateDependenciesImpl<Dependencies, Reserved>;
19
116
  //#endregion
20
- export type { ConfigEnvironment, NoohConfig, NoohConfigOptions, NoohGroup, NoohGroupOptions };
117
+ export type { AnyDependencyReference, ConfigEnvironment, Container, DependencyContext, DependencyDefinition, DependencyEntry, DependencyName, DependencyReference, DependencyResolutionContext, DependencyScope, DependencyValue, DuplicateDependency, ErrorConstructor, ErrorContext, ErrorFactory, InvalidDependencyScope, NoohConfig, NoohConfigOptions, NoohErrorHandler, NoohGroup, NoohGroupOptions, NoohRequestValidationTarget, NoohStandardSchema, NoohStandardSchemaInput, NoohStandardSchemaOutput, NoohValidationTarget, NoohValidatorEngine, NoohValidatorOptions, ReservedDependencyName, ValidateDependencies, ValidateDependencyScopes };
21
118
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config.ts"],"mappings":";UAAiB;WACN;;UAGM,WAAW,qBAAqB;WACtC,YAAY;;KAGX,kBAAkB,KAAK;WACxB,kBAAkB;IAEzB;UAGa,iBAAiB;WACvB,sBAAsB;;UAGhB,UAAU;WAChB,sBAAsB;;qBAGpB,SAAU,aACrB,UAAS,sBACR,WAAW;qBAED,QAAS,sBACpB,UAAS,iBAAiB,gBACzB,UAAU"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/validation.ts","../src/config.ts","../src/di.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -2,6 +2,92 @@
2
2
  const config = (options = {}) => options;
3
3
  const group = (options = {}) => options;
4
4
  //#endregion
5
- export { config, group };
5
+ //#region src/di.ts
6
+ var DependencyCycleError = class extends Error {
7
+ path;
8
+ constructor(path) {
9
+ super(`Circular dependency detected: ${path.join(" -> ")}.`);
10
+ this.name = "DependencyCycleError";
11
+ this.path = path;
12
+ }
13
+ };
14
+ const createDefinition = (scope, dependencies, factory) => ({
15
+ __nooh_definition: true,
16
+ dependencies,
17
+ factory,
18
+ scope
19
+ });
20
+ function singleton(input) {
21
+ if (typeof input === "function") return createDefinition("singleton", [], () => input());
22
+ return createDefinition("singleton", input.deps, input.factory);
23
+ }
24
+ function request(input) {
25
+ if (typeof input === "function") return createDefinition("request", [], () => input());
26
+ return createDefinition("request", input.deps, input.factory);
27
+ }
28
+ function transient(input) {
29
+ if (typeof input === "function") return createDefinition("transient", [], () => input());
30
+ return createDefinition("transient", input.deps, input.factory);
31
+ }
32
+ const value = (input) => createDefinition("value", [], () => input);
33
+ const resolveDependencies = (dependencies, context) => {
34
+ const resolved = Object.create(null);
35
+ for (const dependency of dependencies) resolved[dependency.name] = dependency.resolve(context);
36
+ return resolved;
37
+ };
38
+ const resolveReference = (reference, definition, context) => {
39
+ if (context.resolving.has(reference)) {
40
+ const start = context.stack.indexOf(reference.name);
41
+ throw new DependencyCycleError(start === -1 ? [...context.stack, reference.name] : [...context.stack.slice(start), reference.name]);
42
+ }
43
+ context.resolving.add(reference);
44
+ context.stack.push(reference.name);
45
+ try {
46
+ return definition.factory(resolveDependencies(definition.dependencies, context));
47
+ } finally {
48
+ context.stack.pop();
49
+ context.resolving.delete(reference);
50
+ }
51
+ };
52
+ const createReference = (name, definition) => {
53
+ let singletonInitialized = false;
54
+ let singletonValue;
55
+ let reference;
56
+ reference = Object.freeze({
57
+ __nooh_dependency: true,
58
+ dependencies: definition.dependencies,
59
+ name,
60
+ resolve: (context) => {
61
+ if (definition.scope === "singleton") {
62
+ if (!singletonInitialized) {
63
+ singletonValue = resolveReference(reference, definition, context);
64
+ singletonInitialized = true;
65
+ }
66
+ return singletonValue;
67
+ }
68
+ if (definition.scope === "request") {
69
+ if (context.cache.has(reference)) return context.cache.get(reference);
70
+ const resolved = resolveReference(reference, definition, context);
71
+ context.cache.set(reference, resolved);
72
+ return resolved;
73
+ }
74
+ return resolveReference(reference, definition, context);
75
+ },
76
+ scope: definition.scope
77
+ });
78
+ return reference;
79
+ };
80
+ const container = (entries) => {
81
+ const result = Object.create(null);
82
+ const keys = Object.keys(entries);
83
+ for (const name of keys) {
84
+ const entry = entries[name];
85
+ const definition = typeof entry === "function" ? singleton(entry) : entry;
86
+ result[name] = createReference(name, definition);
87
+ }
88
+ return Object.freeze(result);
89
+ };
90
+ //#endregion
91
+ export { DependencyCycleError, config, container, group, request, singleton, transient, value };
6
92
 
7
93
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["export interface NoohConfigOptions {\n readonly routes?: string;\n}\n\nexport interface NoohConfig<Environment> extends NoohConfigOptions {\n readonly __nooh_env: Environment;\n}\n\nexport type ConfigEnvironment<T> = T extends {\n readonly __nooh_env: infer Environment;\n}\n ? Environment\n : never;\n\nexport interface NoohGroupOptions<Middleware = unknown> {\n readonly middleware?: readonly Middleware[];\n}\n\nexport interface NoohGroup<Middleware = unknown> {\n readonly middleware?: readonly Middleware[];\n}\n\nexport const config = <Environment>(\n options: NoohConfigOptions = {}\n): NoohConfig<Environment> => options as NoohConfig<Environment>;\n\nexport const group = <Middleware = unknown>(\n options: NoohGroupOptions<Middleware> = {}\n): NoohGroup<Middleware> => options;\n"],"mappings":";AAsBA,MAAa,UACX,UAA6B,CAAC,MACF;AAE9B,MAAa,SACX,UAAwC,CAAC,MACf"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/config.ts","../src/di.ts"],"sourcesContent":["import type { Env } from \"hono\";\n\nimport type { NoohErrorHandler } from \"@/errors\";\nimport type { NoohValidatorOptions } from \"@/validation\";\n\nexport interface NoohConfigOptions<Environment extends Env = Env> {\n readonly dependencies?: string;\n readonly onError?: NoohErrorHandler<Environment>;\n readonly routes?: string;\n readonly validator?: NoohValidatorOptions;\n}\n\nexport interface NoohConfig<Environment extends Env = Env>\n extends NoohConfigOptions<Environment> {\n readonly __nooh_env: Environment;\n}\n\nexport type ConfigEnvironment<T> = T extends {\n readonly __nooh_env: infer Environment;\n}\n ? Environment\n : never;\n\nexport interface NoohGroupOptions<\n Environment extends Env = Env,\n Middleware = unknown,\n> {\n readonly middleware?: readonly Middleware[];\n readonly onError?: NoohErrorHandler<Environment>;\n}\n\nexport interface NoohGroup<\n Environment extends Env = Env,\n Middleware = unknown,\n> {\n readonly middleware?: readonly Middleware[];\n readonly onError?: NoohErrorHandler<Environment>;\n}\n\nexport const config = <Environment extends Env>(\n options: NoohConfigOptions<Environment> = {}\n): NoohConfig<Environment> => options as NoohConfig<Environment>;\n\nexport const group = <Environment extends Env = Env, Middleware = unknown>(\n options: NoohGroupOptions<Environment, Middleware> = {}\n): NoohGroup<Environment, Middleware> => options;\n","export type DependencyScope = \"singleton\" | \"request\" | \"transient\" | \"value\";\n\nexport interface DependencyResolutionContext {\n readonly cache: Map<object, unknown>;\n readonly resolving: Set<object>;\n readonly stack: string[];\n}\n\nexport class DependencyCycleError extends Error {\n readonly path: readonly string[];\n\n constructor(path: readonly string[]) {\n super(`Circular dependency detected: ${path.join(\" -> \")}.`);\n\n this.name = \"DependencyCycleError\";\n this.path = path;\n }\n}\n\nexport interface DependencyDefinition<\n Value,\n Scope extends DependencyScope = DependencyScope,\n Dependencies extends readonly AnyDependencyReference[] = readonly [],\n> {\n readonly __nooh_definition: true;\n readonly dependencies: Dependencies;\n readonly factory: (dependencies: DependencyContext<Dependencies>) => Value;\n readonly scope: Scope;\n}\n\nexport interface DependencyReference<\n Name extends string,\n Value,\n Scope extends DependencyScope = DependencyScope,\n Dependencies extends readonly AnyDependencyReference[] = readonly [],\n> {\n readonly __nooh_dependency: true;\n readonly dependencies: Dependencies;\n readonly name: Name;\n readonly resolve: (context: DependencyResolutionContext) => Value;\n readonly scope: Scope;\n}\n\nexport type AnyDependencyReference = DependencyReference<\n string,\n unknown,\n DependencyScope,\n readonly AnyDependencyReference[]\n>;\n\ntype AnyDependencyDefinition = DependencyDefinition<\n unknown,\n DependencyScope,\n readonly AnyDependencyReference[]\n>;\n\nexport type DependencyEntry = AnyDependencyDefinition | (() => unknown);\n\ntype DefinitionValue<T> =\n T extends DependencyDefinition<\n infer Value,\n DependencyScope,\n readonly AnyDependencyReference[]\n >\n ? Value\n : T extends () => infer Value\n ? Value\n : never;\n\ntype DefinitionScope<T> =\n T extends DependencyDefinition<\n unknown,\n infer Scope,\n readonly AnyDependencyReference[]\n >\n ? Scope\n : T extends () => unknown\n ? \"singleton\"\n : never;\n\ntype DefinitionDependencies<T> =\n T extends DependencyDefinition<unknown, DependencyScope, infer Dependencies>\n ? Dependencies\n : T extends () => unknown\n ? readonly []\n : never;\n\nexport type Container<Entries extends Record<string, DependencyEntry>> = {\n readonly [Key in keyof Entries & string]: DependencyReference<\n Key,\n DefinitionValue<Entries[Key]>,\n DefinitionScope<Entries[Key]>,\n DefinitionDependencies<Entries[Key]>\n >;\n};\n\ninterface DependencyFactoryOptions<\n Scope extends DependencyScope,\n Dependencies extends readonly AnyDependencyReference[],\n Value,\n> {\n readonly deps: Dependencies & ValidateDependencyScopes<Scope, Dependencies>;\n readonly factory: (dependencies: DependencyContext<Dependencies>) => Value;\n}\n\ntype CanDependOn<\n Parent extends DependencyScope,\n Child extends DependencyScope,\n> = Parent extends \"singleton\"\n ? Child extends \"singleton\" | \"value\"\n ? true\n : false\n : Parent extends \"request\"\n ? Child extends \"singleton\" | \"request\" | \"transient\" | \"value\"\n ? true\n : false\n : Parent extends \"transient\"\n ? true\n : Child extends \"value\"\n ? true\n : false;\n\nexport interface InvalidDependencyScope<\n Parent extends DependencyScope,\n Child extends DependencyScope,\n> {\n readonly __nooh_dependency_error__: `A ${Parent} dependency cannot depend on a ${Child} dependency.`;\n}\n\ntype ValidateDependencyScopesImpl<\n Parent extends DependencyScope,\n Dependencies extends readonly AnyDependencyReference[],\n> = Dependencies extends readonly [infer Head, ...infer Tail]\n ? Head extends AnyDependencyReference\n ? Head extends DependencyReference<\n string,\n unknown,\n infer ChildScope,\n readonly AnyDependencyReference[]\n >\n ? CanDependOn<Parent, ChildScope> extends true\n ? readonly [\n Head,\n ...ValidateDependencyScopesImpl<\n Parent,\n Tail extends readonly AnyDependencyReference[] ? Tail : []\n >,\n ]\n : readonly [\n Head & InvalidDependencyScope<Parent, ChildScope>,\n ...ValidateDependencyScopesImpl<\n Parent,\n Tail extends readonly AnyDependencyReference[] ? Tail : []\n >,\n ]\n : Dependencies\n : Dependencies\n : Dependencies;\n\nexport type ValidateDependencyScopes<\n Parent extends DependencyScope,\n Dependencies extends readonly AnyDependencyReference[],\n> = ValidateDependencyScopesImpl<Parent, Dependencies>;\n\nconst createDefinition = <\n Value,\n Scope extends DependencyScope,\n const Dependencies extends readonly AnyDependencyReference[],\n>(\n scope: Scope,\n dependencies: Dependencies,\n factory: (dependencies: DependencyContext<Dependencies>) => Value\n): DependencyDefinition<Value, Scope, Dependencies> => ({\n __nooh_definition: true,\n dependencies,\n factory,\n scope,\n});\n\nexport function singleton<Value>(\n factory: () => Value\n): DependencyDefinition<Value, \"singleton\", readonly []>;\n\nexport function singleton<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n options: DependencyFactoryOptions<\"singleton\", Dependencies, Value>\n): DependencyDefinition<Value, \"singleton\", Dependencies>;\n\nexport function singleton<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n input:\n | (() => Value)\n | DependencyFactoryOptions<\"singleton\", Dependencies, Value>\n): DependencyDefinition<Value, \"singleton\", Dependencies> {\n if (typeof input === \"function\") {\n return createDefinition(\"singleton\", [], () =>\n input()\n ) as unknown as DependencyDefinition<Value, \"singleton\", Dependencies>;\n }\n\n return createDefinition(\"singleton\", input.deps, input.factory);\n}\n\nexport function request<Value>(\n factory: () => Value\n): DependencyDefinition<Value, \"request\", readonly []>;\n\nexport function request<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n options: DependencyFactoryOptions<\"request\", Dependencies, Value>\n): DependencyDefinition<Value, \"request\", Dependencies>;\n\nexport function request<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n input:\n | (() => Value)\n | DependencyFactoryOptions<\"request\", Dependencies, Value>\n): DependencyDefinition<Value, \"request\", Dependencies> {\n if (typeof input === \"function\") {\n return createDefinition(\"request\", [], () =>\n input()\n ) as unknown as DependencyDefinition<Value, \"request\", Dependencies>;\n }\n\n return createDefinition(\"request\", input.deps, input.factory);\n}\n\nexport function transient<Value>(\n factory: () => Value\n): DependencyDefinition<Value, \"transient\", readonly []>;\n\nexport function transient<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n options: DependencyFactoryOptions<\"transient\", Dependencies, Value>\n): DependencyDefinition<Value, \"transient\", Dependencies>;\n\nexport function transient<\n const Dependencies extends readonly AnyDependencyReference[],\n Value,\n>(\n input:\n | (() => Value)\n | DependencyFactoryOptions<\"transient\", Dependencies, Value>\n): DependencyDefinition<Value, \"transient\", Dependencies> {\n if (typeof input === \"function\") {\n return createDefinition(\"transient\", [], () =>\n input()\n ) as unknown as DependencyDefinition<Value, \"transient\", Dependencies>;\n }\n\n return createDefinition(\"transient\", input.deps, input.factory);\n}\n\nexport const value = <Value>(\n input: Value\n): DependencyDefinition<Value, \"value\", readonly []> =>\n createDefinition(\"value\", [], () => input);\n\nconst resolveDependencies = <\n const Dependencies extends readonly AnyDependencyReference[],\n>(\n dependencies: Dependencies,\n context: DependencyResolutionContext\n): DependencyContext<Dependencies> => {\n const resolved = Object.create(null) as Record<string, unknown>;\n\n for (const dependency of dependencies) {\n resolved[dependency.name] = dependency.resolve(context);\n }\n\n return resolved as DependencyContext<Dependencies>;\n};\n\nconst resolveReference = <\n Name extends string,\n Value,\n Scope extends DependencyScope,\n const Dependencies extends readonly AnyDependencyReference[],\n>(\n reference: DependencyReference<Name, Value, Scope, Dependencies>,\n definition: DependencyDefinition<Value, Scope, Dependencies>,\n context: DependencyResolutionContext\n): Value => {\n if (context.resolving.has(reference)) {\n const start = context.stack.indexOf(reference.name);\n\n const cycle =\n start === -1\n ? [...context.stack, reference.name]\n : [...context.stack.slice(start), reference.name];\n\n throw new DependencyCycleError(cycle);\n }\n\n context.resolving.add(reference);\n context.stack.push(reference.name);\n\n try {\n return definition.factory(\n resolveDependencies(definition.dependencies, context)\n );\n } finally {\n context.stack.pop();\n context.resolving.delete(reference);\n }\n};\n\nconst createReference = <\n Name extends string,\n Value,\n Scope extends DependencyScope,\n const Dependencies extends readonly AnyDependencyReference[],\n>(\n name: Name,\n definition: DependencyDefinition<Value, Scope, Dependencies>\n): DependencyReference<Name, Value, Scope, Dependencies> => {\n let singletonInitialized = false;\n let singletonValue!: Value;\n\n let reference!: DependencyReference<Name, Value, Scope, Dependencies>;\n\n reference = Object.freeze({\n __nooh_dependency: true as const,\n\n dependencies: definition.dependencies,\n\n name,\n\n resolve: (context: DependencyResolutionContext): Value => {\n if (definition.scope === \"singleton\") {\n if (!singletonInitialized) {\n singletonValue = resolveReference(reference, definition, context);\n\n singletonInitialized = true;\n }\n\n return singletonValue;\n }\n\n if (definition.scope === \"request\") {\n if (context.cache.has(reference)) {\n return context.cache.get(reference) as Value;\n }\n\n const resolved = resolveReference(reference, definition, context);\n\n context.cache.set(reference, resolved);\n\n return resolved;\n }\n\n return resolveReference(reference, definition, context);\n },\n\n scope: definition.scope,\n });\n\n return reference;\n};\n\nexport const container = <\n const Entries extends Record<string, DependencyEntry>,\n>(\n entries: Entries\n): Container<Entries> => {\n const result: Record<string, unknown> = Object.create(null);\n\n const keys = Object.keys(entries) as Array<keyof Entries & string>;\n\n for (const name of keys) {\n const entry = entries[name];\n\n const definition = typeof entry === \"function\" ? singleton(entry) : entry;\n\n result[name] = createReference(\n name,\n definition as DependencyDefinition<\n DefinitionValue<typeof entry>,\n DefinitionScope<typeof entry>,\n DefinitionDependencies<typeof entry>\n >\n );\n }\n\n return Object.freeze(result) as Container<Entries>;\n};\n\nexport type DependencyName<Dependency> =\n Dependency extends DependencyReference<\n infer Name,\n unknown,\n DependencyScope,\n readonly AnyDependencyReference[]\n >\n ? Name\n : never;\n\nexport type DependencyValue<Dependency> =\n Dependency extends DependencyReference<\n string,\n infer Value,\n DependencyScope,\n readonly AnyDependencyReference[]\n >\n ? Value\n : never;\n\nexport type DependencyContext<\n Dependencies extends readonly AnyDependencyReference[],\n> = {\n [Dependency in Dependencies[number] as DependencyName<Dependency>]: DependencyValue<Dependency>;\n};\n\nexport interface DuplicateDependency<Name extends string> {\n readonly __nooh_dependency_error__: `Duplicate dependency name \"${Name}\".`;\n}\n\nexport interface ReservedDependencyName<Name extends string> {\n readonly __nooh_dependency_error__: `Dependency name \"${Name}\" is reserved by the handler context.`;\n}\n\ntype ValidateDependenciesImpl<\n Dependencies extends readonly AnyDependencyReference[],\n Reserved extends string,\n Seen extends string = never,\n> = Dependencies extends readonly [infer Head, ...infer Tail]\n ? Head extends AnyDependencyReference\n ? DependencyName<Head> extends infer Name\n ? Name extends string\n ? Name extends Reserved\n ? readonly [\n Head & ReservedDependencyName<Name>,\n ...ValidateDependenciesImpl<\n Tail extends readonly AnyDependencyReference[] ? Tail : [],\n Reserved,\n Seen\n >,\n ]\n : Name extends Seen\n ? readonly [\n Head & DuplicateDependency<Name>,\n ...ValidateDependenciesImpl<\n Tail extends readonly AnyDependencyReference[] ? Tail : [],\n Reserved,\n Seen\n >,\n ]\n : readonly [\n Head,\n ...ValidateDependenciesImpl<\n Tail extends readonly AnyDependencyReference[] ? Tail : [],\n Reserved,\n Seen | Name\n >,\n ]\n : Dependencies\n : Dependencies\n : Dependencies\n : Dependencies;\n\nexport type ValidateDependencies<\n Dependencies extends readonly AnyDependencyReference[],\n Reserved extends string = never,\n> = ValidateDependenciesImpl<Dependencies, Reserved>;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nooh-ts/nooh",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "🧊 A zero-dependency, compile-time metaframework for building type-safe file-based Hono APIs.",
5
5
  "keywords": [
6
6
  "nooh",
@@ -35,7 +35,8 @@
35
35
  "typescript": "^7.0.2"
36
36
  },
37
37
  "peerDependencies": {
38
- "@hono/standard-validator": "^0.4.0"
38
+ "@hono/standard-validator": "^0.4.0",
39
+ "hono": "^4.13.7"
39
40
  },
40
41
  "publishConfig": {
41
42
  "access": "public"