@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.
- package/dist/config-production.d.ts +22 -0
- package/dist/config-production.js +16 -0
- package/dist/config.js +60 -0
- package/dist/controllers/base.js +38 -0
- package/dist/imports.js +224 -0
- package/dist/index.js +5 -1309
- package/dist/maintenance.js +365 -0
- package/dist/proxy.js +28 -0
- package/dist/start.d.ts +1 -0
- package/dist/start.js +54 -0
- package/package.json +5 -5
|
@@ -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
|
+
}
|
package/dist/imports.js
ADDED
|
@@ -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
|
+
}
|