nextly 0.0.1 → 0.0.2-alpha.1
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/LICENSE +22 -0
- package/README.md +122 -0
- package/dist/_dts-chunks/collections-handler.d-DjgO74Wt.d.ts +20540 -0
- package/dist/_dts-chunks/config.d-DNwsDnjs.d.ts +2589 -0
- package/dist/_dts-chunks/define-component.d-BUgTHmt3.d.ts +1149 -0
- package/dist/_dts-chunks/image-processor.d-OO1PmMrv.d.ts +335 -0
- package/dist/_dts-chunks/index.d-axCAzZ7m.d.ts +17842 -0
- package/dist/_dts-chunks/media.d-DjDOZo4B.d.ts +117 -0
- package/dist/_dts-chunks/on-error.d-CHIKWNxd.d.ts +38 -0
- package/dist/_dts-chunks/storage.d-BUhQ2we_.d.ts +404 -0
- package/dist/actions/index.d.ts +239 -0
- package/dist/actions/index.mjs +281 -0
- package/dist/api/auth-state.d.ts +5 -0
- package/dist/api/auth-state.mjs +131 -0
- package/dist/api/collections-schema-detail.d.ts +56 -0
- package/dist/api/collections-schema-detail.mjs +244 -0
- package/dist/api/collections-schema-export.d.ts +56 -0
- package/dist/api/collections-schema-export.mjs +129 -0
- package/dist/api/collections-schema.d.ts +59 -0
- package/dist/api/collections-schema.mjs +207 -0
- package/dist/api/components-detail.d.ts +50 -0
- package/dist/api/components-detail.mjs +132 -0
- package/dist/api/components.d.ts +69 -0
- package/dist/api/components.mjs +144 -0
- package/dist/api/email-providers-default.d.ts +40 -0
- package/dist/api/email-providers-default.mjs +75 -0
- package/dist/api/email-providers-detail.d.ts +81 -0
- package/dist/api/email-providers-detail.mjs +109 -0
- package/dist/api/email-providers-test.d.ts +43 -0
- package/dist/api/email-providers-test.mjs +114 -0
- package/dist/api/email-providers.d.ts +69 -0
- package/dist/api/email-providers.mjs +110 -0
- package/dist/api/email-send-template.d.ts +41 -0
- package/dist/api/email-send-template.mjs +58 -0
- package/dist/api/email-send.d.ts +42 -0
- package/dist/api/email-send.mjs +58 -0
- package/dist/api/email-templates-detail.d.ts +74 -0
- package/dist/api/email-templates-detail.mjs +112 -0
- package/dist/api/email-templates-layout.d.ts +55 -0
- package/dist/api/email-templates-layout.mjs +92 -0
- package/dist/api/email-templates-preview.d.ts +48 -0
- package/dist/api/email-templates-preview.mjs +93 -0
- package/dist/api/email-templates.d.ts +61 -0
- package/dist/api/email-templates.mjs +118 -0
- package/dist/api/health.d.ts +68 -0
- package/dist/api/health.mjs +67 -0
- package/dist/api/index.d.ts +54 -0
- package/dist/api/index.mjs +16 -0
- package/dist/api/media-bulk.d.ts +74 -0
- package/dist/api/media-bulk.mjs +196 -0
- package/dist/api/media-folders.d.ts +112 -0
- package/dist/api/media-folders.mjs +187 -0
- package/dist/api/media-handlers.d.ts +102 -0
- package/dist/api/media-handlers.mjs +437 -0
- package/dist/api/media.d.ts +117 -0
- package/dist/api/media.mjs +242 -0
- package/dist/api/singles-detail.d.ts +87 -0
- package/dist/api/singles-detail.mjs +170 -0
- package/dist/api/singles-schema-detail.d.ts +54 -0
- package/dist/api/singles-schema-detail.mjs +182 -0
- package/dist/api/singles.d.ts +34 -0
- package/dist/api/singles.mjs +94 -0
- package/dist/api/storage-upload-url.d.ts +48 -0
- package/dist/api/storage-upload-url.mjs +202 -0
- package/dist/api/uploads.d.ts +109 -0
- package/dist/api/uploads.mjs +359 -0
- package/dist/auth/index.d.ts +425 -0
- package/dist/auth/index.mjs +199 -0
- package/dist/boot-apply-PQSYLDIN.mjs +7 -0
- package/dist/chunk-2OALJTK6.mjs +489 -0
- package/dist/chunk-2Q2SX2CS.mjs +365 -0
- package/dist/chunk-2TFX4ND3.mjs +13 -0
- package/dist/chunk-2TWPDSYD.mjs +87 -0
- package/dist/chunk-2W3DVD7S.mjs +647 -0
- package/dist/chunk-2ZFKXPQM.mjs +88 -0
- package/dist/chunk-3FA7FKAV.mjs +832 -0
- package/dist/chunk-3NZ2KMBL.mjs +58 -0
- package/dist/chunk-4MJLT6PZ.mjs +0 -0
- package/dist/chunk-56WO4WX7.mjs +0 -0
- package/dist/chunk-5APFUGAD.mjs +89 -0
- package/dist/chunk-5HMZ644B.mjs +108 -0
- package/dist/chunk-67GXH6PR.mjs +32 -0
- package/dist/chunk-6JNEPWRW.mjs +14368 -0
- package/dist/chunk-6NFHQIJD.mjs +45 -0
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/chunk-A3WPLSDT.mjs +1364 -0
- package/dist/chunk-AGJ6F2T3.mjs +144 -0
- package/dist/chunk-AK6Z23OX.mjs +1464 -0
- package/dist/chunk-APKKRD2G.mjs +102 -0
- package/dist/chunk-B2GV2BWH.mjs +73 -0
- package/dist/chunk-D5HQBNUB.mjs +74 -0
- package/dist/chunk-DNNG377Z.mjs +204 -0
- package/dist/chunk-DP3G27G5.mjs +135 -0
- package/dist/chunk-DV6WVX2Q.mjs +0 -0
- package/dist/chunk-DXGGXIUZ.mjs +57 -0
- package/dist/chunk-EGXBZCGC.mjs +943 -0
- package/dist/chunk-ERCNLX3V.mjs +176 -0
- package/dist/chunk-FQULBZ53.mjs +850 -0
- package/dist/chunk-G2AA4QLC.mjs +262 -0
- package/dist/chunk-GDBJ5JCU.mjs +488 -0
- package/dist/chunk-GJNSJU4S.mjs +19 -0
- package/dist/chunk-GZ6DCQKC.mjs +69 -0
- package/dist/chunk-H26B4FYG.mjs +167 -0
- package/dist/chunk-I4JMR3UR.mjs +21 -0
- package/dist/chunk-INV7QKLG.mjs +508 -0
- package/dist/chunk-IUDOC7N7.mjs +46 -0
- package/dist/chunk-IZWPRDC3.mjs +206 -0
- package/dist/chunk-KIMNCZGV.mjs +15 -0
- package/dist/chunk-L6HW2DA7.mjs +15 -0
- package/dist/chunk-LAZXX4HR.mjs +100 -0
- package/dist/chunk-LDKCUMHK.mjs +95 -0
- package/dist/chunk-LRXMECUA.mjs +0 -0
- package/dist/chunk-M52VMPGA.mjs +119 -0
- package/dist/chunk-MGUWEEI6.mjs +160 -0
- package/dist/chunk-NRUWQ5Z7.mjs +419 -0
- package/dist/chunk-NSEFNNU4.mjs +25360 -0
- package/dist/chunk-NTHVDFGO.mjs +138 -0
- package/dist/chunk-O3QHXMOX.mjs +3166 -0
- package/dist/chunk-P7NH2OSC.mjs +2605 -0
- package/dist/chunk-PKMABBB5.mjs +184 -0
- package/dist/chunk-PWS6XGJK.mjs +76 -0
- package/dist/chunk-R6JJQHFC.mjs +20 -0
- package/dist/chunk-RJLLGGPG.mjs +0 -0
- package/dist/chunk-SBACDPNX.mjs +689 -0
- package/dist/chunk-TO5AFLVQ.mjs +124 -0
- package/dist/chunk-TS7GHTG2.mjs +5436 -0
- package/dist/chunk-UJ2IMJ4W.mjs +133 -0
- package/dist/chunk-UOP63Q54.mjs +102 -0
- package/dist/chunk-UUOFWCM6.mjs +78 -0
- package/dist/chunk-V4EQTOA4.mjs +893 -0
- package/dist/chunk-VJ66NCL4.mjs +193 -0
- package/dist/chunk-VQJQHVEV.mjs +29 -0
- package/dist/chunk-VTJADRO3.mjs +141 -0
- package/dist/chunk-VWF3JO32.mjs +0 -0
- package/dist/chunk-W4MGXIRR.mjs +27 -0
- package/dist/chunk-W5KKPZT5.mjs +1204 -0
- package/dist/chunk-WD34YQ6T.mjs +381 -0
- package/dist/chunk-WZBYMYVW.mjs +14 -0
- package/dist/chunk-X23WKS3Z.mjs +50 -0
- package/dist/chunk-X7TXCYYN.mjs +6496 -0
- package/dist/chunk-XGI4EMS3.mjs +140 -0
- package/dist/chunk-XZKLBMN6.mjs +1153 -0
- package/dist/chunk-YB7INWPY.mjs +0 -0
- package/dist/chunk-YV4Y7SDL.mjs +83 -0
- package/dist/chunk-YZNBLFIW.mjs +1688 -0
- package/dist/chunk-YZZCTONM.mjs +263 -0
- package/dist/chunk-ZE6A3FYH.mjs +289 -0
- package/dist/cli/nextly.mjs +68 -0
- package/dist/cli/utils/index.d.ts +449 -0
- package/dist/cli/utils/index.mjs +49 -0
- package/dist/component-schema-service-5577KVW6.mjs +11 -0
- package/dist/config-loader-23YEMC3Z.mjs +23 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.mjs +109 -0
- package/dist/container-ORGFGYSZ.mjs +9 -0
- package/dist/database/index.d.ts +12 -0
- package/dist/database/index.mjs +40 -0
- package/dist/database/seeders/index.d.ts +93 -0
- package/dist/database/seeders/index.mjs +47 -0
- package/dist/db-sync-demote-LJGKLB3S.mjs +117 -0
- package/dist/db-sync-promote-B26VSYQF.mjs +113 -0
- package/dist/dev-reload-broadcaster-B73IQ53V.mjs +25 -0
- package/dist/dist-M2NOU37V.mjs +19 -0
- package/dist/drizzle-kit-lazy-D2M2PXR2.mjs +13 -0
- package/dist/dynamic-collection-schema-service-IEXTPIZ7.mjs +8 -0
- package/dist/errors/index.d.ts +159 -0
- package/dist/errors/index.mjs +10 -0
- package/dist/factory-IWMBKUJM.mjs +15 -0
- package/dist/first-run-QIVKWJIF.mjs +63 -0
- package/dist/fresh-push-NR67DC3R.mjs +8 -0
- package/dist/index.d.ts +4175 -0
- package/dist/index.mjs +1336 -0
- package/dist/local-plugin-PTET4NAT.mjs +7 -0
- package/dist/logger-NU46DXNY.mjs +15 -0
- package/dist/logger-YE4TC7ZN.mjs +9 -0
- package/dist/migration-journal-EP532Y4L.mjs +139 -0
- package/dist/migrations/mysql/0000_eager_sentry.sql +174 -0
- package/dist/migrations/mysql/0001_soft_giant_girl.sql +27 -0
- package/dist/migrations/mysql/0002_media_table.sql +24 -0
- package/dist/migrations/mysql/0003_dynamic_singles.sql +37 -0
- package/dist/migrations/mysql/0004_dynamic_components.sql +35 -0
- package/dist/migrations/mysql/0005_user_management_tables.sql +92 -0
- package/dist/migrations/mysql/0006_api_keys.sql +36 -0
- package/dist/migrations/mysql/0007_general_settings.sql +20 -0
- package/dist/migrations/mysql/0008_site_settings_logo_url.sql +9 -0
- package/dist/migrations/mysql/0009_activity_log.sql +30 -0
- package/dist/migrations/mysql/0010_site_settings_sidebar.sql +13 -0
- package/dist/migrations/mysql/0011_missing_tables_and_columns.sql +54 -0
- package/dist/migrations/mysql/0012_image_sizes_and_focal_point.sql +30 -0
- package/dist/migrations/mysql/0012_media_folders.sql +43 -0
- package/dist/migrations/mysql/0013_user_brute_force_protection.sql +31 -0
- package/dist/migrations/mysql/0014_email_template_attachments.sql +12 -0
- package/dist/migrations/mysql/0015_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/mysql/20260429_000000_000_initial_journal.sql +22 -0
- package/dist/migrations/mysql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/mysql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/mysql/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/mysql/meta/0000_snapshot.json +1005 -0
- package/dist/migrations/mysql/meta/0001_snapshot.json +1099 -0
- package/dist/migrations/mysql/meta/_journal.json +41 -0
- package/dist/migrations/postgresql/0000_misty_king_bedlam.sql +169 -0
- package/dist/migrations/postgresql/0001_perpetual_captain_marvel.sql +8 -0
- package/dist/migrations/postgresql/0002_sad_spectrum.sql +16 -0
- package/dist/migrations/postgresql/0003_hesitant_ultron.sql +17 -0
- package/dist/migrations/postgresql/0004_media_table.sql +24 -0
- package/dist/migrations/postgresql/0005_media_folders.sql +36 -0
- package/dist/migrations/postgresql/0006_dynamic_collections_update.sql +50 -0
- package/dist/migrations/postgresql/0007_dynamic_singles.sql +38 -0
- package/dist/migrations/postgresql/0008_dynamic_components.sql +37 -0
- package/dist/migrations/postgresql/0009_user_management_tables.sql +95 -0
- package/dist/migrations/postgresql/0010_api_keys.sql +34 -0
- package/dist/migrations/postgresql/0011_general_settings.sql +20 -0
- package/dist/migrations/postgresql/0012_site_settings_logo_url.sql +9 -0
- package/dist/migrations/postgresql/0013_activity_log.sql +29 -0
- package/dist/migrations/postgresql/0014_image_sizes_and_focal_point.sql +33 -0
- package/dist/migrations/postgresql/0014_site_settings_sidebar.sql +13 -0
- package/dist/migrations/postgresql/0015_user_brute_force_protection.sql +29 -0
- package/dist/migrations/postgresql/0016_email_template_attachments.sql +12 -0
- package/dist/migrations/postgresql/0017_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/postgresql/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/postgresql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/postgresql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/postgresql/20260504_000000_nextly_meta.sql +22 -0
- package/dist/migrations/postgresql/meta/0000_snapshot.json +1286 -0
- package/dist/migrations/postgresql/meta/0001_snapshot.json +1407 -0
- package/dist/migrations/postgresql/meta/0002_snapshot.json +1552 -0
- package/dist/migrations/postgresql/meta/0003_snapshot.json +1695 -0
- package/dist/migrations/postgresql/meta/0010_snapshot.json +2345 -0
- package/dist/migrations/postgresql/meta/_journal.json +90 -0
- package/dist/migrations/sqlite/0000_api_keys.sql +34 -0
- package/dist/migrations/sqlite/0001_general_settings.sql +20 -0
- package/dist/migrations/sqlite/0002_site_settings_logo_url.sql +9 -0
- package/dist/migrations/sqlite/0003_activity_log.sql +29 -0
- package/dist/migrations/sqlite/0004_image_sizes_and_focal_point.sql +29 -0
- package/dist/migrations/sqlite/0004_site_settings_sidebar.sql +11 -0
- package/dist/migrations/sqlite/0005_user_brute_force_protection.sql +29 -0
- package/dist/migrations/sqlite/0006_email_template_attachments.sql +12 -0
- package/dist/migrations/sqlite/0007_media_uploaded_by_nullable.sql +111 -0
- package/dist/migrations/sqlite/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/sqlite/20260501_000000_journal_batch.sql +19 -0
- package/dist/migrations/sqlite/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/sqlite/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/sqlite/20260505_000000_user_management_tables.sql +77 -0
- package/dist/next.d.ts +57 -0
- package/dist/next.mjs +55 -0
- package/dist/observability/index.d.ts +87 -0
- package/dist/observability/index.mjs +57 -0
- package/dist/permissions-3DZZQZMI.mjs +39 -0
- package/dist/pipeline-YOML7SWF.mjs +29 -0
- package/dist/preview-ZZTR3QGS.mjs +9 -0
- package/dist/program-PW6UB2ZC.mjs +5934 -0
- package/dist/reconcile-single-tables-7ENVXJGB.mjs +7 -0
- package/dist/register-SF6E6FVU.mjs +49 -0
- package/dist/reload-config-HWQ4G5MM.mjs +23 -0
- package/dist/resolve-single-table-name-JSOMUB3R.mjs +7 -0
- package/dist/routeHandler-UNMMJIBM.mjs +77 -0
- package/dist/runtime-schema-generator-NRA6A6Z6.mjs +8 -0
- package/dist/runtime.d.ts +120 -0
- package/dist/runtime.mjs +73 -0
- package/dist/schema-hash-FMMG6VPJ.mjs +13 -0
- package/dist/schema-registry-EQ36FZDP.mjs +7 -0
- package/dist/scripts/load-env.mjs +42 -0
- package/dist/storage/index.d.ts +566 -0
- package/dist/storage/index.mjs +45 -0
- package/dist/super-admin-G5ZK5F4T.mjs +39 -0
- package/dist/system-table-service-WGSRVEGT.mjs +17 -0
- package/dist/users-7KELGRYJ.mjs +38 -0
- package/package.json +308 -9
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
// src/schemas/api-keys.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var ApiKeyTokenTypeSchema = z.enum(
|
|
4
|
+
["read-only", "full-access", "role-based"],
|
|
5
|
+
{ message: "Token type must be one of: read-only, full-access, role-based" }
|
|
6
|
+
);
|
|
7
|
+
var ExpiresInSchema = z.enum(["7d", "30d", "90d", "unlimited"], {
|
|
8
|
+
message: "Expires in must be one of: 7d, 30d, 90d, unlimited"
|
|
9
|
+
});
|
|
10
|
+
var CreateApiKeySchema = z.object({
|
|
11
|
+
/** Human-readable label, e.g. "Frontend App Key". */
|
|
12
|
+
name: z.string().min(1, "Name is required").max(255, "Name must be 255 characters or less"),
|
|
13
|
+
/** Optional documentation string for the key. */
|
|
14
|
+
description: z.string().optional(),
|
|
15
|
+
/** Determines how permissions are resolved on each request. */
|
|
16
|
+
tokenType: ApiKeyTokenTypeSchema,
|
|
17
|
+
/**
|
|
18
|
+
* ID of the role whose permissions this key will use.
|
|
19
|
+
* Required when tokenType is "role-based"; must be absent otherwise.
|
|
20
|
+
*/
|
|
21
|
+
roleId: z.string().min(1, "Role ID is required").optional(),
|
|
22
|
+
/** How long the key is valid for. "unlimited" = no expiry. */
|
|
23
|
+
expiresIn: ExpiresInSchema
|
|
24
|
+
}).superRefine((data, ctx) => {
|
|
25
|
+
if (data.tokenType === "role-based" && !data.roleId) {
|
|
26
|
+
ctx.addIssue({
|
|
27
|
+
code: z.ZodIssueCode.custom,
|
|
28
|
+
message: "A role must be selected for role-based token type",
|
|
29
|
+
path: ["roleId"]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (data.tokenType !== "role-based" && data.roleId !== void 0) {
|
|
33
|
+
ctx.addIssue({
|
|
34
|
+
code: z.ZodIssueCode.custom,
|
|
35
|
+
message: "roleId must not be provided for non-role-based token types",
|
|
36
|
+
path: ["roleId"]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
var UpdateApiKeySchema = z.object({
|
|
41
|
+
/** Updated human-readable label. Omit to leave unchanged. */
|
|
42
|
+
name: z.string().min(1, "Name cannot be empty").max(255, "Name must be 255 characters or less").optional(),
|
|
43
|
+
/**
|
|
44
|
+
* Updated documentation string.
|
|
45
|
+
* - Omit (undefined) to leave unchanged.
|
|
46
|
+
* - Pass null to explicitly clear the description.
|
|
47
|
+
*/
|
|
48
|
+
description: z.string().nullable().optional()
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// src/middleware/cors.ts
|
|
52
|
+
var DEFAULT_METHODS = ["GET", "POST", "PATCH", "DELETE", "OPTIONS"];
|
|
53
|
+
var DEFAULT_ALLOWED_HEADERS = ["Content-Type", "Authorization"];
|
|
54
|
+
var DEFAULT_EXPOSED_HEADERS = [
|
|
55
|
+
"X-RateLimit-Limit",
|
|
56
|
+
"X-RateLimit-Remaining",
|
|
57
|
+
"X-RateLimit-Reset"
|
|
58
|
+
];
|
|
59
|
+
var DEFAULT_MAX_AGE = 86400;
|
|
60
|
+
function resolveOriginMode(origins) {
|
|
61
|
+
if (origins.length === 0) return "none";
|
|
62
|
+
if (origins.length === 1 && origins[0] === "*") return "wildcard";
|
|
63
|
+
return "allowlist";
|
|
64
|
+
}
|
|
65
|
+
function isOriginAllowed(requestOrigin, allowlist) {
|
|
66
|
+
return allowlist.includes(requestOrigin);
|
|
67
|
+
}
|
|
68
|
+
function createCorsMiddleware(config) {
|
|
69
|
+
const origins = config?.origin ?? [];
|
|
70
|
+
const methods = config?.methods ?? DEFAULT_METHODS;
|
|
71
|
+
const allowedHeaders = config?.allowedHeaders ?? DEFAULT_ALLOWED_HEADERS;
|
|
72
|
+
const exposedHeaders = config?.exposedHeaders ?? DEFAULT_EXPOSED_HEADERS;
|
|
73
|
+
const credentials = config?.credentials ?? true;
|
|
74
|
+
const maxAge = config?.maxAge ?? DEFAULT_MAX_AGE;
|
|
75
|
+
const mode = resolveOriginMode(origins);
|
|
76
|
+
const methodsString = methods.join(", ");
|
|
77
|
+
const allowedHeadersString = allowedHeaders.join(", ");
|
|
78
|
+
const exposedHeadersString = exposedHeaders.join(", ");
|
|
79
|
+
const maxAgeString = String(maxAge);
|
|
80
|
+
if (mode === "wildcard" && process.env.NODE_ENV === "production") {
|
|
81
|
+
console.warn(
|
|
82
|
+
"[nextly] CORS origin is set to '*' (wildcard) in production. This allows any website to make cross-origin requests to your API. Consider restricting to specific origins for production use."
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (mode === "none") {
|
|
86
|
+
return {
|
|
87
|
+
handlePreflight(_request) {
|
|
88
|
+
if (_request.method === "OPTIONS") {
|
|
89
|
+
return new Response(null, {
|
|
90
|
+
status: 204,
|
|
91
|
+
headers: { "Content-Length": "0" }
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
},
|
|
96
|
+
applyHeaders(_request, response) {
|
|
97
|
+
return response;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (mode === "wildcard") {
|
|
102
|
+
return {
|
|
103
|
+
handlePreflight(request) {
|
|
104
|
+
if (request.method !== "OPTIONS") return null;
|
|
105
|
+
return new Response(null, {
|
|
106
|
+
status: 204,
|
|
107
|
+
headers: {
|
|
108
|
+
"Access-Control-Allow-Origin": "*",
|
|
109
|
+
"Access-Control-Allow-Methods": methodsString,
|
|
110
|
+
"Access-Control-Allow-Headers": allowedHeadersString,
|
|
111
|
+
"Access-Control-Max-Age": maxAgeString,
|
|
112
|
+
"Content-Length": "0"
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
applyHeaders(_request, response) {
|
|
117
|
+
const newHeaders = new Headers(response.headers);
|
|
118
|
+
newHeaders.set("Access-Control-Allow-Origin", "*");
|
|
119
|
+
if (exposedHeadersString) {
|
|
120
|
+
newHeaders.set("Access-Control-Expose-Headers", exposedHeadersString);
|
|
121
|
+
}
|
|
122
|
+
return new Response(response.body, {
|
|
123
|
+
status: response.status,
|
|
124
|
+
statusText: response.statusText,
|
|
125
|
+
headers: newHeaders
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const originSet = new Set(origins);
|
|
131
|
+
return {
|
|
132
|
+
handlePreflight(request) {
|
|
133
|
+
if (request.method !== "OPTIONS") return null;
|
|
134
|
+
const requestOrigin = request.headers.get("Origin");
|
|
135
|
+
const headers = {
|
|
136
|
+
"Access-Control-Allow-Methods": methodsString,
|
|
137
|
+
"Access-Control-Allow-Headers": allowedHeadersString,
|
|
138
|
+
"Access-Control-Max-Age": maxAgeString,
|
|
139
|
+
Vary: "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
140
|
+
"Content-Length": "0"
|
|
141
|
+
};
|
|
142
|
+
if (requestOrigin && isOriginAllowed(requestOrigin, [...originSet])) {
|
|
143
|
+
headers["Access-Control-Allow-Origin"] = requestOrigin;
|
|
144
|
+
if (credentials) {
|
|
145
|
+
headers["Access-Control-Allow-Credentials"] = "true";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return new Response(null, { status: 204, headers });
|
|
149
|
+
},
|
|
150
|
+
applyHeaders(request, response) {
|
|
151
|
+
const requestOrigin = request.headers.get("Origin");
|
|
152
|
+
if (!requestOrigin) return response;
|
|
153
|
+
if (!isOriginAllowed(requestOrigin, [...originSet])) {
|
|
154
|
+
const newHeaders2 = new Headers(response.headers);
|
|
155
|
+
newHeaders2.append("Vary", "Origin");
|
|
156
|
+
return new Response(response.body, {
|
|
157
|
+
status: response.status,
|
|
158
|
+
statusText: response.statusText,
|
|
159
|
+
headers: newHeaders2
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const newHeaders = new Headers(response.headers);
|
|
163
|
+
newHeaders.set("Access-Control-Allow-Origin", requestOrigin);
|
|
164
|
+
newHeaders.append("Vary", "Origin");
|
|
165
|
+
if (credentials) {
|
|
166
|
+
newHeaders.set("Access-Control-Allow-Credentials", "true");
|
|
167
|
+
}
|
|
168
|
+
if (exposedHeadersString) {
|
|
169
|
+
newHeaders.set("Access-Control-Expose-Headers", exposedHeadersString);
|
|
170
|
+
}
|
|
171
|
+
return new Response(response.body, {
|
|
172
|
+
status: response.status,
|
|
173
|
+
statusText: response.statusText,
|
|
174
|
+
headers: newHeaders
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/middleware/security-headers.ts
|
|
181
|
+
var DEFAULT_CSP = [
|
|
182
|
+
"default-src 'self'",
|
|
183
|
+
"script-src 'self'",
|
|
184
|
+
"style-src 'self' 'unsafe-inline'",
|
|
185
|
+
"img-src 'self' data: blob:",
|
|
186
|
+
"font-src 'self' data:",
|
|
187
|
+
"connect-src 'self'",
|
|
188
|
+
"frame-ancestors 'none'",
|
|
189
|
+
"base-uri 'self'",
|
|
190
|
+
"form-action 'self'",
|
|
191
|
+
"object-src 'none'"
|
|
192
|
+
].join("; ");
|
|
193
|
+
var DEFAULT_HEADERS = {
|
|
194
|
+
contentSecurityPolicy: {
|
|
195
|
+
header: "Content-Security-Policy",
|
|
196
|
+
value: DEFAULT_CSP
|
|
197
|
+
},
|
|
198
|
+
xContentTypeOptions: {
|
|
199
|
+
header: "X-Content-Type-Options",
|
|
200
|
+
value: "nosniff"
|
|
201
|
+
},
|
|
202
|
+
xFrameOptions: {
|
|
203
|
+
header: "X-Frame-Options",
|
|
204
|
+
value: "DENY"
|
|
205
|
+
},
|
|
206
|
+
strictTransportSecurity: {
|
|
207
|
+
header: "Strict-Transport-Security",
|
|
208
|
+
value: "max-age=31536000; includeSubDomains"
|
|
209
|
+
},
|
|
210
|
+
referrerPolicy: {
|
|
211
|
+
header: "Referrer-Policy",
|
|
212
|
+
value: "strict-origin-when-cross-origin"
|
|
213
|
+
},
|
|
214
|
+
permissionsPolicy: {
|
|
215
|
+
header: "Permissions-Policy",
|
|
216
|
+
value: "camera=(), microphone=(), geolocation=()"
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
function buildHeaderMap(config) {
|
|
220
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
221
|
+
const entries = [];
|
|
222
|
+
for (const [key, def] of Object.entries(DEFAULT_HEADERS)) {
|
|
223
|
+
const configKey = key;
|
|
224
|
+
const userValue = config?.[configKey];
|
|
225
|
+
if (userValue === false) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (configKey === "strictTransportSecurity") {
|
|
229
|
+
if (userValue === void 0 && !isProduction) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const value = typeof userValue === "string" ? userValue : def.value;
|
|
234
|
+
entries.push([def.header, value]);
|
|
235
|
+
}
|
|
236
|
+
return entries;
|
|
237
|
+
}
|
|
238
|
+
function createSecurityHeadersMiddleware(config) {
|
|
239
|
+
const headerEntries = buildHeaderMap(config);
|
|
240
|
+
if (headerEntries.length === 0) {
|
|
241
|
+
return (response) => response;
|
|
242
|
+
}
|
|
243
|
+
return function applySecurityHeaders(response) {
|
|
244
|
+
const newHeaders = new Headers(response.headers);
|
|
245
|
+
for (const [name, value] of headerEntries) {
|
|
246
|
+
newHeaders.set(name, value);
|
|
247
|
+
}
|
|
248
|
+
return new Response(response.body, {
|
|
249
|
+
status: response.status,
|
|
250
|
+
statusText: response.statusText,
|
|
251
|
+
headers: newHeaders
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export {
|
|
257
|
+
ApiKeyTokenTypeSchema,
|
|
258
|
+
ExpiresInSchema,
|
|
259
|
+
CreateApiKeySchema,
|
|
260
|
+
UpdateApiKeySchema,
|
|
261
|
+
createCorsMiddleware,
|
|
262
|
+
createSecurityHeadersMiddleware
|
|
263
|
+
};
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineConfig
|
|
3
|
+
} from "./chunk-GDBJ5JCU.mjs";
|
|
4
|
+
import {
|
|
5
|
+
NextlyError
|
|
6
|
+
} from "./chunk-NRUWQ5Z7.mjs";
|
|
7
|
+
|
|
8
|
+
// src/cli/utils/config-loader.ts
|
|
9
|
+
import { existsSync, watch } from "fs";
|
|
10
|
+
import { resolve, dirname as dirname2 } from "path";
|
|
11
|
+
|
|
12
|
+
// src/cli/utils/config-bundler.ts
|
|
13
|
+
import { randomUUID } from "crypto";
|
|
14
|
+
import { mkdir, rm } from "fs/promises";
|
|
15
|
+
import { dirname, join, basename, extname } from "path";
|
|
16
|
+
import { pathToFileURL } from "url";
|
|
17
|
+
import { build } from "esbuild";
|
|
18
|
+
var opaqueImport = new Function(
|
|
19
|
+
"path",
|
|
20
|
+
"return import(path)"
|
|
21
|
+
);
|
|
22
|
+
async function bundleAndRequire(options) {
|
|
23
|
+
const { filepath } = options;
|
|
24
|
+
const projectRoot = options.cwd ?? dirname(filepath);
|
|
25
|
+
const cacheRoot = join(projectRoot, "node_modules", ".cache", "nextly");
|
|
26
|
+
await mkdir(cacheRoot, { recursive: true });
|
|
27
|
+
const ext = extname(filepath);
|
|
28
|
+
const baseNoExt = basename(filepath, ext);
|
|
29
|
+
const outFile = join(cacheRoot, `${baseNoExt}.${randomUUID()}.mjs`);
|
|
30
|
+
const nodeModulesExternalPlugin = {
|
|
31
|
+
name: "external-node-modules",
|
|
32
|
+
setup(b) {
|
|
33
|
+
b.onResolve({ filter: /.*/ }, (args) => {
|
|
34
|
+
if (args.kind === "entry-point" || args.path.startsWith(".") || args.path.startsWith("/")) {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
return { path: args.path, external: true };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
try {
|
|
42
|
+
const result = await build({
|
|
43
|
+
entryPoints: [filepath],
|
|
44
|
+
bundle: true,
|
|
45
|
+
platform: "node",
|
|
46
|
+
target: "node20",
|
|
47
|
+
format: "esm",
|
|
48
|
+
outfile: outFile,
|
|
49
|
+
external: options.external,
|
|
50
|
+
sourcemap: false,
|
|
51
|
+
metafile: true,
|
|
52
|
+
logLevel: "silent",
|
|
53
|
+
plugins: [nodeModulesExternalPlugin],
|
|
54
|
+
// absWorkingDir lets esbuild resolve relative imports from
|
|
55
|
+
// the user's project, not nextly's package directory.
|
|
56
|
+
absWorkingDir: options.cwd
|
|
57
|
+
});
|
|
58
|
+
const mod = await opaqueImport(pathToFileURL(outFile).toString());
|
|
59
|
+
const dependencies = result.metafile ? Object.keys(result.metafile.inputs) : [];
|
|
60
|
+
return { mod, dependencies };
|
|
61
|
+
} finally {
|
|
62
|
+
try {
|
|
63
|
+
await rm(outFile, { force: true });
|
|
64
|
+
} catch {
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/cli/utils/config-loader.ts
|
|
70
|
+
var CONFIG_FILE_NAMES = [
|
|
71
|
+
"nextly.config.ts",
|
|
72
|
+
"nextly.config.mts",
|
|
73
|
+
"nextly.config.js",
|
|
74
|
+
"nextly.config.mjs"
|
|
75
|
+
];
|
|
76
|
+
var CONFIG_SEARCH_DIRS = [".", "./src", "./config"];
|
|
77
|
+
var cachedConfig = null;
|
|
78
|
+
var fileWatcher = null;
|
|
79
|
+
var changeCallbacks = /* @__PURE__ */ new Set();
|
|
80
|
+
function findConfigFile(cwd) {
|
|
81
|
+
for (const dir of CONFIG_SEARCH_DIRS) {
|
|
82
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
83
|
+
const filePath = resolve(cwd, dir, fileName);
|
|
84
|
+
if (existsSync(filePath)) {
|
|
85
|
+
return filePath;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
function debugLog(options, ...args) {
|
|
92
|
+
if (options.debug) {
|
|
93
|
+
console.log("[config-loader]", ...args);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function startWatching(configPath, options) {
|
|
97
|
+
stopWatching();
|
|
98
|
+
debugLog(options, "Starting file watcher for:", configPath);
|
|
99
|
+
fileWatcher = watch(configPath, (eventType) => {
|
|
100
|
+
void (async () => {
|
|
101
|
+
if (eventType === "change") {
|
|
102
|
+
debugLog(options, "Config file changed, reloading...");
|
|
103
|
+
cachedConfig = null;
|
|
104
|
+
try {
|
|
105
|
+
const result = await loadConfigInternal(options);
|
|
106
|
+
for (const callback of changeCallbacks) {
|
|
107
|
+
try {
|
|
108
|
+
callback(result);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error("[config-loader] Error in change callback:", error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error("[config-loader] Error reloading config:", error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
})();
|
|
118
|
+
});
|
|
119
|
+
fileWatcher.on("error", (error) => {
|
|
120
|
+
console.error("[config-loader] File watcher error:", error);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function stopWatching() {
|
|
124
|
+
if (fileWatcher) {
|
|
125
|
+
fileWatcher.close();
|
|
126
|
+
fileWatcher = null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function loadConfigInternal(options) {
|
|
130
|
+
const cwd = options.cwd ?? process.cwd();
|
|
131
|
+
const configPath = options.configPath ? resolve(cwd, options.configPath) : findConfigFile(cwd);
|
|
132
|
+
if (!configPath) {
|
|
133
|
+
debugLog(options, "No config file found, using default config");
|
|
134
|
+
return {
|
|
135
|
+
config: defineConfig({}),
|
|
136
|
+
configPath: void 0,
|
|
137
|
+
dependencies: []
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (!existsSync(configPath)) {
|
|
141
|
+
throw new NextlyError({
|
|
142
|
+
code: "INVALID_INPUT",
|
|
143
|
+
publicMessage: "Failed to load Nextly configuration.",
|
|
144
|
+
statusCode: 400,
|
|
145
|
+
logMessage: "Config loader error",
|
|
146
|
+
logContext: { configPath, reason: "config-not-found" }
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
debugLog(options, "Loading config from:", configPath);
|
|
150
|
+
try {
|
|
151
|
+
const { mod, dependencies } = await bundleAndRequire({
|
|
152
|
+
filepath: configPath,
|
|
153
|
+
cwd: dirname2(configPath),
|
|
154
|
+
external: [
|
|
155
|
+
"nextly",
|
|
156
|
+
"@nextly/*",
|
|
157
|
+
"drizzle-orm",
|
|
158
|
+
"drizzle-orm/*",
|
|
159
|
+
"better-sqlite3",
|
|
160
|
+
"pg",
|
|
161
|
+
"mysql2",
|
|
162
|
+
"next",
|
|
163
|
+
"next/*",
|
|
164
|
+
"react",
|
|
165
|
+
"react-dom",
|
|
166
|
+
"dotenv",
|
|
167
|
+
"crypto",
|
|
168
|
+
"fs",
|
|
169
|
+
"path",
|
|
170
|
+
"node:*"
|
|
171
|
+
]
|
|
172
|
+
});
|
|
173
|
+
const rawConfig = mod.default ?? mod;
|
|
174
|
+
if (!rawConfig || typeof rawConfig !== "object") {
|
|
175
|
+
throw new NextlyError({
|
|
176
|
+
code: "INVALID_INPUT",
|
|
177
|
+
publicMessage: "Failed to load Nextly configuration.",
|
|
178
|
+
statusCode: 400,
|
|
179
|
+
logMessage: "Config loader error",
|
|
180
|
+
logContext: {
|
|
181
|
+
configPath,
|
|
182
|
+
reason: "invalid-config-export",
|
|
183
|
+
exportType: typeof rawConfig
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
let config = defineConfig(rawConfig);
|
|
188
|
+
const plugins = config.plugins ?? [];
|
|
189
|
+
if (plugins.length > 0) {
|
|
190
|
+
let transformedConfig = { ...config };
|
|
191
|
+
for (const plugin of plugins) {
|
|
192
|
+
if (plugin.config) {
|
|
193
|
+
try {
|
|
194
|
+
transformedConfig = plugin.config(transformedConfig);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
throw new NextlyError({
|
|
197
|
+
code: "INVALID_INPUT",
|
|
198
|
+
publicMessage: "Failed to load Nextly configuration.",
|
|
199
|
+
statusCode: 400,
|
|
200
|
+
logMessage: "Config loader error",
|
|
201
|
+
logContext: {
|
|
202
|
+
configPath,
|
|
203
|
+
reason: "plugin-config-transformer-failed",
|
|
204
|
+
pluginName: plugin.name,
|
|
205
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
206
|
+
},
|
|
207
|
+
cause: error instanceof Error ? error : void 0
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
config = {
|
|
213
|
+
...config,
|
|
214
|
+
collections: transformedConfig.collections ?? config.collections,
|
|
215
|
+
singles: transformedConfig.singles ?? config.singles,
|
|
216
|
+
plugins: transformedConfig.plugins ?? config.plugins,
|
|
217
|
+
storage: transformedConfig.storage ?? config.storage
|
|
218
|
+
};
|
|
219
|
+
debugLog(
|
|
220
|
+
options,
|
|
221
|
+
`Applied config transformers from ${plugins.length} plugin(s)`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
debugLog(options, "Config loaded successfully");
|
|
225
|
+
debugLog(options, "Dependencies:", dependencies);
|
|
226
|
+
return {
|
|
227
|
+
config,
|
|
228
|
+
configPath,
|
|
229
|
+
dependencies
|
|
230
|
+
};
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (NextlyError.is(error)) {
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
throw new NextlyError({
|
|
236
|
+
code: "INVALID_INPUT",
|
|
237
|
+
publicMessage: "Failed to load Nextly configuration.",
|
|
238
|
+
statusCode: 400,
|
|
239
|
+
logMessage: "Config loader error",
|
|
240
|
+
logContext: {
|
|
241
|
+
configPath,
|
|
242
|
+
reason: "load-error",
|
|
243
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
244
|
+
},
|
|
245
|
+
cause: error instanceof Error ? error : void 0
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function loadConfig(options = {}) {
|
|
250
|
+
if (cachedConfig && !options.watch) {
|
|
251
|
+
debugLog(options, "Returning cached config");
|
|
252
|
+
return cachedConfig;
|
|
253
|
+
}
|
|
254
|
+
const result = await loadConfigInternal(options);
|
|
255
|
+
cachedConfig = result;
|
|
256
|
+
if (options.watch && result.configPath) {
|
|
257
|
+
startWatching(result.configPath, options);
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
function watchConfig(callback) {
|
|
262
|
+
changeCallbacks.add(callback);
|
|
263
|
+
return () => {
|
|
264
|
+
changeCallbacks.delete(callback);
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function clearConfigCache() {
|
|
268
|
+
cachedConfig = null;
|
|
269
|
+
stopWatching();
|
|
270
|
+
changeCallbacks.clear();
|
|
271
|
+
}
|
|
272
|
+
function getCachedConfig() {
|
|
273
|
+
return cachedConfig;
|
|
274
|
+
}
|
|
275
|
+
function findNextlyConfig(cwd = process.cwd()) {
|
|
276
|
+
return findConfigFile(cwd);
|
|
277
|
+
}
|
|
278
|
+
var SUPPORTED_EXTENSIONS = CONFIG_FILE_NAMES;
|
|
279
|
+
var SEARCH_DIRECTORIES = CONFIG_SEARCH_DIRS;
|
|
280
|
+
|
|
281
|
+
export {
|
|
282
|
+
loadConfig,
|
|
283
|
+
watchConfig,
|
|
284
|
+
clearConfigCache,
|
|
285
|
+
getCachedConfig,
|
|
286
|
+
findNextlyConfig,
|
|
287
|
+
SUPPORTED_EXTENSIONS,
|
|
288
|
+
SEARCH_DIRECTORIES
|
|
289
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/nextly.ts
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { config } from "dotenv";
|
|
7
|
+
var envPath = join(process.cwd(), ".env");
|
|
8
|
+
if (existsSync(envPath)) {
|
|
9
|
+
config({ path: envPath });
|
|
10
|
+
}
|
|
11
|
+
async function main() {
|
|
12
|
+
const { createProgram } = await import("../program-PW6UB2ZC.mjs");
|
|
13
|
+
const { createLogger } = await import("../logger-NU46DXNY.mjs");
|
|
14
|
+
const { NextlyError } = await import("../errors/index.mjs");
|
|
15
|
+
const telemetry = await import("../dist-M2NOU37V.mjs");
|
|
16
|
+
const program = createProgram();
|
|
17
|
+
try {
|
|
18
|
+
await program.parseAsync(process.argv);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
const logger = createLogger();
|
|
21
|
+
try {
|
|
22
|
+
telemetry.capture("command_failed", {
|
|
23
|
+
command: process.argv[2] ?? "unknown",
|
|
24
|
+
duration_ms: 0,
|
|
25
|
+
error_code: telemetry.classifyError(error, "other")
|
|
26
|
+
});
|
|
27
|
+
await telemetry.shutdown();
|
|
28
|
+
} catch {
|
|
29
|
+
}
|
|
30
|
+
const debugMode = process.env.DEBUG === "true" || process.env.DEBUG === "1";
|
|
31
|
+
if (NextlyError.is(error)) {
|
|
32
|
+
logger.error(error.publicMessage);
|
|
33
|
+
const ctxParts = [`[${String(error.code)}]`];
|
|
34
|
+
if (error.logContext) {
|
|
35
|
+
for (const [k, v] of Object.entries(error.logContext)) {
|
|
36
|
+
if (v === void 0) continue;
|
|
37
|
+
ctxParts.push(
|
|
38
|
+
`${k}=${typeof v === "string" ? v : JSON.stringify(v)}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (ctxParts.length > 1) {
|
|
43
|
+
console.error(ctxParts.join(" "));
|
|
44
|
+
}
|
|
45
|
+
if (debugMode && error.cause?.stack) {
|
|
46
|
+
logger.newline();
|
|
47
|
+
console.error(error.cause.stack);
|
|
48
|
+
}
|
|
49
|
+
} else if (error instanceof Error) {
|
|
50
|
+
if ("code" in error) {
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
logger.error(error.message);
|
|
54
|
+
if (debugMode) {
|
|
55
|
+
logger.newline();
|
|
56
|
+
console.error(error.stack);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
logger.error("An unexpected error occurred");
|
|
60
|
+
console.error(error);
|
|
61
|
+
}
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
main().catch((error) => {
|
|
66
|
+
console.error("Fatal error:", error);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
});
|