@sonicjs-cms/core 2.18.1 → 3.0.0-beta.10
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 +52 -52
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs.map +1 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js.map +1 -0
- package/dist/app-Bo0X1OWX.d.ts +1268 -0
- package/dist/app-Do66yCcV.d.cts +1268 -0
- package/dist/cache-DDARE4QE.js +4 -0
- package/dist/cache-DDARE4QE.js.map +1 -0
- package/dist/cache-LVYS4BPL.cjs +33 -0
- package/dist/cache-LVYS4BPL.cjs.map +1 -0
- package/dist/chunk-2CB4KY7I.cjs +771 -0
- package/dist/chunk-2CB4KY7I.cjs.map +1 -0
- package/dist/{chunk-ABB34XUS.cjs → chunk-3KYKEXV7.cjs} +667 -19
- package/dist/chunk-3KYKEXV7.cjs.map +1 -0
- package/dist/chunk-4BTBSXMR.cjs +912 -0
- package/dist/chunk-4BTBSXMR.cjs.map +1 -0
- package/dist/{chunk-55RDMDOP.js → chunk-5V62WT6M.js} +181 -57
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/{chunk-XXDFQERJ.js → chunk-6OC6MF3C.js} +7192 -9806
- package/dist/chunk-6OC6MF3C.js.map +1 -0
- package/dist/chunk-AI663NBO.js +821 -0
- package/dist/chunk-AI663NBO.js.map +1 -0
- package/dist/chunk-ALDRXTUO.js +273 -0
- package/dist/chunk-ALDRXTUO.js.map +1 -0
- package/dist/{chunk-TFNTM3OA.js → chunk-ATUPB6MN.js} +645 -15
- package/dist/chunk-ATUPB6MN.js.map +1 -0
- package/dist/chunk-BLMTL57B.js +767 -0
- package/dist/chunk-BLMTL57B.js.map +1 -0
- package/dist/{chunk-4ZSNJDLS.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/chunk-CRGUD4KC.cjs.map +1 -0
- package/dist/chunk-F67UK75A.cjs +158 -0
- package/dist/chunk-F67UK75A.cjs.map +1 -0
- package/dist/chunk-GCDZZNIN.js +192 -0
- package/dist/chunk-GCDZZNIN.js.map +1 -0
- package/dist/chunk-HIKBY7MS.cjs +70 -0
- package/dist/chunk-HIKBY7MS.cjs.map +1 -0
- package/dist/chunk-IDCZBF35.js +1186 -0
- package/dist/chunk-IDCZBF35.js.map +1 -0
- package/dist/chunk-IESEVHXL.js +66 -0
- package/dist/chunk-IESEVHXL.js.map +1 -0
- package/dist/chunk-IGADDMXH.js +387 -0
- package/dist/chunk-IGADDMXH.js.map +1 -0
- package/dist/chunk-IHTXB7AT.cjs +276 -0
- package/dist/chunk-IHTXB7AT.cjs.map +1 -0
- package/dist/chunk-IVPRUGTY.js +242 -0
- package/dist/chunk-IVPRUGTY.js.map +1 -0
- package/dist/{chunk-SQ6FNXU2.cjs → chunk-IXUHXTHW.cjs} +2 -151
- package/dist/chunk-IXUHXTHW.cjs.map +1 -0
- package/dist/chunk-J6JTWD2A.cjs +100 -0
- package/dist/chunk-J6JTWD2A.cjs.map +1 -0
- package/dist/chunk-JEQ7FLOD.cjs +199 -0
- package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
- package/dist/{chunk-ON5ZMSU4.js → chunk-JQISFW6U.js} +3 -3
- package/dist/chunk-JQISFW6U.js.map +1 -0
- package/dist/chunk-K25XHMM3.js +566 -0
- package/dist/chunk-K25XHMM3.js.map +1 -0
- package/dist/{chunk-UYJ6TJHX.cjs → chunk-K623Q6WD.cjs} +181 -56
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/chunk-MUNO67TT.cjs +1219 -0
- package/dist/chunk-MUNO67TT.cjs.map +1 -0
- package/dist/chunk-N32OWET6.cjs +327 -0
- package/dist/chunk-N32OWET6.cjs.map +1 -0
- package/dist/chunk-NUKJ54GA.cjs +245 -0
- package/dist/chunk-NUKJ54GA.cjs.map +1 -0
- package/dist/{chunk-XWIA3HVX.js → chunk-OBA2RYZN.js} +6 -1249
- package/dist/chunk-OBA2RYZN.js.map +1 -0
- package/dist/chunk-PMGOBS6X.cjs +408 -0
- package/dist/chunk-PMGOBS6X.cjs.map +1 -0
- package/dist/{chunk-OHYBNCVL.cjs → chunk-PXNTCCPE.cjs} +10 -1256
- package/dist/chunk-PXNTCCPE.cjs.map +1 -0
- package/dist/chunk-PYVFXCSD.js +1828 -0
- package/dist/chunk-PYVFXCSD.js.map +1 -0
- package/dist/{chunk-MGFRZO24.js → chunk-QZGABF2M.js} +3 -149
- package/dist/chunk-QZGABF2M.js.map +1 -0
- package/dist/{chunk-T3Q5V33G.cjs → chunk-R4ILO3W6.cjs} +876 -829
- package/dist/chunk-R4ILO3W6.cjs.map +1 -0
- package/dist/chunk-RMRJGMDE.js +323 -0
- package/dist/chunk-RMRJGMDE.js.map +1 -0
- package/dist/chunk-RNZFGN4R.js +88 -0
- package/dist/chunk-RNZFGN4R.js.map +1 -0
- package/dist/chunk-RQ6N3FTV.js +900 -0
- package/dist/chunk-RQ6N3FTV.js.map +1 -0
- package/dist/{chunk-SXXTQETM.cjs → chunk-TO6EY4P7.cjs} +8722 -11323
- package/dist/chunk-TO6EY4P7.cjs.map +1 -0
- package/dist/chunk-V464XBYS.js +154 -0
- package/dist/chunk-V464XBYS.js.map +1 -0
- package/dist/chunk-YA3TJ65D.cjs +575 -0
- package/dist/chunk-YA3TJ65D.cjs.map +1 -0
- package/dist/chunk-YP7GW2G5.cjs +866 -0
- package/dist/chunk-YP7GW2G5.cjs.map +1 -0
- package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
- package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
- package/dist/config-HFXANXCC.js +6 -0
- package/dist/config-HFXANXCC.js.map +1 -0
- package/dist/config-ON6FNMYX.cjs +19 -0
- package/dist/config-ON6FNMYX.cjs.map +1 -0
- package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
- package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
- package/dist/document-projection-TDWRJX3Z.cjs +13 -0
- package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
- package/dist/document-projection-YYMC6I4U.js +4 -0
- package/dist/document-projection-YYMC6I4U.js.map +1 -0
- package/dist/index.cjs +13737 -4327
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -493
- package/dist/index.d.ts +331 -493
- package/dist/index.js +13456 -4068
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +38 -32
- package/dist/middleware.d.cts +69 -7
- package/dist/middleware.d.ts +69 -7
- package/dist/middleware.js +9 -3
- package/dist/migrations-2XHQEGOQ.cjs +13 -0
- package/dist/{migrations-IYNTWDC6.cjs.map → migrations-2XHQEGOQ.cjs.map} +1 -1
- package/dist/migrations-PE3CDVSM.js +4 -0
- package/dist/{migrations-R337UD46.js.map → migrations-PE3CDVSM.js.map} +1 -1
- package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
- package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
- package/dist/plugins.cjs +171 -12
- package/dist/plugins.d.cts +36 -2
- package/dist/plugins.d.ts +36 -2
- package/dist/plugins.js +5 -2
- package/dist/rbac-O73MFKDA.js +5 -0
- package/dist/rbac-O73MFKDA.js.map +1 -0
- package/dist/rbac-VONLJJKB.cjs +14 -0
- package/dist/rbac-VONLJJKB.cjs.map +1 -0
- package/dist/routes.cjs +42 -46
- package/dist/routes.d.cts +56 -146
- package/dist/routes.d.ts +56 -146
- package/dist/routes.js +18 -10
- package/dist/services.cjs +43 -76
- package/dist/services.d.cts +93 -55
- package/dist/services.d.ts +93 -55
- package/dist/services.js +6 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -29
- package/dist/templates.d.cts +2 -89
- package/dist/templates.d.ts +2 -89
- package/dist/templates.js +3 -3
- package/dist/types-Dea1eNxU.d.cts +286 -0
- package/dist/types-Dea1eNxU.d.ts +286 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +21 -20
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/migrations/0001_core.sql +184 -0
- package/migrations/0002_documents.sql +163 -0
- package/package.json +12 -7
- package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
- package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
- package/dist/app-C9esKLmh.d.cts +0 -112
- package/dist/app-C9esKLmh.d.ts +0 -112
- package/dist/chunk-4R3NOOL3.js +0 -2217
- package/dist/chunk-4R3NOOL3.js.map +0 -1
- package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
- package/dist/chunk-55RDMDOP.js.map +0 -1
- package/dist/chunk-635JAMSE.cjs +0 -653
- package/dist/chunk-635JAMSE.cjs.map +0 -1
- package/dist/chunk-ABB34XUS.cjs.map +0 -1
- package/dist/chunk-C54YUA23.cjs +0 -2219
- package/dist/chunk-C54YUA23.cjs.map +0 -1
- package/dist/chunk-DSUJ5YQH.cjs +0 -722
- package/dist/chunk-DSUJ5YQH.cjs.map +0 -1
- package/dist/chunk-EW5NOBVU.js +0 -1783
- package/dist/chunk-EW5NOBVU.js.map +0 -1
- package/dist/chunk-EXNEW5US.js +0 -648
- package/dist/chunk-EXNEW5US.js.map +0 -1
- package/dist/chunk-I2H5NGJQ.js +0 -692
- package/dist/chunk-I2H5NGJQ.js.map +0 -1
- package/dist/chunk-MGFRZO24.js.map +0 -1
- package/dist/chunk-OHYBNCVL.cjs.map +0 -1
- package/dist/chunk-ON5ZMSU4.js.map +0 -1
- package/dist/chunk-QFWHAFEO.js +0 -1843
- package/dist/chunk-QFWHAFEO.js.map +0 -1
- package/dist/chunk-SQ6FNXU2.cjs.map +0 -1
- package/dist/chunk-SXXTQETM.cjs.map +0 -1
- package/dist/chunk-T3Q5V33G.cjs.map +0 -1
- package/dist/chunk-TFNTM3OA.js.map +0 -1
- package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
- package/dist/chunk-WAEQXGCX.cjs +0 -1898
- package/dist/chunk-WAEQXGCX.cjs.map +0 -1
- package/dist/chunk-XWIA3HVX.js.map +0 -1
- package/dist/chunk-XXDFQERJ.js.map +0 -1
- package/dist/migrations-IYNTWDC6.cjs +0 -13
- package/dist/migrations-R337UD46.js +0 -4
- package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
- package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
- package/migrations/001_initial_schema.sql +0 -170
- package/migrations/002_faq_plugin.sql +0 -86
- package/migrations/003_stage5_enhancements.sql +0 -121
- package/migrations/004_stage6_user_management.sql +0 -183
- package/migrations/005_stage7_workflow_automation.sql +0 -294
- package/migrations/006_plugin_system.sql +0 -155
- package/migrations/007_demo_login_plugin.sql +0 -23
- package/migrations/008_fix_slug_validation.sql +0 -22
- package/migrations/009_system_logging.sql +0 -57
- package/migrations/011_config_managed_collections.sql +0 -15
- package/migrations/012_testimonials_plugin.sql +0 -80
- package/migrations/013_code_examples_plugin.sql +0 -177
- package/migrations/014_fix_plugin_registry.sql +0 -88
- package/migrations/015_add_remaining_plugins.sql +0 -89
- package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
- package/migrations/017_auth_configurable_fields.sql +0 -49
- package/migrations/018_settings_table.sql +0 -23
- package/migrations/019_remove_blog_posts_collection.sql +0 -15
- package/migrations/020_add_email_plugin.sql +0 -22
- package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
- package/migrations/022_add_tinymce_plugin.sql +0 -25
- package/migrations/023_add_easy_mdx_plugin.sql +0 -25
- package/migrations/024_add_quill_editor_plugin.sql +0 -25
- package/migrations/025_add_easymde_plugin.sql +0 -25
- package/migrations/026_add_otp_login.sql +0 -42
- package/migrations/027_fix_slug_field_type.sql +0 -18
- package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
- package/migrations/029_add_forms_system.sql +0 -184
- package/migrations/030_add_turnstile_to_forms.sql +0 -14
- package/migrations/031_ai_search_plugin.sql +0 -45
- package/migrations/032_user_profiles.sql +0 -37
- package/migrations/033_form_content_integration.sql +0 -19
- package/migrations/034_security_audit_plugin.sql +0 -27
- package/migrations/035_user_profiles_data_column.sql +0 -16
- package/migrations/036_analytics_events.sql +0 -22
package/dist/chunk-QFWHAFEO.js
DELETED
|
@@ -1,1843 +0,0 @@
|
|
|
1
|
-
import { getTelemetryConfig, sanitizeErrorMessage, sanitizeRoute, generateInstallationId, generateProjectId } from './chunk-X7ZAEI5S.js';
|
|
2
|
-
import { __export } from './chunk-V4OQ3NZ2.js';
|
|
3
|
-
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
|
|
4
|
-
import { z } from 'zod/v4';
|
|
5
|
-
import { isTable, getTableColumns, getViewSelectedFields, is, Column, SQL, isView, inArray, eq, like, gte, lte, and, count, asc, desc } from 'drizzle-orm';
|
|
6
|
-
import { drizzle } from 'drizzle-orm/d1';
|
|
7
|
-
import { inspectRoutes } from 'hono/dev';
|
|
8
|
-
|
|
9
|
-
// src/db/schema.ts
|
|
10
|
-
var schema_exports = {};
|
|
11
|
-
__export(schema_exports, {
|
|
12
|
-
apiTokens: () => apiTokens,
|
|
13
|
-
collections: () => collections,
|
|
14
|
-
content: () => content,
|
|
15
|
-
contentVersions: () => contentVersions,
|
|
16
|
-
formFiles: () => formFiles,
|
|
17
|
-
formSubmissions: () => formSubmissions,
|
|
18
|
-
forms: () => forms,
|
|
19
|
-
insertCollectionSchema: () => insertCollectionSchema,
|
|
20
|
-
insertContentSchema: () => insertContentSchema,
|
|
21
|
-
insertFormFileSchema: () => insertFormFileSchema,
|
|
22
|
-
insertFormSchema: () => insertFormSchema,
|
|
23
|
-
insertFormSubmissionSchema: () => insertFormSubmissionSchema,
|
|
24
|
-
insertLogConfigSchema: () => insertLogConfigSchema,
|
|
25
|
-
insertMediaSchema: () => insertMediaSchema,
|
|
26
|
-
insertPluginActivityLogSchema: () => insertPluginActivityLogSchema,
|
|
27
|
-
insertPluginAssetSchema: () => insertPluginAssetSchema,
|
|
28
|
-
insertPluginHookSchema: () => insertPluginHookSchema,
|
|
29
|
-
insertPluginRouteSchema: () => insertPluginRouteSchema,
|
|
30
|
-
insertPluginSchema: () => insertPluginSchema,
|
|
31
|
-
insertSecurityEventSchema: () => insertSecurityEventSchema,
|
|
32
|
-
insertSystemLogSchema: () => insertSystemLogSchema,
|
|
33
|
-
insertUserSchema: () => insertUserSchema,
|
|
34
|
-
insertWorkflowHistorySchema: () => insertWorkflowHistorySchema,
|
|
35
|
-
logConfig: () => logConfig,
|
|
36
|
-
media: () => media,
|
|
37
|
-
pluginActivityLog: () => pluginActivityLog,
|
|
38
|
-
pluginAssets: () => pluginAssets,
|
|
39
|
-
pluginHooks: () => pluginHooks,
|
|
40
|
-
pluginRoutes: () => pluginRoutes,
|
|
41
|
-
plugins: () => plugins,
|
|
42
|
-
securityEvents: () => securityEvents,
|
|
43
|
-
selectCollectionSchema: () => selectCollectionSchema,
|
|
44
|
-
selectContentSchema: () => selectContentSchema,
|
|
45
|
-
selectFormFileSchema: () => selectFormFileSchema,
|
|
46
|
-
selectFormSchema: () => selectFormSchema,
|
|
47
|
-
selectFormSubmissionSchema: () => selectFormSubmissionSchema,
|
|
48
|
-
selectLogConfigSchema: () => selectLogConfigSchema,
|
|
49
|
-
selectMediaSchema: () => selectMediaSchema,
|
|
50
|
-
selectPluginActivityLogSchema: () => selectPluginActivityLogSchema,
|
|
51
|
-
selectPluginAssetSchema: () => selectPluginAssetSchema,
|
|
52
|
-
selectPluginHookSchema: () => selectPluginHookSchema,
|
|
53
|
-
selectPluginRouteSchema: () => selectPluginRouteSchema,
|
|
54
|
-
selectPluginSchema: () => selectPluginSchema,
|
|
55
|
-
selectSecurityEventSchema: () => selectSecurityEventSchema,
|
|
56
|
-
selectSystemLogSchema: () => selectSystemLogSchema,
|
|
57
|
-
selectUserSchema: () => selectUserSchema,
|
|
58
|
-
selectWorkflowHistorySchema: () => selectWorkflowHistorySchema,
|
|
59
|
-
systemLogs: () => systemLogs,
|
|
60
|
-
users: () => users,
|
|
61
|
-
workflowHistory: () => workflowHistory
|
|
62
|
-
});
|
|
63
|
-
var CONSTANTS = {
|
|
64
|
-
INT8_MIN: -128,
|
|
65
|
-
INT8_MAX: 127,
|
|
66
|
-
INT8_UNSIGNED_MAX: 255,
|
|
67
|
-
INT16_MIN: -32768,
|
|
68
|
-
INT16_MAX: 32767,
|
|
69
|
-
INT16_UNSIGNED_MAX: 65535,
|
|
70
|
-
INT24_MIN: -8388608,
|
|
71
|
-
INT24_MAX: 8388607,
|
|
72
|
-
INT24_UNSIGNED_MAX: 16777215,
|
|
73
|
-
INT32_MIN: -2147483648,
|
|
74
|
-
INT32_MAX: 2147483647,
|
|
75
|
-
INT32_UNSIGNED_MAX: 4294967295,
|
|
76
|
-
INT48_MIN: -140737488355328,
|
|
77
|
-
INT48_MAX: 140737488355327,
|
|
78
|
-
INT48_UNSIGNED_MAX: 281474976710655,
|
|
79
|
-
INT64_MIN: -9223372036854775808n,
|
|
80
|
-
INT64_MAX: 9223372036854775807n,
|
|
81
|
-
INT64_UNSIGNED_MAX: 18446744073709551615n
|
|
82
|
-
};
|
|
83
|
-
function isColumnType(column, columnTypes) {
|
|
84
|
-
return columnTypes.includes(column.columnType);
|
|
85
|
-
}
|
|
86
|
-
function isWithEnum(column) {
|
|
87
|
-
return "enumValues" in column && Array.isArray(column.enumValues) && column.enumValues.length > 0;
|
|
88
|
-
}
|
|
89
|
-
var isPgEnum = isWithEnum;
|
|
90
|
-
var literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
91
|
-
var jsonSchema = z.union([
|
|
92
|
-
literalSchema,
|
|
93
|
-
z.record(z.string(), z.any()),
|
|
94
|
-
z.array(z.any())
|
|
95
|
-
]);
|
|
96
|
-
var bufferSchema = z.custom((v) => v instanceof Buffer);
|
|
97
|
-
function columnToSchema(column, factory) {
|
|
98
|
-
const z$1 = z;
|
|
99
|
-
const coerce = {};
|
|
100
|
-
let schema;
|
|
101
|
-
if (isWithEnum(column)) {
|
|
102
|
-
schema = column.enumValues.length ? z$1.enum(column.enumValues) : z$1.string();
|
|
103
|
-
}
|
|
104
|
-
if (!schema) {
|
|
105
|
-
if (isColumnType(column, ["PgGeometry", "PgPointTuple"])) {
|
|
106
|
-
schema = z$1.tuple([z$1.number(), z$1.number()]);
|
|
107
|
-
} else if (isColumnType(column, ["PgGeometryObject", "PgPointObject"])) {
|
|
108
|
-
schema = z$1.object({ x: z$1.number(), y: z$1.number() });
|
|
109
|
-
} else if (isColumnType(column, ["PgHalfVector", "PgVector"])) {
|
|
110
|
-
schema = z$1.array(z$1.number());
|
|
111
|
-
schema = column.dimensions ? schema.length(column.dimensions) : schema;
|
|
112
|
-
} else if (isColumnType(column, ["PgLine"])) {
|
|
113
|
-
schema = z$1.tuple([z$1.number(), z$1.number(), z$1.number()]);
|
|
114
|
-
} else if (isColumnType(column, ["PgLineABC"])) {
|
|
115
|
-
schema = z$1.object({
|
|
116
|
-
a: z$1.number(),
|
|
117
|
-
b: z$1.number(),
|
|
118
|
-
c: z$1.number()
|
|
119
|
-
});
|
|
120
|
-
} else if (isColumnType(column, ["PgArray"])) {
|
|
121
|
-
schema = z$1.array(columnToSchema(column.baseColumn));
|
|
122
|
-
schema = column.size ? schema.length(column.size) : schema;
|
|
123
|
-
} else if (column.dataType === "array") {
|
|
124
|
-
schema = z$1.array(z$1.any());
|
|
125
|
-
} else if (column.dataType === "number") {
|
|
126
|
-
schema = numberColumnToSchema(column, z$1, coerce);
|
|
127
|
-
} else if (column.dataType === "bigint") {
|
|
128
|
-
schema = bigintColumnToSchema(column, z$1, coerce);
|
|
129
|
-
} else if (column.dataType === "boolean") {
|
|
130
|
-
schema = coerce === true || coerce.boolean ? z$1.coerce.boolean() : z$1.boolean();
|
|
131
|
-
} else if (column.dataType === "date") {
|
|
132
|
-
schema = coerce === true || coerce.date ? z$1.coerce.date() : z$1.date();
|
|
133
|
-
} else if (column.dataType === "string") {
|
|
134
|
-
schema = stringColumnToSchema(column, z$1, coerce);
|
|
135
|
-
} else if (column.dataType === "json") {
|
|
136
|
-
schema = jsonSchema;
|
|
137
|
-
} else if (column.dataType === "custom") {
|
|
138
|
-
schema = z$1.any();
|
|
139
|
-
} else if (column.dataType === "buffer") {
|
|
140
|
-
schema = bufferSchema;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (!schema) {
|
|
144
|
-
schema = z$1.any();
|
|
145
|
-
}
|
|
146
|
-
return schema;
|
|
147
|
-
}
|
|
148
|
-
function numberColumnToSchema(column, z2, coerce) {
|
|
149
|
-
let unsigned = column.getSQLType().includes("unsigned");
|
|
150
|
-
let min;
|
|
151
|
-
let max;
|
|
152
|
-
let integer2 = false;
|
|
153
|
-
if (isColumnType(column, ["MySqlTinyInt", "SingleStoreTinyInt"])) {
|
|
154
|
-
min = unsigned ? 0 : CONSTANTS.INT8_MIN;
|
|
155
|
-
max = unsigned ? CONSTANTS.INT8_UNSIGNED_MAX : CONSTANTS.INT8_MAX;
|
|
156
|
-
integer2 = true;
|
|
157
|
-
} else if (isColumnType(column, [
|
|
158
|
-
"PgSmallInt",
|
|
159
|
-
"PgSmallSerial",
|
|
160
|
-
"MySqlSmallInt",
|
|
161
|
-
"SingleStoreSmallInt"
|
|
162
|
-
])) {
|
|
163
|
-
min = unsigned ? 0 : CONSTANTS.INT16_MIN;
|
|
164
|
-
max = unsigned ? CONSTANTS.INT16_UNSIGNED_MAX : CONSTANTS.INT16_MAX;
|
|
165
|
-
integer2 = true;
|
|
166
|
-
} else if (isColumnType(column, [
|
|
167
|
-
"PgReal",
|
|
168
|
-
"MySqlFloat",
|
|
169
|
-
"MySqlMediumInt",
|
|
170
|
-
"SingleStoreMediumInt",
|
|
171
|
-
"SingleStoreFloat"
|
|
172
|
-
])) {
|
|
173
|
-
min = unsigned ? 0 : CONSTANTS.INT24_MIN;
|
|
174
|
-
max = unsigned ? CONSTANTS.INT24_UNSIGNED_MAX : CONSTANTS.INT24_MAX;
|
|
175
|
-
integer2 = isColumnType(column, ["MySqlMediumInt", "SingleStoreMediumInt"]);
|
|
176
|
-
} else if (isColumnType(column, [
|
|
177
|
-
"PgInteger",
|
|
178
|
-
"PgSerial",
|
|
179
|
-
"MySqlInt",
|
|
180
|
-
"SingleStoreInt"
|
|
181
|
-
])) {
|
|
182
|
-
min = unsigned ? 0 : CONSTANTS.INT32_MIN;
|
|
183
|
-
max = unsigned ? CONSTANTS.INT32_UNSIGNED_MAX : CONSTANTS.INT32_MAX;
|
|
184
|
-
integer2 = true;
|
|
185
|
-
} else if (isColumnType(column, [
|
|
186
|
-
"PgDoublePrecision",
|
|
187
|
-
"MySqlReal",
|
|
188
|
-
"MySqlDouble",
|
|
189
|
-
"SingleStoreReal",
|
|
190
|
-
"SingleStoreDouble",
|
|
191
|
-
"SQLiteReal"
|
|
192
|
-
])) {
|
|
193
|
-
min = unsigned ? 0 : CONSTANTS.INT48_MIN;
|
|
194
|
-
max = unsigned ? CONSTANTS.INT48_UNSIGNED_MAX : CONSTANTS.INT48_MAX;
|
|
195
|
-
} else if (isColumnType(column, [
|
|
196
|
-
"PgBigInt53",
|
|
197
|
-
"PgBigSerial53",
|
|
198
|
-
"MySqlBigInt53",
|
|
199
|
-
"MySqlSerial",
|
|
200
|
-
"SingleStoreBigInt53",
|
|
201
|
-
"SingleStoreSerial",
|
|
202
|
-
"SQLiteInteger"
|
|
203
|
-
])) {
|
|
204
|
-
unsigned = unsigned || isColumnType(column, ["MySqlSerial", "SingleStoreSerial"]);
|
|
205
|
-
min = unsigned ? 0 : Number.MIN_SAFE_INTEGER;
|
|
206
|
-
max = Number.MAX_SAFE_INTEGER;
|
|
207
|
-
integer2 = true;
|
|
208
|
-
} else if (isColumnType(column, ["MySqlYear", "SingleStoreYear"])) {
|
|
209
|
-
min = 1901;
|
|
210
|
-
max = 2155;
|
|
211
|
-
integer2 = true;
|
|
212
|
-
} else {
|
|
213
|
-
min = Number.MIN_SAFE_INTEGER;
|
|
214
|
-
max = Number.MAX_SAFE_INTEGER;
|
|
215
|
-
}
|
|
216
|
-
let schema = coerce === true || coerce?.number ? integer2 ? z2.coerce.number() : z2.coerce.number().int() : integer2 ? z2.int() : z2.number();
|
|
217
|
-
schema = schema.gte(min).lte(max);
|
|
218
|
-
return schema;
|
|
219
|
-
}
|
|
220
|
-
function bigintColumnToSchema(column, z2, coerce) {
|
|
221
|
-
const unsigned = column.getSQLType().includes("unsigned");
|
|
222
|
-
const min = unsigned ? 0n : CONSTANTS.INT64_MIN;
|
|
223
|
-
const max = unsigned ? CONSTANTS.INT64_UNSIGNED_MAX : CONSTANTS.INT64_MAX;
|
|
224
|
-
const schema = coerce === true || coerce?.bigint ? z2.coerce.bigint() : z2.bigint();
|
|
225
|
-
return schema.gte(min).lte(max);
|
|
226
|
-
}
|
|
227
|
-
function stringColumnToSchema(column, z2, coerce) {
|
|
228
|
-
if (isColumnType(column, ["PgUUID"])) {
|
|
229
|
-
return z2.uuid();
|
|
230
|
-
}
|
|
231
|
-
let max;
|
|
232
|
-
let regex;
|
|
233
|
-
let fixed = false;
|
|
234
|
-
if (isColumnType(column, ["PgVarchar", "SQLiteText"])) {
|
|
235
|
-
max = column.length;
|
|
236
|
-
} else if (isColumnType(column, ["MySqlVarChar", "SingleStoreVarChar"])) {
|
|
237
|
-
max = column.length ?? CONSTANTS.INT16_UNSIGNED_MAX;
|
|
238
|
-
} else if (isColumnType(column, ["MySqlText", "SingleStoreText"])) {
|
|
239
|
-
if (column.textType === "longtext") {
|
|
240
|
-
max = CONSTANTS.INT32_UNSIGNED_MAX;
|
|
241
|
-
} else if (column.textType === "mediumtext") {
|
|
242
|
-
max = CONSTANTS.INT24_UNSIGNED_MAX;
|
|
243
|
-
} else if (column.textType === "text") {
|
|
244
|
-
max = CONSTANTS.INT16_UNSIGNED_MAX;
|
|
245
|
-
} else {
|
|
246
|
-
max = CONSTANTS.INT8_UNSIGNED_MAX;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (isColumnType(column, [
|
|
250
|
-
"PgChar",
|
|
251
|
-
"MySqlChar",
|
|
252
|
-
"SingleStoreChar"
|
|
253
|
-
])) {
|
|
254
|
-
max = column.length;
|
|
255
|
-
fixed = true;
|
|
256
|
-
}
|
|
257
|
-
if (isColumnType(column, ["PgBinaryVector"])) {
|
|
258
|
-
regex = /^[01]+$/;
|
|
259
|
-
max = column.dimensions;
|
|
260
|
-
}
|
|
261
|
-
let schema = coerce === true || coerce?.string ? z2.coerce.string() : z2.string();
|
|
262
|
-
schema = regex ? schema.regex(regex) : schema;
|
|
263
|
-
return max && fixed ? schema.length(max) : max ? schema.max(max) : schema;
|
|
264
|
-
}
|
|
265
|
-
function getColumns(tableLike) {
|
|
266
|
-
return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike);
|
|
267
|
-
}
|
|
268
|
-
function handleColumns(columns, refinements, conditions, factory) {
|
|
269
|
-
const columnSchemas = {};
|
|
270
|
-
for (const [key, selected] of Object.entries(columns)) {
|
|
271
|
-
if (!is(selected, Column) && !is(selected, SQL) && !is(selected, SQL.Aliased) && typeof selected === "object") {
|
|
272
|
-
const columns2 = isTable(selected) || isView(selected) ? getColumns(selected) : selected;
|
|
273
|
-
columnSchemas[key] = handleColumns(columns2, refinements[key] ?? {}, conditions);
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
const refinement = refinements[key];
|
|
277
|
-
if (refinement !== void 0 && typeof refinement !== "function") {
|
|
278
|
-
columnSchemas[key] = refinement;
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
const column = is(selected, Column) ? selected : void 0;
|
|
282
|
-
const schema = column ? columnToSchema(column) : z.any();
|
|
283
|
-
const refined = typeof refinement === "function" ? refinement(schema) : schema;
|
|
284
|
-
if (conditions.never(column)) {
|
|
285
|
-
continue;
|
|
286
|
-
} else {
|
|
287
|
-
columnSchemas[key] = refined;
|
|
288
|
-
}
|
|
289
|
-
if (column) {
|
|
290
|
-
if (conditions.nullable(column)) {
|
|
291
|
-
columnSchemas[key] = columnSchemas[key].nullable();
|
|
292
|
-
}
|
|
293
|
-
if (conditions.optional(column)) {
|
|
294
|
-
columnSchemas[key] = columnSchemas[key].optional();
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return z.object(columnSchemas);
|
|
299
|
-
}
|
|
300
|
-
function handleEnum(enum_, factory) {
|
|
301
|
-
const zod = z;
|
|
302
|
-
return zod.enum(enum_.enumValues);
|
|
303
|
-
}
|
|
304
|
-
var selectConditions = {
|
|
305
|
-
never: () => false,
|
|
306
|
-
optional: () => false,
|
|
307
|
-
nullable: (column) => !column.notNull
|
|
308
|
-
};
|
|
309
|
-
var insertConditions = {
|
|
310
|
-
never: (column) => column?.generated?.type === "always" || column?.generatedIdentity?.type === "always",
|
|
311
|
-
optional: (column) => !column.notNull || column.notNull && column.hasDefault,
|
|
312
|
-
nullable: (column) => !column.notNull
|
|
313
|
-
};
|
|
314
|
-
var createSelectSchema = (entity, refine) => {
|
|
315
|
-
if (isPgEnum(entity)) {
|
|
316
|
-
return handleEnum(entity);
|
|
317
|
-
}
|
|
318
|
-
const columns = getColumns(entity);
|
|
319
|
-
return handleColumns(columns, {}, selectConditions);
|
|
320
|
-
};
|
|
321
|
-
var createInsertSchema = (entity, refine) => {
|
|
322
|
-
const columns = getColumns(entity);
|
|
323
|
-
return handleColumns(columns, refine ?? {}, insertConditions);
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
// src/db/schema.ts
|
|
327
|
-
var users = sqliteTable("users", {
|
|
328
|
-
id: text("id").primaryKey(),
|
|
329
|
-
email: text("email").notNull().unique(),
|
|
330
|
-
username: text("username").notNull().unique(),
|
|
331
|
-
firstName: text("first_name").notNull(),
|
|
332
|
-
lastName: text("last_name").notNull(),
|
|
333
|
-
passwordHash: text("password_hash"),
|
|
334
|
-
// Hashed password, nullable for OAuth users
|
|
335
|
-
role: text("role").notNull().default("viewer"),
|
|
336
|
-
// 'admin', 'editor', 'author', 'viewer'
|
|
337
|
-
avatar: text("avatar"),
|
|
338
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
339
|
-
lastLoginAt: integer("last_login_at"),
|
|
340
|
-
createdAt: integer("created_at").notNull(),
|
|
341
|
-
updatedAt: integer("updated_at").notNull()
|
|
342
|
-
});
|
|
343
|
-
var collections = sqliteTable("collections", {
|
|
344
|
-
id: text("id").primaryKey(),
|
|
345
|
-
name: text("name").notNull().unique(),
|
|
346
|
-
displayName: text("display_name").notNull(),
|
|
347
|
-
description: text("description"),
|
|
348
|
-
schema: text("schema", { mode: "json" }).notNull(),
|
|
349
|
-
// JSON schema definition
|
|
350
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
351
|
-
managed: integer("managed", { mode: "boolean" }).notNull().default(false),
|
|
352
|
-
// Config-managed collections cannot be edited in UI
|
|
353
|
-
sourceType: text("source_type").default("user"),
|
|
354
|
-
// 'user' (normal), 'form' (form-derived)
|
|
355
|
-
sourceId: text("source_id"),
|
|
356
|
-
// stores the form ID for form-derived collections
|
|
357
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
358
|
-
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
359
|
-
});
|
|
360
|
-
var content = sqliteTable("content", {
|
|
361
|
-
id: text("id").primaryKey(),
|
|
362
|
-
collectionId: text("collection_id").notNull().references(() => collections.id),
|
|
363
|
-
slug: text("slug").notNull(),
|
|
364
|
-
title: text("title").notNull(),
|
|
365
|
-
data: text("data", { mode: "json" }).notNull(),
|
|
366
|
-
// JSON content data
|
|
367
|
-
status: text("status").notNull().default("draft"),
|
|
368
|
-
// 'draft', 'published', 'archived'
|
|
369
|
-
publishedAt: integer("published_at", { mode: "timestamp" }),
|
|
370
|
-
authorId: text("author_id").notNull().references(() => users.id),
|
|
371
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
372
|
-
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
373
|
-
});
|
|
374
|
-
var contentVersions = sqliteTable("content_versions", {
|
|
375
|
-
id: text("id").primaryKey(),
|
|
376
|
-
contentId: text("content_id").notNull().references(() => content.id),
|
|
377
|
-
version: integer("version").notNull(),
|
|
378
|
-
data: text("data", { mode: "json" }).notNull(),
|
|
379
|
-
authorId: text("author_id").notNull().references(() => users.id),
|
|
380
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
381
|
-
});
|
|
382
|
-
var media = sqliteTable("media", {
|
|
383
|
-
id: text("id").primaryKey(),
|
|
384
|
-
filename: text("filename").notNull(),
|
|
385
|
-
originalName: text("original_name").notNull(),
|
|
386
|
-
mimeType: text("mime_type").notNull(),
|
|
387
|
-
size: integer("size").notNull(),
|
|
388
|
-
width: integer("width"),
|
|
389
|
-
height: integer("height"),
|
|
390
|
-
folder: text("folder").notNull().default("uploads"),
|
|
391
|
-
r2Key: text("r2_key").notNull(),
|
|
392
|
-
// R2 storage key
|
|
393
|
-
publicUrl: text("public_url").notNull(),
|
|
394
|
-
// CDN URL
|
|
395
|
-
thumbnailUrl: text("thumbnail_url"),
|
|
396
|
-
alt: text("alt"),
|
|
397
|
-
caption: text("caption"),
|
|
398
|
-
tags: text("tags", { mode: "json" }),
|
|
399
|
-
// JSON array of tags
|
|
400
|
-
uploadedBy: text("uploaded_by").notNull().references(() => users.id),
|
|
401
|
-
uploadedAt: integer("uploaded_at").notNull(),
|
|
402
|
-
updatedAt: integer("updated_at"),
|
|
403
|
-
publishedAt: integer("published_at"),
|
|
404
|
-
scheduledAt: integer("scheduled_at"),
|
|
405
|
-
archivedAt: integer("archived_at"),
|
|
406
|
-
deletedAt: integer("deleted_at")
|
|
407
|
-
});
|
|
408
|
-
var apiTokens = sqliteTable("api_tokens", {
|
|
409
|
-
id: text("id").primaryKey(),
|
|
410
|
-
name: text("name").notNull(),
|
|
411
|
-
token: text("token").notNull().unique(),
|
|
412
|
-
userId: text("user_id").notNull().references(() => users.id),
|
|
413
|
-
permissions: text("permissions", { mode: "json" }).notNull(),
|
|
414
|
-
// Array of permissions
|
|
415
|
-
expiresAt: integer("expires_at", { mode: "timestamp" }),
|
|
416
|
-
lastUsedAt: integer("last_used_at", { mode: "timestamp" }),
|
|
417
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
418
|
-
});
|
|
419
|
-
var workflowHistory = sqliteTable("workflow_history", {
|
|
420
|
-
id: text("id").primaryKey(),
|
|
421
|
-
contentId: text("content_id").notNull().references(() => content.id),
|
|
422
|
-
action: text("action").notNull(),
|
|
423
|
-
fromStatus: text("from_status").notNull(),
|
|
424
|
-
toStatus: text("to_status").notNull(),
|
|
425
|
-
userId: text("user_id").notNull().references(() => users.id),
|
|
426
|
-
comment: text("comment"),
|
|
427
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
428
|
-
});
|
|
429
|
-
var plugins = sqliteTable("plugins", {
|
|
430
|
-
id: text("id").primaryKey(),
|
|
431
|
-
name: text("name").notNull().unique(),
|
|
432
|
-
displayName: text("display_name").notNull(),
|
|
433
|
-
description: text("description"),
|
|
434
|
-
version: text("version").notNull(),
|
|
435
|
-
author: text("author").notNull(),
|
|
436
|
-
category: text("category").notNull(),
|
|
437
|
-
icon: text("icon"),
|
|
438
|
-
status: text("status").notNull().default("inactive"),
|
|
439
|
-
// 'active', 'inactive', 'error'
|
|
440
|
-
isCore: integer("is_core", { mode: "boolean" }).notNull().default(false),
|
|
441
|
-
settings: text("settings", { mode: "json" }),
|
|
442
|
-
permissions: text("permissions", { mode: "json" }),
|
|
443
|
-
dependencies: text("dependencies", { mode: "json" }),
|
|
444
|
-
downloadCount: integer("download_count").notNull().default(0),
|
|
445
|
-
rating: integer("rating").notNull().default(0),
|
|
446
|
-
installedAt: integer("installed_at").notNull(),
|
|
447
|
-
activatedAt: integer("activated_at"),
|
|
448
|
-
lastUpdated: integer("last_updated").notNull(),
|
|
449
|
-
errorMessage: text("error_message"),
|
|
450
|
-
createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3)),
|
|
451
|
-
updatedAt: integer("updated_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
|
|
452
|
-
});
|
|
453
|
-
var pluginHooks = sqliteTable("plugin_hooks", {
|
|
454
|
-
id: text("id").primaryKey(),
|
|
455
|
-
pluginId: text("plugin_id").notNull().references(() => plugins.id),
|
|
456
|
-
hookName: text("hook_name").notNull(),
|
|
457
|
-
handlerName: text("handler_name").notNull(),
|
|
458
|
-
priority: integer("priority").notNull().default(10),
|
|
459
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
460
|
-
createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
|
|
461
|
-
});
|
|
462
|
-
var pluginRoutes = sqliteTable("plugin_routes", {
|
|
463
|
-
id: text("id").primaryKey(),
|
|
464
|
-
pluginId: text("plugin_id").notNull().references(() => plugins.id),
|
|
465
|
-
path: text("path").notNull(),
|
|
466
|
-
method: text("method").notNull(),
|
|
467
|
-
handlerName: text("handler_name").notNull(),
|
|
468
|
-
middleware: text("middleware", { mode: "json" }),
|
|
469
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
470
|
-
createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
|
|
471
|
-
});
|
|
472
|
-
var pluginAssets = sqliteTable("plugin_assets", {
|
|
473
|
-
id: text("id").primaryKey(),
|
|
474
|
-
pluginId: text("plugin_id").notNull().references(() => plugins.id),
|
|
475
|
-
assetType: text("asset_type").notNull(),
|
|
476
|
-
// 'css', 'js', 'image', 'font'
|
|
477
|
-
assetPath: text("asset_path").notNull(),
|
|
478
|
-
loadOrder: integer("load_order").notNull().default(100),
|
|
479
|
-
loadLocation: text("load_location").notNull().default("footer"),
|
|
480
|
-
// 'header', 'footer'
|
|
481
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
482
|
-
createdAt: integer("created_at").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
|
|
483
|
-
});
|
|
484
|
-
var pluginActivityLog = sqliteTable("plugin_activity_log", {
|
|
485
|
-
id: text("id").primaryKey(),
|
|
486
|
-
pluginId: text("plugin_id").notNull().references(() => plugins.id),
|
|
487
|
-
action: text("action").notNull(),
|
|
488
|
-
userId: text("user_id"),
|
|
489
|
-
details: text("details", { mode: "json" }),
|
|
490
|
-
timestamp: integer("timestamp").notNull().$defaultFn(() => Math.floor(Date.now() / 1e3))
|
|
491
|
-
});
|
|
492
|
-
var insertUserSchema = createInsertSchema(users, {
|
|
493
|
-
email: (schema) => schema.email(),
|
|
494
|
-
firstName: (schema) => schema.min(1),
|
|
495
|
-
lastName: (schema) => schema.min(1),
|
|
496
|
-
username: (schema) => schema.min(3)
|
|
497
|
-
});
|
|
498
|
-
var selectUserSchema = createSelectSchema(users);
|
|
499
|
-
var insertCollectionSchema = createInsertSchema(collections, {
|
|
500
|
-
name: (schema) => schema.min(1).regex(/^[a-z0-9_]+$/, "Collection name must be lowercase with underscores"),
|
|
501
|
-
displayName: (schema) => schema.min(1)
|
|
502
|
-
});
|
|
503
|
-
var selectCollectionSchema = createSelectSchema(collections);
|
|
504
|
-
var insertContentSchema = createInsertSchema(content, {
|
|
505
|
-
slug: (schema) => schema.min(1).regex(/^[a-zA-Z0-9_-]+$/, "Slug must contain only letters, numbers, underscores, and hyphens"),
|
|
506
|
-
title: (schema) => schema.min(1),
|
|
507
|
-
status: (schema) => schema
|
|
508
|
-
});
|
|
509
|
-
var selectContentSchema = createSelectSchema(content);
|
|
510
|
-
var insertMediaSchema = createInsertSchema(media, {
|
|
511
|
-
filename: (schema) => schema.min(1),
|
|
512
|
-
originalName: (schema) => schema.min(1),
|
|
513
|
-
mimeType: (schema) => schema.min(1),
|
|
514
|
-
size: (schema) => schema.positive(),
|
|
515
|
-
r2Key: (schema) => schema.min(1),
|
|
516
|
-
publicUrl: (schema) => schema.url(),
|
|
517
|
-
folder: (schema) => schema.min(1)
|
|
518
|
-
});
|
|
519
|
-
var selectMediaSchema = createSelectSchema(media);
|
|
520
|
-
var insertWorkflowHistorySchema = createInsertSchema(workflowHistory, {
|
|
521
|
-
action: (schema) => schema.min(1),
|
|
522
|
-
fromStatus: (schema) => schema.min(1),
|
|
523
|
-
toStatus: (schema) => schema.min(1)
|
|
524
|
-
});
|
|
525
|
-
var selectWorkflowHistorySchema = createSelectSchema(workflowHistory);
|
|
526
|
-
var insertPluginSchema = createInsertSchema(plugins, {
|
|
527
|
-
name: (schema) => schema.min(1),
|
|
528
|
-
displayName: (schema) => schema.min(1),
|
|
529
|
-
version: (schema) => schema.min(1),
|
|
530
|
-
author: (schema) => schema.min(1),
|
|
531
|
-
category: (schema) => schema.min(1)
|
|
532
|
-
});
|
|
533
|
-
var selectPluginSchema = createSelectSchema(plugins);
|
|
534
|
-
var insertPluginHookSchema = createInsertSchema(pluginHooks, {
|
|
535
|
-
hookName: (schema) => schema.min(1),
|
|
536
|
-
handlerName: (schema) => schema.min(1)
|
|
537
|
-
});
|
|
538
|
-
var selectPluginHookSchema = createSelectSchema(pluginHooks);
|
|
539
|
-
var insertPluginRouteSchema = createInsertSchema(pluginRoutes, {
|
|
540
|
-
path: (schema) => schema.min(1),
|
|
541
|
-
method: (schema) => schema.min(1),
|
|
542
|
-
handlerName: (schema) => schema.min(1)
|
|
543
|
-
});
|
|
544
|
-
var selectPluginRouteSchema = createSelectSchema(pluginRoutes);
|
|
545
|
-
var insertPluginAssetSchema = createInsertSchema(pluginAssets, {
|
|
546
|
-
assetType: (schema) => schema.min(1),
|
|
547
|
-
assetPath: (schema) => schema.min(1)
|
|
548
|
-
});
|
|
549
|
-
var selectPluginAssetSchema = createSelectSchema(pluginAssets);
|
|
550
|
-
var insertPluginActivityLogSchema = createInsertSchema(pluginActivityLog, {
|
|
551
|
-
action: (schema) => schema.min(1)
|
|
552
|
-
});
|
|
553
|
-
var selectPluginActivityLogSchema = createSelectSchema(pluginActivityLog);
|
|
554
|
-
var systemLogs = sqliteTable("system_logs", {
|
|
555
|
-
id: text("id").primaryKey(),
|
|
556
|
-
level: text("level").notNull(),
|
|
557
|
-
// 'debug', 'info', 'warn', 'error', 'fatal'
|
|
558
|
-
category: text("category").notNull(),
|
|
559
|
-
// 'auth', 'api', 'workflow', 'plugin', 'media', 'system', etc.
|
|
560
|
-
message: text("message").notNull(),
|
|
561
|
-
data: text("data", { mode: "json" }),
|
|
562
|
-
// Additional structured data
|
|
563
|
-
userId: text("user_id").references(() => users.id),
|
|
564
|
-
sessionId: text("session_id"),
|
|
565
|
-
requestId: text("request_id"),
|
|
566
|
-
ipAddress: text("ip_address"),
|
|
567
|
-
userAgent: text("user_agent"),
|
|
568
|
-
method: text("method"),
|
|
569
|
-
// HTTP method for API logs
|
|
570
|
-
url: text("url"),
|
|
571
|
-
// Request URL for API logs
|
|
572
|
-
statusCode: integer("status_code"),
|
|
573
|
-
// HTTP status code for API logs
|
|
574
|
-
duration: integer("duration"),
|
|
575
|
-
// Request duration in milliseconds
|
|
576
|
-
stackTrace: text("stack_trace"),
|
|
577
|
-
// Error stack trace for error logs
|
|
578
|
-
tags: text("tags", { mode: "json" }),
|
|
579
|
-
// Array of tags for categorization
|
|
580
|
-
source: text("source"),
|
|
581
|
-
// Source component/module that generated the log
|
|
582
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
583
|
-
});
|
|
584
|
-
var logConfig = sqliteTable("log_config", {
|
|
585
|
-
id: text("id").primaryKey(),
|
|
586
|
-
category: text("category").notNull().unique(),
|
|
587
|
-
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
|
588
|
-
level: text("level").notNull().default("info"),
|
|
589
|
-
// minimum log level to store
|
|
590
|
-
retention: integer("retention").notNull().default(30),
|
|
591
|
-
// days to keep logs
|
|
592
|
-
maxSize: integer("max_size").default(1e4),
|
|
593
|
-
// max number of logs per category
|
|
594
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date()),
|
|
595
|
-
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => /* @__PURE__ */ new Date())
|
|
596
|
-
});
|
|
597
|
-
var insertSystemLogSchema = createInsertSchema(systemLogs, {
|
|
598
|
-
level: (schema) => schema.min(1),
|
|
599
|
-
category: (schema) => schema.min(1),
|
|
600
|
-
message: (schema) => schema.min(1)
|
|
601
|
-
});
|
|
602
|
-
var selectSystemLogSchema = createSelectSchema(systemLogs);
|
|
603
|
-
var insertLogConfigSchema = createInsertSchema(logConfig, {
|
|
604
|
-
category: (schema) => schema.min(1),
|
|
605
|
-
level: (schema) => schema.min(1)
|
|
606
|
-
});
|
|
607
|
-
var selectLogConfigSchema = createSelectSchema(logConfig);
|
|
608
|
-
var securityEvents = sqliteTable("security_events", {
|
|
609
|
-
id: text("id").primaryKey(),
|
|
610
|
-
eventType: text("event_type").notNull(),
|
|
611
|
-
severity: text("severity").notNull().default("info"),
|
|
612
|
-
userId: text("user_id"),
|
|
613
|
-
email: text("email"),
|
|
614
|
-
ipAddress: text("ip_address"),
|
|
615
|
-
userAgent: text("user_agent"),
|
|
616
|
-
countryCode: text("country_code"),
|
|
617
|
-
requestPath: text("request_path"),
|
|
618
|
-
requestMethod: text("request_method"),
|
|
619
|
-
details: text("details", { mode: "json" }),
|
|
620
|
-
fingerprint: text("fingerprint"),
|
|
621
|
-
blocked: integer("blocked").notNull().default(0),
|
|
622
|
-
createdAt: integer("created_at").notNull().$defaultFn(() => Date.now())
|
|
623
|
-
});
|
|
624
|
-
var insertSecurityEventSchema = createInsertSchema(securityEvents, {
|
|
625
|
-
eventType: (schema) => schema.min(1),
|
|
626
|
-
severity: (schema) => schema.min(1)
|
|
627
|
-
});
|
|
628
|
-
var selectSecurityEventSchema = createSelectSchema(securityEvents);
|
|
629
|
-
var forms = sqliteTable("forms", {
|
|
630
|
-
id: text("id").primaryKey(),
|
|
631
|
-
name: text("name").notNull().unique(),
|
|
632
|
-
// Machine name (e.g., "contact-form")
|
|
633
|
-
displayName: text("display_name").notNull(),
|
|
634
|
-
// Human name (e.g., "Contact Form")
|
|
635
|
-
description: text("description"),
|
|
636
|
-
category: text("category").notNull().default("general"),
|
|
637
|
-
// contact, survey, registration, etc.
|
|
638
|
-
// Form.io schema (JSON)
|
|
639
|
-
formioSchema: text("formio_schema", { mode: "json" }).notNull(),
|
|
640
|
-
// Complete Form.io JSON schema
|
|
641
|
-
// Settings (JSON)
|
|
642
|
-
settings: text("settings", { mode: "json" }),
|
|
643
|
-
// emailNotifications, successMessage, etc.
|
|
644
|
-
// Status & Management
|
|
645
|
-
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
646
|
-
isPublic: integer("is_public", { mode: "boolean" }).notNull().default(true),
|
|
647
|
-
managed: integer("managed", { mode: "boolean" }).notNull().default(false),
|
|
648
|
-
// Metadata
|
|
649
|
-
icon: text("icon"),
|
|
650
|
-
color: text("color"),
|
|
651
|
-
tags: text("tags", { mode: "json" }),
|
|
652
|
-
// JSON array
|
|
653
|
-
// Stats
|
|
654
|
-
submissionCount: integer("submission_count").notNull().default(0),
|
|
655
|
-
viewCount: integer("view_count").notNull().default(0),
|
|
656
|
-
// Ownership
|
|
657
|
-
createdBy: text("created_by").references(() => users.id),
|
|
658
|
-
updatedBy: text("updated_by").references(() => users.id),
|
|
659
|
-
// Timestamps
|
|
660
|
-
createdAt: integer("created_at").notNull(),
|
|
661
|
-
updatedAt: integer("updated_at").notNull()
|
|
662
|
-
});
|
|
663
|
-
var formSubmissions = sqliteTable("form_submissions", {
|
|
664
|
-
id: text("id").primaryKey(),
|
|
665
|
-
formId: text("form_id").notNull().references(() => forms.id, { onDelete: "cascade" }),
|
|
666
|
-
// Submission data
|
|
667
|
-
submissionData: text("submission_data", { mode: "json" }).notNull(),
|
|
668
|
-
// The actual form data
|
|
669
|
-
// Submission metadata
|
|
670
|
-
status: text("status").notNull().default("pending"),
|
|
671
|
-
// pending, reviewed, approved, rejected, spam
|
|
672
|
-
submissionNumber: integer("submission_number"),
|
|
673
|
-
// User information
|
|
674
|
-
userId: text("user_id").references(() => users.id),
|
|
675
|
-
userEmail: text("user_email"),
|
|
676
|
-
// Tracking
|
|
677
|
-
ipAddress: text("ip_address"),
|
|
678
|
-
userAgent: text("user_agent"),
|
|
679
|
-
referrer: text("referrer"),
|
|
680
|
-
utmSource: text("utm_source"),
|
|
681
|
-
utmMedium: text("utm_medium"),
|
|
682
|
-
utmCampaign: text("utm_campaign"),
|
|
683
|
-
// Review/Processing
|
|
684
|
-
reviewedBy: text("reviewed_by").references(() => users.id),
|
|
685
|
-
reviewedAt: integer("reviewed_at"),
|
|
686
|
-
reviewNotes: text("review_notes"),
|
|
687
|
-
// Flags
|
|
688
|
-
isSpam: integer("is_spam", { mode: "boolean" }).notNull().default(false),
|
|
689
|
-
isArchived: integer("is_archived", { mode: "boolean" }).notNull().default(false),
|
|
690
|
-
// Content integration
|
|
691
|
-
contentId: text("content_id").references(() => content.id),
|
|
692
|
-
// Links submission to its content item
|
|
693
|
-
// Timestamps
|
|
694
|
-
submittedAt: integer("submitted_at").notNull(),
|
|
695
|
-
updatedAt: integer("updated_at").notNull()
|
|
696
|
-
});
|
|
697
|
-
var formFiles = sqliteTable("form_files", {
|
|
698
|
-
id: text("id").primaryKey(),
|
|
699
|
-
submissionId: text("submission_id").notNull().references(() => formSubmissions.id, { onDelete: "cascade" }),
|
|
700
|
-
mediaId: text("media_id").notNull().references(() => media.id, { onDelete: "cascade" }),
|
|
701
|
-
fieldName: text("field_name").notNull(),
|
|
702
|
-
// Form field that uploaded this file
|
|
703
|
-
uploadedAt: integer("uploaded_at").notNull()
|
|
704
|
-
});
|
|
705
|
-
var insertFormSchema = createInsertSchema(forms);
|
|
706
|
-
var selectFormSchema = createSelectSchema(forms);
|
|
707
|
-
var insertFormSubmissionSchema = createInsertSchema(formSubmissions);
|
|
708
|
-
var selectFormSubmissionSchema = createSelectSchema(formSubmissions);
|
|
709
|
-
var insertFormFileSchema = createInsertSchema(formFiles);
|
|
710
|
-
var selectFormFileSchema = createSelectSchema(formFiles);
|
|
711
|
-
var Logger = class {
|
|
712
|
-
db;
|
|
713
|
-
enabled = true;
|
|
714
|
-
configCache = /* @__PURE__ */ new Map();
|
|
715
|
-
lastConfigRefresh = 0;
|
|
716
|
-
configRefreshInterval = 6e4;
|
|
717
|
-
// 1 minute
|
|
718
|
-
constructor(database) {
|
|
719
|
-
this.db = drizzle(database);
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Log a debug message
|
|
723
|
-
*/
|
|
724
|
-
async debug(category, message, data, context) {
|
|
725
|
-
return this.log("debug", category, message, data, context);
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Log an info message
|
|
729
|
-
*/
|
|
730
|
-
async info(category, message, data, context) {
|
|
731
|
-
return this.log("info", category, message, data, context);
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* Log a warning message
|
|
735
|
-
*/
|
|
736
|
-
async warn(category, message, data, context) {
|
|
737
|
-
return this.log("warn", category, message, data, context);
|
|
738
|
-
}
|
|
739
|
-
/**
|
|
740
|
-
* Log an error message
|
|
741
|
-
*/
|
|
742
|
-
async error(category, message, error, context) {
|
|
743
|
-
const errorData = error instanceof Error ? {
|
|
744
|
-
name: error.name,
|
|
745
|
-
message: error.message,
|
|
746
|
-
stack: error.stack
|
|
747
|
-
} : error;
|
|
748
|
-
return this.log("error", category, message, errorData, {
|
|
749
|
-
...context,
|
|
750
|
-
stackTrace: error instanceof Error ? error.stack : void 0
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
/**
|
|
754
|
-
* Log a fatal message
|
|
755
|
-
*/
|
|
756
|
-
async fatal(category, message, error, context) {
|
|
757
|
-
const errorData = error instanceof Error ? {
|
|
758
|
-
name: error.name,
|
|
759
|
-
message: error.message,
|
|
760
|
-
stack: error.stack
|
|
761
|
-
} : error;
|
|
762
|
-
return this.log("fatal", category, message, errorData, {
|
|
763
|
-
...context,
|
|
764
|
-
stackTrace: error instanceof Error ? error.stack : void 0
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
/**
|
|
768
|
-
* Log an API request
|
|
769
|
-
*/
|
|
770
|
-
async logRequest(method, url, statusCode, duration, context) {
|
|
771
|
-
const level = statusCode >= 500 ? "error" : statusCode >= 400 ? "warn" : "info";
|
|
772
|
-
return this.log(level, "api", `${method} ${url} - ${statusCode}`, {
|
|
773
|
-
method,
|
|
774
|
-
url,
|
|
775
|
-
statusCode,
|
|
776
|
-
duration
|
|
777
|
-
}, {
|
|
778
|
-
...context,
|
|
779
|
-
method,
|
|
780
|
-
url,
|
|
781
|
-
statusCode,
|
|
782
|
-
duration
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
/**
|
|
786
|
-
* Log an authentication event
|
|
787
|
-
*/
|
|
788
|
-
async logAuth(action, userId, success = true, context) {
|
|
789
|
-
const level = success ? "info" : "warn";
|
|
790
|
-
return this.log(level, "auth", `Authentication ${action}: ${success ? "success" : "failed"}`, {
|
|
791
|
-
action,
|
|
792
|
-
success,
|
|
793
|
-
userId
|
|
794
|
-
}, {
|
|
795
|
-
...context,
|
|
796
|
-
userId,
|
|
797
|
-
tags: ["authentication", action]
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Log a security event
|
|
802
|
-
*/
|
|
803
|
-
async logSecurity(event, severity, context) {
|
|
804
|
-
const level = severity === "critical" ? "fatal" : severity === "high" ? "error" : "warn";
|
|
805
|
-
return this.log(level, "security", `Security event: ${event}`, {
|
|
806
|
-
event,
|
|
807
|
-
severity
|
|
808
|
-
}, {
|
|
809
|
-
...context,
|
|
810
|
-
tags: ["security", severity]
|
|
811
|
-
});
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* Core logging method
|
|
815
|
-
*/
|
|
816
|
-
async log(level, category, message, data, context) {
|
|
817
|
-
if (!this.enabled) return;
|
|
818
|
-
try {
|
|
819
|
-
const config = await this.getConfig(category);
|
|
820
|
-
if (!config || !config.enabled || !this.shouldLog(level, config.level)) {
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
const logEntry = {
|
|
824
|
-
id: crypto.randomUUID(),
|
|
825
|
-
level,
|
|
826
|
-
category,
|
|
827
|
-
message,
|
|
828
|
-
data: data ? JSON.stringify(data) : null,
|
|
829
|
-
userId: context?.userId || null,
|
|
830
|
-
sessionId: context?.sessionId || null,
|
|
831
|
-
requestId: context?.requestId || null,
|
|
832
|
-
ipAddress: context?.ipAddress || null,
|
|
833
|
-
userAgent: context?.userAgent || null,
|
|
834
|
-
method: context?.method || null,
|
|
835
|
-
url: context?.url || null,
|
|
836
|
-
statusCode: context?.statusCode || null,
|
|
837
|
-
duration: context?.duration || null,
|
|
838
|
-
stackTrace: context?.stackTrace || null,
|
|
839
|
-
tags: context?.tags ? JSON.stringify(context.tags) : null,
|
|
840
|
-
source: context?.source || null,
|
|
841
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
842
|
-
};
|
|
843
|
-
await this.db.insert(systemLogs).values(logEntry);
|
|
844
|
-
if (config.maxSize) {
|
|
845
|
-
await this.cleanupCategory(category, config.maxSize);
|
|
846
|
-
}
|
|
847
|
-
} catch (error) {
|
|
848
|
-
console.error("Logger error:", error);
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
/**
|
|
852
|
-
* Get logs with filtering and pagination
|
|
853
|
-
*/
|
|
854
|
-
async getLogs(filter = {}) {
|
|
855
|
-
try {
|
|
856
|
-
const conditions = [];
|
|
857
|
-
if (filter.level && filter.level.length > 0) {
|
|
858
|
-
conditions.push(inArray(systemLogs.level, filter.level));
|
|
859
|
-
}
|
|
860
|
-
if (filter.category && filter.category.length > 0) {
|
|
861
|
-
conditions.push(inArray(systemLogs.category, filter.category));
|
|
862
|
-
}
|
|
863
|
-
if (filter.userId) {
|
|
864
|
-
conditions.push(eq(systemLogs.userId, filter.userId));
|
|
865
|
-
}
|
|
866
|
-
if (filter.source) {
|
|
867
|
-
conditions.push(eq(systemLogs.source, filter.source));
|
|
868
|
-
}
|
|
869
|
-
if (filter.search) {
|
|
870
|
-
conditions.push(
|
|
871
|
-
like(systemLogs.message, `%${filter.search}%`)
|
|
872
|
-
);
|
|
873
|
-
}
|
|
874
|
-
if (filter.startDate) {
|
|
875
|
-
conditions.push(gte(systemLogs.createdAt, filter.startDate));
|
|
876
|
-
}
|
|
877
|
-
if (filter.endDate) {
|
|
878
|
-
conditions.push(lte(systemLogs.createdAt, filter.endDate));
|
|
879
|
-
}
|
|
880
|
-
const whereClause = conditions.length > 0 ? and(...conditions) : void 0;
|
|
881
|
-
const totalResult = await this.db.select({ count: count() }).from(systemLogs).where(whereClause);
|
|
882
|
-
const total = totalResult[0]?.count || 0;
|
|
883
|
-
const sortColumn = filter.sortBy === "level" ? systemLogs.level : filter.sortBy === "category" ? systemLogs.category : systemLogs.createdAt;
|
|
884
|
-
const sortFn = filter.sortOrder === "asc" ? asc : desc;
|
|
885
|
-
const logs = await this.db.select().from(systemLogs).where(whereClause).orderBy(sortFn(sortColumn)).limit(filter.limit || 50).offset(filter.offset || 0);
|
|
886
|
-
return { logs, total };
|
|
887
|
-
} catch (error) {
|
|
888
|
-
console.error("Error getting logs:", error);
|
|
889
|
-
return { logs: [], total: 0 };
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
* Get log configuration for a category
|
|
894
|
-
*/
|
|
895
|
-
async getConfig(category) {
|
|
896
|
-
try {
|
|
897
|
-
const now = Date.now();
|
|
898
|
-
if (this.configCache.has(category) && now - this.lastConfigRefresh < this.configRefreshInterval) {
|
|
899
|
-
return this.configCache.get(category) || null;
|
|
900
|
-
}
|
|
901
|
-
const configs = await this.db.select().from(logConfig).where(eq(logConfig.category, category));
|
|
902
|
-
const config = configs[0] || null;
|
|
903
|
-
if (config) {
|
|
904
|
-
this.configCache.set(category, config);
|
|
905
|
-
this.lastConfigRefresh = now;
|
|
906
|
-
}
|
|
907
|
-
return config;
|
|
908
|
-
} catch (error) {
|
|
909
|
-
console.error("Error getting log config:", error);
|
|
910
|
-
return null;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
/**
|
|
914
|
-
* Update log configuration
|
|
915
|
-
*/
|
|
916
|
-
async updateConfig(category, updates) {
|
|
917
|
-
try {
|
|
918
|
-
await this.db.update(logConfig).set({
|
|
919
|
-
...updates,
|
|
920
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
921
|
-
}).where(eq(logConfig.category, category));
|
|
922
|
-
this.configCache.delete(category);
|
|
923
|
-
} catch (error) {
|
|
924
|
-
console.error("Error updating log config:", error);
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
/**
|
|
928
|
-
* Get all log configurations
|
|
929
|
-
*/
|
|
930
|
-
async getAllConfigs() {
|
|
931
|
-
try {
|
|
932
|
-
return await this.db.select().from(logConfig);
|
|
933
|
-
} catch (error) {
|
|
934
|
-
console.error("Error getting log configs:", error);
|
|
935
|
-
return [];
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Clean up old logs for a category
|
|
940
|
-
*/
|
|
941
|
-
async cleanupCategory(category, maxSize) {
|
|
942
|
-
try {
|
|
943
|
-
const countResult = await this.db.select({ count: count() }).from(systemLogs).where(eq(systemLogs.category, category));
|
|
944
|
-
const currentCount = countResult[0]?.count || 0;
|
|
945
|
-
if (currentCount > maxSize) {
|
|
946
|
-
const cutoffLogs = await this.db.select({ createdAt: systemLogs.createdAt }).from(systemLogs).where(eq(systemLogs.category, category)).orderBy(desc(systemLogs.createdAt)).limit(1).offset(maxSize - 1);
|
|
947
|
-
if (cutoffLogs[0]) {
|
|
948
|
-
await this.db.delete(systemLogs).where(
|
|
949
|
-
and(
|
|
950
|
-
eq(systemLogs.category, category),
|
|
951
|
-
lte(systemLogs.createdAt, cutoffLogs[0].createdAt)
|
|
952
|
-
)
|
|
953
|
-
);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
} catch (error) {
|
|
957
|
-
console.error("Error cleaning up logs:", error);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
/**
|
|
961
|
-
* Clean up logs based on retention policy
|
|
962
|
-
*/
|
|
963
|
-
async cleanupByRetention() {
|
|
964
|
-
try {
|
|
965
|
-
const configs = await this.getAllConfigs();
|
|
966
|
-
for (const config of configs) {
|
|
967
|
-
if (config.retention > 0) {
|
|
968
|
-
const cutoffDate = /* @__PURE__ */ new Date();
|
|
969
|
-
cutoffDate.setDate(cutoffDate.getDate() - config.retention);
|
|
970
|
-
await this.db.delete(systemLogs).where(
|
|
971
|
-
and(
|
|
972
|
-
eq(systemLogs.category, config.category),
|
|
973
|
-
lte(systemLogs.createdAt, cutoffDate)
|
|
974
|
-
)
|
|
975
|
-
);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
} catch (error) {
|
|
979
|
-
console.error("Error cleaning up logs by retention:", error);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* Check if a log level should be recorded based on configuration
|
|
984
|
-
*/
|
|
985
|
-
shouldLog(level, configLevel) {
|
|
986
|
-
const levels = ["debug", "info", "warn", "error", "fatal"];
|
|
987
|
-
const levelIndex = levels.indexOf(level);
|
|
988
|
-
const configLevelIndex = levels.indexOf(configLevel);
|
|
989
|
-
return levelIndex >= configLevelIndex;
|
|
990
|
-
}
|
|
991
|
-
/**
|
|
992
|
-
* Enable or disable logging
|
|
993
|
-
*/
|
|
994
|
-
setEnabled(enabled) {
|
|
995
|
-
this.enabled = enabled;
|
|
996
|
-
}
|
|
997
|
-
/**
|
|
998
|
-
* Check if logging is enabled
|
|
999
|
-
*/
|
|
1000
|
-
isEnabled() {
|
|
1001
|
-
return this.enabled;
|
|
1002
|
-
}
|
|
1003
|
-
};
|
|
1004
|
-
var loggerInstance = null;
|
|
1005
|
-
function getLogger(database) {
|
|
1006
|
-
if (!loggerInstance && database) {
|
|
1007
|
-
loggerInstance = new Logger(database);
|
|
1008
|
-
}
|
|
1009
|
-
if (!loggerInstance) {
|
|
1010
|
-
throw new Error("Logger not initialized. Call getLogger with a database instance first.");
|
|
1011
|
-
}
|
|
1012
|
-
return loggerInstance;
|
|
1013
|
-
}
|
|
1014
|
-
function initLogger(database) {
|
|
1015
|
-
loggerInstance = new Logger(database);
|
|
1016
|
-
return loggerInstance;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
// src/services/cache.ts
|
|
1020
|
-
var CacheService = class {
|
|
1021
|
-
config;
|
|
1022
|
-
memoryCache = /* @__PURE__ */ new Map();
|
|
1023
|
-
constructor(config) {
|
|
1024
|
-
this.config = config;
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Generate cache key with prefix
|
|
1028
|
-
*/
|
|
1029
|
-
generateKey(type, identifier) {
|
|
1030
|
-
const parts = [this.config.keyPrefix, type];
|
|
1031
|
-
if (identifier) {
|
|
1032
|
-
parts.push(identifier);
|
|
1033
|
-
}
|
|
1034
|
-
return parts.join(":");
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* Get value from cache
|
|
1038
|
-
*/
|
|
1039
|
-
async get(key) {
|
|
1040
|
-
const cached = this.memoryCache.get(key);
|
|
1041
|
-
if (!cached) {
|
|
1042
|
-
return null;
|
|
1043
|
-
}
|
|
1044
|
-
if (Date.now() > cached.expires) {
|
|
1045
|
-
this.memoryCache.delete(key);
|
|
1046
|
-
return null;
|
|
1047
|
-
}
|
|
1048
|
-
return cached.value;
|
|
1049
|
-
}
|
|
1050
|
-
/**
|
|
1051
|
-
* Get value from cache with source information
|
|
1052
|
-
*/
|
|
1053
|
-
async getWithSource(key) {
|
|
1054
|
-
const cached = this.memoryCache.get(key);
|
|
1055
|
-
if (!cached) {
|
|
1056
|
-
return {
|
|
1057
|
-
hit: false,
|
|
1058
|
-
data: null,
|
|
1059
|
-
source: "none"
|
|
1060
|
-
};
|
|
1061
|
-
}
|
|
1062
|
-
if (Date.now() > cached.expires) {
|
|
1063
|
-
this.memoryCache.delete(key);
|
|
1064
|
-
return {
|
|
1065
|
-
hit: false,
|
|
1066
|
-
data: null,
|
|
1067
|
-
source: "expired"
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
return {
|
|
1071
|
-
hit: true,
|
|
1072
|
-
data: cached.value,
|
|
1073
|
-
source: "memory",
|
|
1074
|
-
ttl: (cached.expires - Date.now()) / 1e3
|
|
1075
|
-
// TTL in seconds
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Set value in cache
|
|
1080
|
-
*/
|
|
1081
|
-
async set(key, value, ttl) {
|
|
1082
|
-
const expires = Date.now() + (ttl || this.config.ttl) * 1e3;
|
|
1083
|
-
this.memoryCache.set(key, { value, expires });
|
|
1084
|
-
}
|
|
1085
|
-
/**
|
|
1086
|
-
* Delete specific key from cache
|
|
1087
|
-
*/
|
|
1088
|
-
async delete(key) {
|
|
1089
|
-
this.memoryCache.delete(key);
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Invalidate cache keys matching a pattern
|
|
1093
|
-
* For memory cache, we do simple string matching
|
|
1094
|
-
*/
|
|
1095
|
-
async invalidate(pattern) {
|
|
1096
|
-
const regexPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
1097
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
1098
|
-
for (const key of this.memoryCache.keys()) {
|
|
1099
|
-
if (regex.test(key)) {
|
|
1100
|
-
this.memoryCache.delete(key);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
/**
|
|
1105
|
-
* Clear all cache
|
|
1106
|
-
*/
|
|
1107
|
-
async clear() {
|
|
1108
|
-
this.memoryCache.clear();
|
|
1109
|
-
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Get value from cache or set it using a callback
|
|
1112
|
-
*/
|
|
1113
|
-
async getOrSet(key, callback, ttl) {
|
|
1114
|
-
const cached = await this.get(key);
|
|
1115
|
-
if (cached !== null) {
|
|
1116
|
-
return cached;
|
|
1117
|
-
}
|
|
1118
|
-
const value = await callback();
|
|
1119
|
-
await this.set(key, value, ttl);
|
|
1120
|
-
return value;
|
|
1121
|
-
}
|
|
1122
|
-
};
|
|
1123
|
-
var CACHE_CONFIGS = {
|
|
1124
|
-
api: {
|
|
1125
|
-
ttl: 300,
|
|
1126
|
-
// 5 minutes
|
|
1127
|
-
keyPrefix: "api"
|
|
1128
|
-
},
|
|
1129
|
-
user: {
|
|
1130
|
-
ttl: 600,
|
|
1131
|
-
// 10 minutes
|
|
1132
|
-
keyPrefix: "user"
|
|
1133
|
-
},
|
|
1134
|
-
content: {
|
|
1135
|
-
ttl: 300,
|
|
1136
|
-
// 5 minutes
|
|
1137
|
-
keyPrefix: "content"
|
|
1138
|
-
},
|
|
1139
|
-
collection: {
|
|
1140
|
-
ttl: 600,
|
|
1141
|
-
// 10 minutes
|
|
1142
|
-
keyPrefix: "collection"
|
|
1143
|
-
}
|
|
1144
|
-
};
|
|
1145
|
-
function getCacheService(config) {
|
|
1146
|
-
return new CacheService(config);
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
// src/services/settings.ts
|
|
1150
|
-
var SettingsService = class {
|
|
1151
|
-
constructor(db) {
|
|
1152
|
-
this.db = db;
|
|
1153
|
-
}
|
|
1154
|
-
/**
|
|
1155
|
-
* Get a setting value by category and key
|
|
1156
|
-
*/
|
|
1157
|
-
async getSetting(category, key) {
|
|
1158
|
-
try {
|
|
1159
|
-
const result = await this.db.prepare("SELECT value FROM settings WHERE category = ? AND key = ?").bind(category, key).first();
|
|
1160
|
-
if (!result) {
|
|
1161
|
-
return null;
|
|
1162
|
-
}
|
|
1163
|
-
return JSON.parse(result.value);
|
|
1164
|
-
} catch (error) {
|
|
1165
|
-
console.error(`Error getting setting ${category}.${key}:`, error);
|
|
1166
|
-
return null;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
/**
|
|
1170
|
-
* Get all settings for a category
|
|
1171
|
-
*/
|
|
1172
|
-
async getCategorySettings(category) {
|
|
1173
|
-
try {
|
|
1174
|
-
const { results } = await this.db.prepare("SELECT key, value FROM settings WHERE category = ?").bind(category).all();
|
|
1175
|
-
const settings = {};
|
|
1176
|
-
for (const row of results || []) {
|
|
1177
|
-
const r = row;
|
|
1178
|
-
settings[r.key] = JSON.parse(r.value);
|
|
1179
|
-
}
|
|
1180
|
-
return settings;
|
|
1181
|
-
} catch (error) {
|
|
1182
|
-
console.error(`Error getting category settings for ${category}:`, error);
|
|
1183
|
-
return {};
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
/**
|
|
1187
|
-
* Set a setting value
|
|
1188
|
-
*/
|
|
1189
|
-
async setSetting(category, key, value) {
|
|
1190
|
-
try {
|
|
1191
|
-
const now = Date.now();
|
|
1192
|
-
const jsonValue = JSON.stringify(value);
|
|
1193
|
-
await this.db.prepare(`
|
|
1194
|
-
INSERT INTO settings (id, category, key, value, created_at, updated_at)
|
|
1195
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
1196
|
-
ON CONFLICT(category, key) DO UPDATE SET
|
|
1197
|
-
value = excluded.value,
|
|
1198
|
-
updated_at = excluded.updated_at
|
|
1199
|
-
`).bind(crypto.randomUUID(), category, key, jsonValue, now, now).run();
|
|
1200
|
-
return true;
|
|
1201
|
-
} catch (error) {
|
|
1202
|
-
console.error(`Error setting ${category}.${key}:`, error);
|
|
1203
|
-
return false;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Set multiple settings at once
|
|
1208
|
-
*/
|
|
1209
|
-
async setMultipleSettings(category, settings) {
|
|
1210
|
-
try {
|
|
1211
|
-
const now = Date.now();
|
|
1212
|
-
for (const [key, value] of Object.entries(settings)) {
|
|
1213
|
-
const jsonValue = JSON.stringify(value);
|
|
1214
|
-
await this.db.prepare(`
|
|
1215
|
-
INSERT INTO settings (id, category, key, value, created_at, updated_at)
|
|
1216
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
1217
|
-
ON CONFLICT(category, key) DO UPDATE SET
|
|
1218
|
-
value = excluded.value,
|
|
1219
|
-
updated_at = excluded.updated_at
|
|
1220
|
-
`).bind(crypto.randomUUID(), category, key, jsonValue, now, now).run();
|
|
1221
|
-
}
|
|
1222
|
-
return true;
|
|
1223
|
-
} catch (error) {
|
|
1224
|
-
console.error(`Error setting multiple settings for ${category}:`, error);
|
|
1225
|
-
return false;
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
/**
|
|
1229
|
-
* Get general settings with defaults
|
|
1230
|
-
*/
|
|
1231
|
-
async getGeneralSettings(userEmail) {
|
|
1232
|
-
const settings = await this.getCategorySettings("general");
|
|
1233
|
-
return {
|
|
1234
|
-
siteName: settings.siteName || "SonicJS AI",
|
|
1235
|
-
siteDescription: settings.siteDescription || "A modern headless CMS powered by AI",
|
|
1236
|
-
adminEmail: settings.adminEmail || userEmail || "admin@example.com",
|
|
1237
|
-
timezone: settings.timezone || "UTC",
|
|
1238
|
-
language: settings.language || "en",
|
|
1239
|
-
maintenanceMode: settings.maintenanceMode || false
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
/**
|
|
1243
|
-
* Save general settings
|
|
1244
|
-
*/
|
|
1245
|
-
async saveGeneralSettings(settings) {
|
|
1246
|
-
const settingsToSave = {};
|
|
1247
|
-
if (settings.siteName !== void 0) settingsToSave.siteName = settings.siteName;
|
|
1248
|
-
if (settings.siteDescription !== void 0) settingsToSave.siteDescription = settings.siteDescription;
|
|
1249
|
-
if (settings.adminEmail !== void 0) settingsToSave.adminEmail = settings.adminEmail;
|
|
1250
|
-
if (settings.timezone !== void 0) settingsToSave.timezone = settings.timezone;
|
|
1251
|
-
if (settings.language !== void 0) settingsToSave.language = settings.language;
|
|
1252
|
-
if (settings.maintenanceMode !== void 0) settingsToSave.maintenanceMode = settings.maintenanceMode;
|
|
1253
|
-
return await this.setMultipleSettings("general", settingsToSave);
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* Get security settings with defaults
|
|
1257
|
-
*/
|
|
1258
|
-
async getSecuritySettings() {
|
|
1259
|
-
const settings = await this.getCategorySettings("security");
|
|
1260
|
-
return {
|
|
1261
|
-
jwtExpiresIn: settings.jwtExpiresIn || "30d",
|
|
1262
|
-
jwtRefreshGraceSeconds: typeof settings.jwtRefreshGraceSeconds === "number" ? settings.jwtRefreshGraceSeconds : 60 * 60 * 24 * 7
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
* Save security settings
|
|
1267
|
-
*/
|
|
1268
|
-
async saveSecuritySettings(settings) {
|
|
1269
|
-
const settingsToSave = {};
|
|
1270
|
-
if (settings.jwtExpiresIn !== void 0) settingsToSave.jwtExpiresIn = settings.jwtExpiresIn;
|
|
1271
|
-
if (settings.jwtRefreshGraceSeconds !== void 0)
|
|
1272
|
-
settingsToSave.jwtRefreshGraceSeconds = settings.jwtRefreshGraceSeconds;
|
|
1273
|
-
return await this.setMultipleSettings("security", settingsToSave);
|
|
1274
|
-
}
|
|
1275
|
-
};
|
|
1276
|
-
|
|
1277
|
-
// src/services/telemetry-service.ts
|
|
1278
|
-
var TelemetryService = class {
|
|
1279
|
-
config;
|
|
1280
|
-
identity = null;
|
|
1281
|
-
enabled = true;
|
|
1282
|
-
eventQueue = [];
|
|
1283
|
-
isInitialized = false;
|
|
1284
|
-
constructor(config) {
|
|
1285
|
-
this.config = {
|
|
1286
|
-
...getTelemetryConfig(),
|
|
1287
|
-
...config
|
|
1288
|
-
};
|
|
1289
|
-
this.enabled = this.config.enabled;
|
|
1290
|
-
}
|
|
1291
|
-
/**
|
|
1292
|
-
* Initialize the telemetry service
|
|
1293
|
-
*/
|
|
1294
|
-
async initialize(identity) {
|
|
1295
|
-
if (!this.enabled) {
|
|
1296
|
-
if (this.config.debug) {
|
|
1297
|
-
console.log("[Telemetry] Disabled via configuration");
|
|
1298
|
-
}
|
|
1299
|
-
return;
|
|
1300
|
-
}
|
|
1301
|
-
try {
|
|
1302
|
-
this.identity = identity;
|
|
1303
|
-
if (this.config.debug) {
|
|
1304
|
-
console.log("[Telemetry] Initialized with installation ID:", identity.installationId);
|
|
1305
|
-
}
|
|
1306
|
-
this.isInitialized = true;
|
|
1307
|
-
await this.flushQueue();
|
|
1308
|
-
} catch (error) {
|
|
1309
|
-
if (this.config.debug) {
|
|
1310
|
-
console.error("[Telemetry] Initialization failed:", error);
|
|
1311
|
-
}
|
|
1312
|
-
this.enabled = false;
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
/**
|
|
1316
|
-
* Track a telemetry event
|
|
1317
|
-
*/
|
|
1318
|
-
async track(event, properties) {
|
|
1319
|
-
if (!this.enabled) return;
|
|
1320
|
-
try {
|
|
1321
|
-
const sanitizedProps = this.sanitizeProperties(properties);
|
|
1322
|
-
const enrichedProps = {
|
|
1323
|
-
...sanitizedProps,
|
|
1324
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1325
|
-
version: this.getVersion()
|
|
1326
|
-
};
|
|
1327
|
-
if (!this.isInitialized) {
|
|
1328
|
-
this.eventQueue.push({ event, properties: enrichedProps });
|
|
1329
|
-
if (this.config.debug) {
|
|
1330
|
-
console.log("[Telemetry] Queued event:", event, enrichedProps);
|
|
1331
|
-
}
|
|
1332
|
-
return;
|
|
1333
|
-
}
|
|
1334
|
-
if (this.identity && this.config.host) {
|
|
1335
|
-
const payload = {
|
|
1336
|
-
data: {
|
|
1337
|
-
installation_id: this.identity.installationId,
|
|
1338
|
-
event_type: event,
|
|
1339
|
-
properties: enrichedProps,
|
|
1340
|
-
timestamp: enrichedProps.timestamp
|
|
1341
|
-
}
|
|
1342
|
-
};
|
|
1343
|
-
fetch(`${this.config.host}/v1/events`, {
|
|
1344
|
-
method: "POST",
|
|
1345
|
-
headers: { "Content-Type": "application/json" },
|
|
1346
|
-
body: JSON.stringify(payload)
|
|
1347
|
-
}).catch(() => {
|
|
1348
|
-
});
|
|
1349
|
-
if (this.config.debug) {
|
|
1350
|
-
console.log("[Telemetry] Tracked event:", event, enrichedProps);
|
|
1351
|
-
}
|
|
1352
|
-
} else if (this.config.debug) {
|
|
1353
|
-
console.log("[Telemetry] Event (no endpoint):", event, enrichedProps);
|
|
1354
|
-
}
|
|
1355
|
-
} catch (error) {
|
|
1356
|
-
if (this.config.debug) {
|
|
1357
|
-
console.error("[Telemetry] Failed to track event:", error);
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
/**
|
|
1362
|
-
* Track installation started
|
|
1363
|
-
*/
|
|
1364
|
-
async trackInstallationStarted(properties) {
|
|
1365
|
-
await this.track("installation_started", properties);
|
|
1366
|
-
}
|
|
1367
|
-
/**
|
|
1368
|
-
* Track installation completed
|
|
1369
|
-
*/
|
|
1370
|
-
async trackInstallationCompleted(properties) {
|
|
1371
|
-
await this.track("installation_completed", properties);
|
|
1372
|
-
}
|
|
1373
|
-
/**
|
|
1374
|
-
* Track installation failed
|
|
1375
|
-
*/
|
|
1376
|
-
async trackInstallationFailed(error, properties) {
|
|
1377
|
-
await this.track("installation_failed", {
|
|
1378
|
-
...properties,
|
|
1379
|
-
errorType: sanitizeErrorMessage(error)
|
|
1380
|
-
});
|
|
1381
|
-
}
|
|
1382
|
-
/**
|
|
1383
|
-
* Track dev server started
|
|
1384
|
-
*/
|
|
1385
|
-
async trackDevServerStarted(properties) {
|
|
1386
|
-
await this.track("dev_server_started", properties);
|
|
1387
|
-
}
|
|
1388
|
-
/**
|
|
1389
|
-
* Track page view in admin UI
|
|
1390
|
-
*/
|
|
1391
|
-
async trackPageView(route, properties) {
|
|
1392
|
-
await this.track("page_viewed", {
|
|
1393
|
-
...properties,
|
|
1394
|
-
route: sanitizeRoute(route)
|
|
1395
|
-
});
|
|
1396
|
-
}
|
|
1397
|
-
/**
|
|
1398
|
-
* Track error (sanitized)
|
|
1399
|
-
*/
|
|
1400
|
-
async trackError(error, properties) {
|
|
1401
|
-
await this.track("error_occurred", {
|
|
1402
|
-
...properties,
|
|
1403
|
-
errorType: sanitizeErrorMessage(error)
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* Track plugin activation
|
|
1408
|
-
*/
|
|
1409
|
-
async trackPluginActivated(properties) {
|
|
1410
|
-
await this.track("plugin_activated", properties);
|
|
1411
|
-
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Track migration run
|
|
1414
|
-
*/
|
|
1415
|
-
async trackMigrationRun(properties) {
|
|
1416
|
-
await this.track("migration_run", properties);
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* Flush queued events
|
|
1420
|
-
*/
|
|
1421
|
-
async flushQueue() {
|
|
1422
|
-
if (this.eventQueue.length === 0) return;
|
|
1423
|
-
const queue = [...this.eventQueue];
|
|
1424
|
-
this.eventQueue = [];
|
|
1425
|
-
for (const { event, properties } of queue) {
|
|
1426
|
-
await this.track(event, properties);
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
/**
|
|
1430
|
-
* Sanitize properties to ensure no PII
|
|
1431
|
-
*/
|
|
1432
|
-
sanitizeProperties(properties) {
|
|
1433
|
-
if (!properties) return {};
|
|
1434
|
-
const sanitized = {};
|
|
1435
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
1436
|
-
if (value === void 0) continue;
|
|
1437
|
-
if (key === "route" && typeof value === "string") {
|
|
1438
|
-
sanitized[key] = sanitizeRoute(value);
|
|
1439
|
-
continue;
|
|
1440
|
-
}
|
|
1441
|
-
if (key.toLowerCase().includes("error") && typeof value === "string") {
|
|
1442
|
-
sanitized[key] = sanitizeErrorMessage(value);
|
|
1443
|
-
continue;
|
|
1444
|
-
}
|
|
1445
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1446
|
-
sanitized[key] = value;
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
return sanitized;
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* Get SonicJS version
|
|
1453
|
-
*/
|
|
1454
|
-
getVersion() {
|
|
1455
|
-
try {
|
|
1456
|
-
if (typeof process !== "undefined" && process.env) {
|
|
1457
|
-
return process.env.SONICJS_VERSION || "2.0.0";
|
|
1458
|
-
}
|
|
1459
|
-
return "2.0.0";
|
|
1460
|
-
} catch {
|
|
1461
|
-
return "unknown";
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
/**
|
|
1465
|
-
* Shutdown the telemetry service (no-op for fetch-based telemetry)
|
|
1466
|
-
*/
|
|
1467
|
-
async shutdown() {
|
|
1468
|
-
}
|
|
1469
|
-
/**
|
|
1470
|
-
* Enable telemetry
|
|
1471
|
-
*/
|
|
1472
|
-
enable() {
|
|
1473
|
-
this.enabled = true;
|
|
1474
|
-
}
|
|
1475
|
-
/**
|
|
1476
|
-
* Disable telemetry
|
|
1477
|
-
*/
|
|
1478
|
-
disable() {
|
|
1479
|
-
this.enabled = false;
|
|
1480
|
-
}
|
|
1481
|
-
/**
|
|
1482
|
-
* Check if telemetry is enabled
|
|
1483
|
-
*/
|
|
1484
|
-
isEnabled() {
|
|
1485
|
-
return this.enabled;
|
|
1486
|
-
}
|
|
1487
|
-
};
|
|
1488
|
-
var telemetryInstance = null;
|
|
1489
|
-
function getTelemetryService(config) {
|
|
1490
|
-
if (!telemetryInstance) {
|
|
1491
|
-
telemetryInstance = new TelemetryService(config);
|
|
1492
|
-
}
|
|
1493
|
-
return telemetryInstance;
|
|
1494
|
-
}
|
|
1495
|
-
async function initTelemetry(identity, config) {
|
|
1496
|
-
const service = getTelemetryService(config);
|
|
1497
|
-
await service.initialize(identity);
|
|
1498
|
-
return service;
|
|
1499
|
-
}
|
|
1500
|
-
function createInstallationIdentity(projectName) {
|
|
1501
|
-
const installationId = generateInstallationId();
|
|
1502
|
-
const identity = { installationId };
|
|
1503
|
-
if (projectName) {
|
|
1504
|
-
identity.projectId = generateProjectId(projectName);
|
|
1505
|
-
}
|
|
1506
|
-
return identity;
|
|
1507
|
-
}
|
|
1508
|
-
var appInstance = null;
|
|
1509
|
-
function setAppInstance(app) {
|
|
1510
|
-
appInstance = app;
|
|
1511
|
-
}
|
|
1512
|
-
function getAppInstance() {
|
|
1513
|
-
return appInstance;
|
|
1514
|
-
}
|
|
1515
|
-
var CATEGORY_INFO = {
|
|
1516
|
-
"Auth": {
|
|
1517
|
-
title: "Authentication",
|
|
1518
|
-
description: "User authentication and authorization endpoints",
|
|
1519
|
-
icon: "🔐"
|
|
1520
|
-
},
|
|
1521
|
-
"Content": {
|
|
1522
|
-
title: "Content Management",
|
|
1523
|
-
description: "Content creation, retrieval, and management",
|
|
1524
|
-
icon: "📝"
|
|
1525
|
-
},
|
|
1526
|
-
"Media": {
|
|
1527
|
-
title: "Media Management",
|
|
1528
|
-
description: "File upload, storage, and media operations",
|
|
1529
|
-
icon: "🖼️"
|
|
1530
|
-
},
|
|
1531
|
-
"Admin": {
|
|
1532
|
-
title: "Admin Interface",
|
|
1533
|
-
description: "Administrative panel and management features",
|
|
1534
|
-
icon: "⚙️"
|
|
1535
|
-
},
|
|
1536
|
-
"System": {
|
|
1537
|
-
title: "System",
|
|
1538
|
-
description: "Health checks and system information",
|
|
1539
|
-
icon: "🔧"
|
|
1540
|
-
},
|
|
1541
|
-
"Search": {
|
|
1542
|
-
title: "Search",
|
|
1543
|
-
description: "AI-powered search, full-text search, and analytics",
|
|
1544
|
-
icon: "🔍"
|
|
1545
|
-
},
|
|
1546
|
-
"API Keys": {
|
|
1547
|
-
title: "API Keys",
|
|
1548
|
-
description: "API key management and authentication",
|
|
1549
|
-
icon: "🔑"
|
|
1550
|
-
},
|
|
1551
|
-
"Workflow": {
|
|
1552
|
-
title: "Workflow",
|
|
1553
|
-
description: "Content workflow and approval processes",
|
|
1554
|
-
icon: "🔄"
|
|
1555
|
-
},
|
|
1556
|
-
"Cache": {
|
|
1557
|
-
title: "Cache",
|
|
1558
|
-
description: "Cache management and invalidation",
|
|
1559
|
-
icon: "⚡"
|
|
1560
|
-
},
|
|
1561
|
-
"Forms": {
|
|
1562
|
-
title: "Forms",
|
|
1563
|
-
description: "Form submissions and management",
|
|
1564
|
-
icon: "📋"
|
|
1565
|
-
},
|
|
1566
|
-
"Files": {
|
|
1567
|
-
title: "Files",
|
|
1568
|
-
description: "File serving from R2 storage",
|
|
1569
|
-
icon: "📁"
|
|
1570
|
-
}
|
|
1571
|
-
};
|
|
1572
|
-
var ROUTE_METADATA = {
|
|
1573
|
-
// Auth endpoints
|
|
1574
|
-
"POST /auth/login": { description: "Authenticate user with email and password (returns JWT)", category: "Auth", authentication: false },
|
|
1575
|
-
"POST /auth/login/form": { description: "Form-based login (sets session cookie)", category: "Auth", authentication: false },
|
|
1576
|
-
"POST /auth/register": { description: "Register a new user account", category: "Auth", authentication: false },
|
|
1577
|
-
"POST /auth/logout": { description: "Log out the current user and invalidate session", category: "Auth", authentication: true },
|
|
1578
|
-
"GET /auth/me": { description: "Get current authenticated user information", category: "Auth", authentication: true },
|
|
1579
|
-
"POST /auth/refresh": { description: "Refresh authentication token", category: "Auth", authentication: true },
|
|
1580
|
-
"POST /auth/seed-admin": { description: "Create or reset the admin user account", category: "Auth", authentication: false },
|
|
1581
|
-
"POST /auth/magic-link/request": { description: "Request a magic link login email", category: "Auth", authentication: false },
|
|
1582
|
-
"GET /auth/magic-link/verify": { description: "Verify magic link token and authenticate", category: "Auth", authentication: false },
|
|
1583
|
-
"POST /auth/otp/request": { description: "Request a one-time password via email", category: "Auth", authentication: false },
|
|
1584
|
-
"POST /auth/otp/verify": { description: "Verify OTP code and authenticate", category: "Auth", authentication: false },
|
|
1585
|
-
// Content endpoints
|
|
1586
|
-
"GET /api/collections": { description: "List all available collections", category: "Content", authentication: false },
|
|
1587
|
-
"GET /api/collections/:collection/content": { description: "Get all content items from a specific collection", category: "Content", authentication: false },
|
|
1588
|
-
"GET /api/content/:id": { description: "Get a specific content item by ID", category: "Content", authentication: false },
|
|
1589
|
-
"POST /api/content": { description: "Create a new content item", category: "Content", authentication: true },
|
|
1590
|
-
"PUT /api/content/:id": { description: "Update an existing content item", category: "Content", authentication: true },
|
|
1591
|
-
"DELETE /api/content/:id": { description: "Delete a content item", category: "Content", authentication: true },
|
|
1592
|
-
"GET /api/content/:id/versions": { description: "Get version history for a content item", category: "Content", authentication: true },
|
|
1593
|
-
"POST /api/content/:id/restore/:versionId": { description: "Restore a content item to a previous version", category: "Content", authentication: true },
|
|
1594
|
-
// Media endpoints
|
|
1595
|
-
"GET /api/media": { description: "List all media files with pagination", category: "Media", authentication: false },
|
|
1596
|
-
"GET /api/media/:id": { description: "Get a specific media file by ID", category: "Media", authentication: false },
|
|
1597
|
-
"POST /api/media/upload": { description: "Upload a new media file to R2 storage", category: "Media", authentication: true },
|
|
1598
|
-
"DELETE /api/media/:id": { description: "Delete a media file from storage", category: "Media", authentication: true },
|
|
1599
|
-
// Admin API endpoints
|
|
1600
|
-
"GET /admin/api/stats": { description: "Get dashboard statistics (collections, content, media, users)", category: "Admin", authentication: true },
|
|
1601
|
-
"GET /admin/api/storage": { description: "Get storage usage information", category: "Admin", authentication: true },
|
|
1602
|
-
"GET /admin/api/activity": { description: "Get recent activity logs", category: "Admin", authentication: true },
|
|
1603
|
-
"GET /admin/api/collections": { description: "List all collections with field counts", category: "Admin", authentication: true },
|
|
1604
|
-
"POST /admin/api/collections": { description: "Create a new collection", category: "Admin", authentication: true },
|
|
1605
|
-
"GET /admin/api/collections/:id": { description: "Get a specific collection with its fields", category: "Admin", authentication: true },
|
|
1606
|
-
"PATCH /admin/api/collections/:id": { description: "Update an existing collection", category: "Admin", authentication: true },
|
|
1607
|
-
"DELETE /admin/api/collections/:id": { description: "Delete a collection (must be empty)", category: "Admin", authentication: true },
|
|
1608
|
-
"GET /admin/api/collections/:id/fields": { description: "Get fields for a specific collection", category: "Admin", authentication: true },
|
|
1609
|
-
"POST /admin/api/collections/:id/fields": { description: "Add a field to a collection", category: "Admin", authentication: true },
|
|
1610
|
-
"PATCH /admin/api/collections/:id/fields/:fieldId": { description: "Update a collection field", category: "Admin", authentication: true },
|
|
1611
|
-
"DELETE /admin/api/collections/:id/fields/:fieldId": { description: "Remove a field from a collection", category: "Admin", authentication: true },
|
|
1612
|
-
"POST /admin/api/collections/:id/fields/reorder": { description: "Reorder fields in a collection", category: "Admin", authentication: true },
|
|
1613
|
-
"GET /admin/api/migrations/status": { description: "Get database migration status", category: "Admin", authentication: true },
|
|
1614
|
-
"POST /admin/api/migrations/run": { description: "Run pending database migrations", category: "Admin", authentication: true },
|
|
1615
|
-
"GET /admin/api/content": { description: "List content items with filtering and pagination", category: "Admin", authentication: true },
|
|
1616
|
-
"GET /admin/api/content/:id": { description: "Get a content item for admin editing", category: "Admin", authentication: true },
|
|
1617
|
-
"POST /admin/api/content": { description: "Create content via admin API", category: "Admin", authentication: true },
|
|
1618
|
-
"PUT /admin/api/content/:id": { description: "Update content via admin API", category: "Admin", authentication: true },
|
|
1619
|
-
"DELETE /admin/api/content/:id": { description: "Delete content via admin API", category: "Admin", authentication: true },
|
|
1620
|
-
"GET /admin/api/media": { description: "List media files for admin management", category: "Admin", authentication: true },
|
|
1621
|
-
"POST /admin/api/media/upload": { description: "Upload media via admin interface", category: "Admin", authentication: true },
|
|
1622
|
-
"DELETE /admin/api/media/:id": { description: "Delete media via admin interface", category: "Admin", authentication: true },
|
|
1623
|
-
"GET /admin/api/users": { description: "List all users", category: "Admin", authentication: true },
|
|
1624
|
-
"POST /admin/api/users": { description: "Create a new user", category: "Admin", authentication: true },
|
|
1625
|
-
"PUT /admin/api/users/:id": { description: "Update a user", category: "Admin", authentication: true },
|
|
1626
|
-
"DELETE /admin/api/users/:id": { description: "Delete a user", category: "Admin", authentication: true },
|
|
1627
|
-
"GET /admin/api/logs": { description: "Get application logs with filtering", category: "Admin", authentication: true },
|
|
1628
|
-
"GET /admin/api/plugins": { description: "List all registered plugins", category: "Admin", authentication: true },
|
|
1629
|
-
"POST /admin/api/plugins/:id/toggle": { description: "Enable or disable a plugin", category: "Admin", authentication: true },
|
|
1630
|
-
"GET /admin/api/settings": { description: "Get application settings", category: "Admin", authentication: true },
|
|
1631
|
-
"PUT /admin/api/settings": { description: "Update application settings", category: "Admin", authentication: true },
|
|
1632
|
-
"GET /admin/api/forms": { description: "List all forms", category: "Admin", authentication: true },
|
|
1633
|
-
"GET /admin/api/forms/:id": { description: "Get form details and submissions", category: "Admin", authentication: true },
|
|
1634
|
-
"POST /admin/api/forms": { description: "Create a new form", category: "Admin", authentication: true },
|
|
1635
|
-
"PUT /admin/api/forms/:id": { description: "Update a form", category: "Admin", authentication: true },
|
|
1636
|
-
"DELETE /admin/api/forms/:id": { description: "Delete a form", category: "Admin", authentication: true },
|
|
1637
|
-
"GET /admin/api/forms/:id/submissions": { description: "Get form submissions", category: "Admin", authentication: true },
|
|
1638
|
-
"DELETE /admin/api/forms/:id/submissions/:submissionId": { description: "Delete a form submission", category: "Admin", authentication: true },
|
|
1639
|
-
// Search endpoints
|
|
1640
|
-
"GET /api/search": { description: "Search content using AI, FTS5, keyword, or hybrid mode", category: "Search", authentication: false },
|
|
1641
|
-
"POST /api/search/click": { description: "Track a search result click for analytics", category: "Search", authentication: false },
|
|
1642
|
-
"GET /admin/plugins/ai-search/api/status": { description: "Get search plugin status and configuration", category: "Search", authentication: true },
|
|
1643
|
-
"POST /admin/plugins/ai-search/api/index": { description: "Trigger content indexing for search", category: "Search", authentication: true },
|
|
1644
|
-
"POST /admin/plugins/ai-search/api/index/reset": { description: "Reset the search index", category: "Search", authentication: true },
|
|
1645
|
-
"GET /admin/plugins/ai-search/api/analytics": { description: "Get search analytics and metrics", category: "Search", authentication: true },
|
|
1646
|
-
"GET /admin/plugins/ai-search/api/analytics/queries": { description: "Get top search queries", category: "Search", authentication: true },
|
|
1647
|
-
"GET /admin/plugins/ai-search/api/analytics/clicks": { description: "Get click-through analytics", category: "Search", authentication: true },
|
|
1648
|
-
"GET /admin/plugins/ai-search/api/fts5/status": { description: "Get FTS5 full-text search status", category: "Search", authentication: true },
|
|
1649
|
-
"POST /admin/plugins/ai-search/api/fts5/rebuild": { description: "Rebuild the FTS5 search index", category: "Search", authentication: true },
|
|
1650
|
-
"GET /admin/plugins/ai-search/api/facets": { description: "Get available search facets", category: "Search", authentication: true },
|
|
1651
|
-
"GET /admin/plugins/ai-search/api/experiments": { description: "List search A/B test experiments", category: "Search", authentication: true },
|
|
1652
|
-
"POST /admin/plugins/ai-search/api/experiments": { description: "Create a search A/B test experiment", category: "Search", authentication: true },
|
|
1653
|
-
"GET /admin/plugins/ai-search/api/experiments/:id": { description: "Get experiment details", category: "Search", authentication: true },
|
|
1654
|
-
"PUT /admin/plugins/ai-search/api/experiments/:id": { description: "Update an experiment", category: "Search", authentication: true },
|
|
1655
|
-
"DELETE /admin/plugins/ai-search/api/experiments/:id": { description: "Delete an experiment", category: "Search", authentication: true },
|
|
1656
|
-
"POST /admin/plugins/ai-search/api/experiments/:id/start": { description: "Start an experiment", category: "Search", authentication: true },
|
|
1657
|
-
"POST /admin/plugins/ai-search/api/experiments/:id/stop": { description: "Stop a running experiment", category: "Search", authentication: true },
|
|
1658
|
-
"GET /admin/plugins/ai-search/api/experiments/:id/results": { description: "Get experiment results and statistics", category: "Search", authentication: true },
|
|
1659
|
-
"GET /admin/plugins/ai-search/api/quality": { description: "Get search quality agent analysis", category: "Search", authentication: true },
|
|
1660
|
-
"POST /admin/plugins/ai-search/api/quality/run": { description: "Run search quality analysis", category: "Search", authentication: true },
|
|
1661
|
-
"GET /admin/plugins/ai-search/api/quality/recommendations": { description: "Get quality improvement recommendations", category: "Search", authentication: true },
|
|
1662
|
-
"POST /admin/plugins/ai-search/api/quality/recommendations/:id/apply": { description: "Apply a quality recommendation", category: "Search", authentication: true },
|
|
1663
|
-
"POST /admin/plugins/ai-search/api/quality/recommendations/:id/dismiss": { description: "Dismiss a quality recommendation", category: "Search", authentication: true },
|
|
1664
|
-
"GET /admin/plugins/ai-search/api/synonyms": { description: "List search synonyms", category: "Search", authentication: true },
|
|
1665
|
-
"POST /admin/plugins/ai-search/api/synonyms": { description: "Add a search synonym", category: "Search", authentication: true },
|
|
1666
|
-
"DELETE /admin/plugins/ai-search/api/synonyms/:id": { description: "Delete a search synonym", category: "Search", authentication: true },
|
|
1667
|
-
"GET /admin/plugins/ai-search/api/query-rules": { description: "List search query rules", category: "Search", authentication: true },
|
|
1668
|
-
"POST /admin/plugins/ai-search/api/query-rules": { description: "Create a query rule", category: "Search", authentication: true },
|
|
1669
|
-
"PUT /admin/plugins/ai-search/api/query-rules/:id": { description: "Update a query rule", category: "Search", authentication: true },
|
|
1670
|
-
"DELETE /admin/plugins/ai-search/api/query-rules/:id": { description: "Delete a query rule", category: "Search", authentication: true },
|
|
1671
|
-
"GET /admin/plugins/ai-search/api/settings": { description: "Get search plugin settings", category: "Search", authentication: true },
|
|
1672
|
-
"PUT /admin/plugins/ai-search/api/settings": { description: "Update search plugin settings", category: "Search", authentication: true },
|
|
1673
|
-
// API Key endpoints
|
|
1674
|
-
"GET /admin/api-keys/api/keys": { description: "List all API keys", category: "API Keys", authentication: true },
|
|
1675
|
-
"POST /admin/api-keys/api/keys": { description: "Create a new API key", category: "API Keys", authentication: true },
|
|
1676
|
-
"DELETE /admin/api-keys/api/keys/:id": { description: "Revoke an API key", category: "API Keys", authentication: true },
|
|
1677
|
-
"PUT /admin/api-keys/api/keys/:id": { description: "Update an API key", category: "API Keys", authentication: true },
|
|
1678
|
-
// Cache endpoints
|
|
1679
|
-
"GET /admin/cache/api/stats": { description: "Get cache statistics", category: "Cache", authentication: true },
|
|
1680
|
-
"POST /admin/cache/api/purge": { description: "Purge cache entries", category: "Cache", authentication: true },
|
|
1681
|
-
"GET /admin/cache/api/entries": { description: "List cache entries", category: "Cache", authentication: true },
|
|
1682
|
-
"DELETE /admin/cache/api/entries/:key": { description: "Delete a specific cache entry", category: "Cache", authentication: true },
|
|
1683
|
-
// Workflow endpoints
|
|
1684
|
-
"GET /workflow/status/:id": { description: "Get workflow status for a content item", category: "Workflow", authentication: true },
|
|
1685
|
-
"POST /workflow/submit/:id": { description: "Submit content for review", category: "Workflow", authentication: true },
|
|
1686
|
-
"POST /workflow/approve/:id": { description: "Approve content in review", category: "Workflow", authentication: true },
|
|
1687
|
-
"POST /workflow/reject/:id": { description: "Reject content in review", category: "Workflow", authentication: true },
|
|
1688
|
-
"POST /workflow/publish/:id": { description: "Publish approved content", category: "Workflow", authentication: true },
|
|
1689
|
-
"POST /workflow/unpublish/:id": { description: "Unpublish content", category: "Workflow", authentication: true },
|
|
1690
|
-
"GET /workflow/history/:id": { description: "Get workflow history for a content item", category: "Workflow", authentication: true },
|
|
1691
|
-
// Form endpoints (public)
|
|
1692
|
-
"POST /forms/:formId/submit": { description: "Submit a form (public endpoint)", category: "Forms", authentication: false },
|
|
1693
|
-
"GET /forms/:formId": { description: "Get form definition for rendering", category: "Forms", authentication: false },
|
|
1694
|
-
"POST /api/forms/:formId/submit": { description: "Submit a form via API", category: "Forms", authentication: false },
|
|
1695
|
-
"GET /api/forms/:formId": { description: "Get form definition via API", category: "Forms", authentication: false },
|
|
1696
|
-
// System endpoints
|
|
1697
|
-
"GET /health": { description: "Health check endpoint for monitoring", category: "System", authentication: false },
|
|
1698
|
-
"GET /api/health": { description: "API health check with schema information", category: "System", authentication: false },
|
|
1699
|
-
"GET /api": { description: "API root - returns API information and available endpoints", category: "System", authentication: false },
|
|
1700
|
-
"GET /api/system/info": { description: "Get system information and version", category: "System", authentication: false },
|
|
1701
|
-
"GET /api/system/schema": { description: "Get database schema information", category: "System", authentication: false },
|
|
1702
|
-
// File serving
|
|
1703
|
-
"GET /files/*": { description: "Serve files from R2 storage (public access)", category: "Files", authentication: false },
|
|
1704
|
-
// Database tools
|
|
1705
|
-
"POST /admin/database-tools/api/query": { description: "Execute a database query", category: "Admin", authentication: true },
|
|
1706
|
-
"GET /admin/database-tools/api/tables": { description: "List database tables", category: "Admin", authentication: true },
|
|
1707
|
-
"GET /admin/database-tools/api/tables/:name": { description: "Get table schema and sample data", category: "Admin", authentication: true },
|
|
1708
|
-
// Seed data
|
|
1709
|
-
"POST /admin/seed-data/api/generate": { description: "Generate seed data for development", category: "Admin", authentication: true },
|
|
1710
|
-
"GET /admin/seed-data/api/status": { description: "Get seed data generation status", category: "Admin", authentication: true },
|
|
1711
|
-
// Email plugin
|
|
1712
|
-
"POST /admin/plugins/email/api/send": { description: "Send an email", category: "Admin", authentication: true },
|
|
1713
|
-
"GET /admin/plugins/email/api/templates": { description: "List email templates", category: "Admin", authentication: true },
|
|
1714
|
-
"POST /admin/plugins/email/api/test": { description: "Send a test email", category: "Admin", authentication: true }
|
|
1715
|
-
};
|
|
1716
|
-
var INCLUDED_ROUTE_PATTERNS = [
|
|
1717
|
-
/^\/api\//,
|
|
1718
|
-
// All /api/* routes
|
|
1719
|
-
/^\/api$/,
|
|
1720
|
-
// API root
|
|
1721
|
-
/^\/auth\/(?!login$|register$)/,
|
|
1722
|
-
// Auth routes except GET login/register HTML pages
|
|
1723
|
-
/^\/auth\/login$/,
|
|
1724
|
-
// POST /auth/login (method filtered later)
|
|
1725
|
-
/^\/auth\/register$/,
|
|
1726
|
-
// POST /auth/register (method filtered later)
|
|
1727
|
-
/^\/admin\/api\//,
|
|
1728
|
-
// Admin API endpoints
|
|
1729
|
-
/^\/admin\/api-keys\/api\//,
|
|
1730
|
-
// API key management
|
|
1731
|
-
/^\/admin\/cache\/api\//,
|
|
1732
|
-
// Cache management API
|
|
1733
|
-
/^\/admin\/plugins\/.*\/api\//,
|
|
1734
|
-
// Plugin API endpoints
|
|
1735
|
-
/^\/admin\/database-tools\/api\//,
|
|
1736
|
-
// Database tools API
|
|
1737
|
-
/^\/admin\/seed-data\/api\//,
|
|
1738
|
-
// Seed data API
|
|
1739
|
-
/^\/workflow\//,
|
|
1740
|
-
// Workflow endpoints
|
|
1741
|
-
/^\/health$/,
|
|
1742
|
-
// Health check
|
|
1743
|
-
/^\/files\//,
|
|
1744
|
-
// File serving
|
|
1745
|
-
/^\/forms\//
|
|
1746
|
-
// Public form endpoints
|
|
1747
|
-
];
|
|
1748
|
-
var EXCLUDED_ROUTES = /* @__PURE__ */ new Set([
|
|
1749
|
-
"GET /auth/login",
|
|
1750
|
-
"GET /auth/register",
|
|
1751
|
-
"GET /auth/login/form"
|
|
1752
|
-
]);
|
|
1753
|
-
var cachedRouteList = null;
|
|
1754
|
-
function isIncludedRoute(method, path) {
|
|
1755
|
-
const key = `${method} ${path}`;
|
|
1756
|
-
if (EXCLUDED_ROUTES.has(key)) {
|
|
1757
|
-
return false;
|
|
1758
|
-
}
|
|
1759
|
-
return INCLUDED_ROUTE_PATTERNS.some((pattern) => pattern.test(path));
|
|
1760
|
-
}
|
|
1761
|
-
function inferCategory(path) {
|
|
1762
|
-
if (path.startsWith("/auth/")) return "Auth";
|
|
1763
|
-
if (path.startsWith("/api/search")) return "Search";
|
|
1764
|
-
if (path.startsWith("/api/media")) return "Media";
|
|
1765
|
-
if (path.startsWith("/api/system")) return "System";
|
|
1766
|
-
if (path.startsWith("/api/content") || path.startsWith("/api/collections")) return "Content";
|
|
1767
|
-
if (path.startsWith("/api/forms")) return "Forms";
|
|
1768
|
-
if (path.startsWith("/admin/api-keys")) return "API Keys";
|
|
1769
|
-
if (path.startsWith("/admin/cache")) return "Cache";
|
|
1770
|
-
if (path.startsWith("/admin/plugins/ai-search")) return "Search";
|
|
1771
|
-
if (path.startsWith("/admin/api")) return "Admin";
|
|
1772
|
-
if (path.startsWith("/admin/database-tools")) return "Admin";
|
|
1773
|
-
if (path.startsWith("/admin/seed-data")) return "Admin";
|
|
1774
|
-
if (path.startsWith("/admin/plugins/email")) return "Admin";
|
|
1775
|
-
if (path.startsWith("/workflow/")) return "Workflow";
|
|
1776
|
-
if (path.startsWith("/forms/")) return "Forms";
|
|
1777
|
-
if (path.startsWith("/files/")) return "Files";
|
|
1778
|
-
if (path === "/health" || path.startsWith("/api")) return "System";
|
|
1779
|
-
return "Other";
|
|
1780
|
-
}
|
|
1781
|
-
function inferAuth(path) {
|
|
1782
|
-
if (path === "/health" || path === "/api" || path === "/api/health") return false;
|
|
1783
|
-
if (path === "/api/system/info" || path === "/api/system/schema") return false;
|
|
1784
|
-
if (path.startsWith("/files/")) return false;
|
|
1785
|
-
if (path.startsWith("/forms/") || path.startsWith("/api/forms/")) return false;
|
|
1786
|
-
if (path.startsWith("/admin/")) return true;
|
|
1787
|
-
if (path.startsWith("/workflow/")) return true;
|
|
1788
|
-
return "unknown";
|
|
1789
|
-
}
|
|
1790
|
-
function buildRouteList(app) {
|
|
1791
|
-
if (cachedRouteList) return cachedRouteList;
|
|
1792
|
-
if (!app) return [];
|
|
1793
|
-
try {
|
|
1794
|
-
const routes = inspectRoutes(app);
|
|
1795
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1796
|
-
const result = [];
|
|
1797
|
-
for (const route of routes) {
|
|
1798
|
-
if (route.isMiddleware) continue;
|
|
1799
|
-
if (route.method === "ALL") continue;
|
|
1800
|
-
const key = `${route.method} ${route.path}`;
|
|
1801
|
-
if (seen.has(key)) continue;
|
|
1802
|
-
seen.add(key);
|
|
1803
|
-
if (!isIncludedRoute(route.method, route.path)) continue;
|
|
1804
|
-
const meta = ROUTE_METADATA[key];
|
|
1805
|
-
if (meta) {
|
|
1806
|
-
result.push({
|
|
1807
|
-
method: route.method,
|
|
1808
|
-
path: route.path,
|
|
1809
|
-
description: meta.description,
|
|
1810
|
-
authentication: meta.authentication,
|
|
1811
|
-
category: meta.category,
|
|
1812
|
-
documented: true
|
|
1813
|
-
});
|
|
1814
|
-
} else {
|
|
1815
|
-
result.push({
|
|
1816
|
-
method: route.method,
|
|
1817
|
-
path: route.path,
|
|
1818
|
-
description: "",
|
|
1819
|
-
authentication: inferAuth(route.path),
|
|
1820
|
-
category: inferCategory(route.path),
|
|
1821
|
-
documented: false
|
|
1822
|
-
});
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
const methodOrder = { GET: 0, POST: 1, PUT: 2, PATCH: 3, DELETE: 4 };
|
|
1826
|
-
result.sort((a, b) => {
|
|
1827
|
-
const catCmp = a.category.localeCompare(b.category);
|
|
1828
|
-
if (catCmp !== 0) return catCmp;
|
|
1829
|
-
const methCmp = (methodOrder[a.method] ?? 5) - (methodOrder[b.method] ?? 5);
|
|
1830
|
-
if (methCmp !== 0) return methCmp;
|
|
1831
|
-
return a.path.localeCompare(b.path);
|
|
1832
|
-
});
|
|
1833
|
-
cachedRouteList = result;
|
|
1834
|
-
return result;
|
|
1835
|
-
} catch (error) {
|
|
1836
|
-
console.error("Failed to inspect routes:", error);
|
|
1837
|
-
return [];
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
export { CACHE_CONFIGS, CATEGORY_INFO, CacheService, Logger, SettingsService, TelemetryService, apiTokens, buildRouteList, collections, content, contentVersions, createInstallationIdentity, getAppInstance, getCacheService, getLogger, getTelemetryService, initLogger, initTelemetry, insertCollectionSchema, insertContentSchema, insertLogConfigSchema, insertMediaSchema, insertPluginActivityLogSchema, insertPluginAssetSchema, insertPluginHookSchema, insertPluginRouteSchema, insertPluginSchema, insertSystemLogSchema, insertUserSchema, insertWorkflowHistorySchema, logConfig, media, pluginActivityLog, pluginAssets, pluginHooks, pluginRoutes, plugins, schema_exports, selectCollectionSchema, selectContentSchema, selectLogConfigSchema, selectMediaSchema, selectPluginActivityLogSchema, selectPluginAssetSchema, selectPluginHookSchema, selectPluginRouteSchema, selectPluginSchema, selectSystemLogSchema, selectUserSchema, selectWorkflowHistorySchema, setAppInstance, systemLogs, users, workflowHistory };
|
|
1842
|
-
//# sourceMappingURL=chunk-QFWHAFEO.js.map
|
|
1843
|
-
//# sourceMappingURL=chunk-QFWHAFEO.js.map
|