@zintrust/core 0.1.17 → 0.1.19
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/README.md +6 -0
- package/package.json +10 -1
- package/public/index.html +1 -1
- package/routes/api.d.ts +7 -0
- package/routes/api.d.ts.map +1 -0
- package/routes/api.js +91 -0
- package/routes/broadcast.d.ts +9 -0
- package/routes/broadcast.d.ts.map +1 -0
- package/routes/broadcast.js +27 -0
- package/routes/health.d.ts +7 -0
- package/routes/health.d.ts.map +1 -0
- package/routes/health.js +127 -0
- package/routes/storage.d.ts +4 -0
- package/routes/storage.d.ts.map +1 -0
- package/routes/storage.js +35 -0
- package/src/boot/Application.js +1 -1
- package/src/boot/bootstrap.js +1 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +2 -0
- package/src/cli/PromptHelper.d.ts.map +1 -1
- package/src/cli/PromptHelper.js +5 -4
- package/src/cli/commands/NewCommand.d.ts +1 -1
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +27 -10
- package/src/cli/commands/SimulateCommand.js +1 -1
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +90 -3
- package/src/cli/commands/UpgradeCommand.d.ts +16 -0
- package/src/cli/commands/UpgradeCommand.d.ts.map +1 -0
- package/src/cli/commands/UpgradeCommand.js +107 -0
- package/src/cli/commands/runner/index.d.ts +3 -0
- package/src/cli/commands/runner/index.d.ts.map +1 -0
- package/src/cli/commands/runner/index.js +139 -0
- package/src/cli/config/ConfigSchema.js +1 -1
- package/src/cli/env/EnvFileBackfill.d.ts +10 -0
- package/src/cli/env/EnvFileBackfill.d.ts.map +1 -0
- package/src/cli/env/EnvFileBackfill.js +64 -0
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +53 -23
- package/src/cli/utils/DistPackager.d.ts.map +1 -1
- package/src/cli/utils/DistPackager.js +8 -0
- package/src/config/broadcast.js +1 -1
- package/src/config/database.d.ts +6 -0
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +7 -1
- package/src/config/index.d.ts +7 -1
- package/src/config/index.d.ts.map +1 -1
- package/src/config/middleware.d.ts +2 -1
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +47 -11
- package/src/config/notification.js +1 -1
- package/src/config/storage.js +1 -1
- package/src/config/type.d.ts +7 -1
- package/src/config/type.d.ts.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.d.ts.map +1 -1
- package/src/middleware/RateLimiter.d.ts +35 -0
- package/src/middleware/RateLimiter.d.ts.map +1 -1
- package/src/middleware/RateLimiter.js +213 -16
- package/src/node.d.ts +1 -1
- package/src/node.d.ts.map +1 -1
- package/src/node.js +4 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +4 -0
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +7 -3
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +5 -1
- package/src/routes/api.d.ts +2 -0
- package/src/routes/api.d.ts.map +1 -0
- package/src/routes/api.js +1 -0
- package/src/routes/broadcast.d.ts +2 -0
- package/src/routes/broadcast.d.ts.map +1 -0
- package/src/routes/broadcast.js +1 -0
- package/src/routes/health.d.ts +2 -0
- package/src/routes/health.d.ts.map +1 -0
- package/src/routes/health.js +1 -0
- package/src/routes/storage.d.ts +2 -0
- package/src/routes/storage.d.ts.map +1 -0
- package/src/routes/storage.js +1 -0
- package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
- package/src/runtime/RuntimeAdapter.js +20 -1
- package/src/runtime/adapters/DenoAdapter.js +2 -2
- package/src/scripts/TemplateImportsCheck.js +7 -7
- package/src/scripts/TemplateSync.js +6 -0
- package/src/start.d.ts +21 -0
- package/src/start.d.ts.map +1 -0
- package/src/start.js +60 -0
- package/src/templates/features/Queue.ts.tpl +2 -3
- package/src/templates/project/basic/.env.example.tpl +1 -1
- package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +2 -4
- package/src/templates/project/basic/app/Middleware/ProfilerMiddleware.ts.tpl +1 -3
- package/src/templates/project/basic/app/Middleware/index.ts.tpl +3 -8
- package/src/templates/project/basic/app/Models/Post.ts.tpl +2 -3
- package/src/templates/project/basic/app/Models/User.ts.tpl +1 -1
- package/src/templates/project/basic/config/FileLogWriter.ts.tpl +1 -1
- package/src/templates/project/basic/config/SecretsManager.ts.tpl +2 -2
- package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +2 -2
- package/src/templates/project/basic/config/app.ts.tpl +3 -3
- package/src/templates/project/basic/config/broadcast.ts.tpl +4 -5
- package/src/templates/project/basic/config/cache.ts.tpl +2 -3
- package/src/templates/project/basic/config/cloudflare.ts.tpl +1 -1
- package/src/templates/project/basic/config/database.ts.tpl +9 -3
- package/src/templates/project/basic/config/env.ts.tpl +1 -1
- package/src/templates/project/basic/config/features.ts.tpl +2 -2
- package/src/templates/project/basic/config/index.ts.tpl +38 -20
- package/src/templates/project/basic/config/logger.ts.tpl +5 -381
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +2 -2
- package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/mail.ts.tpl +2 -3
- package/src/templates/project/basic/config/microservices.ts.tpl +1 -1
- package/src/templates/project/basic/config/middleware.ts.tpl +40 -13
- package/src/templates/project/basic/config/notification.ts.tpl +3 -4
- package/src/templates/project/basic/config/queue.ts.tpl +2 -2
- package/src/templates/project/basic/config/security.ts.tpl +3 -3
- package/src/templates/project/basic/config/startup.ts.tpl +1 -1
- package/src/templates/project/basic/config/storage.ts.tpl +3 -4
- package/src/templates/project/basic/config/type.ts.tpl +12 -2
- package/src/templates/project/basic/package.json.tpl +1 -1
- package/src/templates/project/basic/routes/api.ts.tpl +4 -4
- package/src/templates/project/basic/routes/health.ts.tpl +1 -6
- package/src/templates/project/basic/src/index.ts.tpl +7 -80
- package/src/templates/project/basic/tsconfig.json.tpl +0 -2
package/README.md
CHANGED
|
@@ -21,6 +21,12 @@ zin start
|
|
|
21
21
|
|
|
22
22
|
Your API is now running at `http://localhost:7777`
|
|
23
23
|
|
|
24
|
+
If you’re targeting a different runtime:
|
|
25
|
+
|
|
26
|
+
- Cloudflare Workers (Wrangler): `zin start --wg`
|
|
27
|
+
- AWS Lambda adapter mode: `zin start --lambda`
|
|
28
|
+
- Deno adapter mode: `zin start --deno`
|
|
29
|
+
|
|
24
30
|
The canonical CLI is `zin`. `z` is a shorthand alias.
|
|
25
31
|
|
|
26
32
|
## Install adapters (database/cache/etc.)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Production-grade TypeScript backend framework for JavaScript",
|
|
5
5
|
"homepage": "https://zintrust.com",
|
|
6
6
|
"repository": {
|
|
@@ -18,10 +18,18 @@
|
|
|
18
18
|
"types": "./src/index.d.ts",
|
|
19
19
|
"import": "./src/index.js"
|
|
20
20
|
},
|
|
21
|
+
"./start": {
|
|
22
|
+
"types": "./src/start.d.ts",
|
|
23
|
+
"import": "./src/start.js"
|
|
24
|
+
},
|
|
21
25
|
"./node": {
|
|
22
26
|
"types": "./src/node.d.ts",
|
|
23
27
|
"import": "./src/node.js"
|
|
24
28
|
},
|
|
29
|
+
"./routes/*": {
|
|
30
|
+
"types": "./routes/*.d.ts",
|
|
31
|
+
"import": "./routes/*.js"
|
|
32
|
+
},
|
|
25
33
|
"./package.json": "./package.json"
|
|
26
34
|
},
|
|
27
35
|
"dependencies": {
|
|
@@ -45,6 +53,7 @@
|
|
|
45
53
|
"files": [
|
|
46
54
|
"bin",
|
|
47
55
|
"src",
|
|
56
|
+
"routes",
|
|
48
57
|
"public"
|
|
49
58
|
],
|
|
50
59
|
"engines": {
|
package/public/index.html
CHANGED
package/routes/api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../routes/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,iBAAiB,CAAC;AAEvD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAKpD"}
|
package/routes/api.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Routes
|
|
3
|
+
* Demonstrates routing patterns
|
|
4
|
+
*/
|
|
5
|
+
import { UserController } from '../app/Controllers/UserController.js';
|
|
6
|
+
import { Env } from '../src/config/env.js';
|
|
7
|
+
import { registerBroadcastRoutes } from './broadcast.js';
|
|
8
|
+
import { registerHealthRoutes } from './health.js';
|
|
9
|
+
import { registerStorageRoutes } from './storage.js';
|
|
10
|
+
import { Router } from '../src/routing/Router.js';
|
|
11
|
+
export function registerRoutes(router) {
|
|
12
|
+
const userController = UserController.create();
|
|
13
|
+
registerPublicRoutes(router);
|
|
14
|
+
registerApiV1Routes(router, userController);
|
|
15
|
+
registerAdminRoutes(router);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register public routes
|
|
19
|
+
*/
|
|
20
|
+
function registerPublicRoutes(router) {
|
|
21
|
+
registerRootRoute(router);
|
|
22
|
+
registerHealthRoutes(router);
|
|
23
|
+
registerBroadcastRoutes(router);
|
|
24
|
+
registerStorageRoutes(router);
|
|
25
|
+
}
|
|
26
|
+
function registerRootRoute(router) {
|
|
27
|
+
Router.get(router, '/', async (_req, res) => {
|
|
28
|
+
res.json({
|
|
29
|
+
framework: 'Zintrust Framework',
|
|
30
|
+
app_name: Env.APP_NAME,
|
|
31
|
+
version: '0.1.0',
|
|
32
|
+
env: Env.NODE_ENV ?? 'development',
|
|
33
|
+
database: Env.DB_CONNECTION ?? 'sqlite',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Register API V1 routes
|
|
39
|
+
*/
|
|
40
|
+
function registerApiV1Routes(router, userController) {
|
|
41
|
+
Router.group(router, '/api/v1', (r) => {
|
|
42
|
+
// Auth routes
|
|
43
|
+
Router.post(r, '/auth/login', async (_req, res) => {
|
|
44
|
+
res.json({ message: 'Login endpoint' });
|
|
45
|
+
});
|
|
46
|
+
Router.post(r, '/auth/register', async (_req, res) => {
|
|
47
|
+
res.json({ message: 'Register endpoint' });
|
|
48
|
+
});
|
|
49
|
+
// Protected routes (middleware is not modeled in Router.ts yet)
|
|
50
|
+
const pr = r;
|
|
51
|
+
// User resource (REST-ish)
|
|
52
|
+
Router.resource(pr, '/users', {
|
|
53
|
+
index: userController.index,
|
|
54
|
+
store: userController.store,
|
|
55
|
+
show: userController.show,
|
|
56
|
+
update: userController.update,
|
|
57
|
+
destroy: userController.destroy,
|
|
58
|
+
});
|
|
59
|
+
// If the controller exposes create/edit, wire them explicitly.
|
|
60
|
+
Router.get(pr, '/users/create', userController.create);
|
|
61
|
+
Router.get(pr, '/users/:id/edit', userController.edit);
|
|
62
|
+
// Custom user routes
|
|
63
|
+
Router.get(pr, '/profile', async (_req, res) => {
|
|
64
|
+
res.json({ message: 'Get user profile' });
|
|
65
|
+
});
|
|
66
|
+
Router.put(pr, '/profile', async (_req, res) => {
|
|
67
|
+
res.json({ message: 'Update user profile' });
|
|
68
|
+
});
|
|
69
|
+
// Posts resource
|
|
70
|
+
Router.get(r, '/posts', async (_req, res) => {
|
|
71
|
+
res.json({ data: [] });
|
|
72
|
+
});
|
|
73
|
+
Router.get(r, '/posts/:id', async (req, res) => {
|
|
74
|
+
const id = req.getParam('id');
|
|
75
|
+
res.json({ data: { id } });
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Register admin routes
|
|
81
|
+
*/
|
|
82
|
+
function registerAdminRoutes(router) {
|
|
83
|
+
Router.group(router, '/admin', (r) => {
|
|
84
|
+
Router.get(r, '/dashboard', async (_req, res) => {
|
|
85
|
+
res.json({ message: 'Admin dashboard' });
|
|
86
|
+
});
|
|
87
|
+
Router.get(r, '/users', async (_req, res) => {
|
|
88
|
+
res.json({ data: [] });
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadcast Routes
|
|
3
|
+
*
|
|
4
|
+
* Runtime-only endpoints for broadcast.
|
|
5
|
+
* Provider setup and secret provisioning remain CLI-only.
|
|
6
|
+
*/
|
|
7
|
+
import { type IRouter } from '../src/routing/Router';
|
|
8
|
+
export declare function registerBroadcastRoutes(router: IRouter): void;
|
|
9
|
+
//# sourceMappingURL=broadcast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../routes/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,iBAAiB,CAAC;AAEvD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAsB7D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadcast Routes
|
|
3
|
+
*
|
|
4
|
+
* Runtime-only endpoints for broadcast.
|
|
5
|
+
* Provider setup and secret provisioning remain CLI-only.
|
|
6
|
+
*/
|
|
7
|
+
import { Router } from '../src/routing/Router.js';
|
|
8
|
+
export function registerBroadcastRoutes(router) {
|
|
9
|
+
Router.get(router, '/broadcast/health', async (_req, res) => {
|
|
10
|
+
res.json({ ok: true });
|
|
11
|
+
});
|
|
12
|
+
Router.post(router, '/broadcast/send', async (req, res) => {
|
|
13
|
+
const body = (req.body ?? {});
|
|
14
|
+
const channel = typeof body['channel'] === 'string' ? body['channel'] : '';
|
|
15
|
+
const event = typeof body['event'] === 'string' ? body['event'] : '';
|
|
16
|
+
const data = body['data'];
|
|
17
|
+
if (!channel || !event) {
|
|
18
|
+
res
|
|
19
|
+
.setStatus(400)
|
|
20
|
+
.json({ ok: false, error: 'Invalid payload: channel and event are required' });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const { Broadcast } = await import('../src/tools/broadcast/Broadcast.js');
|
|
24
|
+
const result = await Broadcast.send(channel, event, data);
|
|
25
|
+
res.json({ ok: true, result });
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../routes/health.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,iBAAiB,CAAC;AAEvD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAI1D"}
|
package/routes/health.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Routes
|
|
3
|
+
* Provides health, liveness, and readiness endpoints.
|
|
4
|
+
*/
|
|
5
|
+
import { appConfig } from '../src/config/index.js';
|
|
6
|
+
import { RuntimeHealthProbes } from '../src/health/RuntimeHealthProbes.js';
|
|
7
|
+
import { Env } from '../src/config/env.js';
|
|
8
|
+
import { Logger } from '../src/config/logger.js';
|
|
9
|
+
import { useDatabase } from '../src/orm/Database.js';
|
|
10
|
+
import { QueryBuilder } from '../src/orm/QueryBuilder.js';
|
|
11
|
+
import { Router } from '../src/routing/Router.js';
|
|
12
|
+
export function registerHealthRoutes(router) {
|
|
13
|
+
registerHealthRoute(router);
|
|
14
|
+
registerHealthLiveRoute(router);
|
|
15
|
+
registerHealthReadyRoute(router);
|
|
16
|
+
}
|
|
17
|
+
function registerHealthRoute(router) {
|
|
18
|
+
Router.get(router, '/health', async (_req, res) => {
|
|
19
|
+
const environment = Env.NODE_ENV ?? 'development';
|
|
20
|
+
try {
|
|
21
|
+
const db = useDatabase();
|
|
22
|
+
const maybeIsConnected = db.isConnected;
|
|
23
|
+
const maybeConnect = db.connect;
|
|
24
|
+
if (typeof maybeIsConnected === 'function' && maybeIsConnected.call(db) === false) {
|
|
25
|
+
if (typeof maybeConnect === 'function') {
|
|
26
|
+
await maybeConnect.call(db);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
await QueryBuilder.ping(db);
|
|
30
|
+
const uptime = typeof process !== 'undefined' && typeof process.uptime === 'function'
|
|
31
|
+
? process.uptime()
|
|
32
|
+
: 0;
|
|
33
|
+
res.json({
|
|
34
|
+
status: 'healthy',
|
|
35
|
+
timestamp: new Date().toISOString(),
|
|
36
|
+
uptime,
|
|
37
|
+
database: 'connected',
|
|
38
|
+
environment,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
Logger.error('Health check failed:', error);
|
|
43
|
+
const isProd = environment === 'production' || environment === 'prod';
|
|
44
|
+
res.setStatus(503).json({
|
|
45
|
+
status: 'unhealthy',
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
47
|
+
database: 'disconnected',
|
|
48
|
+
error: isProd ? 'Service unavailable' : error.message,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function registerHealthLiveRoute(router) {
|
|
54
|
+
Router.get(router, '/health/live', async (_req, res) => {
|
|
55
|
+
const uptime = typeof process !== 'undefined' && typeof process.uptime === 'function' ? process.uptime() : 0;
|
|
56
|
+
res.json({
|
|
57
|
+
status: 'alive',
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
uptime,
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function registerHealthReadyRoute(router) {
|
|
64
|
+
Router.get(router, '/health/ready', async (_req, res) => {
|
|
65
|
+
const startTime = Date.now();
|
|
66
|
+
const environment = appConfig.environment;
|
|
67
|
+
let databaseResponseTime = null;
|
|
68
|
+
let cacheResponseTime = null;
|
|
69
|
+
try {
|
|
70
|
+
const db = useDatabase();
|
|
71
|
+
const maybeIsConnected = db.isConnected;
|
|
72
|
+
const maybeConnect = db.connect;
|
|
73
|
+
if (typeof maybeIsConnected === 'function' && maybeIsConnected.call(db) === false) {
|
|
74
|
+
if (typeof maybeConnect === 'function') {
|
|
75
|
+
await maybeConnect.call(db);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
await QueryBuilder.ping(db);
|
|
79
|
+
databaseResponseTime = Date.now() - startTime;
|
|
80
|
+
// Only probe KV at runtime when explicitly configured.
|
|
81
|
+
cacheResponseTime = await RuntimeHealthProbes.pingKvCache(2000);
|
|
82
|
+
res.json({
|
|
83
|
+
status: 'ready',
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
environment,
|
|
86
|
+
dependencies: {
|
|
87
|
+
database: {
|
|
88
|
+
status: 'ready',
|
|
89
|
+
responseTime: databaseResponseTime,
|
|
90
|
+
},
|
|
91
|
+
...(cacheResponseTime === null
|
|
92
|
+
? {}
|
|
93
|
+
: {
|
|
94
|
+
cache: {
|
|
95
|
+
status: 'ready',
|
|
96
|
+
responseTime: cacheResponseTime,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
Logger.error('Readiness check failed:', error);
|
|
104
|
+
const isProd = environment === 'production';
|
|
105
|
+
const responseTime = Date.now() - startTime;
|
|
106
|
+
const dependencies = {
|
|
107
|
+
database: {
|
|
108
|
+
status: databaseResponseTime === null ? 'unavailable' : 'ready',
|
|
109
|
+
responseTime: databaseResponseTime ?? responseTime,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
if (RuntimeHealthProbes.getCacheDriverName() === 'kv') {
|
|
113
|
+
dependencies['cache'] = {
|
|
114
|
+
status: 'unavailable',
|
|
115
|
+
responseTime: cacheResponseTime ?? responseTime,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
res.setStatus(503).json({
|
|
119
|
+
status: 'not_ready',
|
|
120
|
+
timestamp: new Date().toISOString(),
|
|
121
|
+
environment,
|
|
122
|
+
dependencies,
|
|
123
|
+
error: isProd ? 'Service unavailable' : error.message,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../routes/storage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,iBAAiB,CAAC;AAIvD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAiC3D;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { HTTP_HEADERS } from '../src/config/constants.js';
|
|
2
|
+
import { Env } from '../src/config/env.js';
|
|
3
|
+
import { Router } from '../src/routing/Router.js';
|
|
4
|
+
import { LocalSignedUrl } from '../src/tools/storage/LocalSignedUrl.js';
|
|
5
|
+
import { Storage } from '../src/tools/storage/index.js';
|
|
6
|
+
export function registerStorageRoutes(router) {
|
|
7
|
+
Router.get(router, '/storage/download', async (req, res) => {
|
|
8
|
+
const tokenRaw = req.getQueryParam('token');
|
|
9
|
+
const token = typeof tokenRaw === 'string' ? tokenRaw : '';
|
|
10
|
+
if (token.trim() === '') {
|
|
11
|
+
res.setStatus(400).json({ message: 'Missing token' });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const appKey = Env.get('APP_KEY', '');
|
|
15
|
+
if (appKey.trim() === '') {
|
|
16
|
+
res.setStatus(500).json({ message: 'Storage signing is not configured' });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const payload = LocalSignedUrl.verifyToken(token, appKey);
|
|
21
|
+
// Only local disk is supported by this route.
|
|
22
|
+
if (payload.disk !== 'local') {
|
|
23
|
+
res.setStatus(400).json({ message: 'Unsupported disk' });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const contents = await Storage.get('local', payload.key);
|
|
27
|
+
res.setHeader(HTTP_HEADERS.CONTENT_TYPE, 'application/octet-stream');
|
|
28
|
+
res.setStatus(200).send(contents);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
res.setStatus(403).json({ message: 'Invalid or expired token' });
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export default registerStorageRoutes;
|
package/src/boot/Application.js
CHANGED
|
@@ -164,7 +164,7 @@ const registerRoutes = async (resolvedBasePath, router) => {
|
|
|
164
164
|
mod.registerRoutes(router);
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
-
const { registerRoutes: registerFrameworkRoutes } = await import('
|
|
167
|
+
const { registerRoutes: registerFrameworkRoutes } = await import('../routes/api.js');
|
|
168
168
|
registerFrameworkRoutes(router);
|
|
169
169
|
}
|
|
170
170
|
catch (error) {
|
package/src/boot/bootstrap.js
CHANGED
|
@@ -126,7 +126,7 @@ const BootstrapFunctions = Object.freeze({
|
|
|
126
126
|
// Boot application
|
|
127
127
|
await app.boot();
|
|
128
128
|
// Get port and host from environment
|
|
129
|
-
const port = Env.getInt('PORT',
|
|
129
|
+
const port = Env.getInt('PORT', 7777);
|
|
130
130
|
const host = Env.get('HOST', 'localhost');
|
|
131
131
|
// Create and start server
|
|
132
132
|
const server = Server.create(app, port, host);
|
package/src/cli/CLI.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AA0LD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
|
package/src/cli/CLI.js
CHANGED
|
@@ -22,6 +22,7 @@ import { SecretsCommand } from './commands/SecretsCommand.js';
|
|
|
22
22
|
import { SimulateCommand } from './commands/SimulateCommand.js';
|
|
23
23
|
import { StartCommand } from './commands/StartCommand.js';
|
|
24
24
|
import { TemplatesCommand } from './commands/TemplatesCommand.js';
|
|
25
|
+
import { UpgradeCommand } from './commands/UpgradeCommand.js';
|
|
25
26
|
import { ErrorHandler } from './ErrorHandler.js';
|
|
26
27
|
import { esmDirname } from '../common/index.js';
|
|
27
28
|
import { Logger } from '../config/logger.js';
|
|
@@ -68,6 +69,7 @@ const setupProgram = (program, version) => {
|
|
|
68
69
|
const registerCommands = (program) => {
|
|
69
70
|
const commands = [
|
|
70
71
|
NewCommand.create(),
|
|
72
|
+
UpgradeCommand.create(),
|
|
71
73
|
PrepareCommand,
|
|
72
74
|
AddCommand.create(),
|
|
73
75
|
StartCommand.create(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PromptHelper.d.ts","sourceRoot":"","sources":["../../../src/cli/PromptHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;sBACqB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMlE;;OAEG;8BAC6B,MAAM,gBAAe,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAuBrF;;OAEG;6BAEU,MAAM,gBACJ,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"PromptHelper.d.ts","sourceRoot":"","sources":["../../../src/cli/PromptHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;sBACqB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMlE;;OAEG;8BAC6B,MAAM,gBAAe,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAuBrF;;OAEG;6BAEU,MAAM,gBACJ,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAuBlB;;OAEG;uBACqB,MAAM,gBAAsB,OAAO,GAAU,OAAO,CAAC,MAAM,CAAC;IAqBpF;;OAEG;uCAEkB,MAAM,EAAE,gBACd,OAAO,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBpB;;OAEG;qBAEQ,MAAM,mBACC,OAAO,gBACV,OAAO,GACnB,OAAO,CAAC,OAAO,CAAC;IAiBnB;;OAEG;wBAEQ,MAAM,WACN,MAAM,EAAE,kBACF,MAAM,gBACR,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;IAkBlB;;OAEG;uBAEQ,MAAM,iBACD,MAAM,gBACP,OAAO,GACnB,OAAO,CAAC,MAAM,CAAC;EAgBlB,CAAC"}
|
package/src/cli/PromptHelper.js
CHANGED
|
@@ -51,9 +51,10 @@ export const PromptHelper = Object.freeze({
|
|
|
51
51
|
name: 'database',
|
|
52
52
|
message: 'Select database:',
|
|
53
53
|
choices: [
|
|
54
|
-
{ name: 'PostgreSQL
|
|
55
|
-
{ name: 'MySQL', value: 'mysql' },
|
|
56
|
-
{ name: 'SQLite', value: 'sqlite' },
|
|
54
|
+
{ name: 'PostgreSQL — Production-ready relational DB', value: 'postgresql' },
|
|
55
|
+
{ name: 'MySQL — Production-ready relational DB', value: 'mysql' },
|
|
56
|
+
{ name: 'SQLite — Local dev (file-based)', value: 'sqlite' },
|
|
57
|
+
{ name: 'd1-proxy — Cloudflare D1 via HTTPS proxy', value: 'd1-remote' },
|
|
57
58
|
],
|
|
58
59
|
default: defaultDb,
|
|
59
60
|
},
|
|
@@ -63,7 +64,7 @@ export const PromptHelper = Object.freeze({
|
|
|
63
64
|
/**
|
|
64
65
|
* Ask for port number
|
|
65
66
|
*/
|
|
66
|
-
async port(defaultPort =
|
|
67
|
+
async port(defaultPort = 7777, interactive = true) {
|
|
67
68
|
if (!interactive) {
|
|
68
69
|
return defaultPort;
|
|
69
70
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { CommandOptions, IBaseCommand } from '../BaseCommand';
|
|
6
6
|
type TemplateType = 'basic' | 'api' | 'microservice' | 'fullstack';
|
|
7
|
-
type DatabaseType = 'sqlite' | 'mysql' | 'postgresql' | 'mongodb';
|
|
7
|
+
type DatabaseType = 'sqlite' | 'mysql' | 'postgresql' | 'mongodb' | 'd1-remote';
|
|
8
8
|
interface NewProjectConfigResult {
|
|
9
9
|
template: TemplateType;
|
|
10
10
|
database: DatabaseType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/NewCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAe,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAY7E,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,CAAC;AACnE,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"NewCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/NewCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAe,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAY7E,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,CAAC;AACnE,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AAYhF,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAuPhD,UAAU,WAAY,SAAQ,YAAY;IACxC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACxF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACzF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,gBAAgB,EAAE,CAAC;IACjF,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC;IAChC,YAAY,IAAI,MAAM,CAAC;IACvB,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,sBAAsB,EAC9B,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpE;AA2ND;;;GAGG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;cACO,WAAW;EAGrB,CAAC"}
|
|
@@ -51,10 +51,26 @@ const getBooleanOption = (options, key, fallback) => {
|
|
|
51
51
|
};
|
|
52
52
|
const getProjectDefaults = (name, options) => {
|
|
53
53
|
const template = getStringOption(options, 'template', 'basic');
|
|
54
|
-
const
|
|
54
|
+
const normalizeDatabase = (value) => {
|
|
55
|
+
const v = value.trim();
|
|
56
|
+
if (v === 'd1-proxy')
|
|
57
|
+
return 'd1-remote';
|
|
58
|
+
if (v === 'd1-remote')
|
|
59
|
+
return 'd1-remote';
|
|
60
|
+
if (v === 'sqlite')
|
|
61
|
+
return 'sqlite';
|
|
62
|
+
if (v === 'mysql')
|
|
63
|
+
return 'mysql';
|
|
64
|
+
if (v === 'postgresql' || v === 'postgres')
|
|
65
|
+
return 'postgresql';
|
|
66
|
+
if (v === 'mongodb')
|
|
67
|
+
return 'mongodb';
|
|
68
|
+
return 'sqlite';
|
|
69
|
+
};
|
|
70
|
+
const database = normalizeDatabase(getStringOption(options, 'database', 'sqlite'));
|
|
55
71
|
const portRaw = getStringOption(options, 'port', '7777');
|
|
56
72
|
const portParsed = Number.parseInt(portRaw, 10);
|
|
57
|
-
const port = Number.isFinite(portParsed) && portParsed > 0 ? portParsed :
|
|
73
|
+
const port = Number.isFinite(portParsed) && portParsed > 0 ? portParsed : 7777;
|
|
58
74
|
const author = getStringOption(options, 'author', '');
|
|
59
75
|
const description = getStringOption(options, 'description', `A new Zintrust project: ${name}`);
|
|
60
76
|
const interactive = getBooleanOption(options, 'interactive', true);
|
|
@@ -80,7 +96,13 @@ const getQuestions = (name, defaults) => {
|
|
|
80
96
|
type: 'rawlist',
|
|
81
97
|
name: 'database',
|
|
82
98
|
message: 'Database driver:',
|
|
83
|
-
choices: [
|
|
99
|
+
choices: [
|
|
100
|
+
{ name: 'sqlite — Local dev (file-based)', value: 'sqlite' },
|
|
101
|
+
{ name: 'postgresql — Production-ready relational DB', value: 'postgresql' },
|
|
102
|
+
{ name: 'mysql — Production-ready relational DB', value: 'mysql' },
|
|
103
|
+
{ name: 'd1-proxy — Cloudflare D1 via HTTPS proxy', value: 'd1-remote' },
|
|
104
|
+
{ name: 'mongodb — Document DB (may require additional setup)', value: 'mongodb' },
|
|
105
|
+
],
|
|
84
106
|
default: defaults.database,
|
|
85
107
|
},
|
|
86
108
|
{
|
|
@@ -289,14 +311,9 @@ const executeNewCommand = async (options, command) => {
|
|
|
289
311
|
const target = await resolveProjectTarget(options);
|
|
290
312
|
await createProject(target, options, command);
|
|
291
313
|
maybeInitializeGit(options, command, target);
|
|
292
|
-
|
|
314
|
+
await maybeInstallDependencies(options, command, target);
|
|
293
315
|
command.success(`\n✨ Project ${target.name} created successfully!`);
|
|
294
|
-
const
|
|
295
|
-
options['package-manager'];
|
|
296
|
-
const effectivePm = installedWithPm ?? optPm ?? resolvePackageManager();
|
|
297
|
-
const runDevCmd = effectivePm === 'yarn' || effectivePm === 'pnpm'
|
|
298
|
-
? `${effectivePm} dev`
|
|
299
|
-
: `${effectivePm} run dev`;
|
|
316
|
+
const runDevCmd = 'zin start';
|
|
300
317
|
command.info(`\nNext steps:\n cd ${target.cdPath}\n ${runDevCmd}\n`);
|
|
301
318
|
}
|
|
302
319
|
catch (error) {
|
|
@@ -67,7 +67,7 @@ export const SimulateCommand = {
|
|
|
67
67
|
Logger.info(`\n${chalk.bold('Next steps:')}`);
|
|
68
68
|
Logger.info(` cd ${path.relative(process.cwd(), appPath)}`);
|
|
69
69
|
Logger.info(' npm install');
|
|
70
|
-
Logger.info('
|
|
70
|
+
Logger.info(' zin start');
|
|
71
71
|
}
|
|
72
72
|
catch (error) {
|
|
73
73
|
Logger.error('Failed to create simulated app', error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"StartCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/StartCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyZvF,eAAO,MAAM,YAAY;cACb,YAAY;EAyBtB,CAAC"}
|