@stacksjs/server 0.70.87 → 0.70.90

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,22 @@
1
+ /**
2
+ * Production server config - minimal, no runtime file loading
3
+ * This config is inlined at build time for compiled binaries
4
+ * @defaultValue `{ server: { host: '0.0.0.0' } }`
5
+ */
6
+ export declare const config: {
7
+ app: {
8
+ name: unknown;
9
+ env: unknown;
10
+ debug: boolean;
11
+ url: unknown
12
+ };
13
+ server: {
14
+ port: unknown;
15
+ /** @defaultValue '0.0.0.0' */
16
+ host: string
17
+ };
18
+ logging: {
19
+ level: unknown
20
+ }
21
+ };
22
+ export default config;
@@ -0,0 +1,16 @@
1
+ export const config = {
2
+ app: {
3
+ name: process.env.APP_NAME || "Stacks",
4
+ env: process.env.APP_ENV || "production",
5
+ debug: process.env.APP_DEBUG === "true" || !1,
6
+ url: process.env.APP_URL || "https://stacksjs.com"
7
+ },
8
+ server: {
9
+ port: Number(process.env.PORT) || 3000,
10
+ host: "0.0.0.0"
11
+ },
12
+ logging: {
13
+ level: process.env.LOG_LEVEL || "info"
14
+ }
15
+ };
16
+ export default config;
package/dist/config.js ADDED
@@ -0,0 +1,60 @@
1
+ import { ports } from "@stacksjs/config";
2
+ export function config(options) {
3
+ const serversMap = {
4
+ frontend: {
5
+ host: "localhost",
6
+ port: ports.frontend
7
+ },
8
+ backend: {
9
+ host: "localhost",
10
+ port: ports.backend
11
+ },
12
+ api: {
13
+ host: "localhost",
14
+ port: ports.api
15
+ },
16
+ admin: {
17
+ host: "localhost",
18
+ port: ports.admin
19
+ },
20
+ library: {
21
+ host: "localhost",
22
+ port: ports.library
23
+ },
24
+ desktop: {
25
+ host: "localhost",
26
+ port: ports.desktop
27
+ },
28
+ docs: {
29
+ host: "localhost",
30
+ port: ports.docs
31
+ },
32
+ email: {
33
+ host: "localhost",
34
+ port: ports.email
35
+ },
36
+ inspect: {
37
+ host: "localhost",
38
+ port: ports.inspect
39
+ },
40
+ "system-tray": {
41
+ host: "localhost",
42
+ port: ports.systemTray
43
+ },
44
+ database: {
45
+ host: "localhost",
46
+ port: ports.database
47
+ }
48
+ };
49
+ if (options.type && options.type in serversMap)
50
+ return {
51
+ host: serversMap[options.type].host,
52
+ port: serversMap[options.type].port,
53
+ open: !1
54
+ };
55
+ return {
56
+ host: options.host || "stacks.localhost",
57
+ port: options.port || 3000,
58
+ open: !1
59
+ };
60
+ }
@@ -0,0 +1,38 @@
1
+ import { log } from "@stacksjs/logging";
2
+ import { response } from "@stacksjs/router";
3
+
4
+ export class Controller {
5
+ json(data, status = 200) {
6
+ return response.json(data, status);
7
+ }
8
+ success(data) {
9
+ return this.json(data, 200);
10
+ }
11
+ created(data) {
12
+ return this.json(data, 201);
13
+ }
14
+ noContent() {
15
+ return response.noContent();
16
+ }
17
+ error(message, status = 500) {
18
+ return this.json({ error: message }, status);
19
+ }
20
+ notFound(message = "Resource not found") {
21
+ return this.error(message, 404);
22
+ }
23
+ unauthorized(message = "Unauthorized") {
24
+ return this.error(message, 401);
25
+ }
26
+ forbidden(message = "Forbidden") {
27
+ return this.error(message, 403);
28
+ }
29
+ validate(request, rules) {
30
+ try {
31
+ const result = request.validate(rules);
32
+ log.info("Validation result:", result);
33
+ return Promise.resolve();
34
+ } catch (error) {
35
+ return Promise.reject(error);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,224 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, relative } from "node:path";
3
+ import { plugin } from "bun";
4
+ import { log } from "@stacksjs/logging";
5
+ import { path } from "@stacksjs/path";
6
+ import { autoImports, generateRuntimeIndex, generateGlobalsScript } from "bun-plugin-auto-imports";
7
+ import { globSync } from "@stacksjs/storage";
8
+ const OPTIONAL_MODEL_MODULES = {
9
+ commerce: ["config/commerce.ts"],
10
+ Content: ["config/cms.ts", "config/blog.ts"],
11
+ realtime: ["config/realtime.ts"]
12
+ };
13
+ function configEnabled(configRelPaths) {
14
+ return configRelPaths.some((rel) => existsSync(path.projectPath(rel)));
15
+ }
16
+ function resolveDefaultModelDirs() {
17
+ const root = path.storagePath("framework/defaults/app/Models"), dirs = [root];
18
+ for (const [subdir, configPaths] of Object.entries(OPTIONAL_MODEL_MODULES))
19
+ if (configEnabled(configPaths))
20
+ dirs.push(`${root}/${subdir}`);
21
+ return dirs;
22
+ }
23
+ function scanDirTopLevel(dir) {
24
+ try {
25
+ return globSync(`${dir}/*.ts`, { ignore: ["**/*.d.ts", "**/index.ts", "**/README*"] });
26
+ } catch {
27
+ return [];
28
+ }
29
+ }
30
+ function scanDefineModelExports(dir, opts = {}) {
31
+ const { recursive = !0 } = opts;
32
+ let files = [];
33
+ try {
34
+ const pattern = recursive ? `${dir}/**/*.ts` : `${dir}/*.ts`;
35
+ files = globSync(pattern, { ignore: ["**/*.d.ts", "**/index.ts", "**/README*"] });
36
+ } catch {
37
+ return [];
38
+ }
39
+ const exports = [], seen = new Set;
40
+ for (const file of files) {
41
+ const basename = file.split("/").pop()?.replace(".ts", "") || "";
42
+ if (basename && !seen.has(basename)) {
43
+ seen.add(basename);
44
+ exports.push({ name: basename, file, isDefault: !0 });
45
+ }
46
+ }
47
+ return exports;
48
+ }
49
+ const GLOBAL_SHADOW_BLOCKLIST = new Set([
50
+ "Error",
51
+ "Request",
52
+ "Response",
53
+ "URL",
54
+ "Map",
55
+ "Set",
56
+ "Object",
57
+ "Array",
58
+ "Number",
59
+ "String",
60
+ "Date",
61
+ "Promise",
62
+ "Symbol"
63
+ ]);
64
+ async function generateDefineModelIndex(entries, outputPath) {
65
+ const lines = ["// Generated by bun-plugin-auto-imports"], seen = new Set;
66
+ for (const entry of entries) {
67
+ const dir = typeof entry === "string" ? entry : entry.dir, recursive = typeof entry === "string" ? !0 : entry.recursive;
68
+ let files = [];
69
+ try {
70
+ const pattern = recursive ? `${dir}/**/*.ts` : `${dir}/*.ts`;
71
+ files = globSync(pattern, { ignore: ["**/*.d.ts", "**/index.ts", "**/README*"] });
72
+ } catch {
73
+ continue;
74
+ }
75
+ for (const file of files) {
76
+ const basename = file.split("/").pop()?.replace(".ts", "") || "";
77
+ if (!basename || seen.has(basename))
78
+ continue;
79
+ seen.add(basename);
80
+ const relativePath = relative(dirname(outputPath), file).replace(/\.ts$/, "");
81
+ if (GLOBAL_SHADOW_BLOCKLIST.has(basename)) {
82
+ lines.push(`// Skipped '${basename}' \u2014 would shadow a built-in global. Import directly if needed.`);
83
+ lines.push(`// export { default as ${basename} } from '${relativePath}'`);
84
+ continue;
85
+ }
86
+ lines.push(`export { default as ${basename} } from '${relativePath}'`);
87
+ }
88
+ }
89
+ await Bun.write(outputPath, lines.join(`
90
+ `) + `
91
+ `);
92
+ }
93
+ export async function generateAutoImportFiles() {
94
+ const userFunctionsPath = path.resourcesPath("functions"), defaultFunctionsPath = path.storagePath("framework/defaults/functions"), functionsPath = userFunctionsPath, outputDir = path.storagePath("framework/auto-imports"), userModelsPath = path.userModelsPath(), defaultModelDirs = resolveDefaultModelDirs(), [defaultsRoot = path.storagePath("framework/defaults/app/Models"), ...enabledSubdirs] = defaultModelDirs, userJobsPath = path.userJobsPath(), userControllersPath = path.userControllersPath(), defaultControllersPath = path.storagePath("framework/defaults/app/Controllers");
95
+ await Bun.write(`${outputDir}/.gitkeep`, "");
96
+ const functionsIndexPath = `${outputDir}/functions.ts`;
97
+ await generateRuntimeIndex([userFunctionsPath, defaultFunctionsPath], functionsIndexPath);
98
+ const modelsIndexPath = `${outputDir}/models.ts`, modelScan = [
99
+ userModelsPath,
100
+ { dir: defaultsRoot, recursive: !1 },
101
+ ...defaultModelDirs.slice(1).map((d) => ({ dir: d, recursive: !0 }))
102
+ ];
103
+ await generateDefineModelIndex(modelScan, modelsIndexPath);
104
+ const jobsIndexPath = `${outputDir}/jobs.ts`;
105
+ await generateDefineModelIndex([userJobsPath], jobsIndexPath);
106
+ const controllersIndexPath = `${outputDir}/controllers.ts`;
107
+ await generateDefineModelIndex([userControllersPath, defaultControllersPath], controllersIndexPath);
108
+ const combinedContent = `// Generated by bun-plugin-auto-imports
109
+ export * from './functions'
110
+ export * from './models'
111
+ export * from './jobs'
112
+ export * from './controllers'
113
+ `;
114
+ await Bun.write(`${outputDir}/index.ts`, combinedContent);
115
+ const globalsPath = `${outputDir}/globals.ts`;
116
+ await generateGlobalsScript([functionsPath], globalsPath, `${outputDir}/index.ts`);
117
+ log.debug("Auto-import files generated successfully");
118
+ }
119
+ export function initiateImports() {
120
+ const functionsPath = path.resourcesPath("functions"), defaultFunctionsPath = path.storagePath("framework/defaults/functions"), userModelsPath = path.userModelsPath(), defaultModelDirs = resolveDefaultModelDirs(), [defaultsRoot = path.storagePath("framework/defaults/app/Models"), ...enabledSubdirs] = defaultModelDirs, userJobsPath = path.userJobsPath(), userControllersPath = path.userControllersPath(), defaultControllersPath = path.storagePath("framework/defaults/app/Controllers"), defineModelExports = [
121
+ ...scanDefineModelExports(userModelsPath),
122
+ ...scanDefineModelExports(defaultsRoot, { recursive: !1 }),
123
+ ...enabledSubdirs.flatMap((d) => scanDefineModelExports(d))
124
+ ], jobExports = scanDefineModelExports(userJobsPath), seen = new Set, uniqueDefineModelExports = defineModelExports.filter((exp) => {
125
+ if (seen.has(exp.name))
126
+ return !1;
127
+ seen.add(exp.name);
128
+ return !0;
129
+ }), dtsDir = dirname(path.storagePath("framework/types/server-auto-imports.d.ts")), defineModelImports = uniqueDefineModelExports.map((exp) => ({
130
+ from: `./${relative(dtsDir, exp.file).replace(/\\/g, "/").replace(/\.ts$/, "")}`,
131
+ name: "default",
132
+ as: exp.name
133
+ })), jobImports = jobExports.map((exp) => ({
134
+ from: `./${relative(dtsDir, exp.file).replace(/\\/g, "/").replace(/\.ts$/, "")}`,
135
+ name: "default",
136
+ as: exp.name
137
+ })), controllerExports = [
138
+ ...scanDefineModelExports(userControllersPath),
139
+ ...scanDefineModelExports(defaultControllersPath)
140
+ ], seenControllers = new Set, controllerImports = controllerExports.filter((exp) => {
141
+ if (seenControllers.has(exp.name))
142
+ return !1;
143
+ seenControllers.add(exp.name);
144
+ return !0;
145
+ }).map((exp) => ({
146
+ from: `./${relative(dtsDir, exp.file).replace(/\\/g, "/").replace(/\.ts$/, "")}`,
147
+ name: "default",
148
+ as: exp.name
149
+ })), options = {
150
+ dts: path.storagePath("framework/types/server-auto-imports.d.ts"),
151
+ imports: [...defineModelImports, ...jobImports, ...controllerImports],
152
+ dirs: [functionsPath, defaultFunctionsPath],
153
+ eslint: {
154
+ enabled: !0,
155
+ filepath: path.storagePath("framework/server-auto-imports.json")
156
+ }
157
+ };
158
+ plugin(autoImports(options));
159
+ generateAutoImportFiles().catch((err) => {
160
+ console.error("[Server] Failed to generate auto-import files:", err);
161
+ });
162
+ }
163
+ export async function injectGlobalAutoImports() {
164
+ if (globalThis.__stacksAutoImportsInjected)
165
+ return;
166
+ globalThis.__stacksAutoImportsInjected = !0;
167
+ const errors = [], primitiveModules = [
168
+ ["@stacksjs/types", ["Every", "ExitCode"]],
169
+ ["@stacksjs/path", ["path"]],
170
+ ["@stacksjs/error-handling", ["HttpError", "handleError"]],
171
+ ["@stacksjs/logging", ["log"]],
172
+ ["@stacksjs/config", ["config"]],
173
+ ["@stacksjs/validation", ["schema"]],
174
+ ["@stacksjs/router", ["response", "request", "route", "Middleware", "url"]],
175
+ ["@stacksjs/storage", ["storage", "fs"]],
176
+ ["@stacksjs/orm", ["defineModel", "toAttrs"]],
177
+ ["@stacksjs/database", ["db", "sql"]],
178
+ ["@stacksjs/email", ["mail", "template"]],
179
+ ["@stacksjs/queue", ["Job"]],
180
+ ["@stacksjs/scheduler", ["schedule"]],
181
+ ["@stacksjs/actions", ["Action"]],
182
+ ["@stacksjs/auth", ["Auth", "register", "sessionCheck"]],
183
+ ["@stacksjs/events", ["dispatch", "listen", "emitter"]],
184
+ ["@stacksjs/feature-flags", ["Feature"]],
185
+ ["@stacksjs/security", ["makeHash", "verifyHash"]],
186
+ ["@stacksjs/collections", ["collect"]],
187
+ ["@stacksjs/cli", ["quotes"]],
188
+ ["@stacksjs/notifications", ["notify", "useNotification", "useEmail", "useSMS", "useChat", "useDatabase"]],
189
+ ["@stacksjs/realtime", ["emit", "emitToUser", "emitToUsers", "createChannel", "dispatchBroadcast"]],
190
+ ["@stacksjs/i18n", ["I18n", "t", "tc", "te", "setLocale", "getLocale"]],
191
+ ["@stacksjs/stx", ["state", "derived", "effect"]],
192
+ ["@stacksjs/browser", ["useDark", "usePreferredDark", "useToggle", "useStorage"]]
193
+ ], importWithTimeout = async (pkg) => {
194
+ return Promise.race([
195
+ import(pkg),
196
+ new Promise((_, reject) => setTimeout(() => reject(Error(`auto-import timed out: ${pkg}`)), 4000))
197
+ ]);
198
+ };
199
+ await Promise.all(primitiveModules.map(async ([pkg, names]) => {
200
+ try {
201
+ const mod = await importWithTimeout(pkg);
202
+ for (const name of names)
203
+ if (mod[name] !== void 0)
204
+ globalThis[name] = mod[name];
205
+ } catch (err) {
206
+ errors.push(err);
207
+ }
208
+ }));
209
+ try {
210
+ const { ensureLocalesLoaded } = await import("@stacksjs/i18n");
211
+ await ensureLocalesLoaded();
212
+ } catch (err) {
213
+ errors.push(err);
214
+ }
215
+ try {
216
+ const autoImports = await import(path.storagePath("framework/auto-imports/index.ts"));
217
+ Object.assign(globalThis, autoImports);
218
+ } catch (err) {
219
+ errors.push(err);
220
+ }
221
+ if (errors.length)
222
+ for (const err of errors)
223
+ console.warn("[auto-imports]", err.message);
224
+ }