shokupan 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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
package/dist/cli.cjs ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env bun
2
+ "use strict";
3
+ const p = require("@clack/prompts");
4
+ const fs = require("node:fs");
5
+ const path = require("node:path");
6
+ const promises = require("node:timers/promises");
7
+ function _interopNamespaceDefault(e) {
8
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
9
+ if (e) {
10
+ for (const k in e) {
11
+ if (k !== "default") {
12
+ const d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: () => e[k]
16
+ });
17
+ }
18
+ }
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+ const p__namespace = /* @__PURE__ */ _interopNamespaceDefault(p);
24
+ const templates = {
25
+ controller: (name) => `import { Controller, Get, Ctx } from 'shokupan';
26
+ import { ShokupanContext } from 'shokupan';
27
+
28
+ @Controller('/${name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}')
29
+ export class ${name}Controller {
30
+ @Get('/')
31
+ public index(@Ctx() ctx: ShokupanContext) {
32
+ return { message: 'Hello from ${name}Controller' };
33
+ }
34
+ }
35
+ `,
36
+ middleware: (name) => `import { ShokupanContext, NextFn } from 'shokupan';
37
+
38
+ /**
39
+ * ${name} Middleware
40
+ */
41
+ export const ${name}Middleware = async (ctx: ShokupanContext, next: NextFn) => {
42
+ // Before next
43
+ // console.log('${name} Middleware - Request');
44
+
45
+ const result = await next();
46
+
47
+ // After next
48
+ // console.log('${name} Middleware - Response');
49
+
50
+ return result;
51
+ };
52
+ `,
53
+ plugin: (name) => `import { ShokupanRouter } from 'shokupan';
54
+ import { ShokupanContext } from 'shokupan';
55
+
56
+ export interface ${name}Options {
57
+ // Define options here
58
+ }
59
+
60
+ export class ${name}Plugin extends ShokupanRouter {
61
+ constructor(private options: ${name}Options = {}) {
62
+ super();
63
+ this.init();
64
+ }
65
+
66
+ private init() {
67
+ this.get('/', (ctx: ShokupanContext) => {
68
+ return { message: '${name} Plugin Active' };
69
+ });
70
+ }
71
+ }
72
+ `
73
+ };
74
+ async function main() {
75
+ console.clear();
76
+ p__namespace.intro(`Shokupan CLI Scaffolder`);
77
+ if (!fs.existsSync("package.json")) {
78
+ p__namespace.note("Warning: No package.json found in current directory. Are you in the project root?");
79
+ }
80
+ const project = await p__namespace.group(
81
+ {
82
+ type: () => p__namespace.select({
83
+ message: "What do you want to scaffold?",
84
+ options: [
85
+ { value: "controller", label: "Controller" },
86
+ { value: "middleware", label: "Middleware" },
87
+ { value: "plugin", label: "Plugin" }
88
+ ]
89
+ }),
90
+ name: () => p__namespace.text({
91
+ message: "Name (PascalCase, e.g. UserAuth):",
92
+ validate: (value) => {
93
+ if (!value) return "Name is required";
94
+ if (!/^[A-Z][a-zA-Z0-9]*$/.test(value)) return "Please use PascalCase";
95
+ return void 0;
96
+ }
97
+ }),
98
+ dir: () => p__namespace.text({
99
+ message: "Output directory (leave empty for default):",
100
+ placeholder: "src/controllers"
101
+ })
102
+ },
103
+ {
104
+ onCancel: () => {
105
+ p__namespace.cancel("Operation cancelled.");
106
+ process.exit(0);
107
+ }
108
+ }
109
+ );
110
+ const type = project.type;
111
+ const name = project.name;
112
+ let dir = project.dir;
113
+ if (!dir || dir.trim() === "") {
114
+ switch (type) {
115
+ case "controller":
116
+ dir = "src/controllers";
117
+ break;
118
+ case "middleware":
119
+ dir = "src/middleware";
120
+ break;
121
+ case "plugin":
122
+ dir = "src/plugins";
123
+ break;
124
+ }
125
+ }
126
+ const kebabName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
127
+ const fileName = `${kebabName}.ts`;
128
+ const finalPath = path.join(process.cwd(), dir, fileName);
129
+ if (!fs.existsSync(path.dirname(finalPath))) {
130
+ fs.mkdirSync(path.dirname(finalPath), { recursive: true });
131
+ }
132
+ if (fs.existsSync(finalPath)) {
133
+ const overwrite = await p__namespace.confirm({
134
+ message: `File ${finalPath} already exists. Overwrite?`,
135
+ initialValue: false
136
+ });
137
+ if (p__namespace.isCancel(overwrite) || !overwrite) {
138
+ p__namespace.cancel("Operation cancelled.");
139
+ process.exit(0);
140
+ }
141
+ }
142
+ const s = p__namespace.spinner();
143
+ s.start(`Creating ${type}...`);
144
+ await promises.setTimeout(500);
145
+ const content = templates[type](name);
146
+ fs.writeFileSync(finalPath, content);
147
+ s.stop(`Created ${type}`);
148
+ const nextSteps = ` -> ${finalPath}
149
+ Make sure to register it in your main application file if necessary.`;
150
+ p__namespace.note(nextSteps, "Next steps");
151
+ p__namespace.outro(`Problems? Open an issue at https://github.com/dotglitch/express.ts`);
152
+ }
153
+ main().catch(console.error);
154
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs","sources":["../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env bun\nimport * as p from '@clack/prompts';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\n\nconst templates = {\n controller: (name: string) => `import { Controller, Get, Ctx } from 'shokupan';\nimport { ShokupanContext } from 'shokupan';\n\n@Controller('/${name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()}')\nexport class ${name}Controller {\n @Get('/')\n public index(@Ctx() ctx: ShokupanContext) {\n return { message: 'Hello from ${name}Controller' };\n }\n}\n`,\n middleware: (name: string) => `import { ShokupanContext, NextFn } from 'shokupan';\n\n/**\n * ${name} Middleware\n */\nexport const ${name}Middleware = async (ctx: ShokupanContext, next: NextFn) => {\n // Before next\n // console.log('${name} Middleware - Request');\n\n const result = await next();\n\n // After next\n // console.log('${name} Middleware - Response');\n \n return result;\n};\n`,\n plugin: (name: string) => `import { ShokupanRouter } from 'shokupan';\nimport { ShokupanContext } from 'shokupan';\n\nexport interface ${name}Options {\n // Define options here\n}\n\nexport class ${name}Plugin extends ShokupanRouter {\n constructor(private options: ${name}Options = {}) {\n super();\n this.init();\n }\n\n private init() {\n this.get('/', (ctx: ShokupanContext) => {\n return { message: '${name} Plugin Active' };\n });\n }\n}\n`\n};\n\nasync function main() {\n console.clear();\n p.intro(`Shokupan CLI Scaffolder`);\n\n // Check if running in a project root\n if (!fs.existsSync('package.json')) {\n p.note('Warning: No package.json found in current directory. Are you in the project root?');\n }\n\n const project = await p.group(\n {\n type: () => p.select({\n message: 'What do you want to scaffold?',\n options: [\n { value: 'controller', label: 'Controller' },\n { value: 'middleware', label: 'Middleware' },\n { value: 'plugin', label: 'Plugin' },\n ],\n }),\n name: () => p.text({\n message: 'Name (PascalCase, e.g. UserAuth):',\n validate: (value) => {\n if (!value) return 'Name is required';\n if (!/^[A-Z][a-zA-Z0-9]*$/.test(value)) return 'Please use PascalCase';\n return undefined;\n },\n }),\n dir: () => p.text({\n message: 'Output directory (leave empty for default):',\n placeholder: 'src/controllers',\n }),\n },\n {\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n const type = project.type as keyof typeof templates;\n const name = project.name;\n let dir = project.dir;\n\n if (!dir || dir.trim() === '') {\n switch (type) {\n case 'controller': dir = 'src/controllers'; break;\n case 'middleware': dir = 'src/middleware'; break;\n case 'plugin': dir = 'src/plugins'; break;\n }\n }\n\n // Convert PascalCase to kebab-case for filename\n const kebabName = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n const fileName = `${kebabName}.ts`;\n\n const finalPath = path.join(process.cwd(), dir, fileName);\n\n // Ensure directory exists\n if (!fs.existsSync(path.dirname(finalPath))) {\n fs.mkdirSync(path.dirname(finalPath), { recursive: true });\n }\n\n // Check for overwrite\n if (fs.existsSync(finalPath)) {\n const overwrite = await p.confirm({\n message: `File ${finalPath} already exists. Overwrite?`,\n initialValue: false\n });\n\n if (p.isCancel(overwrite) || !overwrite) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n }\n\n const s = p.spinner();\n s.start(`Creating ${type}...`);\n\n await setTimeout(500); // Artificial delay to show spinner\n\n const content = templates[type](name);\n fs.writeFileSync(finalPath, content);\n\n s.stop(`Created ${type}`);\n\n const nextSteps = ` -> ${finalPath}\nMake sure to register it in your main application file if necessary.`;\n\n p.note(nextSteps, 'Next steps');\n\n p.outro(`Problems? Open an issue at https://github.com/dotglitch/express.ts`);\n}\n\nmain().catch(console.error);;\n"],"names":["p","setTimeout"],"mappings":"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"}
package/dist/cli.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env bun
2
+ import * as p from "@clack/prompts";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { setTimeout } from "node:timers/promises";
6
+ const templates = {
7
+ controller: (name) => `import { Controller, Get, Ctx } from 'shokupan';
8
+ import { ShokupanContext } from 'shokupan';
9
+
10
+ @Controller('/${name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}')
11
+ export class ${name}Controller {
12
+ @Get('/')
13
+ public index(@Ctx() ctx: ShokupanContext) {
14
+ return { message: 'Hello from ${name}Controller' };
15
+ }
16
+ }
17
+ `,
18
+ middleware: (name) => `import { ShokupanContext, NextFn } from 'shokupan';
19
+
20
+ /**
21
+ * ${name} Middleware
22
+ */
23
+ export const ${name}Middleware = async (ctx: ShokupanContext, next: NextFn) => {
24
+ // Before next
25
+ // console.log('${name} Middleware - Request');
26
+
27
+ const result = await next();
28
+
29
+ // After next
30
+ // console.log('${name} Middleware - Response');
31
+
32
+ return result;
33
+ };
34
+ `,
35
+ plugin: (name) => `import { ShokupanRouter } from 'shokupan';
36
+ import { ShokupanContext } from 'shokupan';
37
+
38
+ export interface ${name}Options {
39
+ // Define options here
40
+ }
41
+
42
+ export class ${name}Plugin extends ShokupanRouter {
43
+ constructor(private options: ${name}Options = {}) {
44
+ super();
45
+ this.init();
46
+ }
47
+
48
+ private init() {
49
+ this.get('/', (ctx: ShokupanContext) => {
50
+ return { message: '${name} Plugin Active' };
51
+ });
52
+ }
53
+ }
54
+ `
55
+ };
56
+ async function main() {
57
+ console.clear();
58
+ p.intro(`Shokupan CLI Scaffolder`);
59
+ if (!fs.existsSync("package.json")) {
60
+ p.note("Warning: No package.json found in current directory. Are you in the project root?");
61
+ }
62
+ const project = await p.group(
63
+ {
64
+ type: () => p.select({
65
+ message: "What do you want to scaffold?",
66
+ options: [
67
+ { value: "controller", label: "Controller" },
68
+ { value: "middleware", label: "Middleware" },
69
+ { value: "plugin", label: "Plugin" }
70
+ ]
71
+ }),
72
+ name: () => p.text({
73
+ message: "Name (PascalCase, e.g. UserAuth):",
74
+ validate: (value) => {
75
+ if (!value) return "Name is required";
76
+ if (!/^[A-Z][a-zA-Z0-9]*$/.test(value)) return "Please use PascalCase";
77
+ return void 0;
78
+ }
79
+ }),
80
+ dir: () => p.text({
81
+ message: "Output directory (leave empty for default):",
82
+ placeholder: "src/controllers"
83
+ })
84
+ },
85
+ {
86
+ onCancel: () => {
87
+ p.cancel("Operation cancelled.");
88
+ process.exit(0);
89
+ }
90
+ }
91
+ );
92
+ const type = project.type;
93
+ const name = project.name;
94
+ let dir = project.dir;
95
+ if (!dir || dir.trim() === "") {
96
+ switch (type) {
97
+ case "controller":
98
+ dir = "src/controllers";
99
+ break;
100
+ case "middleware":
101
+ dir = "src/middleware";
102
+ break;
103
+ case "plugin":
104
+ dir = "src/plugins";
105
+ break;
106
+ }
107
+ }
108
+ const kebabName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
109
+ const fileName = `${kebabName}.ts`;
110
+ const finalPath = path.join(process.cwd(), dir, fileName);
111
+ if (!fs.existsSync(path.dirname(finalPath))) {
112
+ fs.mkdirSync(path.dirname(finalPath), { recursive: true });
113
+ }
114
+ if (fs.existsSync(finalPath)) {
115
+ const overwrite = await p.confirm({
116
+ message: `File ${finalPath} already exists. Overwrite?`,
117
+ initialValue: false
118
+ });
119
+ if (p.isCancel(overwrite) || !overwrite) {
120
+ p.cancel("Operation cancelled.");
121
+ process.exit(0);
122
+ }
123
+ }
124
+ const s = p.spinner();
125
+ s.start(`Creating ${type}...`);
126
+ await setTimeout(500);
127
+ const content = templates[type](name);
128
+ fs.writeFileSync(finalPath, content);
129
+ s.stop(`Created ${type}`);
130
+ const nextSteps = ` -> ${finalPath}
131
+ Make sure to register it in your main application file if necessary.`;
132
+ p.note(nextSteps, "Next steps");
133
+ p.outro(`Problems? Open an issue at https://github.com/dotglitch/express.ts`);
134
+ }
135
+ main().catch(console.error);
136
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sources":["../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env bun\nimport * as p from '@clack/prompts';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\n\nconst templates = {\n controller: (name: string) => `import { Controller, Get, Ctx } from 'shokupan';\nimport { ShokupanContext } from 'shokupan';\n\n@Controller('/${name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()}')\nexport class ${name}Controller {\n @Get('/')\n public index(@Ctx() ctx: ShokupanContext) {\n return { message: 'Hello from ${name}Controller' };\n }\n}\n`,\n middleware: (name: string) => `import { ShokupanContext, NextFn } from 'shokupan';\n\n/**\n * ${name} Middleware\n */\nexport const ${name}Middleware = async (ctx: ShokupanContext, next: NextFn) => {\n // Before next\n // console.log('${name} Middleware - Request');\n\n const result = await next();\n\n // After next\n // console.log('${name} Middleware - Response');\n \n return result;\n};\n`,\n plugin: (name: string) => `import { ShokupanRouter } from 'shokupan';\nimport { ShokupanContext } from 'shokupan';\n\nexport interface ${name}Options {\n // Define options here\n}\n\nexport class ${name}Plugin extends ShokupanRouter {\n constructor(private options: ${name}Options = {}) {\n super();\n this.init();\n }\n\n private init() {\n this.get('/', (ctx: ShokupanContext) => {\n return { message: '${name} Plugin Active' };\n });\n }\n}\n`\n};\n\nasync function main() {\n console.clear();\n p.intro(`Shokupan CLI Scaffolder`);\n\n // Check if running in a project root\n if (!fs.existsSync('package.json')) {\n p.note('Warning: No package.json found in current directory. Are you in the project root?');\n }\n\n const project = await p.group(\n {\n type: () => p.select({\n message: 'What do you want to scaffold?',\n options: [\n { value: 'controller', label: 'Controller' },\n { value: 'middleware', label: 'Middleware' },\n { value: 'plugin', label: 'Plugin' },\n ],\n }),\n name: () => p.text({\n message: 'Name (PascalCase, e.g. UserAuth):',\n validate: (value) => {\n if (!value) return 'Name is required';\n if (!/^[A-Z][a-zA-Z0-9]*$/.test(value)) return 'Please use PascalCase';\n return undefined;\n },\n }),\n dir: () => p.text({\n message: 'Output directory (leave empty for default):',\n placeholder: 'src/controllers',\n }),\n },\n {\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n const type = project.type as keyof typeof templates;\n const name = project.name;\n let dir = project.dir;\n\n if (!dir || dir.trim() === '') {\n switch (type) {\n case 'controller': dir = 'src/controllers'; break;\n case 'middleware': dir = 'src/middleware'; break;\n case 'plugin': dir = 'src/plugins'; break;\n }\n }\n\n // Convert PascalCase to kebab-case for filename\n const kebabName = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n const fileName = `${kebabName}.ts`;\n\n const finalPath = path.join(process.cwd(), dir, fileName);\n\n // Ensure directory exists\n if (!fs.existsSync(path.dirname(finalPath))) {\n fs.mkdirSync(path.dirname(finalPath), { recursive: true });\n }\n\n // Check for overwrite\n if (fs.existsSync(finalPath)) {\n const overwrite = await p.confirm({\n message: `File ${finalPath} already exists. Overwrite?`,\n initialValue: false\n });\n\n if (p.isCancel(overwrite) || !overwrite) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n }\n\n const s = p.spinner();\n s.start(`Creating ${type}...`);\n\n await setTimeout(500); // Artificial delay to show spinner\n\n const content = templates[type](name);\n fs.writeFileSync(finalPath, content);\n\n s.stop(`Created ${type}`);\n\n const nextSteps = ` -> ${finalPath}\nMake sure to register it in your main application file if necessary.`;\n\n p.note(nextSteps, 'Next steps');\n\n p.outro(`Problems? Open an issue at https://github.com/dotglitch/express.ts`);\n}\n\nmain().catch(console.error);;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { BodyInit } from 'bun';
2
+ import { ShokupanRequest } from './request';
3
+ import { ShokupanResponse } from './response';
4
+ import { CookieOptions } from './types';
5
+ type HeadersInit = Headers | Record<string, string> | [string, string][];
6
+ export declare class ShokupanContext<State extends Record<string, any> = Record<string, any>> {
7
+ readonly request: ShokupanRequest<any>;
8
+ readonly url: URL;
9
+ params: Record<string, string>;
10
+ state: State;
11
+ readonly response: ShokupanResponse;
12
+ constructor(request: ShokupanRequest<any>, state?: State);
13
+ /**
14
+ * Base request
15
+ */
16
+ get req(): any;
17
+ /**
18
+ * HTTP method
19
+ */
20
+ get method(): any;
21
+ /**
22
+ * Request path
23
+ */
24
+ get path(): string;
25
+ /**
26
+ * Request query params
27
+ */
28
+ get query(): {
29
+ [k: string]: string;
30
+ };
31
+ /**
32
+ * Request headers
33
+ */
34
+ get headers(): any;
35
+ /**
36
+ * Base response object
37
+ */
38
+ get res(): ShokupanResponse;
39
+ /**
40
+ * Helper to set a header on the response
41
+ */
42
+ set(key: string, value: string): this;
43
+ /**
44
+ * Set a cookie
45
+ * @param name Cookie name
46
+ * @param value Cookie value
47
+ * @param options Cookie options
48
+ */
49
+ setCookie(name: string, value: string, options?: CookieOptions): this;
50
+ private mergeHeaders;
51
+ /**
52
+ * Send a response
53
+ * @param body Response body
54
+ * @param options Response options
55
+ * @returns Response
56
+ */
57
+ send(body?: BodyInit, options?: ResponseInit): Response;
58
+ /**
59
+ * Read request body
60
+ */
61
+ body<T = any>(): Promise<T>;
62
+ /**
63
+ * Respond with a JSON object
64
+ */
65
+ json(data: any, status?: number, headers?: HeadersInit): Response;
66
+ /**
67
+ * Respond with a text string
68
+ */
69
+ text(data: string, status?: number, headers?: HeadersInit): Response;
70
+ /**
71
+ * Respond with HTML content
72
+ */
73
+ html(html: string, status?: number, headers?: HeadersInit): Response;
74
+ /**
75
+ * Respond with a redirect
76
+ */
77
+ redirect(url: string, status?: number): Response;
78
+ /**
79
+ * Respond with a status code
80
+ * DOES NOT CHAIN!
81
+ */
82
+ status(status: number): Response;
83
+ /**
84
+ * Respond with a file
85
+ */
86
+ file(path: string, fileOptions?: BlobPropertyBag, responseOptions?: ResponseInit): Response;
87
+ }
88
+ export {};
@@ -0,0 +1,23 @@
1
+ import { Middleware } from './types';
2
+ /**
3
+ * Class Decorator: Defines the base path for a controller.
4
+ */
5
+ export declare function Controller(path?: string): (target: any) => void;
6
+ /**
7
+ * Decorator: Applies middleware to a class or method.
8
+ */
9
+ export declare function Use(...middleware: Middleware[]): (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => void;
10
+ export declare const Body: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
11
+ export declare const Param: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
12
+ export declare const Query: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
13
+ export declare const Headers: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
14
+ export declare const Req: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
15
+ export declare const Ctx: (name?: string) => (target: any, propertyKey: string, parameterIndex: number) => void;
16
+ export declare const Get: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
17
+ export declare const Post: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
18
+ export declare const Put: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
19
+ export declare const Delete: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
20
+ export declare const Patch: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
21
+ export declare const Options: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
22
+ export declare const Head: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
23
+ export declare const All: (path?: string) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
package/dist/di.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Simple Dependency Injection Container
3
+ */
4
+ export declare class Container {
5
+ private static services;
6
+ static register<T>(target: new (...args: any[]) => T, instance: T): void;
7
+ static get<T>(target: new (...args: any[]) => T): T | undefined;
8
+ static has(target: any): boolean;
9
+ static resolve<T>(target: new (...args: any[]) => T): T;
10
+ }
11
+ /**
12
+ * Decorator to mark a class as injectable (Service).
13
+ */
14
+ export declare function Injectable(): (target: any) => void;
15
+ /**
16
+ * Property Decorator: Injects a service.
17
+ */
18
+ export declare function Inject(token: any): (target: any, key: string) => void;