@buenojs/bueno 0.8.1 → 0.8.3
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 +79 -29
- package/dist/index.js +28 -9
- package/package.json +1 -1
- package/src/cli/commands/new.ts +80 -5
- package/src/cli/index.ts +7 -2
- 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
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __export = (target, all) => {
|
|
5
|
-
for (var name in all)
|
|
6
|
-
__defProp(target, name, {
|
|
7
|
-
get: all[name],
|
|
8
|
-
enumerable: true,
|
|
9
|
-
configurable: true,
|
|
10
|
-
set: (newValue) => all[name] = () => newValue
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
|
-
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
14
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
15
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
16
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else
|
|
18
|
-
for (var i = decorators.length - 1;i >= 0; i--)
|
|
19
|
-
if (d = decorators[i])
|
|
20
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
22
|
-
};
|
|
23
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
24
3
|
var __require = import.meta.require;
|
|
25
4
|
|
|
5
|
+
// src/cli/index.ts
|
|
6
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
7
|
+
import { join as join2 } from "path";
|
|
8
|
+
|
|
26
9
|
// src/cli/core/args.ts
|
|
27
10
|
function parseArgs(argv = process.argv.slice(2)) {
|
|
28
11
|
const result = {
|
|
@@ -1328,9 +1311,10 @@ function validateProjectName(name) {
|
|
|
1328
1311
|
return true;
|
|
1329
1312
|
}
|
|
1330
1313
|
function getPackageJsonTemplate(config) {
|
|
1331
|
-
const dependencies = {
|
|
1332
|
-
|
|
1333
|
-
|
|
1314
|
+
const dependencies = {};
|
|
1315
|
+
if (!config.link) {
|
|
1316
|
+
dependencies["@buenojs/bueno"] = "^0.8.0";
|
|
1317
|
+
}
|
|
1334
1318
|
const devDependencies = {
|
|
1335
1319
|
"@types/bun": "latest",
|
|
1336
1320
|
typescript: "^5.3.0"
|
|
@@ -1405,8 +1389,44 @@ export class AppController {
|
|
|
1405
1389
|
constructor(private readonly appService: AppService) {}
|
|
1406
1390
|
|
|
1407
1391
|
@Get()
|
|
1408
|
-
|
|
1409
|
-
return
|
|
1392
|
+
hello() {
|
|
1393
|
+
return new Response(\`<html>
|
|
1394
|
+
<head>
|
|
1395
|
+
<title>Welcome to Bueno</title>
|
|
1396
|
+
<style>
|
|
1397
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
|
1398
|
+
h1 { color: #2563eb; }
|
|
1399
|
+
code { background: #f3f4f6; padding: 2px 6px; border-radius: 4px; }
|
|
1400
|
+
pre { background: #f3f4f6; padding: 16px; border-radius: 8px; overflow-x: auto; }
|
|
1401
|
+
a { color: #2563eb; }
|
|
1402
|
+
</style>
|
|
1403
|
+
</head>
|
|
1404
|
+
<body>
|
|
1405
|
+
<h1>\uD83C\uDF89 Welcome to Bueno Framework!</h1>
|
|
1406
|
+
<p>Your Bun-native full-stack framework is running successfully.</p>
|
|
1407
|
+
|
|
1408
|
+
<h2>Getting Started</h2>
|
|
1409
|
+
<ul>
|
|
1410
|
+
<li>Edit <code>server/main.ts</code> to modify this app</li>
|
|
1411
|
+
<li>Add routes using the <code>@Get()</code>, <code>@Post()</code> decorators</li>
|
|
1412
|
+
<li>Create services with <code>@Injectable()</code> and inject them in controllers</li>
|
|
1413
|
+
</ul>
|
|
1414
|
+
|
|
1415
|
+
<h2>Documentation</h2>
|
|
1416
|
+
<p>Visit <a href="https://buenojs.dev">https://buenojs.dev</a> for full documentation.</p>
|
|
1417
|
+
|
|
1418
|
+
<h2>Quick Example</h2>
|
|
1419
|
+
<pre><code>@Controller('/api')
|
|
1420
|
+
class MyController {
|
|
1421
|
+
@Get('/users')
|
|
1422
|
+
getUsers() {
|
|
1423
|
+
return { users: [] };
|
|
1424
|
+
}
|
|
1425
|
+
}</code></pre>
|
|
1426
|
+
</body>
|
|
1427
|
+
</html>\`, {
|
|
1428
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' }
|
|
1429
|
+
});
|
|
1410
1430
|
}
|
|
1411
1431
|
|
|
1412
1432
|
@Get('health')
|
|
@@ -1669,6 +1689,7 @@ async function handleNew(args) {
|
|
|
1669
1689
|
const skipInstall = hasFlag(args, "skip-install");
|
|
1670
1690
|
const skipGit = hasFlag(args, "skip-git");
|
|
1671
1691
|
const docker = hasFlag(args, "docker");
|
|
1692
|
+
const link = hasFlag(args, "link");
|
|
1672
1693
|
const deployPlatforms = getOptionValues(args, "deploy");
|
|
1673
1694
|
const validPlatforms = ["render", "fly", "railway"];
|
|
1674
1695
|
const deploy = [];
|
|
@@ -1717,7 +1738,8 @@ async function handleNew(args) {
|
|
|
1717
1738
|
skipInstall,
|
|
1718
1739
|
skipGit,
|
|
1719
1740
|
docker,
|
|
1720
|
-
deploy
|
|
1741
|
+
deploy,
|
|
1742
|
+
link
|
|
1721
1743
|
};
|
|
1722
1744
|
const projectPath = joinPaths(process.cwd(), kebabCase(name));
|
|
1723
1745
|
if (await fileExists(projectPath)) {
|
|
@@ -1731,6 +1753,7 @@ async function handleNew(args) {
|
|
|
1731
1753
|
["Docker", docker ? colors.green("Yes") : colors.red("No")],
|
|
1732
1754
|
["Deploy", deploy.length > 0 ? colors.green(deploy.map(getDeployPlatformName).join(", ")) : colors.red("None")],
|
|
1733
1755
|
["Install dependencies", skipInstall ? colors.red("No") : colors.green("Yes")],
|
|
1756
|
+
["Use local package", link ? colors.green("Yes (bun link)") : colors.red("No")],
|
|
1734
1757
|
["Initialize git", skipGit ? colors.red("No") : colors.green("Yes")]
|
|
1735
1758
|
];
|
|
1736
1759
|
printTable(["Setting", "Value"], rows);
|
|
@@ -1755,6 +1778,25 @@ async function handleNew(args) {
|
|
|
1755
1778
|
} catch {
|
|
1756
1779
|
installSpinner.warn("Failed to install dependencies. Run `bun install` manually.");
|
|
1757
1780
|
}
|
|
1781
|
+
if (link) {
|
|
1782
|
+
cliConsole.subheader("Linking local @buenojs/bueno...");
|
|
1783
|
+
const linkSpinner = spinner("Running bun link @buenojs/bueno...");
|
|
1784
|
+
try {
|
|
1785
|
+
const proc = Bun.spawn(["bun", "link", "@buenojs/bueno"], {
|
|
1786
|
+
cwd: projectPath,
|
|
1787
|
+
stdout: "pipe",
|
|
1788
|
+
stderr: "pipe"
|
|
1789
|
+
});
|
|
1790
|
+
const exitCode = await proc.exited;
|
|
1791
|
+
if (exitCode === 0) {
|
|
1792
|
+
linkSpinner.success("Local @buenojs/bueno linked successfully");
|
|
1793
|
+
} else {
|
|
1794
|
+
linkSpinner.warn("Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.");
|
|
1795
|
+
}
|
|
1796
|
+
} catch {
|
|
1797
|
+
linkSpinner.warn("Failed to link @buenojs/bueno. Make sure you have run `bun link` in the bueno directory first.");
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1758
1800
|
}
|
|
1759
1801
|
if (!skipGit) {
|
|
1760
1802
|
cliConsole.subheader("Initializing git repository...");
|
|
@@ -1835,6 +1877,12 @@ defineCommand({
|
|
|
1835
1877
|
default: false,
|
|
1836
1878
|
description: "Include Docker configuration (Dockerfile, docker-compose.yml)"
|
|
1837
1879
|
},
|
|
1880
|
+
{
|
|
1881
|
+
name: "link",
|
|
1882
|
+
type: "boolean",
|
|
1883
|
+
default: false,
|
|
1884
|
+
description: "Use local @buenojs/bueno via bun link (for development)"
|
|
1885
|
+
},
|
|
1838
1886
|
{
|
|
1839
1887
|
name: "deploy",
|
|
1840
1888
|
type: "string",
|
|
@@ -1860,7 +1908,8 @@ defineCommand({
|
|
|
1860
1908
|
"bueno new my-app --deploy render --deploy fly",
|
|
1861
1909
|
"bueno new my-app --docker --deploy render",
|
|
1862
1910
|
"bueno new my-app --docker --database postgresql --deploy render",
|
|
1863
|
-
"bueno new my-app -y"
|
|
1911
|
+
"bueno new my-app -y",
|
|
1912
|
+
"bueno new my-app --link"
|
|
1864
1913
|
]
|
|
1865
1914
|
}, handleNew);
|
|
1866
1915
|
|
|
@@ -3163,7 +3212,8 @@ Bueno CLI - Available Commands
|
|
|
3163
3212
|
}
|
|
3164
3213
|
});
|
|
3165
3214
|
// src/cli/index.ts
|
|
3166
|
-
var
|
|
3215
|
+
var packageJson = JSON.parse(readFileSync2(join2(import.meta.dir, "../../package.json"), "utf-8"));
|
|
3216
|
+
var VERSION = packageJson.version;
|
|
3167
3217
|
class CLIError extends Error {
|
|
3168
3218
|
type;
|
|
3169
3219
|
exitCode;
|
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
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',
|
|
@@ -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')
|
|
@@ -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/cli/index.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Main entry point for the Bueno CLI
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
7
9
|
import { parseArgs, hasFlag, generateGlobalHelpText, generateHelpText, type ParsedArgs } from './core/args';
|
|
8
10
|
import { cliConsole, colors, setColorEnabled } from './core/console';
|
|
9
11
|
import { registry } from './commands';
|
|
@@ -17,8 +19,11 @@ import './commands/build';
|
|
|
17
19
|
import './commands/start';
|
|
18
20
|
import './commands/help';
|
|
19
21
|
|
|
20
|
-
//
|
|
21
|
-
const
|
|
22
|
+
// Read version from package.json dynamically
|
|
23
|
+
const packageJson = JSON.parse(
|
|
24
|
+
readFileSync(join(import.meta.dir, '../../package.json'), 'utf-8')
|
|
25
|
+
);
|
|
26
|
+
const VERSION = packageJson.version;
|
|
22
27
|
|
|
23
28
|
/**
|
|
24
29
|
* CLI error types
|
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