@buenojs/bueno 0.8.0 → 0.8.2
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/cli/index.js +98 -28
- package/dist/index.js +28 -9
- package/package.json +1 -1
- package/src/cli/commands/generate.ts +11 -11
- package/src/cli/commands/migration.ts +5 -5
- package/src/cli/commands/new.ts +86 -11
- package/src/container/index.ts +2 -2
- package/src/modules/index.ts +27 -6
- package/tsconfig.json +3 -1
package/dist/cli/index.js
CHANGED
|
@@ -20,6 +20,10 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
|
20
20
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
21
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
22
22
|
};
|
|
23
|
+
var __legacyMetadataTS = (k, v) => {
|
|
24
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
25
|
+
return Reflect.metadata(k, v);
|
|
26
|
+
};
|
|
23
27
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
24
28
|
var __require = import.meta.require;
|
|
25
29
|
|
|
@@ -1328,9 +1332,10 @@ function validateProjectName(name) {
|
|
|
1328
1332
|
return true;
|
|
1329
1333
|
}
|
|
1330
1334
|
function getPackageJsonTemplate(config) {
|
|
1331
|
-
const dependencies = {
|
|
1332
|
-
|
|
1333
|
-
|
|
1335
|
+
const dependencies = {};
|
|
1336
|
+
if (!config.link) {
|
|
1337
|
+
dependencies["@buenojs/bueno"] = "^0.8.0";
|
|
1338
|
+
}
|
|
1334
1339
|
const devDependencies = {
|
|
1335
1340
|
"@types/bun": "latest",
|
|
1336
1341
|
typescript: "^5.3.0"
|
|
@@ -1368,7 +1373,7 @@ function getTsConfigTemplate() {
|
|
|
1368
1373
|
allowSyntheticDefaultImports: true,
|
|
1369
1374
|
jsx: "react-jsx",
|
|
1370
1375
|
paths: {
|
|
1371
|
-
bueno: ["./node_modules/bueno/dist/index.d.ts"]
|
|
1376
|
+
"@buenojs/bueno": ["./node_modules/@buenojs/bueno/dist/index.d.ts"]
|
|
1372
1377
|
}
|
|
1373
1378
|
},
|
|
1374
1379
|
include: ["server/**/*", "client/**/*"],
|
|
@@ -1377,7 +1382,7 @@ function getTsConfigTemplate() {
|
|
|
1377
1382
|
}
|
|
1378
1383
|
function getMainTemplate(config) {
|
|
1379
1384
|
if (config.template === "minimal") {
|
|
1380
|
-
return `import { createServer } from 'bueno';
|
|
1385
|
+
return `import { createServer } from '@buenojs/bueno';
|
|
1381
1386
|
|
|
1382
1387
|
const app = createServer();
|
|
1383
1388
|
|
|
@@ -1388,8 +1393,8 @@ app.router.get('/', () => {
|
|
|
1388
1393
|
await app.listen(3000);
|
|
1389
1394
|
`;
|
|
1390
1395
|
}
|
|
1391
|
-
return `import { createApp, Module, Controller, Get, Injectable } from 'bueno';
|
|
1392
|
-
import type { Context } from 'bueno';
|
|
1396
|
+
return `import { createApp, Module, Controller, Get, Injectable } from '@buenojs/bueno';
|
|
1397
|
+
import type { Context } from '@buenojs/bueno';
|
|
1393
1398
|
|
|
1394
1399
|
// Services
|
|
1395
1400
|
@Injectable()
|
|
@@ -1405,8 +1410,44 @@ export class AppController {
|
|
|
1405
1410
|
constructor(private readonly appService: AppService) {}
|
|
1406
1411
|
|
|
1407
1412
|
@Get()
|
|
1408
|
-
|
|
1409
|
-
return
|
|
1413
|
+
hello() {
|
|
1414
|
+
return new Response(\`<html>
|
|
1415
|
+
<head>
|
|
1416
|
+
<title>Welcome to Bueno</title>
|
|
1417
|
+
<style>
|
|
1418
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
|
1419
|
+
h1 { color: #2563eb; }
|
|
1420
|
+
code { background: #f3f4f6; padding: 2px 6px; border-radius: 4px; }
|
|
1421
|
+
pre { background: #f3f4f6; padding: 16px; border-radius: 8px; overflow-x: auto; }
|
|
1422
|
+
a { color: #2563eb; }
|
|
1423
|
+
</style>
|
|
1424
|
+
</head>
|
|
1425
|
+
<body>
|
|
1426
|
+
<h1>\uD83C\uDF89 Welcome to Bueno Framework!</h1>
|
|
1427
|
+
<p>Your Bun-native full-stack framework is running successfully.</p>
|
|
1428
|
+
|
|
1429
|
+
<h2>Getting Started</h2>
|
|
1430
|
+
<ul>
|
|
1431
|
+
<li>Edit <code>server/main.ts</code> to modify this app</li>
|
|
1432
|
+
<li>Add routes using the <code>@Get()</code>, <code>@Post()</code> decorators</li>
|
|
1433
|
+
<li>Create services with <code>@Injectable()</code> and inject them in controllers</li>
|
|
1434
|
+
</ul>
|
|
1435
|
+
|
|
1436
|
+
<h2>Documentation</h2>
|
|
1437
|
+
<p>Visit <a href="https://buenojs.dev">https://buenojs.dev</a> for full documentation.</p>
|
|
1438
|
+
|
|
1439
|
+
<h2>Quick Example</h2>
|
|
1440
|
+
<pre><code>@Controller('/api')
|
|
1441
|
+
class MyController {
|
|
1442
|
+
@Get('/users')
|
|
1443
|
+
getUsers() {
|
|
1444
|
+
return { users: [] };
|
|
1445
|
+
}
|
|
1446
|
+
}</code></pre>
|
|
1447
|
+
</body>
|
|
1448
|
+
</html>\`, {
|
|
1449
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' }
|
|
1450
|
+
});
|
|
1410
1451
|
}
|
|
1411
1452
|
|
|
1412
1453
|
@Get('health')
|
|
@@ -1429,7 +1470,7 @@ await app.listen(3000);
|
|
|
1429
1470
|
}
|
|
1430
1471
|
function getConfigTemplate(config) {
|
|
1431
1472
|
const dbConfig = config.database === "sqlite" ? `{ url: 'sqlite:./data.db' }` : `{ url: process.env.DATABASE_URL ?? '${config.database}://localhost/${kebabCase(config.name)}' }`;
|
|
1432
|
-
return `import { defineConfig } from 'bueno';
|
|
1473
|
+
return `import { defineConfig } from '@buenojs/bueno';
|
|
1433
1474
|
|
|
1434
1475
|
export default defineConfig({
|
|
1435
1476
|
server: {
|
|
@@ -1669,6 +1710,7 @@ async function handleNew(args) {
|
|
|
1669
1710
|
const skipInstall = hasFlag(args, "skip-install");
|
|
1670
1711
|
const skipGit = hasFlag(args, "skip-git");
|
|
1671
1712
|
const docker = hasFlag(args, "docker");
|
|
1713
|
+
const link = hasFlag(args, "link");
|
|
1672
1714
|
const deployPlatforms = getOptionValues(args, "deploy");
|
|
1673
1715
|
const validPlatforms = ["render", "fly", "railway"];
|
|
1674
1716
|
const deploy = [];
|
|
@@ -1717,7 +1759,8 @@ async function handleNew(args) {
|
|
|
1717
1759
|
skipInstall,
|
|
1718
1760
|
skipGit,
|
|
1719
1761
|
docker,
|
|
1720
|
-
deploy
|
|
1762
|
+
deploy,
|
|
1763
|
+
link
|
|
1721
1764
|
};
|
|
1722
1765
|
const projectPath = joinPaths(process.cwd(), kebabCase(name));
|
|
1723
1766
|
if (await fileExists(projectPath)) {
|
|
@@ -1731,6 +1774,7 @@ async function handleNew(args) {
|
|
|
1731
1774
|
["Docker", docker ? colors.green("Yes") : colors.red("No")],
|
|
1732
1775
|
["Deploy", deploy.length > 0 ? colors.green(deploy.map(getDeployPlatformName).join(", ")) : colors.red("None")],
|
|
1733
1776
|
["Install dependencies", skipInstall ? colors.red("No") : colors.green("Yes")],
|
|
1777
|
+
["Use local package", link ? colors.green("Yes (bun link)") : colors.red("No")],
|
|
1734
1778
|
["Initialize git", skipGit ? colors.red("No") : colors.green("Yes")]
|
|
1735
1779
|
];
|
|
1736
1780
|
printTable(["Setting", "Value"], rows);
|
|
@@ -1755,6 +1799,25 @@ async function handleNew(args) {
|
|
|
1755
1799
|
} catch {
|
|
1756
1800
|
installSpinner.warn("Failed to install dependencies. Run `bun install` manually.");
|
|
1757
1801
|
}
|
|
1802
|
+
if (link) {
|
|
1803
|
+
cliConsole.subheader("Linking local @buenojs/bueno...");
|
|
1804
|
+
const linkSpinner = spinner("Running bun link @buenojs/bueno...");
|
|
1805
|
+
try {
|
|
1806
|
+
const proc = Bun.spawn(["bun", "link", "@buenojs/bueno"], {
|
|
1807
|
+
cwd: projectPath,
|
|
1808
|
+
stdout: "pipe",
|
|
1809
|
+
stderr: "pipe"
|
|
1810
|
+
});
|
|
1811
|
+
const exitCode = await proc.exited;
|
|
1812
|
+
if (exitCode === 0) {
|
|
1813
|
+
linkSpinner.success("Local @buenojs/bueno linked successfully");
|
|
1814
|
+
} else {
|
|
1815
|
+
linkSpinner.warn("Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.");
|
|
1816
|
+
}
|
|
1817
|
+
} catch {
|
|
1818
|
+
linkSpinner.warn("Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.");
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1758
1821
|
}
|
|
1759
1822
|
if (!skipGit) {
|
|
1760
1823
|
cliConsole.subheader("Initializing git repository...");
|
|
@@ -1835,6 +1898,12 @@ defineCommand({
|
|
|
1835
1898
|
default: false,
|
|
1836
1899
|
description: "Include Docker configuration (Dockerfile, docker-compose.yml)"
|
|
1837
1900
|
},
|
|
1901
|
+
{
|
|
1902
|
+
name: "link",
|
|
1903
|
+
type: "boolean",
|
|
1904
|
+
default: false,
|
|
1905
|
+
description: "Use local @buenojs/bueno via bun link (for development)"
|
|
1906
|
+
},
|
|
1838
1907
|
{
|
|
1839
1908
|
name: "deploy",
|
|
1840
1909
|
type: "string",
|
|
@@ -1860,7 +1929,8 @@ defineCommand({
|
|
|
1860
1929
|
"bueno new my-app --deploy render --deploy fly",
|
|
1861
1930
|
"bueno new my-app --docker --deploy render",
|
|
1862
1931
|
"bueno new my-app --docker --database postgresql --deploy render",
|
|
1863
|
-
"bueno new my-app -y"
|
|
1932
|
+
"bueno new my-app -y",
|
|
1933
|
+
"bueno new my-app --link"
|
|
1864
1934
|
]
|
|
1865
1935
|
}, handleNew);
|
|
1866
1936
|
|
|
@@ -1879,8 +1949,8 @@ var GENERATOR_ALIASES = {
|
|
|
1879
1949
|
};
|
|
1880
1950
|
function getTemplate(type) {
|
|
1881
1951
|
const templates = {
|
|
1882
|
-
controller: `import { Controller, Get, Post, Put, Delete{{#if path}} } from 'bueno'{{/if}}{{#if service}}, { {{pascalCase service}}Service } from './{{kebabCase service}}.service'{{/if}};
|
|
1883
|
-
import type { Context } from 'bueno';
|
|
1952
|
+
controller: `import { Controller, Get, Post, Put, Delete{{#if path}} } from '@buenojs/bueno'{{/if}}{{#if service}}, { {{pascalCase service}}Service } from './{{kebabCase service}}.service'{{/if}};
|
|
1953
|
+
import type { Context } from '@buenojs/bueno';
|
|
1884
1954
|
|
|
1885
1955
|
@Controller('{{path}}')
|
|
1886
1956
|
export class {{pascalCase name}}Controller {
|
|
@@ -1919,7 +1989,7 @@ export class {{pascalCase name}}Controller {
|
|
|
1919
1989
|
}
|
|
1920
1990
|
}
|
|
1921
1991
|
`,
|
|
1922
|
-
service: `import { Injectable } from 'bueno';
|
|
1992
|
+
service: `import { Injectable } from '@buenojs/bueno';
|
|
1923
1993
|
|
|
1924
1994
|
@Injectable()
|
|
1925
1995
|
export class {{pascalCase name}}Service {
|
|
@@ -1949,7 +2019,7 @@ export class {{pascalCase name}}Service {
|
|
|
1949
2019
|
}
|
|
1950
2020
|
}
|
|
1951
2021
|
`,
|
|
1952
|
-
module: `import { Module } from 'bueno';
|
|
2022
|
+
module: `import { Module } from '@buenojs/bueno';
|
|
1953
2023
|
import { {{pascalCase name}}Controller } from './{{kebabCase name}}.controller';
|
|
1954
2024
|
import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
|
1955
2025
|
|
|
@@ -1960,7 +2030,7 @@ import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
|
|
1960
2030
|
})
|
|
1961
2031
|
export class {{pascalCase name}}Module {}
|
|
1962
2032
|
`,
|
|
1963
|
-
guard: `import { Injectable, type CanActivate, type Context } from 'bueno';
|
|
2033
|
+
guard: `import { Injectable, type CanActivate, type Context } from '@buenojs/bueno';
|
|
1964
2034
|
|
|
1965
2035
|
@Injectable()
|
|
1966
2036
|
export class {{pascalCase name}}Guard implements CanActivate {
|
|
@@ -1971,7 +2041,7 @@ export class {{pascalCase name}}Guard implements CanActivate {
|
|
|
1971
2041
|
}
|
|
1972
2042
|
}
|
|
1973
2043
|
`,
|
|
1974
|
-
interceptor: `import { Injectable, type NestInterceptor, type CallHandler, type Context } from 'bueno';
|
|
2044
|
+
interceptor: `import { Injectable, type NestInterceptor, type CallHandler, type Context } from '@buenojs/bueno';
|
|
1975
2045
|
import type { Observable } from 'rxjs';
|
|
1976
2046
|
|
|
1977
2047
|
@Injectable()
|
|
@@ -1990,7 +2060,7 @@ export class {{pascalCase name}}Interceptor implements NestInterceptor {
|
|
|
1990
2060
|
}
|
|
1991
2061
|
}
|
|
1992
2062
|
`,
|
|
1993
|
-
pipe: `import { Injectable, type PipeTransform, type Context } from 'bueno';
|
|
2063
|
+
pipe: `import { Injectable, type PipeTransform, type Context } from '@buenojs/bueno';
|
|
1994
2064
|
|
|
1995
2065
|
@Injectable()
|
|
1996
2066
|
export class {{pascalCase name}}Pipe implements PipeTransform {
|
|
@@ -2001,8 +2071,8 @@ export class {{pascalCase name}}Pipe implements PipeTransform {
|
|
|
2001
2071
|
}
|
|
2002
2072
|
}
|
|
2003
2073
|
`,
|
|
2004
|
-
filter: `import { Injectable, type ExceptionFilter, type Context } from 'bueno';
|
|
2005
|
-
import type { Response } from 'bueno';
|
|
2074
|
+
filter: `import { Injectable, type ExceptionFilter, type Context } from '@buenojs/bueno';
|
|
2075
|
+
import type { Response } from '@buenojs/bueno';
|
|
2006
2076
|
|
|
2007
2077
|
@Injectable()
|
|
2008
2078
|
export class {{pascalCase name}}Filter implements ExceptionFilter {
|
|
@@ -2048,7 +2118,7 @@ export interface Update{{pascalCase name}}Dto extends Partial<Create{{pascalCase
|
|
|
2048
2118
|
// TODO: Define optional properties for update
|
|
2049
2119
|
}
|
|
2050
2120
|
`,
|
|
2051
|
-
middleware: `import type { Middleware, Context, Handler } from 'bueno';
|
|
2121
|
+
middleware: `import type { Middleware, Context, Handler } from '@buenojs/bueno';
|
|
2052
2122
|
|
|
2053
2123
|
/**
|
|
2054
2124
|
* {{pascalCase name}} Middleware
|
|
@@ -2069,7 +2139,7 @@ export const {{camelCase name}}Middleware: Middleware = async (
|
|
|
2069
2139
|
return result;
|
|
2070
2140
|
};
|
|
2071
2141
|
`,
|
|
2072
|
-
migration: `import { createMigration, type MigrationRunner } from 'bueno';
|
|
2142
|
+
migration: `import { createMigration, type MigrationRunner } from '@buenojs/bueno';
|
|
2073
2143
|
|
|
2074
2144
|
export default createMigration('{{migrationId}}', '{{migrationName}}')
|
|
2075
2145
|
.up(async (db: MigrationRunner) => {
|
|
@@ -2325,7 +2395,7 @@ async function createMigration(name, dryRun) {
|
|
|
2325
2395
|
const kebabName = name.toLowerCase().replace(/\s+/g, "-");
|
|
2326
2396
|
const fileName = `${id}_${kebabName}.ts`;
|
|
2327
2397
|
const filePath = joinPaths(migrationsDir, fileName);
|
|
2328
|
-
const template = `import { createMigration, type MigrationRunner } from 'bueno';
|
|
2398
|
+
const template = `import { createMigration, type MigrationRunner } from '@buenojs/bueno';
|
|
2329
2399
|
|
|
2330
2400
|
export default createMigration('${id}', '${kebabName}')
|
|
2331
2401
|
.up(async (db: MigrationRunner) => {
|
|
@@ -2421,7 +2491,7 @@ async function handleMigration(args) {
|
|
|
2421
2491
|
cliConsole.log("");
|
|
2422
2492
|
cliConsole.log("Example:");
|
|
2423
2493
|
cliConsole.log(colors.cyan(`
|
|
2424
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
2494
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
2425
2495
|
import { db } from './database';
|
|
2426
2496
|
|
|
2427
2497
|
const runner = createMigrationRunner(db);
|
|
@@ -2437,7 +2507,7 @@ await runner.migrate(migrations);
|
|
|
2437
2507
|
cliConsole.log("");
|
|
2438
2508
|
cliConsole.log("Example:");
|
|
2439
2509
|
cliConsole.log(colors.cyan(`
|
|
2440
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
2510
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
2441
2511
|
import { db } from './database';
|
|
2442
2512
|
|
|
2443
2513
|
const runner = createMigrationRunner(db);
|
|
@@ -2453,7 +2523,7 @@ await runner.rollback(migrations, ${steps});
|
|
|
2453
2523
|
cliConsole.log("");
|
|
2454
2524
|
cliConsole.log("Example:");
|
|
2455
2525
|
cliConsole.log(colors.cyan(`
|
|
2456
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
2526
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
2457
2527
|
import { db } from './database';
|
|
2458
2528
|
|
|
2459
2529
|
const runner = createMigrationRunner(db);
|
|
@@ -2469,7 +2539,7 @@ await runner.reset(migrations);
|
|
|
2469
2539
|
cliConsole.log("");
|
|
2470
2540
|
cliConsole.log("Example:");
|
|
2471
2541
|
cliConsole.log(colors.cyan(`
|
|
2472
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
2542
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
2473
2543
|
import { db } from './database';
|
|
2474
2544
|
|
|
2475
2545
|
const runner = createMigrationRunner(db);
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,10 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
|
19
19
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
20
20
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
21
21
|
};
|
|
22
|
+
var __legacyMetadataTS = (k, v) => {
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
24
|
+
return Reflect.metadata(k, v);
|
|
25
|
+
};
|
|
22
26
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
23
27
|
var __require = import.meta.require;
|
|
24
28
|
|
|
@@ -564,7 +568,7 @@ class ResolutionStack {
|
|
|
564
568
|
}
|
|
565
569
|
}
|
|
566
570
|
|
|
567
|
-
class
|
|
571
|
+
class Container2 {
|
|
568
572
|
providers = new Map;
|
|
569
573
|
resolutionStack = new ResolutionStack;
|
|
570
574
|
register(provider) {
|
|
@@ -684,7 +688,7 @@ class Container {
|
|
|
684
688
|
return Array.from(this.providers.keys());
|
|
685
689
|
}
|
|
686
690
|
createChild() {
|
|
687
|
-
const child = new
|
|
691
|
+
const child = new Container2;
|
|
688
692
|
for (const [token, resolved] of this.providers) {
|
|
689
693
|
if (resolved.provider.scope === "singleton") {
|
|
690
694
|
child.providers.set(token, resolved);
|
|
@@ -1901,7 +1905,10 @@ class ModuleLoader {
|
|
|
1901
1905
|
}
|
|
1902
1906
|
}
|
|
1903
1907
|
ModuleLoader = __legacyDecorateClassTS([
|
|
1904
|
-
Injectable2()
|
|
1908
|
+
Injectable2(),
|
|
1909
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1910
|
+
typeof Container === "undefined" ? Object : Container
|
|
1911
|
+
])
|
|
1905
1912
|
], ModuleLoader);
|
|
1906
1913
|
|
|
1907
1914
|
class LazyModuleRegistry {
|
|
@@ -2692,9 +2699,9 @@ function createInternalErrorResponse(exception) {
|
|
|
2692
2699
|
function Inject2(token) {
|
|
2693
2700
|
return (target, propertyKey, parameterIndex) => {
|
|
2694
2701
|
const targetObj = target;
|
|
2695
|
-
const existingTokens =
|
|
2702
|
+
const existingTokens = getContainerMetadata(targetObj, "inject:tokens") ?? [];
|
|
2696
2703
|
existingTokens[parameterIndex] = token;
|
|
2697
|
-
|
|
2704
|
+
setContainerMetadata(targetObj, "inject:tokens", existingTokens);
|
|
2698
2705
|
};
|
|
2699
2706
|
}
|
|
2700
2707
|
function createMethodDecorator(method) {
|
|
@@ -2748,7 +2755,13 @@ class AppModule {
|
|
|
2748
2755
|
}
|
|
2749
2756
|
}
|
|
2750
2757
|
if (metadata.providers) {
|
|
2751
|
-
|
|
2758
|
+
const normalizedProviders = metadata.providers.map((p) => {
|
|
2759
|
+
if (typeof p === "function" && !p.token) {
|
|
2760
|
+
return { token: p, useClass: p };
|
|
2761
|
+
}
|
|
2762
|
+
return p;
|
|
2763
|
+
});
|
|
2764
|
+
this.providers.push(...normalizedProviders);
|
|
2752
2765
|
}
|
|
2753
2766
|
if (metadata.controllers) {
|
|
2754
2767
|
this.controllers.push(...metadata.controllers);
|
|
@@ -2787,7 +2800,7 @@ class Application {
|
|
|
2787
2800
|
moduleLoader;
|
|
2788
2801
|
loadedLazyModules = new Set;
|
|
2789
2802
|
constructor(moduleClass) {
|
|
2790
|
-
this.container = new
|
|
2803
|
+
this.container = new Container2;
|
|
2791
2804
|
this.router = new Router;
|
|
2792
2805
|
this.appModule = new AppModule(moduleClass);
|
|
2793
2806
|
this.lifecycleManager = new LifecycleHookManager;
|
|
@@ -2834,7 +2847,13 @@ class Application {
|
|
|
2834
2847
|
registerController(controllerClass) {
|
|
2835
2848
|
const basePath = getMetadata(controllerClass, "path") ?? "";
|
|
2836
2849
|
const routes = getPrototypeMetadata(controllerClass.prototype, "routes") ?? [];
|
|
2837
|
-
|
|
2850
|
+
let injectTokens = getContainerMetadata(controllerClass, "inject:tokens") ?? [];
|
|
2851
|
+
if (injectTokens.length === 0 && typeof Reflect !== "undefined" && typeof Reflect.getMetadata === "function") {
|
|
2852
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", controllerClass);
|
|
2853
|
+
if (paramTypes) {
|
|
2854
|
+
injectTokens = paramTypes.map((paramType) => paramType);
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2838
2857
|
const deps = injectTokens.map((tokenOrRef) => {
|
|
2839
2858
|
const token = isForwardRef(tokenOrRef) ? resolveForwardRef(tokenOrRef) : tokenOrRef;
|
|
2840
2859
|
return this.container.resolve(token);
|
|
@@ -9004,7 +9023,7 @@ export {
|
|
|
9004
9023
|
Database,
|
|
9005
9024
|
Controller,
|
|
9006
9025
|
Context,
|
|
9007
|
-
Container,
|
|
9026
|
+
Container2 as Container,
|
|
9008
9027
|
ConfigManager,
|
|
9009
9028
|
Cache,
|
|
9010
9029
|
CSRF,
|
package/package.json
CHANGED
|
@@ -69,8 +69,8 @@ interface GeneratorConfig {
|
|
|
69
69
|
*/
|
|
70
70
|
function getTemplate(type: GeneratorType): string {
|
|
71
71
|
const templates: Record<GeneratorType, string> = {
|
|
72
|
-
controller: `import { Controller, Get, Post, Put, Delete{{#if path}} } from 'bueno'{{/if}}{{#if service}}, { {{pascalCase service}}Service } from './{{kebabCase service}}.service'{{/if}};
|
|
73
|
-
import type { Context } from 'bueno';
|
|
72
|
+
controller: `import { Controller, Get, Post, Put, Delete{{#if path}} } from '@buenojs/bueno'{{/if}}{{#if service}}, { {{pascalCase service}}Service } from './{{kebabCase service}}.service'{{/if}};
|
|
73
|
+
import type { Context } from '@buenojs/bueno';
|
|
74
74
|
|
|
75
75
|
@Controller('{{path}}')
|
|
76
76
|
export class {{pascalCase name}}Controller {
|
|
@@ -109,7 +109,7 @@ export class {{pascalCase name}}Controller {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
`,
|
|
112
|
-
service: `import { Injectable } from 'bueno';
|
|
112
|
+
service: `import { Injectable } from '@buenojs/bueno';
|
|
113
113
|
|
|
114
114
|
@Injectable()
|
|
115
115
|
export class {{pascalCase name}}Service {
|
|
@@ -139,7 +139,7 @@ export class {{pascalCase name}}Service {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
`,
|
|
142
|
-
module: `import { Module } from 'bueno';
|
|
142
|
+
module: `import { Module } from '@buenojs/bueno';
|
|
143
143
|
import { {{pascalCase name}}Controller } from './{{kebabCase name}}.controller';
|
|
144
144
|
import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
|
145
145
|
|
|
@@ -150,7 +150,7 @@ import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
|
|
150
150
|
})
|
|
151
151
|
export class {{pascalCase name}}Module {}
|
|
152
152
|
`,
|
|
153
|
-
guard: `import { Injectable, type CanActivate, type Context } from 'bueno';
|
|
153
|
+
guard: `import { Injectable, type CanActivate, type Context } from '@buenojs/bueno';
|
|
154
154
|
|
|
155
155
|
@Injectable()
|
|
156
156
|
export class {{pascalCase name}}Guard implements CanActivate {
|
|
@@ -161,7 +161,7 @@ export class {{pascalCase name}}Guard implements CanActivate {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
`,
|
|
164
|
-
interceptor: `import { Injectable, type NestInterceptor, type CallHandler, type Context } from 'bueno';
|
|
164
|
+
interceptor: `import { Injectable, type NestInterceptor, type CallHandler, type Context } from '@buenojs/bueno';
|
|
165
165
|
import type { Observable } from 'rxjs';
|
|
166
166
|
|
|
167
167
|
@Injectable()
|
|
@@ -180,7 +180,7 @@ export class {{pascalCase name}}Interceptor implements NestInterceptor {
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
`,
|
|
183
|
-
pipe: `import { Injectable, type PipeTransform, type Context } from 'bueno';
|
|
183
|
+
pipe: `import { Injectable, type PipeTransform, type Context } from '@buenojs/bueno';
|
|
184
184
|
|
|
185
185
|
@Injectable()
|
|
186
186
|
export class {{pascalCase name}}Pipe implements PipeTransform {
|
|
@@ -191,8 +191,8 @@ export class {{pascalCase name}}Pipe implements PipeTransform {
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
`,
|
|
194
|
-
filter: `import { Injectable, type ExceptionFilter, type Context } from 'bueno';
|
|
195
|
-
import type { Response } from 'bueno';
|
|
194
|
+
filter: `import { Injectable, type ExceptionFilter, type Context } from '@buenojs/bueno';
|
|
195
|
+
import type { Response } from '@buenojs/bueno';
|
|
196
196
|
|
|
197
197
|
@Injectable()
|
|
198
198
|
export class {{pascalCase name}}Filter implements ExceptionFilter {
|
|
@@ -238,7 +238,7 @@ export interface Update{{pascalCase name}}Dto extends Partial<Create{{pascalCase
|
|
|
238
238
|
// TODO: Define optional properties for update
|
|
239
239
|
}
|
|
240
240
|
`,
|
|
241
|
-
middleware: `import type { Middleware, Context, Handler } from 'bueno';
|
|
241
|
+
middleware: `import type { Middleware, Context, Handler } from '@buenojs/bueno';
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
244
|
* {{pascalCase name}} Middleware
|
|
@@ -259,7 +259,7 @@ export const {{camelCase name}}Middleware: Middleware = async (
|
|
|
259
259
|
return result;
|
|
260
260
|
};
|
|
261
261
|
`,
|
|
262
|
-
migration: `import { createMigration, type MigrationRunner } from 'bueno';
|
|
262
|
+
migration: `import { createMigration, type MigrationRunner } from '@buenojs/bueno';
|
|
263
263
|
|
|
264
264
|
export default createMigration('{{migrationId}}', '{{migrationName}}')
|
|
265
265
|
.up(async (db: MigrationRunner) => {
|
|
@@ -104,7 +104,7 @@ async function createMigration(name: string, dryRun: boolean): Promise<string> {
|
|
|
104
104
|
const fileName = `${id}_${kebabName}.ts`;
|
|
105
105
|
const filePath = joinPaths(migrationsDir, fileName);
|
|
106
106
|
|
|
107
|
-
const template = `import { createMigration, type MigrationRunner } from 'bueno';
|
|
107
|
+
const template = `import { createMigration, type MigrationRunner } from '@buenojs/bueno';
|
|
108
108
|
|
|
109
109
|
export default createMigration('${id}', '${kebabName}')
|
|
110
110
|
.up(async (db: MigrationRunner) => {
|
|
@@ -236,7 +236,7 @@ async function handleMigration(args: ParsedArgs): Promise<void> {
|
|
|
236
236
|
cliConsole.log('');
|
|
237
237
|
cliConsole.log('Example:');
|
|
238
238
|
cliConsole.log(colors.cyan(`
|
|
239
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
239
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
240
240
|
import { db } from './database';
|
|
241
241
|
|
|
242
242
|
const runner = createMigrationRunner(db);
|
|
@@ -255,7 +255,7 @@ await runner.migrate(migrations);
|
|
|
255
255
|
cliConsole.log('');
|
|
256
256
|
cliConsole.log('Example:');
|
|
257
257
|
cliConsole.log(colors.cyan(`
|
|
258
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
258
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
259
259
|
import { db } from './database';
|
|
260
260
|
|
|
261
261
|
const runner = createMigrationRunner(db);
|
|
@@ -274,7 +274,7 @@ await runner.rollback(migrations, ${steps});
|
|
|
274
274
|
cliConsole.log('');
|
|
275
275
|
cliConsole.log('Example:');
|
|
276
276
|
cliConsole.log(colors.cyan(`
|
|
277
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
277
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
278
278
|
import { db } from './database';
|
|
279
279
|
|
|
280
280
|
const runner = createMigrationRunner(db);
|
|
@@ -293,7 +293,7 @@ await runner.reset(migrations);
|
|
|
293
293
|
cliConsole.log('');
|
|
294
294
|
cliConsole.log('Example:');
|
|
295
295
|
cliConsole.log(colors.cyan(`
|
|
296
|
-
import { createMigrationRunner, loadMigrations } from 'bueno';
|
|
296
|
+
import { createMigrationRunner, loadMigrations } from '@buenojs/bueno';
|
|
297
297
|
import { db } from './database';
|
|
298
298
|
|
|
299
299
|
const runner = createMigrationRunner(db);
|
package/src/cli/commands/new.ts
CHANGED
|
@@ -58,6 +58,7 @@ interface ProjectConfig {
|
|
|
58
58
|
skipGit: boolean;
|
|
59
59
|
docker: boolean;
|
|
60
60
|
deploy: DeployPlatform[];
|
|
61
|
+
link: boolean;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
/**
|
|
@@ -87,9 +88,13 @@ function validateProjectName(name: string): boolean | string {
|
|
|
87
88
|
* Get package.json template
|
|
88
89
|
*/
|
|
89
90
|
function getPackageJsonTemplate(config: ProjectConfig): string {
|
|
90
|
-
const dependencies: Record<string, string> = {
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const dependencies: Record<string, string> = {};
|
|
92
|
+
|
|
93
|
+
// If using link, don't add @buenojs/bueno to dependencies
|
|
94
|
+
// It will be linked from the local version
|
|
95
|
+
if (!config.link) {
|
|
96
|
+
dependencies['@buenojs/bueno'] = '^0.8.0';
|
|
97
|
+
}
|
|
93
98
|
|
|
94
99
|
const devDependencies: Record<string, string> = {
|
|
95
100
|
'@types/bun': 'latest',
|
|
@@ -141,8 +146,8 @@ function getTsConfigTemplate(): string {
|
|
|
141
146
|
allowSyntheticDefaultImports: true,
|
|
142
147
|
jsx: 'react-jsx',
|
|
143
148
|
paths: {
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
'@buenojs/bueno': ['./node_modules/@buenojs/bueno/dist/index.d.ts'],
|
|
150
|
+
},
|
|
146
151
|
},
|
|
147
152
|
include: ['server/**/*', 'client/**/*'],
|
|
148
153
|
exclude: ['node_modules', 'dist'],
|
|
@@ -157,7 +162,7 @@ function getTsConfigTemplate(): string {
|
|
|
157
162
|
*/
|
|
158
163
|
function getMainTemplate(config: ProjectConfig): string {
|
|
159
164
|
if (config.template === 'minimal') {
|
|
160
|
-
return `import { createServer } from 'bueno';
|
|
165
|
+
return `import { createServer } from '@buenojs/bueno';
|
|
161
166
|
|
|
162
167
|
const app = createServer();
|
|
163
168
|
|
|
@@ -169,8 +174,8 @@ await app.listen(3000);
|
|
|
169
174
|
`;
|
|
170
175
|
}
|
|
171
176
|
|
|
172
|
-
return `import { createApp, Module, Controller, Get, Injectable } from 'bueno';
|
|
173
|
-
import type { Context } from 'bueno';
|
|
177
|
+
return `import { createApp, Module, Controller, Get, Injectable } from '@buenojs/bueno';
|
|
178
|
+
import type { Context } from '@buenojs/bueno';
|
|
174
179
|
|
|
175
180
|
// Services
|
|
176
181
|
@Injectable()
|
|
@@ -186,8 +191,44 @@ export class AppController {
|
|
|
186
191
|
constructor(private readonly appService: AppService) {}
|
|
187
192
|
|
|
188
193
|
@Get()
|
|
189
|
-
|
|
190
|
-
return
|
|
194
|
+
hello() {
|
|
195
|
+
return new Response(\`<html>
|
|
196
|
+
<head>
|
|
197
|
+
<title>Welcome to Bueno</title>
|
|
198
|
+
<style>
|
|
199
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
|
200
|
+
h1 { color: #2563eb; }
|
|
201
|
+
code { background: #f3f4f6; padding: 2px 6px; border-radius: 4px; }
|
|
202
|
+
pre { background: #f3f4f6; padding: 16px; border-radius: 8px; overflow-x: auto; }
|
|
203
|
+
a { color: #2563eb; }
|
|
204
|
+
</style>
|
|
205
|
+
</head>
|
|
206
|
+
<body>
|
|
207
|
+
<h1>🎉 Welcome to Bueno Framework!</h1>
|
|
208
|
+
<p>Your Bun-native full-stack framework is running successfully.</p>
|
|
209
|
+
|
|
210
|
+
<h2>Getting Started</h2>
|
|
211
|
+
<ul>
|
|
212
|
+
<li>Edit <code>server/main.ts</code> to modify this app</li>
|
|
213
|
+
<li>Add routes using the <code>@Get()</code>, <code>@Post()</code> decorators</li>
|
|
214
|
+
<li>Create services with <code>@Injectable()</code> and inject them in controllers</li>
|
|
215
|
+
</ul>
|
|
216
|
+
|
|
217
|
+
<h2>Documentation</h2>
|
|
218
|
+
<p>Visit <a href="https://buenojs.dev">https://buenojs.dev</a> for full documentation.</p>
|
|
219
|
+
|
|
220
|
+
<h2>Quick Example</h2>
|
|
221
|
+
<pre><code>@Controller('/api')
|
|
222
|
+
class MyController {
|
|
223
|
+
@Get('/users')
|
|
224
|
+
getUsers() {
|
|
225
|
+
return { users: [] };
|
|
226
|
+
}
|
|
227
|
+
}</code></pre>
|
|
228
|
+
</body>
|
|
229
|
+
</html>\`, {
|
|
230
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' }
|
|
231
|
+
});
|
|
191
232
|
}
|
|
192
233
|
|
|
193
234
|
@Get('health')
|
|
@@ -217,7 +258,7 @@ function getConfigTemplate(config: ProjectConfig): string {
|
|
|
217
258
|
? `{ url: 'sqlite:./data.db' }`
|
|
218
259
|
: `{ url: process.env.DATABASE_URL ?? '${config.database}://localhost/${kebabCase(config.name)}' }`;
|
|
219
260
|
|
|
220
|
-
return `import { defineConfig } from 'bueno';
|
|
261
|
+
return `import { defineConfig } from '@buenojs/bueno';
|
|
221
262
|
|
|
222
263
|
export default defineConfig({
|
|
223
264
|
server: {
|
|
@@ -554,6 +595,7 @@ async function handleNew(args: ParsedArgs): Promise<void> {
|
|
|
554
595
|
const skipInstall = hasFlag(args, 'skip-install');
|
|
555
596
|
const skipGit = hasFlag(args, 'skip-git');
|
|
556
597
|
const docker = hasFlag(args, 'docker');
|
|
598
|
+
const link = hasFlag(args, 'link');
|
|
557
599
|
|
|
558
600
|
// Get deployment platforms (can be specified multiple times)
|
|
559
601
|
const deployPlatforms = getOptionValues(args, 'deploy');
|
|
@@ -628,6 +670,7 @@ async function handleNew(args: ParsedArgs): Promise<void> {
|
|
|
628
670
|
skipGit,
|
|
629
671
|
docker,
|
|
630
672
|
deploy,
|
|
673
|
+
link,
|
|
631
674
|
};
|
|
632
675
|
|
|
633
676
|
// Check if directory exists
|
|
@@ -649,6 +692,7 @@ async function handleNew(args: ParsedArgs): Promise<void> {
|
|
|
649
692
|
['Docker', docker ? colors.green('Yes') : colors.red('No')],
|
|
650
693
|
['Deploy', deploy.length > 0 ? colors.green(deploy.map(getDeployPlatformName).join(', ')) : colors.red('None')],
|
|
651
694
|
['Install dependencies', skipInstall ? colors.red('No') : colors.green('Yes')],
|
|
695
|
+
['Use local package', link ? colors.green('Yes (bun link)') : colors.red('No')],
|
|
652
696
|
['Initialize git', skipGit ? colors.red('No') : colors.green('Yes')],
|
|
653
697
|
];
|
|
654
698
|
|
|
@@ -681,6 +725,30 @@ async function handleNew(args: ParsedArgs): Promise<void> {
|
|
|
681
725
|
} catch {
|
|
682
726
|
installSpinner.warn('Failed to install dependencies. Run `bun install` manually.');
|
|
683
727
|
}
|
|
728
|
+
|
|
729
|
+
// Link local @buenojs/bueno if --link flag is set
|
|
730
|
+
if (link) {
|
|
731
|
+
cliConsole.subheader('Linking local @buenojs/bueno...');
|
|
732
|
+
const linkSpinner = spinner('Running bun link @buenojs/bueno...');
|
|
733
|
+
|
|
734
|
+
try {
|
|
735
|
+
const proc = Bun.spawn(['bun', 'link', '@buenojs/bueno'], {
|
|
736
|
+
cwd: projectPath,
|
|
737
|
+
stdout: 'pipe',
|
|
738
|
+
stderr: 'pipe',
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
const exitCode = await proc.exited;
|
|
742
|
+
|
|
743
|
+
if (exitCode === 0) {
|
|
744
|
+
linkSpinner.success('Local @buenojs/bueno linked successfully');
|
|
745
|
+
} else {
|
|
746
|
+
linkSpinner.warn('Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.');
|
|
747
|
+
}
|
|
748
|
+
} catch {
|
|
749
|
+
linkSpinner.warn('Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.');
|
|
750
|
+
}
|
|
751
|
+
}
|
|
684
752
|
}
|
|
685
753
|
|
|
686
754
|
// Initialize git
|
|
@@ -772,6 +840,12 @@ defineCommand(
|
|
|
772
840
|
default: false,
|
|
773
841
|
description: 'Include Docker configuration (Dockerfile, docker-compose.yml)',
|
|
774
842
|
},
|
|
843
|
+
{
|
|
844
|
+
name: 'link',
|
|
845
|
+
type: 'boolean',
|
|
846
|
+
default: false,
|
|
847
|
+
description: 'Use local @buenojs/bueno via bun link (for development)',
|
|
848
|
+
},
|
|
775
849
|
{
|
|
776
850
|
name: 'deploy',
|
|
777
851
|
type: 'string',
|
|
@@ -798,6 +872,7 @@ defineCommand(
|
|
|
798
872
|
'bueno new my-app --docker --deploy render',
|
|
799
873
|
'bueno new my-app --docker --database postgresql --deploy render',
|
|
800
874
|
'bueno new my-app -y',
|
|
875
|
+
'bueno new my-app --link',
|
|
801
876
|
],
|
|
802
877
|
},
|
|
803
878
|
handleNew,
|
package/src/container/index.ts
CHANGED
|
@@ -382,5 +382,5 @@ export function Inject(token: Token | ForwardRef<Token>): ParameterDecorator {
|
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
// Export getter for use by modules
|
|
386
|
-
export { getContainerMetadata as getInjectTokens };
|
|
385
|
+
// Export getter and setter for use by modules
|
|
386
|
+
export { getContainerMetadata as getInjectTokens, setContainerMetadata, getContainerMetadata };
|
package/src/modules/index.ts
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
isForwardRef,
|
|
15
15
|
resolveForwardRef,
|
|
16
16
|
getInjectTokens,
|
|
17
|
+
setContainerMetadata,
|
|
18
|
+
getContainerMetadata,
|
|
17
19
|
} from "../container";
|
|
18
20
|
import {
|
|
19
21
|
type LazyModuleLoader,
|
|
@@ -162,11 +164,11 @@ export function Inject(token: Token | ForwardRef<Token>): ParameterDecorator {
|
|
|
162
164
|
propertyKey: string | symbol | undefined,
|
|
163
165
|
parameterIndex: number,
|
|
164
166
|
) => {
|
|
165
|
-
const targetObj = target as
|
|
167
|
+
const targetObj = target as object;
|
|
166
168
|
const existingTokens: Array<Token | ForwardRef<Token>> =
|
|
167
|
-
|
|
169
|
+
getContainerMetadata<Array<Token | ForwardRef<Token>>>(targetObj, "inject:tokens") ?? [];
|
|
168
170
|
existingTokens[parameterIndex] = token;
|
|
169
|
-
|
|
171
|
+
setContainerMetadata(targetObj, "inject:tokens", existingTokens);
|
|
170
172
|
};
|
|
171
173
|
}
|
|
172
174
|
|
|
@@ -246,9 +248,16 @@ export class AppModule {
|
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
|
|
249
|
-
// Add providers
|
|
251
|
+
// Add providers (normalize class references to provider objects)
|
|
250
252
|
if (metadata.providers) {
|
|
251
|
-
|
|
253
|
+
const normalizedProviders = metadata.providers.map(p => {
|
|
254
|
+
// If it's a class constructor (function) without token, normalize it
|
|
255
|
+
if (typeof p === 'function' && !p.token) {
|
|
256
|
+
return { token: p, useClass: p };
|
|
257
|
+
}
|
|
258
|
+
return p;
|
|
259
|
+
});
|
|
260
|
+
this.providers.push(...normalizedProviders);
|
|
252
261
|
}
|
|
253
262
|
|
|
254
263
|
// Add controllers
|
|
@@ -475,8 +484,20 @@ export class Application {
|
|
|
475
484
|
>(controllerClass.prototype, "routes") ?? [];
|
|
476
485
|
|
|
477
486
|
// Create controller instance
|
|
478
|
-
|
|
487
|
+
// First, check for explicit injection tokens from @Inject decorator
|
|
488
|
+
let injectTokens =
|
|
479
489
|
getInjectTokens<Array<Token | ForwardRef<Token>>>(controllerClass, "inject:tokens") ?? [];
|
|
490
|
+
|
|
491
|
+
// If no explicit tokens, try to use TypeScript's design:paramtypes metadata
|
|
492
|
+
// This requires the reflect-metadata polyfill to be imported by the user
|
|
493
|
+
if (injectTokens.length === 0 && typeof Reflect !== 'undefined' && typeof Reflect.getMetadata === 'function') {
|
|
494
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', controllerClass) as Array<new (...args: unknown[]) => unknown> | undefined;
|
|
495
|
+
if (paramTypes) {
|
|
496
|
+
// Use the constructor parameter types as injection tokens
|
|
497
|
+
injectTokens = paramTypes.map((paramType) => paramType as unknown as Token);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
480
501
|
const deps = injectTokens.map((tokenOrRef) => {
|
|
481
502
|
// Resolve forward reference if needed
|
|
482
503
|
const token = isForwardRef(tokenOrRef) ? resolveForwardRef(tokenOrRef) : tokenOrRef;
|
package/tsconfig.json
CHANGED