@kyro-cms/core 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/WebhookService-BCgL1bLF.d.cts +112 -0
- package/dist/WebhookService-BPVJUgTl.d.ts +112 -0
- package/dist/{base-DlhVlwnN.d.cts → base-B0Y6isUJ.d.cts} +1 -1
- package/dist/{base-CQkFzqQl.d.ts → base-DaP-5PPG.d.ts} +1 -1
- package/dist/bootstrap-BMWVB2T6.cjs +31 -0
- package/dist/{bootstrap-X6TP3NKX.cjs.map → bootstrap-BMWVB2T6.cjs.map} +1 -1
- package/dist/bootstrap-LL6O7PWO.js +6 -0
- package/dist/{bootstrap-BDTTUGY2.js.map → bootstrap-LL6O7PWO.js.map} +1 -1
- package/dist/{chunk-3VZCX4DF.cjs → chunk-42JPONZU.cjs} +77 -14
- package/dist/chunk-42JPONZU.cjs.map +1 -0
- package/dist/{chunk-MHS6CPO5.cjs → chunk-4M5PHMUE.cjs} +66 -346
- package/dist/chunk-4M5PHMUE.cjs.map +1 -0
- package/dist/chunk-4PWRCMTQ.cjs +15 -0
- package/dist/chunk-4PWRCMTQ.cjs.map +1 -0
- package/dist/chunk-6COM32WF.js +47 -0
- package/dist/chunk-6COM32WF.js.map +1 -0
- package/dist/chunk-6MSSF46R.js +941 -0
- package/dist/chunk-6MSSF46R.js.map +1 -0
- package/dist/{chunk-TZFJMPCH.cjs → chunk-7YITG2US.cjs} +9 -18
- package/dist/chunk-7YITG2US.cjs.map +1 -0
- package/dist/{chunk-A3RQWHKD.cjs → chunk-BLMFBDBG.cjs} +56 -6
- package/dist/chunk-BLMFBDBG.cjs.map +1 -0
- package/dist/{chunk-EINVJPFM.js → chunk-BTOE3VUK.js} +65 -3
- package/dist/chunk-BTOE3VUK.js.map +1 -0
- package/dist/chunk-E5X75WNB.js +497 -0
- package/dist/chunk-E5X75WNB.js.map +1 -0
- package/dist/chunk-E63IF3MD.cjs +951 -0
- package/dist/chunk-E63IF3MD.cjs.map +1 -0
- package/dist/{chunk-K7QF2QCM.cjs → chunk-FTSSDDZQ.cjs} +7 -3
- package/dist/chunk-FTSSDDZQ.cjs.map +1 -0
- package/dist/chunk-G7VZBCD6.cjs +35 -0
- package/dist/{chunk-5BLDMQED.cjs.map → chunk-G7VZBCD6.cjs.map} +1 -1
- package/dist/{chunk-VMSRTAH7.js → chunk-GLCPGZPM.js} +56 -6
- package/dist/chunk-GLCPGZPM.js.map +1 -0
- package/dist/{chunk-V3B25QOK.cjs → chunk-GVFB5C6O.cjs} +74 -2
- package/dist/chunk-GVFB5C6O.cjs.map +1 -0
- package/dist/chunk-HVSQDZZJ.cjs +765 -0
- package/dist/chunk-HVSQDZZJ.cjs.map +1 -0
- package/dist/chunk-HYC4GNHX.js +758 -0
- package/dist/chunk-HYC4GNHX.js.map +1 -0
- package/dist/chunk-KDVDIZ4Y.cjs +3479 -0
- package/dist/chunk-KDVDIZ4Y.cjs.map +1 -0
- package/dist/{chunk-OG3KX56O.js → chunk-KWGNR4HM.js} +7 -3
- package/dist/chunk-KWGNR4HM.js.map +1 -0
- package/dist/chunk-LIJVWQKU.cjs +256 -0
- package/dist/chunk-LIJVWQKU.cjs.map +1 -0
- package/dist/{chunk-XTZSUDSI.js → chunk-LTRCYJAG.js} +3 -18
- package/dist/chunk-LTRCYJAG.js.map +1 -0
- package/dist/{chunk-UEYC46RL.js → chunk-OUGKLCYF.js} +71 -8
- package/dist/chunk-OUGKLCYF.js.map +1 -0
- package/dist/chunk-RONAX6UU.js +3456 -0
- package/dist/chunk-RONAX6UU.js.map +1 -0
- package/dist/{chunk-C74MQIRL.js → chunk-RRYXQMZG.js} +66 -344
- package/dist/chunk-RRYXQMZG.js.map +1 -0
- package/dist/{chunk-QUJ4OLSC.js → chunk-U74F3YZU.js} +87 -7
- package/dist/chunk-U74F3YZU.js.map +1 -0
- package/dist/chunk-VIONYQ2K.cjs +517 -0
- package/dist/chunk-VIONYQ2K.cjs.map +1 -0
- package/dist/chunk-VSTRLXMQ.cjs +50 -0
- package/dist/chunk-VSTRLXMQ.cjs.map +1 -0
- package/dist/chunk-YT7HXXVN.js +13 -0
- package/dist/chunk-YT7HXXVN.js.map +1 -0
- package/dist/chunk-Z6ZWNWWR.js +30 -0
- package/dist/{chunk-NSBPE2FW.js.map → chunk-Z6ZWNWWR.js.map} +1 -1
- package/dist/cli/index.cjs +11 -7
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +11 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/drizzle/index.cjs +20 -17
- package/dist/drizzle/index.d.cts +4 -4
- package/dist/drizzle/index.d.ts +4 -4
- package/dist/drizzle/index.js +4 -5
- package/dist/graphql/index.cjs +4 -4
- package/dist/graphql/index.d.cts +3 -2
- package/dist/graphql/index.d.ts +3 -2
- package/dist/graphql/index.js +2 -2
- package/dist/{index-DI0DRPNv.d.cts → index-BwE4NueJ.d.cts} +1 -1
- package/dist/{index-CMUNCIWQ.d.ts → index-DUKmDSeC.d.cts} +96 -24
- package/dist/{index-BMySjW6o.d.cts → index-DtBi3zP0.d.ts} +96 -24
- package/dist/{index-4fJKLFK2.d.ts → index-DupWTmW6.d.ts} +1 -1
- package/dist/index.cjs +3317 -352
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +379 -105
- package/dist/index.d.ts +379 -105
- package/dist/index.js +3211 -310
- package/dist/index.js.map +1 -1
- package/dist/media-HOT3O7RW.js +4 -0
- package/dist/media-HOT3O7RW.js.map +1 -0
- package/dist/media-WKP5AOX2.cjs +17 -0
- package/dist/media-WKP5AOX2.cjs.map +1 -0
- package/dist/mongodb/index.cjs +1 -1
- package/dist/mongodb/index.d.cts +2 -2
- package/dist/mongodb/index.d.ts +2 -2
- package/dist/mongodb/index.js +1 -1
- package/dist/mysql-media-AI6YK767.cjs +48 -0
- package/dist/mysql-media-AI6YK767.cjs.map +1 -0
- package/dist/mysql-media-CDZUS7YX.js +45 -0
- package/dist/mysql-media-CDZUS7YX.js.map +1 -0
- package/dist/postgres-auth-adapter-EVRPO7BQ.cjs +14 -0
- package/dist/{postgres-auth-adapter-VK6GY7LX.cjs.map → postgres-auth-adapter-EVRPO7BQ.cjs.map} +1 -1
- package/dist/postgres-auth-adapter-OTRWSTT5.js +5 -0
- package/dist/{postgres-auth-adapter-REJFUMP7.js.map → postgres-auth-adapter-OTRWSTT5.js.map} +1 -1
- package/dist/redis-adapter-2N6VA7BI.cjs +13 -0
- package/dist/{redis-adapter-LBLNKGNS.cjs.map → redis-adapter-2N6VA7BI.cjs.map} +1 -1
- package/dist/redis-adapter-RA24FNCX.js +4 -0
- package/dist/{redis-adapter-4YDY4LWE.js.map → redis-adapter-RA24FNCX.js.map} +1 -1
- package/dist/rest/index.cjs +7 -5
- package/dist/rest/index.d.cts +29 -3
- package/dist/rest/index.d.ts +29 -3
- package/dist/rest/index.js +5 -3
- package/dist/schema-CNB2DDTX.js +6 -0
- package/dist/schema-CNB2DDTX.js.map +1 -0
- package/dist/schema-Y777CQQS.cjs +67 -0
- package/dist/schema-Y777CQQS.cjs.map +1 -0
- package/dist/templates/index.cjs +24 -28
- package/dist/templates/index.d.cts +2 -4
- package/dist/templates/index.d.ts +2 -4
- package/dist/templates/index.js +2 -2
- package/dist/trpc/index.cjs +12 -12
- package/dist/trpc/index.d.cts +19 -14
- package/dist/trpc/index.d.ts +19 -14
- package/dist/trpc/index.js +3 -3
- package/dist/{types-BGM5MV_K.d.cts → types-BM0s_YOy.d.cts} +67 -35
- package/dist/{types-BGM5MV_K.d.ts → types-BM0s_YOy.d.ts} +67 -35
- package/dist/ws/index.cjs +1 -1
- package/dist/ws/index.js +1 -1
- package/package.json +11 -1
- package/dist/bootstrap-BDTTUGY2.js +0 -4
- package/dist/bootstrap-X6TP3NKX.cjs +0 -29
- package/dist/chunk-3QX6KG2S.js +0 -2125
- package/dist/chunk-3QX6KG2S.js.map +0 -1
- package/dist/chunk-3VZCX4DF.cjs.map +0 -1
- package/dist/chunk-5BLDMQED.cjs +0 -18
- package/dist/chunk-7G6EVYCU.cjs +0 -94
- package/dist/chunk-7G6EVYCU.cjs.map +0 -1
- package/dist/chunk-A3RQWHKD.cjs.map +0 -1
- package/dist/chunk-C74MQIRL.js.map +0 -1
- package/dist/chunk-EINVJPFM.js.map +0 -1
- package/dist/chunk-F5B64H5S.cjs +0 -2149
- package/dist/chunk-F5B64H5S.cjs.map +0 -1
- package/dist/chunk-K7QF2QCM.cjs.map +0 -1
- package/dist/chunk-LRTZJJPD.js +0 -86
- package/dist/chunk-LRTZJJPD.js.map +0 -1
- package/dist/chunk-MHS6CPO5.cjs.map +0 -1
- package/dist/chunk-NSBPE2FW.js +0 -15
- package/dist/chunk-OG3KX56O.js.map +0 -1
- package/dist/chunk-QUJ4OLSC.js.map +0 -1
- package/dist/chunk-R3XIBBAW.cjs +0 -34
- package/dist/chunk-R3XIBBAW.cjs.map +0 -1
- package/dist/chunk-SDMNUYVU.js +0 -30
- package/dist/chunk-SDMNUYVU.js.map +0 -1
- package/dist/chunk-TZFJMPCH.cjs.map +0 -1
- package/dist/chunk-UEG7KMKC.cjs +0 -228
- package/dist/chunk-UEG7KMKC.cjs.map +0 -1
- package/dist/chunk-UEYC46RL.js.map +0 -1
- package/dist/chunk-V3B25QOK.cjs.map +0 -1
- package/dist/chunk-VMSRTAH7.js.map +0 -1
- package/dist/chunk-XTZSUDSI.js.map +0 -1
- package/dist/chunk-YD7Y25W7.cjs +0 -176
- package/dist/chunk-YD7Y25W7.cjs.map +0 -1
- package/dist/chunk-YPAFJ7EV.js +0 -225
- package/dist/chunk-YPAFJ7EV.js.map +0 -1
- package/dist/database-7CJOXEZR.js +0 -5
- package/dist/database-7CJOXEZR.js.map +0 -1
- package/dist/database-QOIV44GT.cjs +0 -22
- package/dist/database-QOIV44GT.cjs.map +0 -1
- package/dist/postgres-auth-adapter-REJFUMP7.js +0 -5
- package/dist/postgres-auth-adapter-VK6GY7LX.cjs +0 -14
- package/dist/redis-adapter-4YDY4LWE.js +0 -4
- package/dist/redis-adapter-LBLNKGNS.cjs +0 -13
package/dist/index.cjs
CHANGED
|
@@ -1,29 +1,1024 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
3
|
+
var chunkKDVDIZ4Y_cjs = require('./chunk-KDVDIZ4Y.cjs');
|
|
4
|
+
var chunkBLMFBDBG_cjs = require('./chunk-BLMFBDBG.cjs');
|
|
5
|
+
var chunk4M5PHMUE_cjs = require('./chunk-4M5PHMUE.cjs');
|
|
6
|
+
var chunk42JPONZU_cjs = require('./chunk-42JPONZU.cjs');
|
|
7
|
+
var chunkFTSSDDZQ_cjs = require('./chunk-FTSSDDZQ.cjs');
|
|
8
|
+
var chunkE63IF3MD_cjs = require('./chunk-E63IF3MD.cjs');
|
|
9
|
+
var chunkHVSQDZZJ_cjs = require('./chunk-HVSQDZZJ.cjs');
|
|
10
|
+
require('./chunk-4PWRCMTQ.cjs');
|
|
11
|
+
var chunkVIONYQ2K_cjs = require('./chunk-VIONYQ2K.cjs');
|
|
10
12
|
var chunkDVD5P72E_cjs = require('./chunk-DVD5P72E.cjs');
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
require('./chunk-TZFJMPCH.cjs');
|
|
13
|
+
var chunkGVFB5C6O_cjs = require('./chunk-GVFB5C6O.cjs');
|
|
14
|
+
var chunkLIJVWQKU_cjs = require('./chunk-LIJVWQKU.cjs');
|
|
15
|
+
require('./chunk-7YITG2US.cjs');
|
|
15
16
|
var chunkHT6VE4NW_cjs = require('./chunk-HT6VE4NW.cjs');
|
|
16
17
|
var chunkRLTG4YZM_cjs = require('./chunk-RLTG4YZM.cjs');
|
|
17
|
-
var
|
|
18
|
+
var chunkG7VZBCD6_cjs = require('./chunk-G7VZBCD6.cjs');
|
|
19
|
+
var stream = require('stream');
|
|
20
|
+
var https = require('https');
|
|
21
|
+
var http2 = require('http2');
|
|
18
22
|
var zod = require('zod');
|
|
19
23
|
var bcrypt = require('bcrypt');
|
|
20
|
-
var
|
|
24
|
+
var jwt = require('jsonwebtoken');
|
|
21
25
|
var crypto = require('crypto');
|
|
26
|
+
var path = require('path');
|
|
27
|
+
var promises = require('fs/promises');
|
|
28
|
+
var fs = require('fs');
|
|
29
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
30
|
+
var basicFtp = require('basic-ftp');
|
|
31
|
+
var sharp = require('sharp');
|
|
22
32
|
|
|
23
33
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
34
|
|
|
35
|
+
var http2__default = /*#__PURE__*/_interopDefault(http2);
|
|
25
36
|
var bcrypt__default = /*#__PURE__*/_interopDefault(bcrypt);
|
|
26
|
-
var
|
|
37
|
+
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
38
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
39
|
+
var sharp__default = /*#__PURE__*/_interopDefault(sharp);
|
|
40
|
+
|
|
41
|
+
// node_modules/@smithy/protocol-http/dist-es/extensions/httpExtensionConfiguration.js
|
|
42
|
+
var init_httpExtensionConfiguration = chunkG7VZBCD6_cjs.__esm({
|
|
43
|
+
"node_modules/@smithy/protocol-http/dist-es/extensions/httpExtensionConfiguration.js"() {
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// node_modules/@smithy/protocol-http/dist-es/extensions/index.js
|
|
48
|
+
var init_extensions = chunkG7VZBCD6_cjs.__esm({
|
|
49
|
+
"node_modules/@smithy/protocol-http/dist-es/extensions/index.js"() {
|
|
50
|
+
init_httpExtensionConfiguration();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// node_modules/@smithy/protocol-http/dist-es/Field.js
|
|
55
|
+
var init_Field = chunkG7VZBCD6_cjs.__esm({
|
|
56
|
+
"node_modules/@smithy/protocol-http/dist-es/Field.js"() {
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// node_modules/@smithy/protocol-http/dist-es/Fields.js
|
|
61
|
+
var init_Fields = chunkG7VZBCD6_cjs.__esm({
|
|
62
|
+
"node_modules/@smithy/protocol-http/dist-es/Fields.js"() {
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// node_modules/@smithy/protocol-http/dist-es/httpHandler.js
|
|
67
|
+
var init_httpHandler = chunkG7VZBCD6_cjs.__esm({
|
|
68
|
+
"node_modules/@smithy/protocol-http/dist-es/httpHandler.js"() {
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// node_modules/@smithy/protocol-http/dist-es/httpRequest.js
|
|
73
|
+
var init_httpRequest = chunkG7VZBCD6_cjs.__esm({
|
|
74
|
+
"node_modules/@smithy/protocol-http/dist-es/httpRequest.js"() {
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// node_modules/@smithy/protocol-http/dist-es/httpResponse.js
|
|
79
|
+
var HttpResponse;
|
|
80
|
+
var init_httpResponse = chunkG7VZBCD6_cjs.__esm({
|
|
81
|
+
"node_modules/@smithy/protocol-http/dist-es/httpResponse.js"() {
|
|
82
|
+
HttpResponse = class {
|
|
83
|
+
statusCode;
|
|
84
|
+
reason;
|
|
85
|
+
headers;
|
|
86
|
+
body;
|
|
87
|
+
constructor(options) {
|
|
88
|
+
this.statusCode = options.statusCode;
|
|
89
|
+
this.reason = options.reason;
|
|
90
|
+
this.headers = options.headers || {};
|
|
91
|
+
this.body = options.body;
|
|
92
|
+
}
|
|
93
|
+
static isInstance(response) {
|
|
94
|
+
if (!response)
|
|
95
|
+
return false;
|
|
96
|
+
const resp = response;
|
|
97
|
+
return typeof resp.statusCode === "number" && typeof resp.headers === "object";
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// node_modules/@smithy/protocol-http/dist-es/isValidHostname.js
|
|
104
|
+
var init_isValidHostname = chunkG7VZBCD6_cjs.__esm({
|
|
105
|
+
"node_modules/@smithy/protocol-http/dist-es/isValidHostname.js"() {
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// node_modules/@smithy/protocol-http/dist-es/types.js
|
|
110
|
+
var init_types = chunkG7VZBCD6_cjs.__esm({
|
|
111
|
+
"node_modules/@smithy/protocol-http/dist-es/types.js"() {
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// node_modules/@smithy/protocol-http/dist-es/index.js
|
|
116
|
+
var init_dist_es = chunkG7VZBCD6_cjs.__esm({
|
|
117
|
+
"node_modules/@smithy/protocol-http/dist-es/index.js"() {
|
|
118
|
+
init_extensions();
|
|
119
|
+
init_Field();
|
|
120
|
+
init_Fields();
|
|
121
|
+
init_httpHandler();
|
|
122
|
+
init_httpRequest();
|
|
123
|
+
init_httpResponse();
|
|
124
|
+
init_isValidHostname();
|
|
125
|
+
init_types();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// node_modules/@smithy/util-uri-escape/dist-es/escape-uri.js
|
|
130
|
+
var escapeUri, hexEncode;
|
|
131
|
+
var init_escape_uri = chunkG7VZBCD6_cjs.__esm({
|
|
132
|
+
"node_modules/@smithy/util-uri-escape/dist-es/escape-uri.js"() {
|
|
133
|
+
escapeUri = (uri) => encodeURIComponent(uri).replace(/[!'()*]/g, hexEncode);
|
|
134
|
+
hexEncode = (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// node_modules/@smithy/util-uri-escape/dist-es/escape-uri-path.js
|
|
139
|
+
var init_escape_uri_path = chunkG7VZBCD6_cjs.__esm({
|
|
140
|
+
"node_modules/@smithy/util-uri-escape/dist-es/escape-uri-path.js"() {
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// node_modules/@smithy/util-uri-escape/dist-es/index.js
|
|
145
|
+
var init_dist_es2 = chunkG7VZBCD6_cjs.__esm({
|
|
146
|
+
"node_modules/@smithy/util-uri-escape/dist-es/index.js"() {
|
|
147
|
+
init_escape_uri();
|
|
148
|
+
init_escape_uri_path();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// node_modules/@smithy/querystring-builder/dist-es/index.js
|
|
153
|
+
function buildQueryString(query) {
|
|
154
|
+
const parts = [];
|
|
155
|
+
for (let key of Object.keys(query).sort()) {
|
|
156
|
+
const value = query[key];
|
|
157
|
+
key = escapeUri(key);
|
|
158
|
+
if (Array.isArray(value)) {
|
|
159
|
+
for (let i = 0, iLen = value.length; i < iLen; i++) {
|
|
160
|
+
parts.push(`${key}=${escapeUri(value[i])}`);
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
let qsEntry = key;
|
|
164
|
+
if (value || typeof value === "string") {
|
|
165
|
+
qsEntry += `=${escapeUri(value)}`;
|
|
166
|
+
}
|
|
167
|
+
parts.push(qsEntry);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return parts.join("&");
|
|
171
|
+
}
|
|
172
|
+
var init_dist_es3 = chunkG7VZBCD6_cjs.__esm({
|
|
173
|
+
"node_modules/@smithy/querystring-builder/dist-es/index.js"() {
|
|
174
|
+
init_dist_es2();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js
|
|
179
|
+
function buildAbortError(abortSignal) {
|
|
180
|
+
const reason = abortSignal && typeof abortSignal === "object" && "reason" in abortSignal ? abortSignal.reason : void 0;
|
|
181
|
+
if (reason) {
|
|
182
|
+
if (reason instanceof Error) {
|
|
183
|
+
const abortError3 = new Error("Request aborted");
|
|
184
|
+
abortError3.name = "AbortError";
|
|
185
|
+
abortError3.cause = reason;
|
|
186
|
+
return abortError3;
|
|
187
|
+
}
|
|
188
|
+
const abortError2 = new Error(String(reason));
|
|
189
|
+
abortError2.name = "AbortError";
|
|
190
|
+
return abortError2;
|
|
191
|
+
}
|
|
192
|
+
const abortError = new Error("Request aborted");
|
|
193
|
+
abortError.name = "AbortError";
|
|
194
|
+
return abortError;
|
|
195
|
+
}
|
|
196
|
+
var init_build_abort_error = chunkG7VZBCD6_cjs.__esm({
|
|
197
|
+
"node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js"() {
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// node_modules/@smithy/node-http-handler/dist-es/constants.js
|
|
202
|
+
var NODEJS_TIMEOUT_ERROR_CODES;
|
|
203
|
+
var init_constants = chunkG7VZBCD6_cjs.__esm({
|
|
204
|
+
"node_modules/@smithy/node-http-handler/dist-es/constants.js"() {
|
|
205
|
+
NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "EPIPE", "ETIMEDOUT"];
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js
|
|
210
|
+
var getTransformedHeaders;
|
|
211
|
+
var init_get_transformed_headers = chunkG7VZBCD6_cjs.__esm({
|
|
212
|
+
"node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js"() {
|
|
213
|
+
getTransformedHeaders = (headers) => {
|
|
214
|
+
const transformedHeaders = {};
|
|
215
|
+
for (const name of Object.keys(headers)) {
|
|
216
|
+
const headerValues = headers[name];
|
|
217
|
+
transformedHeaders[name] = Array.isArray(headerValues) ? headerValues.join(",") : headerValues;
|
|
218
|
+
}
|
|
219
|
+
return transformedHeaders;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// node_modules/@smithy/node-http-handler/dist-es/timing.js
|
|
225
|
+
var timing;
|
|
226
|
+
var init_timing = chunkG7VZBCD6_cjs.__esm({
|
|
227
|
+
"node_modules/@smithy/node-http-handler/dist-es/timing.js"() {
|
|
228
|
+
timing = {
|
|
229
|
+
setTimeout: (cb, ms) => setTimeout(cb, ms),
|
|
230
|
+
clearTimeout: (timeoutId) => clearTimeout(timeoutId)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js
|
|
236
|
+
var DEFER_EVENT_LISTENER_TIME, setConnectionTimeout;
|
|
237
|
+
var init_set_connection_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
238
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js"() {
|
|
239
|
+
init_timing();
|
|
240
|
+
DEFER_EVENT_LISTENER_TIME = 1e3;
|
|
241
|
+
setConnectionTimeout = (request, reject, timeoutInMs = 0) => {
|
|
242
|
+
if (!timeoutInMs) {
|
|
243
|
+
return -1;
|
|
244
|
+
}
|
|
245
|
+
const registerTimeout = (offset) => {
|
|
246
|
+
const timeoutId = timing.setTimeout(() => {
|
|
247
|
+
request.destroy();
|
|
248
|
+
reject(Object.assign(new Error(`@smithy/node-http-handler - the request socket did not establish a connection with the server within the configured timeout of ${timeoutInMs} ms.`), {
|
|
249
|
+
name: "TimeoutError"
|
|
250
|
+
}));
|
|
251
|
+
}, timeoutInMs - offset);
|
|
252
|
+
const doWithSocket = (socket) => {
|
|
253
|
+
if (socket?.connecting) {
|
|
254
|
+
socket.on("connect", () => {
|
|
255
|
+
timing.clearTimeout(timeoutId);
|
|
256
|
+
});
|
|
257
|
+
} else {
|
|
258
|
+
timing.clearTimeout(timeoutId);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
if (request.socket) {
|
|
262
|
+
doWithSocket(request.socket);
|
|
263
|
+
} else {
|
|
264
|
+
request.on("socket", doWithSocket);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
if (timeoutInMs < 2e3) {
|
|
268
|
+
registerTimeout(0);
|
|
269
|
+
return 0;
|
|
270
|
+
}
|
|
271
|
+
return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME);
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js
|
|
277
|
+
var setRequestTimeout;
|
|
278
|
+
var init_set_request_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
279
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js"() {
|
|
280
|
+
init_timing();
|
|
281
|
+
setRequestTimeout = (req, reject, timeoutInMs = 0, throwOnRequestTimeout, logger) => {
|
|
282
|
+
if (timeoutInMs) {
|
|
283
|
+
return timing.setTimeout(() => {
|
|
284
|
+
let msg = `@smithy/node-http-handler - [${throwOnRequestTimeout ? "ERROR" : "WARN"}] a request has exceeded the configured ${timeoutInMs} ms requestTimeout.`;
|
|
285
|
+
if (throwOnRequestTimeout) {
|
|
286
|
+
const error = Object.assign(new Error(msg), {
|
|
287
|
+
name: "TimeoutError",
|
|
288
|
+
code: "ETIMEDOUT"
|
|
289
|
+
});
|
|
290
|
+
req.destroy(error);
|
|
291
|
+
reject(error);
|
|
292
|
+
} else {
|
|
293
|
+
msg += ` Init client requestHandler with throwOnRequestTimeout=true to turn this into an error.`;
|
|
294
|
+
logger?.warn?.(msg);
|
|
295
|
+
}
|
|
296
|
+
}, timeoutInMs);
|
|
297
|
+
}
|
|
298
|
+
return -1;
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js
|
|
304
|
+
var DEFER_EVENT_LISTENER_TIME2, setSocketKeepAlive;
|
|
305
|
+
var init_set_socket_keep_alive = chunkG7VZBCD6_cjs.__esm({
|
|
306
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js"() {
|
|
307
|
+
init_timing();
|
|
308
|
+
DEFER_EVENT_LISTENER_TIME2 = 3e3;
|
|
309
|
+
setSocketKeepAlive = (request, { keepAlive, keepAliveMsecs }, deferTimeMs = DEFER_EVENT_LISTENER_TIME2) => {
|
|
310
|
+
if (keepAlive !== true) {
|
|
311
|
+
return -1;
|
|
312
|
+
}
|
|
313
|
+
const registerListener = () => {
|
|
314
|
+
if (request.socket) {
|
|
315
|
+
request.socket.setKeepAlive(keepAlive, keepAliveMsecs || 0);
|
|
316
|
+
} else {
|
|
317
|
+
request.on("socket", (socket) => {
|
|
318
|
+
socket.setKeepAlive(keepAlive, keepAliveMsecs || 0);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
if (deferTimeMs === 0) {
|
|
323
|
+
registerListener();
|
|
324
|
+
return 0;
|
|
325
|
+
}
|
|
326
|
+
return timing.setTimeout(registerListener, deferTimeMs);
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js
|
|
332
|
+
var DEFER_EVENT_LISTENER_TIME3, setSocketTimeout;
|
|
333
|
+
var init_set_socket_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
334
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js"() {
|
|
335
|
+
init_timing();
|
|
336
|
+
DEFER_EVENT_LISTENER_TIME3 = 3e3;
|
|
337
|
+
setSocketTimeout = (request, reject, timeoutInMs = 0) => {
|
|
338
|
+
const registerTimeout = (offset) => {
|
|
339
|
+
const timeout = timeoutInMs - offset;
|
|
340
|
+
const onTimeout = () => {
|
|
341
|
+
request.destroy();
|
|
342
|
+
reject(Object.assign(new Error(`@smithy/node-http-handler - the request socket timed out after ${timeoutInMs} ms of inactivity (configured by client requestHandler).`), { name: "TimeoutError" }));
|
|
343
|
+
};
|
|
344
|
+
if (request.socket) {
|
|
345
|
+
request.socket.setTimeout(timeout, onTimeout);
|
|
346
|
+
request.on("close", () => request.socket?.removeListener("timeout", onTimeout));
|
|
347
|
+
} else {
|
|
348
|
+
request.setTimeout(timeout, onTimeout);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
if (0 < timeoutInMs && timeoutInMs < 6e3) {
|
|
352
|
+
registerTimeout(0);
|
|
353
|
+
return 0;
|
|
354
|
+
}
|
|
355
|
+
return timing.setTimeout(registerTimeout.bind(null, timeoutInMs === 0 ? 0 : DEFER_EVENT_LISTENER_TIME3), DEFER_EVENT_LISTENER_TIME3);
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
async function writeRequestBody(httpRequest, request, maxContinueTimeoutMs = MIN_WAIT_TIME, externalAgent = false) {
|
|
360
|
+
const headers = request.headers ?? {};
|
|
361
|
+
const expect = headers.Expect || headers.expect;
|
|
362
|
+
let timeoutId = -1;
|
|
363
|
+
let sendBody = true;
|
|
364
|
+
if (!externalAgent && expect === "100-continue") {
|
|
365
|
+
sendBody = await Promise.race([
|
|
366
|
+
new Promise((resolve) => {
|
|
367
|
+
timeoutId = Number(timing.setTimeout(() => resolve(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
|
|
368
|
+
}),
|
|
369
|
+
new Promise((resolve) => {
|
|
370
|
+
httpRequest.on("continue", () => {
|
|
371
|
+
timing.clearTimeout(timeoutId);
|
|
372
|
+
resolve(true);
|
|
373
|
+
});
|
|
374
|
+
httpRequest.on("response", () => {
|
|
375
|
+
timing.clearTimeout(timeoutId);
|
|
376
|
+
resolve(false);
|
|
377
|
+
});
|
|
378
|
+
httpRequest.on("error", () => {
|
|
379
|
+
timing.clearTimeout(timeoutId);
|
|
380
|
+
resolve(false);
|
|
381
|
+
});
|
|
382
|
+
})
|
|
383
|
+
]);
|
|
384
|
+
}
|
|
385
|
+
if (sendBody) {
|
|
386
|
+
writeBody(httpRequest, request.body);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function writeBody(httpRequest, body) {
|
|
390
|
+
if (body instanceof stream.Readable) {
|
|
391
|
+
body.pipe(httpRequest);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (body) {
|
|
395
|
+
const isBuffer = Buffer.isBuffer(body);
|
|
396
|
+
const isString = typeof body === "string";
|
|
397
|
+
if (isBuffer || isString) {
|
|
398
|
+
if (isBuffer && body.byteLength === 0) {
|
|
399
|
+
httpRequest.end();
|
|
400
|
+
} else {
|
|
401
|
+
httpRequest.end(body);
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const uint8 = body;
|
|
406
|
+
if (typeof uint8 === "object" && uint8.buffer && typeof uint8.byteOffset === "number" && typeof uint8.byteLength === "number") {
|
|
407
|
+
httpRequest.end(Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength));
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
httpRequest.end(Buffer.from(body));
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
httpRequest.end();
|
|
414
|
+
}
|
|
415
|
+
var MIN_WAIT_TIME;
|
|
416
|
+
var init_write_request_body = chunkG7VZBCD6_cjs.__esm({
|
|
417
|
+
"node_modules/@smithy/node-http-handler/dist-es/write-request-body.js"() {
|
|
418
|
+
init_timing();
|
|
419
|
+
MIN_WAIT_TIME = 6e3;
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
var DEFAULT_REQUEST_TIMEOUT, hAgent, hRequest, NodeHttpHandler;
|
|
423
|
+
var init_node_http_handler = chunkG7VZBCD6_cjs.__esm({
|
|
424
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js"() {
|
|
425
|
+
init_dist_es();
|
|
426
|
+
init_dist_es3();
|
|
427
|
+
init_build_abort_error();
|
|
428
|
+
init_constants();
|
|
429
|
+
init_get_transformed_headers();
|
|
430
|
+
init_set_connection_timeout();
|
|
431
|
+
init_set_request_timeout();
|
|
432
|
+
init_set_socket_keep_alive();
|
|
433
|
+
init_set_socket_timeout();
|
|
434
|
+
init_timing();
|
|
435
|
+
init_write_request_body();
|
|
436
|
+
DEFAULT_REQUEST_TIMEOUT = 0;
|
|
437
|
+
hAgent = void 0;
|
|
438
|
+
hRequest = void 0;
|
|
439
|
+
NodeHttpHandler = class _NodeHttpHandler {
|
|
440
|
+
config;
|
|
441
|
+
configProvider;
|
|
442
|
+
socketWarningTimestamp = 0;
|
|
443
|
+
externalAgent = false;
|
|
444
|
+
metadata = { handlerProtocol: "http/1.1" };
|
|
445
|
+
static create(instanceOrOptions) {
|
|
446
|
+
if (typeof instanceOrOptions?.handle === "function") {
|
|
447
|
+
return instanceOrOptions;
|
|
448
|
+
}
|
|
449
|
+
return new _NodeHttpHandler(instanceOrOptions);
|
|
450
|
+
}
|
|
451
|
+
static checkSocketUsage(agent, socketWarningTimestamp, logger = console) {
|
|
452
|
+
const { sockets, requests, maxSockets } = agent;
|
|
453
|
+
if (typeof maxSockets !== "number" || maxSockets === Infinity) {
|
|
454
|
+
return socketWarningTimestamp;
|
|
455
|
+
}
|
|
456
|
+
const interval = 15e3;
|
|
457
|
+
if (Date.now() - interval < socketWarningTimestamp) {
|
|
458
|
+
return socketWarningTimestamp;
|
|
459
|
+
}
|
|
460
|
+
if (sockets && requests) {
|
|
461
|
+
for (const origin in sockets) {
|
|
462
|
+
const socketsInUse = sockets[origin]?.length ?? 0;
|
|
463
|
+
const requestsEnqueued = requests[origin]?.length ?? 0;
|
|
464
|
+
if (socketsInUse >= maxSockets && requestsEnqueued >= 2 * maxSockets) {
|
|
465
|
+
logger?.warn?.(`@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued.
|
|
466
|
+
See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html
|
|
467
|
+
or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.`);
|
|
468
|
+
return Date.now();
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return socketWarningTimestamp;
|
|
473
|
+
}
|
|
474
|
+
constructor(options) {
|
|
475
|
+
this.configProvider = new Promise((resolve, reject) => {
|
|
476
|
+
if (typeof options === "function") {
|
|
477
|
+
options().then((_options) => {
|
|
478
|
+
resolve(this.resolveDefaultConfig(_options));
|
|
479
|
+
}).catch(reject);
|
|
480
|
+
} else {
|
|
481
|
+
resolve(this.resolveDefaultConfig(options));
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
destroy() {
|
|
486
|
+
this.config?.httpAgent?.destroy();
|
|
487
|
+
this.config?.httpsAgent?.destroy();
|
|
488
|
+
}
|
|
489
|
+
async handle(request, { abortSignal, requestTimeout } = {}) {
|
|
490
|
+
if (!this.config) {
|
|
491
|
+
this.config = await this.configProvider;
|
|
492
|
+
}
|
|
493
|
+
const config = this.config;
|
|
494
|
+
const isSSL = request.protocol === "https:";
|
|
495
|
+
if (!isSSL && !this.config.httpAgent) {
|
|
496
|
+
this.config.httpAgent = await this.config.httpAgentProvider();
|
|
497
|
+
}
|
|
498
|
+
return new Promise((_resolve, _reject) => {
|
|
499
|
+
let writeRequestBodyPromise = void 0;
|
|
500
|
+
const timeouts = [];
|
|
501
|
+
const resolve = async (arg) => {
|
|
502
|
+
await writeRequestBodyPromise;
|
|
503
|
+
timeouts.forEach(timing.clearTimeout);
|
|
504
|
+
_resolve(arg);
|
|
505
|
+
};
|
|
506
|
+
const reject = async (arg) => {
|
|
507
|
+
await writeRequestBodyPromise;
|
|
508
|
+
timeouts.forEach(timing.clearTimeout);
|
|
509
|
+
_reject(arg);
|
|
510
|
+
};
|
|
511
|
+
if (abortSignal?.aborted) {
|
|
512
|
+
const abortError = buildAbortError(abortSignal);
|
|
513
|
+
reject(abortError);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
const headers = request.headers ?? {};
|
|
517
|
+
const expectContinue = (headers.Expect ?? headers.expect) === "100-continue";
|
|
518
|
+
let agent = isSSL ? config.httpsAgent : config.httpAgent;
|
|
519
|
+
if (expectContinue && !this.externalAgent) {
|
|
520
|
+
agent = new (isSSL ? https.Agent : hAgent)({
|
|
521
|
+
keepAlive: false,
|
|
522
|
+
maxSockets: Infinity
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
timeouts.push(timing.setTimeout(() => {
|
|
526
|
+
this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, config.logger);
|
|
527
|
+
}, config.socketAcquisitionWarningTimeout ?? (config.requestTimeout ?? 2e3) + (config.connectionTimeout ?? 1e3)));
|
|
528
|
+
const queryString = buildQueryString(request.query || {});
|
|
529
|
+
let auth = void 0;
|
|
530
|
+
if (request.username != null || request.password != null) {
|
|
531
|
+
const username = request.username ?? "";
|
|
532
|
+
const password = request.password ?? "";
|
|
533
|
+
auth = `${username}:${password}`;
|
|
534
|
+
}
|
|
535
|
+
let path2 = request.path;
|
|
536
|
+
if (queryString) {
|
|
537
|
+
path2 += `?${queryString}`;
|
|
538
|
+
}
|
|
539
|
+
if (request.fragment) {
|
|
540
|
+
path2 += `#${request.fragment}`;
|
|
541
|
+
}
|
|
542
|
+
let hostname = request.hostname ?? "";
|
|
543
|
+
if (hostname[0] === "[" && hostname.endsWith("]")) {
|
|
544
|
+
hostname = request.hostname.slice(1, -1);
|
|
545
|
+
} else {
|
|
546
|
+
hostname = request.hostname;
|
|
547
|
+
}
|
|
548
|
+
const nodeHttpsOptions = {
|
|
549
|
+
headers: request.headers,
|
|
550
|
+
host: hostname,
|
|
551
|
+
method: request.method,
|
|
552
|
+
path: path2,
|
|
553
|
+
port: request.port,
|
|
554
|
+
agent,
|
|
555
|
+
auth
|
|
556
|
+
};
|
|
557
|
+
const requestFunc = isSSL ? https.request : hRequest;
|
|
558
|
+
const req = requestFunc(nodeHttpsOptions, (res) => {
|
|
559
|
+
const httpResponse = new HttpResponse({
|
|
560
|
+
statusCode: res.statusCode || -1,
|
|
561
|
+
reason: res.statusMessage,
|
|
562
|
+
headers: getTransformedHeaders(res.headers),
|
|
563
|
+
body: res
|
|
564
|
+
});
|
|
565
|
+
resolve({ response: httpResponse });
|
|
566
|
+
});
|
|
567
|
+
req.on("error", (err) => {
|
|
568
|
+
if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
|
|
569
|
+
reject(Object.assign(err, { name: "TimeoutError" }));
|
|
570
|
+
} else {
|
|
571
|
+
reject(err);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
if (abortSignal) {
|
|
575
|
+
const onAbort = () => {
|
|
576
|
+
req.destroy();
|
|
577
|
+
const abortError = buildAbortError(abortSignal);
|
|
578
|
+
reject(abortError);
|
|
579
|
+
};
|
|
580
|
+
if (typeof abortSignal.addEventListener === "function") {
|
|
581
|
+
const signal = abortSignal;
|
|
582
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
583
|
+
req.once("close", () => signal.removeEventListener("abort", onAbort));
|
|
584
|
+
} else {
|
|
585
|
+
abortSignal.onabort = onAbort;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const effectiveRequestTimeout = requestTimeout ?? config.requestTimeout;
|
|
589
|
+
timeouts.push(setConnectionTimeout(req, reject, config.connectionTimeout));
|
|
590
|
+
timeouts.push(setRequestTimeout(req, reject, effectiveRequestTimeout, config.throwOnRequestTimeout, config.logger ?? console));
|
|
591
|
+
timeouts.push(setSocketTimeout(req, reject, config.socketTimeout));
|
|
592
|
+
const httpAgent = nodeHttpsOptions.agent;
|
|
593
|
+
if (typeof httpAgent === "object" && "keepAlive" in httpAgent) {
|
|
594
|
+
timeouts.push(setSocketKeepAlive(req, {
|
|
595
|
+
keepAlive: httpAgent.keepAlive,
|
|
596
|
+
keepAliveMsecs: httpAgent.keepAliveMsecs
|
|
597
|
+
}));
|
|
598
|
+
}
|
|
599
|
+
writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout, this.externalAgent).catch((e) => {
|
|
600
|
+
timeouts.forEach(timing.clearTimeout);
|
|
601
|
+
return _reject(e);
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
updateHttpClientConfig(key, value) {
|
|
606
|
+
this.config = void 0;
|
|
607
|
+
this.configProvider = this.configProvider.then((config) => {
|
|
608
|
+
return {
|
|
609
|
+
...config,
|
|
610
|
+
[key]: value
|
|
611
|
+
};
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
httpHandlerConfigs() {
|
|
615
|
+
return this.config ?? {};
|
|
616
|
+
}
|
|
617
|
+
resolveDefaultConfig(options) {
|
|
618
|
+
const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent, throwOnRequestTimeout, logger } = options || {};
|
|
619
|
+
const keepAlive = true;
|
|
620
|
+
const maxSockets = 50;
|
|
621
|
+
return {
|
|
622
|
+
connectionTimeout,
|
|
623
|
+
requestTimeout,
|
|
624
|
+
socketTimeout,
|
|
625
|
+
socketAcquisitionWarningTimeout,
|
|
626
|
+
throwOnRequestTimeout,
|
|
627
|
+
httpAgentProvider: async () => {
|
|
628
|
+
const { Agent, request } = await import('http');
|
|
629
|
+
hRequest = request;
|
|
630
|
+
hAgent = Agent;
|
|
631
|
+
if (httpAgent instanceof hAgent || typeof httpAgent?.destroy === "function") {
|
|
632
|
+
this.externalAgent = true;
|
|
633
|
+
return httpAgent;
|
|
634
|
+
}
|
|
635
|
+
return new hAgent({ keepAlive, maxSockets, ...httpAgent });
|
|
636
|
+
},
|
|
637
|
+
httpsAgent: (() => {
|
|
638
|
+
if (httpsAgent instanceof https.Agent || typeof httpsAgent?.destroy === "function") {
|
|
639
|
+
this.externalAgent = true;
|
|
640
|
+
return httpsAgent;
|
|
641
|
+
}
|
|
642
|
+
return new https.Agent({ keepAlive, maxSockets, ...httpsAgent });
|
|
643
|
+
})(),
|
|
644
|
+
logger
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js
|
|
652
|
+
var NodeHttp2ConnectionPool;
|
|
653
|
+
var init_node_http2_connection_pool = chunkG7VZBCD6_cjs.__esm({
|
|
654
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js"() {
|
|
655
|
+
NodeHttp2ConnectionPool = class {
|
|
656
|
+
sessions = [];
|
|
657
|
+
constructor(sessions) {
|
|
658
|
+
this.sessions = sessions ?? [];
|
|
659
|
+
}
|
|
660
|
+
poll() {
|
|
661
|
+
if (this.sessions.length > 0) {
|
|
662
|
+
return this.sessions.shift();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
offerLast(session) {
|
|
666
|
+
this.sessions.push(session);
|
|
667
|
+
}
|
|
668
|
+
contains(session) {
|
|
669
|
+
return this.sessions.includes(session);
|
|
670
|
+
}
|
|
671
|
+
remove(session) {
|
|
672
|
+
this.sessions = this.sessions.filter((s) => s !== session);
|
|
673
|
+
}
|
|
674
|
+
[Symbol.iterator]() {
|
|
675
|
+
return this.sessions[Symbol.iterator]();
|
|
676
|
+
}
|
|
677
|
+
destroy(connection) {
|
|
678
|
+
for (const session of this.sessions) {
|
|
679
|
+
if (session === connection) {
|
|
680
|
+
if (!session.destroyed) {
|
|
681
|
+
session.destroy();
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
var NodeHttp2ConnectionManager;
|
|
690
|
+
var init_node_http2_connection_manager = chunkG7VZBCD6_cjs.__esm({
|
|
691
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js"() {
|
|
692
|
+
init_node_http2_connection_pool();
|
|
693
|
+
NodeHttp2ConnectionManager = class {
|
|
694
|
+
constructor(config) {
|
|
695
|
+
this.config = config;
|
|
696
|
+
if (this.config.maxConcurrency && this.config.maxConcurrency <= 0) {
|
|
697
|
+
throw new RangeError("maxConcurrency must be greater than zero.");
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
config;
|
|
701
|
+
sessionCache = /* @__PURE__ */ new Map();
|
|
702
|
+
lease(requestContext, connectionConfiguration) {
|
|
703
|
+
const url = this.getUrlString(requestContext);
|
|
704
|
+
const existingPool = this.sessionCache.get(url);
|
|
705
|
+
if (existingPool) {
|
|
706
|
+
const existingSession = existingPool.poll();
|
|
707
|
+
if (existingSession && !this.config.disableConcurrency) {
|
|
708
|
+
return existingSession;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
const session = http2__default.default.connect(url);
|
|
712
|
+
if (this.config.maxConcurrency) {
|
|
713
|
+
session.settings({ maxConcurrentStreams: this.config.maxConcurrency }, (err) => {
|
|
714
|
+
if (err) {
|
|
715
|
+
throw new Error("Fail to set maxConcurrentStreams to " + this.config.maxConcurrency + "when creating new session for " + requestContext.destination.toString());
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
session.unref();
|
|
720
|
+
const destroySessionCb = () => {
|
|
721
|
+
session.destroy();
|
|
722
|
+
this.deleteSession(url, session);
|
|
723
|
+
};
|
|
724
|
+
session.on("goaway", destroySessionCb);
|
|
725
|
+
session.on("error", destroySessionCb);
|
|
726
|
+
session.on("frameError", destroySessionCb);
|
|
727
|
+
session.on("close", () => this.deleteSession(url, session));
|
|
728
|
+
if (connectionConfiguration.requestTimeout) {
|
|
729
|
+
session.setTimeout(connectionConfiguration.requestTimeout, destroySessionCb);
|
|
730
|
+
}
|
|
731
|
+
const connectionPool = this.sessionCache.get(url) || new NodeHttp2ConnectionPool();
|
|
732
|
+
connectionPool.offerLast(session);
|
|
733
|
+
this.sessionCache.set(url, connectionPool);
|
|
734
|
+
return session;
|
|
735
|
+
}
|
|
736
|
+
deleteSession(authority, session) {
|
|
737
|
+
const existingConnectionPool = this.sessionCache.get(authority);
|
|
738
|
+
if (!existingConnectionPool) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
if (!existingConnectionPool.contains(session)) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
existingConnectionPool.remove(session);
|
|
745
|
+
this.sessionCache.set(authority, existingConnectionPool);
|
|
746
|
+
}
|
|
747
|
+
release(requestContext, session) {
|
|
748
|
+
const cacheKey = this.getUrlString(requestContext);
|
|
749
|
+
this.sessionCache.get(cacheKey)?.offerLast(session);
|
|
750
|
+
}
|
|
751
|
+
destroy() {
|
|
752
|
+
for (const [key, connectionPool] of this.sessionCache) {
|
|
753
|
+
for (const session of connectionPool) {
|
|
754
|
+
if (!session.destroyed) {
|
|
755
|
+
session.destroy();
|
|
756
|
+
}
|
|
757
|
+
connectionPool.remove(session);
|
|
758
|
+
}
|
|
759
|
+
this.sessionCache.delete(key);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
setMaxConcurrentStreams(maxConcurrentStreams) {
|
|
763
|
+
if (maxConcurrentStreams && maxConcurrentStreams <= 0) {
|
|
764
|
+
throw new RangeError("maxConcurrentStreams must be greater than zero.");
|
|
765
|
+
}
|
|
766
|
+
this.config.maxConcurrency = maxConcurrentStreams;
|
|
767
|
+
}
|
|
768
|
+
setDisableConcurrentStreams(disableConcurrentStreams) {
|
|
769
|
+
this.config.disableConcurrency = disableConcurrentStreams;
|
|
770
|
+
}
|
|
771
|
+
getUrlString(request) {
|
|
772
|
+
return request.destination.toString();
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
var NodeHttp2Handler;
|
|
778
|
+
var init_node_http2_handler = chunkG7VZBCD6_cjs.__esm({
|
|
779
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js"() {
|
|
780
|
+
init_dist_es();
|
|
781
|
+
init_dist_es3();
|
|
782
|
+
init_build_abort_error();
|
|
783
|
+
init_get_transformed_headers();
|
|
784
|
+
init_node_http2_connection_manager();
|
|
785
|
+
init_write_request_body();
|
|
786
|
+
NodeHttp2Handler = class _NodeHttp2Handler {
|
|
787
|
+
config;
|
|
788
|
+
configProvider;
|
|
789
|
+
metadata = { handlerProtocol: "h2" };
|
|
790
|
+
connectionManager = new NodeHttp2ConnectionManager({});
|
|
791
|
+
static create(instanceOrOptions) {
|
|
792
|
+
if (typeof instanceOrOptions?.handle === "function") {
|
|
793
|
+
return instanceOrOptions;
|
|
794
|
+
}
|
|
795
|
+
return new _NodeHttp2Handler(instanceOrOptions);
|
|
796
|
+
}
|
|
797
|
+
constructor(options) {
|
|
798
|
+
this.configProvider = new Promise((resolve, reject) => {
|
|
799
|
+
if (typeof options === "function") {
|
|
800
|
+
options().then((opts) => {
|
|
801
|
+
resolve(opts || {});
|
|
802
|
+
}).catch(reject);
|
|
803
|
+
} else {
|
|
804
|
+
resolve(options || {});
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
destroy() {
|
|
809
|
+
this.connectionManager.destroy();
|
|
810
|
+
}
|
|
811
|
+
async handle(request, { abortSignal, requestTimeout } = {}) {
|
|
812
|
+
if (!this.config) {
|
|
813
|
+
this.config = await this.configProvider;
|
|
814
|
+
this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams || false);
|
|
815
|
+
if (this.config.maxConcurrentStreams) {
|
|
816
|
+
this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
const { requestTimeout: configRequestTimeout, disableConcurrentStreams } = this.config;
|
|
820
|
+
const effectiveRequestTimeout = requestTimeout ?? configRequestTimeout;
|
|
821
|
+
return new Promise((_resolve, _reject) => {
|
|
822
|
+
let fulfilled = false;
|
|
823
|
+
let writeRequestBodyPromise = void 0;
|
|
824
|
+
const resolve = async (arg) => {
|
|
825
|
+
await writeRequestBodyPromise;
|
|
826
|
+
_resolve(arg);
|
|
827
|
+
};
|
|
828
|
+
const reject = async (arg) => {
|
|
829
|
+
await writeRequestBodyPromise;
|
|
830
|
+
_reject(arg);
|
|
831
|
+
};
|
|
832
|
+
if (abortSignal?.aborted) {
|
|
833
|
+
fulfilled = true;
|
|
834
|
+
const abortError = buildAbortError(abortSignal);
|
|
835
|
+
reject(abortError);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
const { hostname, method, port, protocol, query } = request;
|
|
839
|
+
let auth = "";
|
|
840
|
+
if (request.username != null || request.password != null) {
|
|
841
|
+
const username = request.username ?? "";
|
|
842
|
+
const password = request.password ?? "";
|
|
843
|
+
auth = `${username}:${password}@`;
|
|
844
|
+
}
|
|
845
|
+
const authority = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`;
|
|
846
|
+
const requestContext = { destination: new URL(authority) };
|
|
847
|
+
const session = this.connectionManager.lease(requestContext, {
|
|
848
|
+
requestTimeout: this.config?.sessionTimeout,
|
|
849
|
+
disableConcurrentStreams: disableConcurrentStreams || false
|
|
850
|
+
});
|
|
851
|
+
const rejectWithDestroy = (err) => {
|
|
852
|
+
if (disableConcurrentStreams) {
|
|
853
|
+
this.destroySession(session);
|
|
854
|
+
}
|
|
855
|
+
fulfilled = true;
|
|
856
|
+
reject(err);
|
|
857
|
+
};
|
|
858
|
+
const queryString = buildQueryString(query || {});
|
|
859
|
+
let path2 = request.path;
|
|
860
|
+
if (queryString) {
|
|
861
|
+
path2 += `?${queryString}`;
|
|
862
|
+
}
|
|
863
|
+
if (request.fragment) {
|
|
864
|
+
path2 += `#${request.fragment}`;
|
|
865
|
+
}
|
|
866
|
+
const req = session.request({
|
|
867
|
+
...request.headers,
|
|
868
|
+
[http2.constants.HTTP2_HEADER_PATH]: path2,
|
|
869
|
+
[http2.constants.HTTP2_HEADER_METHOD]: method
|
|
870
|
+
});
|
|
871
|
+
session.ref();
|
|
872
|
+
req.on("response", (headers) => {
|
|
873
|
+
const httpResponse = new HttpResponse({
|
|
874
|
+
statusCode: headers[":status"] || -1,
|
|
875
|
+
headers: getTransformedHeaders(headers),
|
|
876
|
+
body: req
|
|
877
|
+
});
|
|
878
|
+
fulfilled = true;
|
|
879
|
+
resolve({ response: httpResponse });
|
|
880
|
+
if (disableConcurrentStreams) {
|
|
881
|
+
session.close();
|
|
882
|
+
this.connectionManager.deleteSession(authority, session);
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
if (effectiveRequestTimeout) {
|
|
886
|
+
req.setTimeout(effectiveRequestTimeout, () => {
|
|
887
|
+
req.close();
|
|
888
|
+
const timeoutError = new Error(`Stream timed out because of no activity for ${effectiveRequestTimeout} ms`);
|
|
889
|
+
timeoutError.name = "TimeoutError";
|
|
890
|
+
rejectWithDestroy(timeoutError);
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
if (abortSignal) {
|
|
894
|
+
const onAbort = () => {
|
|
895
|
+
req.close();
|
|
896
|
+
const abortError = buildAbortError(abortSignal);
|
|
897
|
+
rejectWithDestroy(abortError);
|
|
898
|
+
};
|
|
899
|
+
if (typeof abortSignal.addEventListener === "function") {
|
|
900
|
+
const signal = abortSignal;
|
|
901
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
902
|
+
req.once("close", () => signal.removeEventListener("abort", onAbort));
|
|
903
|
+
} else {
|
|
904
|
+
abortSignal.onabort = onAbort;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
req.on("frameError", (type, code, id) => {
|
|
908
|
+
rejectWithDestroy(new Error(`Frame type id ${type} in stream id ${id} has failed with code ${code}.`));
|
|
909
|
+
});
|
|
910
|
+
req.on("error", rejectWithDestroy);
|
|
911
|
+
req.on("aborted", () => {
|
|
912
|
+
rejectWithDestroy(new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${req.rstCode}.`));
|
|
913
|
+
});
|
|
914
|
+
req.on("close", () => {
|
|
915
|
+
session.unref();
|
|
916
|
+
if (disableConcurrentStreams) {
|
|
917
|
+
session.destroy();
|
|
918
|
+
}
|
|
919
|
+
if (!fulfilled) {
|
|
920
|
+
rejectWithDestroy(new Error("Unexpected error: http2 request did not get a response"));
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout);
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
updateHttpClientConfig(key, value) {
|
|
927
|
+
this.config = void 0;
|
|
928
|
+
this.configProvider = this.configProvider.then((config) => {
|
|
929
|
+
return {
|
|
930
|
+
...config,
|
|
931
|
+
[key]: value
|
|
932
|
+
};
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
httpHandlerConfigs() {
|
|
936
|
+
return this.config ?? {};
|
|
937
|
+
}
|
|
938
|
+
destroySession(session) {
|
|
939
|
+
if (!session.destroyed) {
|
|
940
|
+
session.destroy();
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
var Collector;
|
|
947
|
+
var init_collector = chunkG7VZBCD6_cjs.__esm({
|
|
948
|
+
"node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js"() {
|
|
949
|
+
Collector = class extends stream.Writable {
|
|
950
|
+
bufferedBytes = [];
|
|
951
|
+
_write(chunk, encoding, callback) {
|
|
952
|
+
this.bufferedBytes.push(chunk);
|
|
953
|
+
callback();
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
// node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js
|
|
960
|
+
async function collectReadableStream(stream) {
|
|
961
|
+
const chunks = [];
|
|
962
|
+
const reader = stream.getReader();
|
|
963
|
+
let isDone = false;
|
|
964
|
+
let length = 0;
|
|
965
|
+
while (!isDone) {
|
|
966
|
+
const { done, value } = await reader.read();
|
|
967
|
+
if (value) {
|
|
968
|
+
chunks.push(value);
|
|
969
|
+
length += value.length;
|
|
970
|
+
}
|
|
971
|
+
isDone = done;
|
|
972
|
+
}
|
|
973
|
+
const collected = new Uint8Array(length);
|
|
974
|
+
let offset = 0;
|
|
975
|
+
for (const chunk of chunks) {
|
|
976
|
+
collected.set(chunk, offset);
|
|
977
|
+
offset += chunk.length;
|
|
978
|
+
}
|
|
979
|
+
return collected;
|
|
980
|
+
}
|
|
981
|
+
var streamCollector, isReadableStreamInstance;
|
|
982
|
+
var init_stream_collector = chunkG7VZBCD6_cjs.__esm({
|
|
983
|
+
"node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js"() {
|
|
984
|
+
init_collector();
|
|
985
|
+
streamCollector = (stream) => {
|
|
986
|
+
if (isReadableStreamInstance(stream)) {
|
|
987
|
+
return collectReadableStream(stream);
|
|
988
|
+
}
|
|
989
|
+
return new Promise((resolve, reject) => {
|
|
990
|
+
const collector = new Collector();
|
|
991
|
+
stream.pipe(collector);
|
|
992
|
+
stream.on("error", (err) => {
|
|
993
|
+
collector.end();
|
|
994
|
+
reject(err);
|
|
995
|
+
});
|
|
996
|
+
collector.on("error", reject);
|
|
997
|
+
collector.on("finish", function() {
|
|
998
|
+
const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
|
|
999
|
+
resolve(bytes);
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
};
|
|
1003
|
+
isReadableStreamInstance = (stream) => typeof ReadableStream === "function" && stream instanceof ReadableStream;
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// node_modules/@smithy/node-http-handler/dist-es/index.js
|
|
1008
|
+
var dist_es_exports = {};
|
|
1009
|
+
chunkG7VZBCD6_cjs.__export(dist_es_exports, {
|
|
1010
|
+
DEFAULT_REQUEST_TIMEOUT: () => DEFAULT_REQUEST_TIMEOUT,
|
|
1011
|
+
NodeHttp2Handler: () => NodeHttp2Handler,
|
|
1012
|
+
NodeHttpHandler: () => NodeHttpHandler,
|
|
1013
|
+
streamCollector: () => streamCollector
|
|
1014
|
+
});
|
|
1015
|
+
var init_dist_es4 = chunkG7VZBCD6_cjs.__esm({
|
|
1016
|
+
"node_modules/@smithy/node-http-handler/dist-es/index.js"() {
|
|
1017
|
+
init_node_http_handler();
|
|
1018
|
+
init_node_http2_handler();
|
|
1019
|
+
init_stream_collector();
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
27
1022
|
|
|
28
1023
|
// src/registry/validator.ts
|
|
29
1024
|
var ConfigValidationError = class extends Error {
|
|
@@ -377,10 +1372,7 @@ function checkboxToZod(field) {
|
|
|
377
1372
|
return schema;
|
|
378
1373
|
}
|
|
379
1374
|
function dateToZod(field) {
|
|
380
|
-
let schema = zod.z.string().refine(
|
|
381
|
-
(val) => !isNaN(Date.parse(val)),
|
|
382
|
-
"Invalid date format"
|
|
383
|
-
);
|
|
1375
|
+
let schema = zod.z.string().refine((val) => !isNaN(Date.parse(val)), "Invalid date format");
|
|
384
1376
|
if (field.minDate) {
|
|
385
1377
|
schema = schema.refine(
|
|
386
1378
|
(val) => new Date(val) >= new Date(field.minDate),
|
|
@@ -438,19 +1430,28 @@ function radioToZod(field) {
|
|
|
438
1430
|
}
|
|
439
1431
|
function colorToZod(field) {
|
|
440
1432
|
let schema = zod.z.string();
|
|
441
|
-
if (field.format === "hex")
|
|
442
|
-
|
|
443
|
-
if (field.format === "
|
|
1433
|
+
if (field.format === "hex")
|
|
1434
|
+
schema = schema.regex(/^#[0-9A-Fa-f]{6}$/);
|
|
1435
|
+
if (field.format === "rgb")
|
|
1436
|
+
schema = schema.regex(
|
|
1437
|
+
/^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/
|
|
1438
|
+
);
|
|
1439
|
+
if (field.format === "hsl")
|
|
1440
|
+
schema = schema.regex(
|
|
1441
|
+
/^hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\)$/
|
|
1442
|
+
);
|
|
444
1443
|
if (!field.required) schema = schema.optional();
|
|
445
1444
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
446
1445
|
return schema;
|
|
447
1446
|
}
|
|
448
1447
|
function richTextToZod(field) {
|
|
449
|
-
let schema = zod.z.array(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
1448
|
+
let schema = zod.z.array(
|
|
1449
|
+
zod.z.object({
|
|
1450
|
+
type: zod.z.string(),
|
|
1451
|
+
data: zod.z.record(zod.z.any()),
|
|
1452
|
+
children: zod.z.array(zod.z.any()).optional()
|
|
1453
|
+
})
|
|
1454
|
+
);
|
|
454
1455
|
if (!field.required) schema = schema.optional();
|
|
455
1456
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
456
1457
|
return schema;
|
|
@@ -516,7 +1517,8 @@ function groupToZod(field) {
|
|
|
516
1517
|
return schema;
|
|
517
1518
|
}
|
|
518
1519
|
function blocksToZod(field) {
|
|
519
|
-
const
|
|
1520
|
+
const blocks = field.blocks || [];
|
|
1521
|
+
const blockSchemas = blocks.map((block) => {
|
|
520
1522
|
return zod.z.object({
|
|
521
1523
|
blockType: zod.z.literal(block.slug),
|
|
522
1524
|
...Object.fromEntries(
|
|
@@ -524,7 +1526,9 @@ function blocksToZod(field) {
|
|
|
524
1526
|
)
|
|
525
1527
|
});
|
|
526
1528
|
});
|
|
527
|
-
let schema = zod.z.array(
|
|
1529
|
+
let schema = zod.z.array(
|
|
1530
|
+
zod.z.discriminatedUnion("blockType", blockSchemas)
|
|
1531
|
+
);
|
|
528
1532
|
if (field.minRows) schema = schema.min(field.minRows);
|
|
529
1533
|
if (field.maxRows) schema = schema.max(field.maxRows);
|
|
530
1534
|
if (!field.required) schema = schema.optional();
|
|
@@ -984,6 +1988,7 @@ var Kyro = class {
|
|
|
984
1988
|
registry;
|
|
985
1989
|
db;
|
|
986
1990
|
pubsub;
|
|
1991
|
+
settings;
|
|
987
1992
|
wsServer;
|
|
988
1993
|
config;
|
|
989
1994
|
constructor(config) {
|
|
@@ -1005,7 +2010,10 @@ var Kyro = class {
|
|
|
1005
2010
|
}
|
|
1006
2011
|
async init() {
|
|
1007
2012
|
await this.registry.init();
|
|
1008
|
-
await this.db.init(
|
|
2013
|
+
await this.db.init(
|
|
2014
|
+
this.registry.getCollections(),
|
|
2015
|
+
this.registry.getGlobals()
|
|
2016
|
+
);
|
|
1009
2017
|
this.pubsub.autoRegisterHooks();
|
|
1010
2018
|
console.log("\u2705 Kyro CMS initialized");
|
|
1011
2019
|
console.log(` Collections: ${this.registry.getCollections().length}`);
|
|
@@ -1014,34 +2022,58 @@ var Kyro = class {
|
|
|
1014
2022
|
// ============================================================================
|
|
1015
2023
|
// API Methods
|
|
1016
2024
|
// ============================================================================
|
|
2025
|
+
// Load settings from globals if not already loaded
|
|
2026
|
+
async loadSettings() {
|
|
2027
|
+
if (this.settings) return this.settings;
|
|
2028
|
+
try {
|
|
2029
|
+
const accessSettings = await this.db.findOne({
|
|
2030
|
+
collection: "_globals",
|
|
2031
|
+
where: { slug: "access-settings" }
|
|
2032
|
+
});
|
|
2033
|
+
if (accessSettings) {
|
|
2034
|
+
this.settings = accessSettings.data;
|
|
2035
|
+
}
|
|
2036
|
+
} catch (e) {
|
|
2037
|
+
console.log("\u26A0\uFE0F No access-settings found, using defaults");
|
|
2038
|
+
}
|
|
2039
|
+
return this.settings || {};
|
|
2040
|
+
}
|
|
1017
2041
|
getREST(options) {
|
|
1018
|
-
return
|
|
2042
|
+
return chunkE63IF3MD_cjs.createHonoApp({
|
|
1019
2043
|
registry: this.registry,
|
|
1020
2044
|
db: this.db,
|
|
1021
2045
|
...options,
|
|
1022
|
-
cors: this.config.cors
|
|
2046
|
+
cors: this.config.cors,
|
|
2047
|
+
settings: this.settings
|
|
1023
2048
|
});
|
|
1024
2049
|
}
|
|
1025
2050
|
getGraphQL(options) {
|
|
1026
|
-
return
|
|
2051
|
+
return chunkFTSSDDZQ_cjs.buildGraphQLSchema({
|
|
1027
2052
|
registry: this.registry,
|
|
1028
2053
|
db: this.db,
|
|
1029
|
-
...options
|
|
2054
|
+
...options,
|
|
2055
|
+
settings: this.settings
|
|
1030
2056
|
});
|
|
1031
2057
|
}
|
|
1032
2058
|
getTRPC(options) {
|
|
1033
|
-
return
|
|
2059
|
+
return chunk42JPONZU_cjs.createKyroServer({
|
|
1034
2060
|
registry: this.registry,
|
|
1035
2061
|
db: this.db,
|
|
1036
2062
|
req: options?.req || { headers: {} },
|
|
1037
|
-
...options
|
|
2063
|
+
...options,
|
|
2064
|
+
settings: this.settings
|
|
1038
2065
|
});
|
|
1039
2066
|
}
|
|
1040
2067
|
async startWebSocket(options) {
|
|
2068
|
+
const apiAccess = this.settings?.access?.apiAccess;
|
|
2069
|
+
if (apiAccess?.websocketEnabled === false) {
|
|
2070
|
+
console.log("\u26A0\uFE0F WebSocket is disabled in settings");
|
|
2071
|
+
return null;
|
|
2072
|
+
}
|
|
1041
2073
|
this.wsServer = chunkDVD5P72E_cjs.createWSServer({
|
|
1042
2074
|
pubsub: this.pubsub,
|
|
1043
2075
|
port: options?.port || 8080,
|
|
1044
|
-
requireAuth: options?.requireAuth,
|
|
2076
|
+
requireAuth: options?.requireAuth ?? apiAccess?.requireAuth,
|
|
1045
2077
|
verifyToken: options?.verifyToken
|
|
1046
2078
|
});
|
|
1047
2079
|
console.log(`\u{1F50C} WebSocket server started on port ${options?.port || 8080}`);
|
|
@@ -1118,11 +2150,7 @@ var RELATIONAL_FIELD_TYPES = [
|
|
|
1118
2150
|
"group",
|
|
1119
2151
|
"blocks"
|
|
1120
2152
|
];
|
|
1121
|
-
var LAYOUT_FIELD_TYPES = [
|
|
1122
|
-
"row",
|
|
1123
|
-
"collapsible",
|
|
1124
|
-
"tabs"
|
|
1125
|
-
];
|
|
2153
|
+
var LAYOUT_FIELD_TYPES = ["row", "collapsible", "tabs"];
|
|
1126
2154
|
var ALL_FIELD_TYPES = [
|
|
1127
2155
|
...PRIMITIVE_FIELD_TYPES,
|
|
1128
2156
|
...COMPLEX_FIELD_TYPES,
|
|
@@ -1130,6 +2158,414 @@ var ALL_FIELD_TYPES = [
|
|
|
1130
2158
|
...LAYOUT_FIELD_TYPES
|
|
1131
2159
|
];
|
|
1132
2160
|
|
|
2161
|
+
// src/fields/richtext.ts
|
|
2162
|
+
var MIN_COLUMNS = 1;
|
|
2163
|
+
var MAX_COLUMNS = 6;
|
|
2164
|
+
var richTextStyles = `
|
|
2165
|
+
.kyro-richtext {
|
|
2166
|
+
color: inherit;
|
|
2167
|
+
line-height: 1.7;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
.kyro-richtext > *:first-child {
|
|
2171
|
+
margin-top: 0;
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
.kyro-richtext > *:last-child {
|
|
2175
|
+
margin-bottom: 0;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
.kyro-richtext p,
|
|
2179
|
+
.kyro-richtext ul,
|
|
2180
|
+
.kyro-richtext ol,
|
|
2181
|
+
.kyro-richtext blockquote,
|
|
2182
|
+
.kyro-richtext pre,
|
|
2183
|
+
.kyro-richtext kyro-callout,
|
|
2184
|
+
.kyro-richtext kyro-hero,
|
|
2185
|
+
.kyro-richtext kyro-heading,
|
|
2186
|
+
.kyro-richtext kyro-stack,
|
|
2187
|
+
.kyro-richtext kyro-columns {
|
|
2188
|
+
margin: 0 0 1rem;
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
.kyro-richtext h1,
|
|
2192
|
+
.kyro-richtext h2,
|
|
2193
|
+
.kyro-richtext h3,
|
|
2194
|
+
.kyro-richtext h4,
|
|
2195
|
+
.kyro-richtext h5,
|
|
2196
|
+
.kyro-richtext h6 {
|
|
2197
|
+
margin: 0 0 0.75rem;
|
|
2198
|
+
line-height: 1.2;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
.kyro-richtext ul,
|
|
2202
|
+
.kyro-richtext ol {
|
|
2203
|
+
padding-left: 1.5rem;
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
.kyro-richtext blockquote {
|
|
2207
|
+
border-left: 4px solid rgba(148, 163, 184, 0.5);
|
|
2208
|
+
margin-left: 0;
|
|
2209
|
+
padding-left: 1rem;
|
|
2210
|
+
font-style: italic;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
.kyro-richtext pre {
|
|
2214
|
+
overflow-x: auto;
|
|
2215
|
+
border-radius: 0.75rem;
|
|
2216
|
+
background: rgba(15, 23, 42, 0.92);
|
|
2217
|
+
color: #f8fafc;
|
|
2218
|
+
padding: 1rem;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
.kyro-richtext code {
|
|
2222
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
.kyro-richtext img {
|
|
2226
|
+
display: block;
|
|
2227
|
+
max-width: 100%;
|
|
2228
|
+
height: auto;
|
|
2229
|
+
border-radius: 0.75rem;
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
.kyro-richtext kyro-columns {
|
|
2233
|
+
display: grid;
|
|
2234
|
+
grid-template-columns: repeat(var(--kyro-columns-count, 1), minmax(0, 1fr));
|
|
2235
|
+
gap: 1rem;
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
.kyro-richtext kyro-column {
|
|
2239
|
+
display: block;
|
|
2240
|
+
min-width: 0;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
.kyro-richtext kyro-column > *:last-child {
|
|
2244
|
+
margin-bottom: 0;
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
.kyro-richtext kyro-hero,
|
|
2248
|
+
.kyro-richtext kyro-callout,
|
|
2249
|
+
.kyro-richtext kyro-stack,
|
|
2250
|
+
.kyro-richtext kyro-heading {
|
|
2251
|
+
display: block;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
.kyro-richtext kyro-hero {
|
|
2255
|
+
border: 1px solid rgba(148, 163, 184, 0.25);
|
|
2256
|
+
border-radius: 1rem;
|
|
2257
|
+
padding: 1.5rem;
|
|
2258
|
+
text-align: center;
|
|
2259
|
+
background: linear-gradient(to bottom, rgba(148, 163, 184, 0.12), transparent);
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
.kyro-richtext kyro-heading {
|
|
2263
|
+
font-size: 1.125rem;
|
|
2264
|
+
font-weight: 700;
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
.kyro-richtext kyro-callout {
|
|
2268
|
+
border: 1px solid rgba(59, 130, 246, 0.25);
|
|
2269
|
+
border-radius: 0.875rem;
|
|
2270
|
+
padding: 0.875rem 1rem;
|
|
2271
|
+
background: rgba(59, 130, 246, 0.06);
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
@media (max-width: 720px) {
|
|
2275
|
+
.kyro-richtext kyro-columns {
|
|
2276
|
+
grid-template-columns: 1fr;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
`.trim();
|
|
2280
|
+
function createEmptyParagraphNode() {
|
|
2281
|
+
return {
|
|
2282
|
+
type: "paragraph",
|
|
2283
|
+
content: []
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
function createColumnNode(content = [createEmptyParagraphNode()]) {
|
|
2287
|
+
return {
|
|
2288
|
+
type: "kyroColumn",
|
|
2289
|
+
content: content.length > 0 ? content : [createEmptyParagraphNode()]
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2292
|
+
function createColumnsNode(columns = 2) {
|
|
2293
|
+
const count = clampColumns(columns);
|
|
2294
|
+
return {
|
|
2295
|
+
type: "kyroColumns",
|
|
2296
|
+
attrs: { columns: count },
|
|
2297
|
+
content: Array.from({ length: count }, () => createColumnNode())
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
function normalizeRichTextDocument(value) {
|
|
2301
|
+
const documentNode = toRichTextDocument(value);
|
|
2302
|
+
return {
|
|
2303
|
+
type: "doc",
|
|
2304
|
+
content: normalizeNodes(documentNode.content)
|
|
2305
|
+
};
|
|
2306
|
+
}
|
|
2307
|
+
function normalizeRichTextValue(value) {
|
|
2308
|
+
if (Array.isArray(value)) {
|
|
2309
|
+
return normalizeRichTextDocument(value).content;
|
|
2310
|
+
}
|
|
2311
|
+
if (isObject(value) && value.type === "doc") {
|
|
2312
|
+
return normalizeRichTextDocument(value);
|
|
2313
|
+
}
|
|
2314
|
+
return value;
|
|
2315
|
+
}
|
|
2316
|
+
function renderRichText(value) {
|
|
2317
|
+
if (typeof value === "string") {
|
|
2318
|
+
return `<div class="kyro-richtext">${value}</div>`;
|
|
2319
|
+
}
|
|
2320
|
+
const documentNode = normalizeRichTextDocument(value);
|
|
2321
|
+
return `<div class="kyro-richtext">${renderNodes(documentNode.content)}</div>`;
|
|
2322
|
+
}
|
|
2323
|
+
function toRichTextDocument(value) {
|
|
2324
|
+
if (Array.isArray(value)) {
|
|
2325
|
+
return {
|
|
2326
|
+
type: "doc",
|
|
2327
|
+
content: normalizeNodes(value)
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2330
|
+
if (isObject(value) && value.type === "doc") {
|
|
2331
|
+
const doc = value;
|
|
2332
|
+
return {
|
|
2333
|
+
type: "doc",
|
|
2334
|
+
content: normalizeNodes(doc.content ?? [])
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
return {
|
|
2338
|
+
type: "doc",
|
|
2339
|
+
content: []
|
|
2340
|
+
};
|
|
2341
|
+
}
|
|
2342
|
+
function normalizeNodes(nodes) {
|
|
2343
|
+
return nodes.filter((node) => isObject(node) && typeof node.type === "string").map((node) => normalizeNode(node));
|
|
2344
|
+
}
|
|
2345
|
+
function normalizeNode(node) {
|
|
2346
|
+
if (node.type === "kyroColumns") {
|
|
2347
|
+
return normalizeColumnsNode(node);
|
|
2348
|
+
}
|
|
2349
|
+
if (node.type === "kyroColumn") {
|
|
2350
|
+
const normalizedContent = normalizeNodes(
|
|
2351
|
+
Array.isArray(node.content) ? node.content : []
|
|
2352
|
+
).filter((child) => child.type !== "kyroColumns");
|
|
2353
|
+
return {
|
|
2354
|
+
...node,
|
|
2355
|
+
content: normalizedContent.length > 0 ? normalizedContent : [createEmptyParagraphNode()]
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
if (Array.isArray(node.content)) {
|
|
2359
|
+
return {
|
|
2360
|
+
...node,
|
|
2361
|
+
content: normalizeNodes(node.content)
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
return {
|
|
2365
|
+
...node
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
function normalizeColumnsNode(node) {
|
|
2369
|
+
const rawChildren = Array.isArray(node.content) ? node.content : [];
|
|
2370
|
+
const hasStructuredColumns = rawChildren.every((child) => child?.type === "kyroColumn");
|
|
2371
|
+
const targetColumns = clampColumns(
|
|
2372
|
+
typeof node.attrs?.columns === "number" ? node.attrs.columns : hasStructuredColumns && rawChildren.length > 0 ? rawChildren.length : 2
|
|
2373
|
+
);
|
|
2374
|
+
const content = hasStructuredColumns ? normalizeStructuredColumns(rawChildren, targetColumns) : normalizeLegacyColumns(rawChildren, targetColumns);
|
|
2375
|
+
return {
|
|
2376
|
+
...node,
|
|
2377
|
+
attrs: {
|
|
2378
|
+
...node.attrs ?? {},
|
|
2379
|
+
columns: content.length
|
|
2380
|
+
},
|
|
2381
|
+
content
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2384
|
+
function normalizeStructuredColumns(columns, targetColumns) {
|
|
2385
|
+
const normalized = columns.slice(0, MAX_COLUMNS).map((column) => normalizeNode(column)).filter((column) => column.type === "kyroColumn");
|
|
2386
|
+
if (normalized.length === 0) {
|
|
2387
|
+
return Array.from({ length: targetColumns }, () => createColumnNode());
|
|
2388
|
+
}
|
|
2389
|
+
if (normalized.length > targetColumns) {
|
|
2390
|
+
const kept = normalized.slice(0, targetColumns);
|
|
2391
|
+
const extras = normalized.slice(targetColumns);
|
|
2392
|
+
const mergedTail = extras.flatMap(
|
|
2393
|
+
(column) => normalizeColumnChildren(column.content)
|
|
2394
|
+
);
|
|
2395
|
+
const lastIndex = kept.length - 1;
|
|
2396
|
+
kept[lastIndex] = createColumnNode([
|
|
2397
|
+
...normalizeColumnChildren(kept[lastIndex].content),
|
|
2398
|
+
...mergedTail
|
|
2399
|
+
]);
|
|
2400
|
+
return kept;
|
|
2401
|
+
}
|
|
2402
|
+
if (normalized.length < targetColumns) {
|
|
2403
|
+
return [
|
|
2404
|
+
...normalized,
|
|
2405
|
+
...Array.from(
|
|
2406
|
+
{ length: targetColumns - normalized.length },
|
|
2407
|
+
() => createColumnNode()
|
|
2408
|
+
)
|
|
2409
|
+
];
|
|
2410
|
+
}
|
|
2411
|
+
return normalized;
|
|
2412
|
+
}
|
|
2413
|
+
function normalizeLegacyColumns(blocks, targetColumns) {
|
|
2414
|
+
const normalizedBlocks = normalizeNodes(blocks);
|
|
2415
|
+
return Array.from({ length: targetColumns }, (_, index) => {
|
|
2416
|
+
if (index < targetColumns - 1) {
|
|
2417
|
+
const block = normalizedBlocks[index];
|
|
2418
|
+
return block ? createColumnNode([block]) : createColumnNode();
|
|
2419
|
+
}
|
|
2420
|
+
const tail = normalizedBlocks.slice(index);
|
|
2421
|
+
return createColumnNode(tail.length > 0 ? tail : [createEmptyParagraphNode()]);
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
function normalizeColumnChildren(content) {
|
|
2425
|
+
const children = Array.isArray(content) ? normalizeNodes(content) : [];
|
|
2426
|
+
const filtered = children.filter((child) => child.type !== "kyroColumns");
|
|
2427
|
+
return filtered.length > 0 ? filtered : [createEmptyParagraphNode()];
|
|
2428
|
+
}
|
|
2429
|
+
function renderNodes(nodes) {
|
|
2430
|
+
return nodes.map((node) => renderNode(node)).join("");
|
|
2431
|
+
}
|
|
2432
|
+
function renderNode(node) {
|
|
2433
|
+
switch (node.type) {
|
|
2434
|
+
case "paragraph":
|
|
2435
|
+
return `<p>${renderInlineContent(node.content)}</p>`;
|
|
2436
|
+
case "text":
|
|
2437
|
+
return renderTextNode(node);
|
|
2438
|
+
case "heading": {
|
|
2439
|
+
const level = clampHeadingLevel(node.attrs?.level);
|
|
2440
|
+
return `<h${level}>${renderInlineContent(node.content)}</h${level}>`;
|
|
2441
|
+
}
|
|
2442
|
+
case "bulletList":
|
|
2443
|
+
return `<ul>${renderNodes(node.content ?? [])}</ul>`;
|
|
2444
|
+
case "orderedList":
|
|
2445
|
+
return `<ol>${renderNodes(node.content ?? [])}</ol>`;
|
|
2446
|
+
case "listItem":
|
|
2447
|
+
return `<li>${renderNodes(node.content ?? [])}</li>`;
|
|
2448
|
+
case "blockquote":
|
|
2449
|
+
return `<blockquote>${renderNodes(node.content ?? [])}</blockquote>`;
|
|
2450
|
+
case "codeBlock":
|
|
2451
|
+
return `<pre><code>${escapeHtml(extractText(node.content ?? []))}</code></pre>`;
|
|
2452
|
+
case "horizontalRule":
|
|
2453
|
+
return "<hr />";
|
|
2454
|
+
case "hardBreak":
|
|
2455
|
+
return "<br />";
|
|
2456
|
+
case "image":
|
|
2457
|
+
return renderImageNode(node);
|
|
2458
|
+
case "kyroColumns": {
|
|
2459
|
+
const columns = clampColumns(
|
|
2460
|
+
Array.isArray(node.content) ? node.content.length : 1
|
|
2461
|
+
);
|
|
2462
|
+
return `<kyro-columns data-columns="${columns}" style="--kyro-columns-count:${columns}">${renderNodes(node.content ?? [])}</kyro-columns>`;
|
|
2463
|
+
}
|
|
2464
|
+
case "kyroColumn":
|
|
2465
|
+
return `<kyro-column>${renderNodes(node.content ?? [])}</kyro-column>`;
|
|
2466
|
+
case "kyroHero":
|
|
2467
|
+
return `<kyro-hero>${renderInlineContent(node.content)}</kyro-hero>`;
|
|
2468
|
+
case "kyroHeading":
|
|
2469
|
+
return `<kyro-heading>${renderInlineContent(node.content)}</kyro-heading>`;
|
|
2470
|
+
case "kyroDivider":
|
|
2471
|
+
return '<hr class="kyro-divider" />';
|
|
2472
|
+
case "kyroCallout":
|
|
2473
|
+
return `<kyro-callout>${renderInlineContent(node.content)}</kyro-callout>`;
|
|
2474
|
+
case "kyroStack":
|
|
2475
|
+
return `<kyro-stack>${renderNodes(node.content ?? [])}</kyro-stack>`;
|
|
2476
|
+
case "kyroImage":
|
|
2477
|
+
return renderCustomMediaNode("kyro-image", node);
|
|
2478
|
+
case "kyroVideo":
|
|
2479
|
+
return renderCustomMediaNode("kyro-video", node);
|
|
2480
|
+
default:
|
|
2481
|
+
return renderNodes(node.content ?? []);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
function renderInlineContent(content) {
|
|
2485
|
+
const nodes = content ?? [];
|
|
2486
|
+
if (nodes.length === 0) {
|
|
2487
|
+
return "<br />";
|
|
2488
|
+
}
|
|
2489
|
+
return nodes.map((node) => renderNode(node)).join("");
|
|
2490
|
+
}
|
|
2491
|
+
function renderTextNode(node) {
|
|
2492
|
+
const text = typeof node.text === "string" ? escapeHtml(node.text) : "";
|
|
2493
|
+
return (node.marks ?? []).reduce((acc, mark) => applyMark(acc, mark), text);
|
|
2494
|
+
}
|
|
2495
|
+
function renderImageNode(node) {
|
|
2496
|
+
const src = typeof node.attrs?.src === "string" ? node.attrs.src : "";
|
|
2497
|
+
if (!src) {
|
|
2498
|
+
return "";
|
|
2499
|
+
}
|
|
2500
|
+
const alt = typeof node.attrs?.alt === "string" ? node.attrs.alt : "";
|
|
2501
|
+
return `<img src="${escapeAttribute(src)}" alt="${escapeAttribute(alt)}" />`;
|
|
2502
|
+
}
|
|
2503
|
+
function renderCustomMediaNode(tagName, node) {
|
|
2504
|
+
const attrs = renderAttributes(node.attrs);
|
|
2505
|
+
return `<${tagName}${attrs}></${tagName}>`;
|
|
2506
|
+
}
|
|
2507
|
+
function renderAttributes(attrs, keysToSkip = []) {
|
|
2508
|
+
if (!attrs) {
|
|
2509
|
+
return "";
|
|
2510
|
+
}
|
|
2511
|
+
const entries = Object.entries(attrs).filter(([key, value]) => !keysToSkip.includes(key) && value !== void 0 && value !== null).map(([key, value]) => `${key}="${escapeAttribute(String(value))}"`);
|
|
2512
|
+
return entries.length > 0 ? ` ${entries.join(" ")}` : "";
|
|
2513
|
+
}
|
|
2514
|
+
function applyMark(content, mark) {
|
|
2515
|
+
switch (mark.type) {
|
|
2516
|
+
case "bold":
|
|
2517
|
+
return `<strong>${content}</strong>`;
|
|
2518
|
+
case "italic":
|
|
2519
|
+
return `<em>${content}</em>`;
|
|
2520
|
+
case "underline":
|
|
2521
|
+
return `<u>${content}</u>`;
|
|
2522
|
+
case "strike":
|
|
2523
|
+
return `<s>${content}</s>`;
|
|
2524
|
+
case "code":
|
|
2525
|
+
return `<code>${content}</code>`;
|
|
2526
|
+
case "link": {
|
|
2527
|
+
const href = typeof mark.attrs?.href === "string" ? escapeAttribute(mark.attrs.href) : "#";
|
|
2528
|
+
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${content}</a>`;
|
|
2529
|
+
}
|
|
2530
|
+
default:
|
|
2531
|
+
return content;
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
function extractText(nodes) {
|
|
2535
|
+
return nodes.map((node) => {
|
|
2536
|
+
if (node.type === "text") {
|
|
2537
|
+
return typeof node.text === "string" ? node.text : "";
|
|
2538
|
+
}
|
|
2539
|
+
if (node.type === "hardBreak") {
|
|
2540
|
+
return "\n";
|
|
2541
|
+
}
|
|
2542
|
+
return extractText(node.content ?? []);
|
|
2543
|
+
}).join("");
|
|
2544
|
+
}
|
|
2545
|
+
function clampColumns(value) {
|
|
2546
|
+
const numericValue = typeof value === "number" ? value : Number(value);
|
|
2547
|
+
if (!Number.isFinite(numericValue)) {
|
|
2548
|
+
return 2;
|
|
2549
|
+
}
|
|
2550
|
+
return Math.max(MIN_COLUMNS, Math.min(MAX_COLUMNS, Math.round(numericValue)));
|
|
2551
|
+
}
|
|
2552
|
+
function clampHeadingLevel(level) {
|
|
2553
|
+
const numericLevel = typeof level === "number" ? level : Number(level);
|
|
2554
|
+
if (!Number.isFinite(numericLevel)) {
|
|
2555
|
+
return 2;
|
|
2556
|
+
}
|
|
2557
|
+
return Math.max(1, Math.min(6, Math.round(numericLevel)));
|
|
2558
|
+
}
|
|
2559
|
+
function escapeHtml(value) {
|
|
2560
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
2561
|
+
}
|
|
2562
|
+
function escapeAttribute(value) {
|
|
2563
|
+
return escapeHtml(value).replaceAll('"', """);
|
|
2564
|
+
}
|
|
2565
|
+
function isObject(value) {
|
|
2566
|
+
return typeof value === "object" && value !== null;
|
|
2567
|
+
}
|
|
2568
|
+
|
|
1133
2569
|
// src/hooks/types.ts
|
|
1134
2570
|
async function runHooks(hooks, args) {
|
|
1135
2571
|
let result = args.data;
|
|
@@ -1649,9 +3085,19 @@ var SEOPLugin = class extends KyroPlugin {
|
|
|
1649
3085
|
slug: "seo-settings",
|
|
1650
3086
|
label: "SEO Settings",
|
|
1651
3087
|
fields: [
|
|
1652
|
-
{
|
|
1653
|
-
|
|
1654
|
-
|
|
3088
|
+
{
|
|
3089
|
+
name: "sitemap",
|
|
3090
|
+
type: "checkbox",
|
|
3091
|
+
label: "Enable Sitemap",
|
|
3092
|
+
defaultValue: true
|
|
3093
|
+
},
|
|
3094
|
+
{ name: "robotsTxt", type: "richtext", label: "robots.txt Content" },
|
|
3095
|
+
{
|
|
3096
|
+
name: "canonicalUrl",
|
|
3097
|
+
type: "text",
|
|
3098
|
+
variant: "url",
|
|
3099
|
+
label: "Canonical URL"
|
|
3100
|
+
},
|
|
1655
3101
|
{ name: "ogImage", type: "text", label: "Default OG Image URL" }
|
|
1656
3102
|
]
|
|
1657
3103
|
});
|
|
@@ -1683,7 +3129,7 @@ var CommentsPlugin = class extends KyroPlugin {
|
|
|
1683
3129
|
slug: "comments",
|
|
1684
3130
|
label: "Comments",
|
|
1685
3131
|
fields: [
|
|
1686
|
-
{ name: "content", type: "
|
|
3132
|
+
{ name: "content", type: "richtext", required: true },
|
|
1687
3133
|
{ name: "author", type: "text", required: true },
|
|
1688
3134
|
{ name: "email", type: "email" },
|
|
1689
3135
|
{ name: "approved", type: "checkbox", defaultValue: false },
|
|
@@ -1705,12 +3151,22 @@ var ReviewsPlugin = class extends KyroPlugin {
|
|
|
1705
3151
|
fields: [
|
|
1706
3152
|
{ name: "rating", type: "number", required: true, min: 1, max: 5 },
|
|
1707
3153
|
{ name: "title", type: "text" },
|
|
1708
|
-
{ name: "content", type: "
|
|
3154
|
+
{ name: "content", type: "richtext", required: true },
|
|
1709
3155
|
{ name: "author", type: "relationship", relationTo: "customers" },
|
|
1710
|
-
{
|
|
3156
|
+
{
|
|
3157
|
+
name: "product",
|
|
3158
|
+
type: "relationship",
|
|
3159
|
+
relationTo: "products",
|
|
3160
|
+
required: true
|
|
3161
|
+
},
|
|
1711
3162
|
{ name: "approved", type: "checkbox", defaultValue: false },
|
|
1712
3163
|
{ name: "verified", type: "checkbox", label: "Verified Purchase" },
|
|
1713
|
-
{
|
|
3164
|
+
{
|
|
3165
|
+
name: "helpful",
|
|
3166
|
+
type: "number",
|
|
3167
|
+
label: "Helpful Count",
|
|
3168
|
+
defaultValue: 0
|
|
3169
|
+
}
|
|
1714
3170
|
]
|
|
1715
3171
|
});
|
|
1716
3172
|
this.adminComponents["ReviewModeration"] = {};
|
|
@@ -1724,24 +3180,47 @@ var WishlistPlugin = class extends KyroPlugin {
|
|
|
1724
3180
|
slug: "wishlists",
|
|
1725
3181
|
label: "Wishlists",
|
|
1726
3182
|
fields: [
|
|
1727
|
-
{
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
3183
|
+
{
|
|
3184
|
+
name: "customer",
|
|
3185
|
+
type: "relationship",
|
|
3186
|
+
relationTo: "customers",
|
|
3187
|
+
required: true
|
|
3188
|
+
},
|
|
3189
|
+
{
|
|
3190
|
+
name: "name",
|
|
3191
|
+
type: "text",
|
|
3192
|
+
label: "Wishlist Name",
|
|
3193
|
+
defaultValue: "My Wishlist"
|
|
3194
|
+
},
|
|
3195
|
+
{
|
|
3196
|
+
name: "items",
|
|
3197
|
+
type: "blocks",
|
|
3198
|
+
label: "Items",
|
|
3199
|
+
blocks: [
|
|
3200
|
+
{
|
|
3201
|
+
slug: "wishlist-item",
|
|
3202
|
+
label: "Item",
|
|
3203
|
+
fields: [
|
|
3204
|
+
{
|
|
3205
|
+
name: "product",
|
|
3206
|
+
type: "relationship",
|
|
3207
|
+
relationTo: "products"
|
|
3208
|
+
},
|
|
3209
|
+
{ name: "quantity", type: "number", defaultValue: 1 },
|
|
3210
|
+
{ name: "addedAt", type: "date" },
|
|
3211
|
+
{
|
|
3212
|
+
name: "priority",
|
|
3213
|
+
type: "select",
|
|
3214
|
+
options: [
|
|
3215
|
+
{ label: "Low", value: "low" },
|
|
3216
|
+
{ label: "Medium", value: "medium" },
|
|
3217
|
+
{ label: "High", value: "high" }
|
|
3218
|
+
]
|
|
3219
|
+
}
|
|
3220
|
+
]
|
|
3221
|
+
}
|
|
3222
|
+
]
|
|
3223
|
+
}
|
|
1745
3224
|
]
|
|
1746
3225
|
});
|
|
1747
3226
|
}
|
|
@@ -2502,10 +3981,9 @@ var InMemoryAuthAdapter = class {
|
|
|
2502
3981
|
users = /* @__PURE__ */ new Map();
|
|
2503
3982
|
sessions = /* @__PURE__ */ new Map();
|
|
2504
3983
|
refreshTokens = /* @__PURE__ */ new Map();
|
|
2505
|
-
// refreshToken -> sessionId
|
|
2506
3984
|
emailToUserId = /* @__PURE__ */ new Map();
|
|
2507
3985
|
passwordHistory = /* @__PURE__ */ new Map();
|
|
2508
|
-
|
|
3986
|
+
auditLogs = [];
|
|
2509
3987
|
externalDb = false;
|
|
2510
3988
|
constructor() {
|
|
2511
3989
|
}
|
|
@@ -2521,10 +3999,11 @@ var InMemoryAuthAdapter = class {
|
|
|
2521
3999
|
async createUser(data) {
|
|
2522
4000
|
const userId = crypto.randomBytes(16).toString("hex");
|
|
2523
4001
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4002
|
+
const passwordHash = await this.hashPassword(data.password);
|
|
2524
4003
|
const user = {
|
|
2525
4004
|
id: userId,
|
|
2526
4005
|
email: data.email.toLowerCase(),
|
|
2527
|
-
passwordHash
|
|
4006
|
+
passwordHash,
|
|
2528
4007
|
role: data.role || "customer",
|
|
2529
4008
|
tenantId: data.tenantId,
|
|
2530
4009
|
createdAt: now,
|
|
@@ -2582,9 +4061,12 @@ var InMemoryAuthAdapter = class {
|
|
|
2582
4061
|
const bcrypt2 = (await import('bcryptjs')).default;
|
|
2583
4062
|
return bcrypt2.hash(password, 12);
|
|
2584
4063
|
}
|
|
2585
|
-
async verifyPassword(
|
|
4064
|
+
async verifyPassword(email, password) {
|
|
4065
|
+
const user = await this.findUserByEmail(email);
|
|
4066
|
+
if (!user || !user.passwordHash) return null;
|
|
2586
4067
|
const bcrypt2 = (await import('bcryptjs')).default;
|
|
2587
|
-
|
|
4068
|
+
const valid = await bcrypt2.compare(password, user.passwordHash);
|
|
4069
|
+
return valid ? user : null;
|
|
2588
4070
|
}
|
|
2589
4071
|
async createSession(userId, data = {}) {
|
|
2590
4072
|
const sessionId = crypto.randomBytes(32).toString("hex");
|
|
@@ -2655,145 +4137,31 @@ var InMemoryAuthAdapter = class {
|
|
|
2655
4137
|
async hasAnyUsers() {
|
|
2656
4138
|
return this.users.size > 0;
|
|
2657
4139
|
}
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
this.limits = { ...DEFAULT_RATE_LIMITS2, ...limits };
|
|
2668
|
-
this.userLimits = userLimits || {
|
|
2669
|
-
"user:api": { window: 6e4, max: 500 },
|
|
2670
|
-
"user:write": { window: 36e5, max: 100 }
|
|
2671
|
-
};
|
|
2672
|
-
}
|
|
2673
|
-
getKey(type, identifier) {
|
|
2674
|
-
return `${type}:${identifier}`;
|
|
2675
|
-
}
|
|
2676
|
-
getUserKey(type, userId, identifier) {
|
|
2677
|
-
return `user:${type}:${userId}:${identifier}`;
|
|
2678
|
-
}
|
|
2679
|
-
cleanupOldEntries(entries, window) {
|
|
2680
|
-
const now = Date.now();
|
|
2681
|
-
const windowStart = now - window;
|
|
2682
|
-
while (entries.length > 0 && entries[0].timestamp < windowStart) {
|
|
2683
|
-
entries.shift();
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
async check(type, identifier) {
|
|
2687
|
-
const config = this.limits[type] || this.limits["api:general"];
|
|
2688
|
-
const key = this.getKey(type, identifier);
|
|
2689
|
-
let entries = this.storage.get(key);
|
|
2690
|
-
if (!entries) {
|
|
2691
|
-
entries = [];
|
|
2692
|
-
this.storage.set(key, entries);
|
|
2693
|
-
}
|
|
2694
|
-
this.cleanupOldEntries(entries, config.window);
|
|
2695
|
-
const now = Date.now();
|
|
2696
|
-
const count = entries.reduce((sum, entry) => sum + entry.count, 0);
|
|
2697
|
-
entries.push({ timestamp: now, count: 1 });
|
|
2698
|
-
if (count >= config.max) {
|
|
2699
|
-
const oldestEntry = entries.reduce(
|
|
2700
|
-
(oldest, current) => oldest.timestamp < current.timestamp ? oldest : current,
|
|
2701
|
-
entries[0]
|
|
2702
|
-
);
|
|
2703
|
-
const resetAt = oldestEntry.timestamp + config.window;
|
|
2704
|
-
return {
|
|
2705
|
-
allowed: false,
|
|
2706
|
-
remaining: 0,
|
|
2707
|
-
resetAt,
|
|
2708
|
-
retryAfter: Math.ceil((resetAt - now) / 1e3)
|
|
2709
|
-
};
|
|
2710
|
-
}
|
|
2711
|
-
return {
|
|
2712
|
-
allowed: true,
|
|
2713
|
-
remaining: config.max - count - 1,
|
|
2714
|
-
resetAt: now + config.window
|
|
2715
|
-
};
|
|
2716
|
-
}
|
|
2717
|
-
async checkUser(type, userId, identifier) {
|
|
2718
|
-
const config = this.userLimits[type] || this.userLimits["user:api"];
|
|
2719
|
-
const userMap = this.userStorage.get(userId);
|
|
2720
|
-
let entries = [];
|
|
2721
|
-
if (userMap) {
|
|
2722
|
-
entries = userMap.get(this.getKey(type, identifier)) || [];
|
|
2723
|
-
} else {
|
|
2724
|
-
if (!this.userStorage.has(userId)) {
|
|
2725
|
-
this.userStorage.set(userId, /* @__PURE__ */ new Map());
|
|
4140
|
+
async findAuditLogs(filter) {
|
|
4141
|
+
const { limit = 50, offset = 0 } = filter;
|
|
4142
|
+
let logs = this.auditLogs.slice().reverse();
|
|
4143
|
+
if (filter.userId) logs = logs.filter((l) => l.userId === filter.userId);
|
|
4144
|
+
if (filter.action) {
|
|
4145
|
+
if (Array.isArray(filter.action)) {
|
|
4146
|
+
logs = logs.filter((l) => filter.action.includes(String(l.action)));
|
|
4147
|
+
} else {
|
|
4148
|
+
logs = logs.filter((l) => l.action === filter.action);
|
|
2726
4149
|
}
|
|
2727
|
-
this.userStorage.get(userId).set(this.getKey(type, identifier), entries);
|
|
2728
|
-
}
|
|
2729
|
-
this.cleanupOldEntries(entries, config.window);
|
|
2730
|
-
const now = Date.now();
|
|
2731
|
-
const count = entries.reduce((sum, entry) => sum + entry.count, 0);
|
|
2732
|
-
entries.push({ timestamp: now, count: 1 });
|
|
2733
|
-
if (count >= config.max) {
|
|
2734
|
-
const oldestEntry = entries.reduce(
|
|
2735
|
-
(oldest, current) => oldest.timestamp < current.timestamp ? oldest : current,
|
|
2736
|
-
entries[0]
|
|
2737
|
-
);
|
|
2738
|
-
const resetAt = oldestEntry.timestamp + config.window;
|
|
2739
|
-
return {
|
|
2740
|
-
allowed: false,
|
|
2741
|
-
remaining: 0,
|
|
2742
|
-
resetAt,
|
|
2743
|
-
retryAfter: Math.ceil((resetAt - now) / 1e3)
|
|
2744
|
-
};
|
|
2745
|
-
}
|
|
2746
|
-
return {
|
|
2747
|
-
allowed: true,
|
|
2748
|
-
remaining: config.max - count - 1,
|
|
2749
|
-
resetAt: now + config.window
|
|
2750
|
-
};
|
|
2751
|
-
}
|
|
2752
|
-
async reset(type, identifier) {
|
|
2753
|
-
const key = this.getKey(type, identifier);
|
|
2754
|
-
this.storage.delete(key);
|
|
2755
|
-
}
|
|
2756
|
-
async resetUser(type, userId, identifier) {
|
|
2757
|
-
const userMap = this.userStorage.get(userId);
|
|
2758
|
-
if (userMap) {
|
|
2759
|
-
const key = this.getKey(type, identifier);
|
|
2760
|
-
userMap.delete(key);
|
|
2761
|
-
}
|
|
2762
|
-
}
|
|
2763
|
-
async getStatus(type, identifier) {
|
|
2764
|
-
const config = this.limits[type] || this.limits["api:general"];
|
|
2765
|
-
const key = this.getKey(type, identifier);
|
|
2766
|
-
let entries = this.storage.get(key);
|
|
2767
|
-
if (!entries) {
|
|
2768
|
-
entries = [];
|
|
2769
|
-
this.storage.set(key, entries);
|
|
2770
4150
|
}
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
limit: config.max,
|
|
2777
|
-
remaining: Math.max(0, config.max - count),
|
|
2778
|
-
resetAt: now + config.window
|
|
2779
|
-
};
|
|
2780
|
-
}
|
|
2781
|
-
setLimit(type, config) {
|
|
2782
|
-
this.limits[type] = config;
|
|
4151
|
+
if (filter.resource)
|
|
4152
|
+
logs = logs.filter((l) => l.resource === filter.resource);
|
|
4153
|
+
if (filter.success !== void 0)
|
|
4154
|
+
logs = logs.filter((l) => l.success === filter.success);
|
|
4155
|
+
return { logs: logs.slice(offset, offset + limit), total: logs.length };
|
|
2783
4156
|
}
|
|
2784
|
-
|
|
2785
|
-
|
|
4157
|
+
async createAuditLog(data) {
|
|
4158
|
+
const id = crypto.randomBytes(16).toString("hex");
|
|
4159
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
4160
|
+
const log = { ...data, id, timestamp };
|
|
4161
|
+
this.auditLogs.push(log);
|
|
4162
|
+
return log;
|
|
2786
4163
|
}
|
|
2787
4164
|
};
|
|
2788
|
-
var DEFAULT_RATE_LIMITS2 = {
|
|
2789
|
-
"auth:login": { window: 9e5, max: 5 },
|
|
2790
|
-
"auth:register": { window: 36e5, max: 3 },
|
|
2791
|
-
"auth:forgot": { window: 36e5, max: 3 },
|
|
2792
|
-
"auth:reset": { window: 36e5, max: 5 },
|
|
2793
|
-
"auth:verify": { window: 36e5, max: 5 },
|
|
2794
|
-
"api:general": { window: 6e4, max: 100 },
|
|
2795
|
-
"api:authenticated": { window: 6e4, max: 200 }
|
|
2796
|
-
};
|
|
2797
4165
|
|
|
2798
4166
|
// src/auth/security/in-memory-lockout.ts
|
|
2799
4167
|
var InMemoryAccountLockout = class {
|
|
@@ -3064,32 +4432,6 @@ function createAuditContext2(req) {
|
|
|
3064
4432
|
userAgent: req.headers.get("user-agent") || "unknown"
|
|
3065
4433
|
};
|
|
3066
4434
|
}
|
|
3067
|
-
function defaultExtractToken(req) {
|
|
3068
|
-
const authHeader = req.headers.get("Authorization");
|
|
3069
|
-
if (authHeader?.startsWith("Bearer ")) {
|
|
3070
|
-
return authHeader.slice(7);
|
|
3071
|
-
}
|
|
3072
|
-
const cookieHeader = req.headers.get("Cookie");
|
|
3073
|
-
if (cookieHeader) {
|
|
3074
|
-
const cookies = Object.fromEntries(
|
|
3075
|
-
cookieHeader.split("; ").map((c) => {
|
|
3076
|
-
const [key, ...val] = c.split("=");
|
|
3077
|
-
return [key.trim(), val.join("=")];
|
|
3078
|
-
})
|
|
3079
|
-
);
|
|
3080
|
-
return cookies["auth_token"] || null;
|
|
3081
|
-
}
|
|
3082
|
-
return null;
|
|
3083
|
-
}
|
|
3084
|
-
function generateToken(payload, secret, options = {}) {
|
|
3085
|
-
return jwt2__default.default.sign(payload, secret, {
|
|
3086
|
-
expiresIn: options.expiresIn || "24h",
|
|
3087
|
-
issuer: options.issuer,
|
|
3088
|
-
audience: options.audience
|
|
3089
|
-
});
|
|
3090
|
-
}
|
|
3091
|
-
|
|
3092
|
-
// src/api/rest/auth-routes.ts
|
|
3093
4435
|
var AuthRoutes = class {
|
|
3094
4436
|
authAdapter;
|
|
3095
4437
|
email;
|
|
@@ -3110,7 +4452,7 @@ var AuthRoutes = class {
|
|
|
3110
4452
|
this.jwtExpiresIn = config.jwtExpiresIn || "24h";
|
|
3111
4453
|
this.jwtIssuer = config.jwtIssuer;
|
|
3112
4454
|
this.jwtAudience = config.jwtAudience;
|
|
3113
|
-
this.passwordPolicy = config.passwordPolicy || new
|
|
4455
|
+
this.passwordPolicy = config.passwordPolicy || new chunk4M5PHMUE_cjs.PasswordPolicy();
|
|
3114
4456
|
this.lockout = config.lockout;
|
|
3115
4457
|
this.rateLimiter = config.rateLimiter;
|
|
3116
4458
|
this.auditLogger = config.auditLogger;
|
|
@@ -3141,10 +4483,9 @@ var AuthRoutes = class {
|
|
|
3141
4483
|
if (existingUser) {
|
|
3142
4484
|
return this.errorResponse("Email already registered", 400);
|
|
3143
4485
|
}
|
|
3144
|
-
const passwordHash = await this.authAdapter.hashPassword(body.password);
|
|
3145
4486
|
const user = await this.authAdapter.createUser({
|
|
3146
4487
|
email: body.email,
|
|
3147
|
-
|
|
4488
|
+
password: body.password,
|
|
3148
4489
|
role: body.role || "customer",
|
|
3149
4490
|
tenantId: body.tenantId
|
|
3150
4491
|
});
|
|
@@ -3241,7 +4582,7 @@ var AuthRoutes = class {
|
|
|
3241
4582
|
iat: Math.floor(Date.now() / 1e3),
|
|
3242
4583
|
exp: Math.floor(Date.now() / 1e3) + 86400
|
|
3243
4584
|
};
|
|
3244
|
-
const accessToken = generateToken(payload, this.jwtSecret, {
|
|
4585
|
+
const accessToken = chunkE63IF3MD_cjs.generateToken(payload, this.jwtSecret, {
|
|
3245
4586
|
expiresIn: this.jwtExpiresIn,
|
|
3246
4587
|
issuer: this.jwtIssuer,
|
|
3247
4588
|
audience: this.jwtAudience
|
|
@@ -3273,13 +4614,13 @@ var AuthRoutes = class {
|
|
|
3273
4614
|
}
|
|
3274
4615
|
}
|
|
3275
4616
|
async logout(req) {
|
|
3276
|
-
const token = defaultExtractToken(req);
|
|
4617
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3277
4618
|
if (!token) {
|
|
3278
4619
|
return this.errorResponse("No session to logout", 401);
|
|
3279
4620
|
}
|
|
3280
4621
|
const { ipAddress, userAgent } = createAuditContext2(req);
|
|
3281
4622
|
try {
|
|
3282
|
-
const payload =
|
|
4623
|
+
const payload = jwt__default.default.decode(token);
|
|
3283
4624
|
if (payload && payload.sub) {
|
|
3284
4625
|
await this.authAdapter.deleteUserSessions(payload.sub);
|
|
3285
4626
|
if (this.auditLogger) {
|
|
@@ -3315,12 +4656,12 @@ var AuthRoutes = class {
|
|
|
3315
4656
|
}
|
|
3316
4657
|
}
|
|
3317
4658
|
async me(req) {
|
|
3318
|
-
const token = defaultExtractToken(req);
|
|
4659
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3319
4660
|
if (!token) {
|
|
3320
4661
|
return this.errorResponse("Not authenticated", 401);
|
|
3321
4662
|
}
|
|
3322
4663
|
try {
|
|
3323
|
-
const payload =
|
|
4664
|
+
const payload = jwt__default.default.verify(token, this.jwtSecret, {
|
|
3324
4665
|
issuer: this.jwtIssuer,
|
|
3325
4666
|
audience: this.jwtAudience
|
|
3326
4667
|
});
|
|
@@ -3337,13 +4678,13 @@ var AuthRoutes = class {
|
|
|
3337
4678
|
}
|
|
3338
4679
|
}
|
|
3339
4680
|
async changePassword(req) {
|
|
3340
|
-
const token = defaultExtractToken(req);
|
|
4681
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3341
4682
|
if (!token) {
|
|
3342
4683
|
return this.errorResponse("Not authenticated", 401);
|
|
3343
4684
|
}
|
|
3344
4685
|
const { ipAddress, userAgent } = createAuditContext2(req);
|
|
3345
4686
|
try {
|
|
3346
|
-
const payload =
|
|
4687
|
+
const payload = jwt__default.default.verify(token, this.jwtSecret);
|
|
3347
4688
|
const body = await req.json();
|
|
3348
4689
|
const { currentPassword, newPassword, confirmPassword } = body;
|
|
3349
4690
|
if (!currentPassword || !newPassword) {
|
|
@@ -3549,9 +4890,9 @@ function detectDatabaseType() {
|
|
|
3549
4890
|
return envDb;
|
|
3550
4891
|
}
|
|
3551
4892
|
try {
|
|
3552
|
-
const { readFileSync } =
|
|
3553
|
-
const { join } =
|
|
3554
|
-
const configPath =
|
|
4893
|
+
const { readFileSync } = chunkG7VZBCD6_cjs.__require("fs");
|
|
4894
|
+
const { join: join2 } = chunkG7VZBCD6_cjs.__require("path");
|
|
4895
|
+
const configPath = join2(process.cwd(), "kyro.config.ts");
|
|
3555
4896
|
const configContent = readFileSync(configPath, "utf8");
|
|
3556
4897
|
if (configContent.includes("createLocalAdapter")) {
|
|
3557
4898
|
return "sqlite";
|
|
@@ -3572,16 +4913,16 @@ function detectDatabaseType() {
|
|
|
3572
4913
|
async function createAuthAdapter(databaseType) {
|
|
3573
4914
|
switch (databaseType) {
|
|
3574
4915
|
case "sqlite":
|
|
3575
|
-
return new
|
|
4916
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3576
4917
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3577
4918
|
});
|
|
3578
4919
|
case "postgres":
|
|
3579
4920
|
case "mysql":
|
|
3580
|
-
return new
|
|
4921
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3581
4922
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3582
4923
|
});
|
|
3583
4924
|
case "mongodb":
|
|
3584
|
-
return new
|
|
4925
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3585
4926
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3586
4927
|
});
|
|
3587
4928
|
case "memory":
|
|
@@ -3593,7 +4934,7 @@ async function createAuthConfig(databaseType) {
|
|
|
3593
4934
|
const distributed = getEnvBool("KYRO_DISTRIBUTED", false);
|
|
3594
4935
|
let authAdapter;
|
|
3595
4936
|
if (distributed) {
|
|
3596
|
-
const { RedisAuthAdapter: RedisAuthAdapter2 } = await import('./redis-adapter-
|
|
4937
|
+
const { RedisAuthAdapter: RedisAuthAdapter2 } = await import('./redis-adapter-2N6VA7BI.cjs');
|
|
3597
4938
|
const redisUrl = getEnv("REDIS_URL", "redis://localhost:6379");
|
|
3598
4939
|
const redisTls = getEnvBool("REDIS_TLS", false);
|
|
3599
4940
|
const redisAdapter = new RedisAuthAdapter2({ url: redisUrl, tls: redisTls });
|
|
@@ -3606,9 +4947,8 @@ async function createAuthConfig(databaseType) {
|
|
|
3606
4947
|
await authAdapter.connect();
|
|
3607
4948
|
}
|
|
3608
4949
|
}
|
|
3609
|
-
const
|
|
3610
|
-
const
|
|
3611
|
-
const passwordPolicy = new chunkMHS6CPO5_cjs.PasswordPolicy({
|
|
4950
|
+
const email = chunkHVSQDZZJ_cjs.EmailTransport.fromEnv() || void 0;
|
|
4951
|
+
const passwordPolicy = new chunk4M5PHMUE_cjs.PasswordPolicy({
|
|
3612
4952
|
minLength: getEnvNum("PASSWORD_MIN_LENGTH", 12),
|
|
3613
4953
|
requireUppercase: getEnvBool("PASSWORD_REQUIRE_UPPERCASE", true),
|
|
3614
4954
|
requireLowercase: getEnvBool("PASSWORD_REQUIRE_LOWERCASE", true),
|
|
@@ -3646,7 +4986,7 @@ async function createAuthConfig(databaseType) {
|
|
|
3646
4986
|
maxAttempts: getEnvNum("LOCKOUT_MAX_ATTEMPTS", 5),
|
|
3647
4987
|
lockDuration: getEnvNum("LOCKOUT_DURATION_MINUTES", 15) * 60 * 1e3
|
|
3648
4988
|
});
|
|
3649
|
-
rateLimiter = new InMemoryRateLimiter({
|
|
4989
|
+
rateLimiter = new chunkE63IF3MD_cjs.InMemoryRateLimiter({
|
|
3650
4990
|
"auth:login": {
|
|
3651
4991
|
window: getEnvNum("RATE_LIMIT_AUTH_WINDOW_MS", 9e5),
|
|
3652
4992
|
max: getEnvNum("RATE_LIMIT_AUTH_MAX_REQUESTS", 10)
|
|
@@ -3684,21 +5024,6 @@ async function createAuthConfig(databaseType) {
|
|
|
3684
5024
|
routes
|
|
3685
5025
|
};
|
|
3686
5026
|
}
|
|
3687
|
-
function getEmailConfig() {
|
|
3688
|
-
const host = getEnv("SMTP_HOST");
|
|
3689
|
-
if (!host) return void 0;
|
|
3690
|
-
return {
|
|
3691
|
-
host,
|
|
3692
|
-
port: getEnvNum("SMTP_PORT", 587),
|
|
3693
|
-
secure: getEnvBool("SMTP_SECURE", false),
|
|
3694
|
-
auth: {
|
|
3695
|
-
user: getEnv("SMTP_USER"),
|
|
3696
|
-
pass: getEnv("SMTP_PASS")
|
|
3697
|
-
},
|
|
3698
|
-
from: getEnv("SMTP_FROM", "noreply@example.com"),
|
|
3699
|
-
fromName: getEnv("SMTP_FROM_NAME", "Kyro CMS")
|
|
3700
|
-
};
|
|
3701
|
-
}
|
|
3702
5027
|
var authConfig = createAuthConfig();
|
|
3703
5028
|
|
|
3704
5029
|
// src/auth/index.ts
|
|
@@ -3725,10 +5050,9 @@ var Auth = class {
|
|
|
3725
5050
|
if (existing) {
|
|
3726
5051
|
return { success: false, error: "Email already registered" };
|
|
3727
5052
|
}
|
|
3728
|
-
const passwordHash = await this.hashPassword(data.password);
|
|
3729
5053
|
const user = await this.adapter.createUser({
|
|
3730
5054
|
email: data.email,
|
|
3731
|
-
|
|
5055
|
+
password: data.password,
|
|
3732
5056
|
role: data.role ?? "customer",
|
|
3733
5057
|
tenantId: data.tenantId
|
|
3734
5058
|
});
|
|
@@ -3739,15 +5063,11 @@ var Auth = class {
|
|
|
3739
5063
|
}
|
|
3740
5064
|
async login(credentials) {
|
|
3741
5065
|
try {
|
|
3742
|
-
const user = await this.adapter.
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
}
|
|
3746
|
-
const valid = await this.adapter.verifyPassword(
|
|
3747
|
-
credentials.password,
|
|
3748
|
-
user.passwordHash
|
|
5066
|
+
const user = await this.adapter.verifyPassword(
|
|
5067
|
+
credentials.email,
|
|
5068
|
+
credentials.password
|
|
3749
5069
|
);
|
|
3750
|
-
if (!
|
|
5070
|
+
if (!user) {
|
|
3751
5071
|
return { success: false, error: "Invalid credentials" };
|
|
3752
5072
|
}
|
|
3753
5073
|
return this.createSessionForUser(user);
|
|
@@ -3776,7 +5096,7 @@ var Auth = class {
|
|
|
3776
5096
|
}
|
|
3777
5097
|
async verifyToken(token) {
|
|
3778
5098
|
try {
|
|
3779
|
-
const decoded =
|
|
5099
|
+
const decoded = jwt__default.default.verify(token, this.config.secret, {
|
|
3780
5100
|
issuer: this.config.issuer,
|
|
3781
5101
|
audience: this.config.audience.length > 0 ? this.config.audience[0] : void 0
|
|
3782
5102
|
});
|
|
@@ -3793,18 +5113,17 @@ var Auth = class {
|
|
|
3793
5113
|
async changePassword(userId, currentPassword, newPassword) {
|
|
3794
5114
|
try {
|
|
3795
5115
|
const user = await this.adapter.findUserById(userId);
|
|
3796
|
-
if (!user
|
|
5116
|
+
if (!user) {
|
|
3797
5117
|
return { success: false, error: "User not found" };
|
|
3798
5118
|
}
|
|
3799
5119
|
const valid = await this.adapter.verifyPassword(
|
|
3800
|
-
|
|
3801
|
-
|
|
5120
|
+
user.email,
|
|
5121
|
+
currentPassword
|
|
3802
5122
|
);
|
|
3803
5123
|
if (!valid) {
|
|
3804
5124
|
return { success: false, error: "Current password is incorrect" };
|
|
3805
5125
|
}
|
|
3806
|
-
|
|
3807
|
-
await this.adapter.updateUser(userId, { passwordHash: newHash });
|
|
5126
|
+
await this.adapter.updateUser(userId, { password: newPassword });
|
|
3808
5127
|
await this.adapter.deleteUserSessions(userId);
|
|
3809
5128
|
return { success: true, user };
|
|
3810
5129
|
} catch (error) {
|
|
@@ -3817,8 +5136,7 @@ var Auth = class {
|
|
|
3817
5136
|
if (!user) {
|
|
3818
5137
|
return { success: false, error: "User not found" };
|
|
3819
5138
|
}
|
|
3820
|
-
|
|
3821
|
-
await this.adapter.updateUser(user.id, { passwordHash });
|
|
5139
|
+
await this.adapter.updateUser(user.id, { password: newPassword });
|
|
3822
5140
|
await this.adapter.deleteUserSessions(user.id);
|
|
3823
5141
|
return { success: true, user };
|
|
3824
5142
|
} catch (error) {
|
|
@@ -3862,7 +5180,7 @@ var Auth = class {
|
|
|
3862
5180
|
if (this.config.audience.length > 0) {
|
|
3863
5181
|
signOptions.audience = this.config.audience[0];
|
|
3864
5182
|
}
|
|
3865
|
-
return
|
|
5183
|
+
return jwt__default.default.sign(payload, this.config.secret, signOptions);
|
|
3866
5184
|
}
|
|
3867
5185
|
async hashPassword(password) {
|
|
3868
5186
|
return bcrypt__default.default.hash(password, this.config.saltRounds);
|
|
@@ -4036,20 +5354,1604 @@ function isDraft(status) {
|
|
|
4036
5354
|
function isArchived(status) {
|
|
4037
5355
|
return status === "archived";
|
|
4038
5356
|
}
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
function
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
}
|
|
4046
|
-
function
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
5357
|
+
function createLocalStorage(config) {
|
|
5358
|
+
const { uploadDir, baseUrl = "/uploads" } = config;
|
|
5359
|
+
async function ensureDir(dir) {
|
|
5360
|
+
if (!fs.existsSync(dir)) {
|
|
5361
|
+
await promises.mkdir(dir, { recursive: true });
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
5364
|
+
function getMimeType(filename) {
|
|
5365
|
+
const ext = path.extname(filename).toLowerCase();
|
|
5366
|
+
const mimeTypes = {
|
|
5367
|
+
".jpg": "image/jpeg",
|
|
5368
|
+
".jpeg": "image/jpeg",
|
|
5369
|
+
".png": "image/png",
|
|
5370
|
+
".gif": "image/gif",
|
|
5371
|
+
".webp": "image/webp",
|
|
5372
|
+
".svg": "image/svg+xml",
|
|
5373
|
+
".mp4": "video/mp4",
|
|
5374
|
+
".webm": "video/webm",
|
|
5375
|
+
".pdf": "application/pdf",
|
|
5376
|
+
".doc": "application/msword",
|
|
5377
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
5378
|
+
".xls": "application/vnd.ms-excel",
|
|
5379
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
5380
|
+
".zip": "application/zip"
|
|
5381
|
+
};
|
|
5382
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
5383
|
+
}
|
|
5384
|
+
async function getImageDimensions(buffer) {
|
|
5385
|
+
try {
|
|
5386
|
+
const header = buffer.toString("hex", 0, 8);
|
|
5387
|
+
if (header.startsWith("89504e47")) {
|
|
5388
|
+
const width = buffer.readUInt32BE(16);
|
|
5389
|
+
const height = buffer.readUInt32BE(20);
|
|
5390
|
+
return { width, height };
|
|
5391
|
+
}
|
|
5392
|
+
if (header.startsWith("ffd8")) {
|
|
5393
|
+
let offset = 2;
|
|
5394
|
+
while (offset < buffer.length) {
|
|
5395
|
+
if (buffer[offset] !== 255) break;
|
|
5396
|
+
const marker = buffer[offset + 1];
|
|
5397
|
+
if (marker === 192 || marker === 194) {
|
|
5398
|
+
const height = buffer.readUInt16BE(offset + 5);
|
|
5399
|
+
const width = buffer.readUInt16BE(offset + 7);
|
|
5400
|
+
return { width, height };
|
|
5401
|
+
}
|
|
5402
|
+
offset += 2 + buffer.readUInt16BE(offset + 2);
|
|
5403
|
+
}
|
|
5404
|
+
}
|
|
5405
|
+
} catch {
|
|
5406
|
+
}
|
|
5407
|
+
return {};
|
|
5408
|
+
}
|
|
5409
|
+
return {
|
|
5410
|
+
name: "local",
|
|
5411
|
+
displayName: "Local Storage",
|
|
5412
|
+
supportsDynamicResize: true,
|
|
5413
|
+
async upload(file, options) {
|
|
5414
|
+
await ensureDir(uploadDir);
|
|
5415
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
5416
|
+
const hash = crypto.createHash("md5").update(buffer).digest("hex");
|
|
5417
|
+
const ext = path.extname(file.name);
|
|
5418
|
+
const filename = options?.filename || `${hash}${ext}`;
|
|
5419
|
+
const folder = options?.folder || "";
|
|
5420
|
+
const targetDir = folder ? path.join(uploadDir, folder) : uploadDir;
|
|
5421
|
+
await ensureDir(targetDir);
|
|
5422
|
+
const filepath = path.join(targetDir, filename);
|
|
5423
|
+
await promises.writeFile(filepath, buffer);
|
|
5424
|
+
const dimensions = file.type.startsWith("image/") ? await getImageDimensions(buffer) : {};
|
|
5425
|
+
const normalizedBaseUrl = baseUrl || "/uploads";
|
|
5426
|
+
const urlPath = folder ? `/${folder}/${filename}` : `/${filename}`;
|
|
5427
|
+
const url = normalizedBaseUrl + urlPath;
|
|
5428
|
+
return {
|
|
5429
|
+
id: hash,
|
|
5430
|
+
filename,
|
|
5431
|
+
originalName: file.name,
|
|
5432
|
+
mimeType: file.type || getMimeType(file.name),
|
|
5433
|
+
size: buffer.length,
|
|
5434
|
+
url,
|
|
5435
|
+
thumbnailUrl: file.type.startsWith("image/") ? url : void 0,
|
|
5436
|
+
folder: folder || void 0,
|
|
5437
|
+
provider: "local",
|
|
5438
|
+
metadata: {
|
|
5439
|
+
...dimensions,
|
|
5440
|
+
...options?.metadata
|
|
5441
|
+
},
|
|
5442
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5443
|
+
};
|
|
5444
|
+
},
|
|
5445
|
+
async uploadFromUrl(url, options) {
|
|
5446
|
+
const response = await fetch(url);
|
|
5447
|
+
if (!response.ok) {
|
|
5448
|
+
throw new Error(`Failed to fetch file: ${response.statusText}`);
|
|
5449
|
+
}
|
|
5450
|
+
const blob = await response.blob();
|
|
5451
|
+
const contentDisposition = response.headers.get("content-disposition");
|
|
5452
|
+
let filename = options?.filename;
|
|
5453
|
+
if (!filename && contentDisposition) {
|
|
5454
|
+
const match = contentDisposition.match(
|
|
5455
|
+
/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
|
|
5456
|
+
);
|
|
5457
|
+
if (match) {
|
|
5458
|
+
filename = match[1].replace(/['"]/g, "");
|
|
5459
|
+
}
|
|
5460
|
+
}
|
|
5461
|
+
if (!filename) {
|
|
5462
|
+
filename = path.basename(new URL(url).pathname);
|
|
5463
|
+
}
|
|
5464
|
+
const file = new File([blob], filename, {
|
|
5465
|
+
type: blob.type || getMimeType(filename)
|
|
5466
|
+
});
|
|
5467
|
+
return this.upload(file, options);
|
|
5468
|
+
},
|
|
5469
|
+
async delete(url) {
|
|
5470
|
+
const filepath = path.join(uploadDir, url.replace(baseUrl + "/", ""));
|
|
5471
|
+
try {
|
|
5472
|
+
await promises.unlink(filepath);
|
|
5473
|
+
} catch {
|
|
5474
|
+
}
|
|
5475
|
+
},
|
|
5476
|
+
async rename(oldUrl, newFilename) {
|
|
5477
|
+
const oldPath = path.join(uploadDir, oldUrl.replace(baseUrl + "/", ""));
|
|
5478
|
+
const newPath = path.join(uploadDir, newFilename);
|
|
5479
|
+
await promises.rename(oldPath, newPath);
|
|
5480
|
+
return `${baseUrl}/${newFilename}`;
|
|
5481
|
+
},
|
|
5482
|
+
getImageUrl(url, transforms) {
|
|
5483
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
5484
|
+
const params = new URLSearchParams({ url });
|
|
5485
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5486
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5487
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5488
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
5489
|
+
return `/api/media/resize?${params.toString()}`;
|
|
5490
|
+
},
|
|
5491
|
+
async generateThumbnail(file) {
|
|
5492
|
+
if (!file.mimeType.startsWith("image/")) return "";
|
|
5493
|
+
return this.getImageUrl(file.url, { width: 400, height: 400 });
|
|
5494
|
+
},
|
|
5495
|
+
async list(prefix) {
|
|
5496
|
+
const dir = prefix ? path.join(uploadDir, prefix) : uploadDir;
|
|
5497
|
+
if (!fs.existsSync(dir)) return [];
|
|
5498
|
+
const files = [];
|
|
5499
|
+
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
5500
|
+
for (const entry of entries) {
|
|
5501
|
+
if (entry.isFile()) {
|
|
5502
|
+
const filepath = path.join(dir, entry.name);
|
|
5503
|
+
const stats = await promises.stat(filepath);
|
|
5504
|
+
const url = `${baseUrl}${prefix ? `/${prefix}` : ""}/${entry.name}`;
|
|
5505
|
+
files.push({
|
|
5506
|
+
id: crypto.createHash("md5").update(entry.name).digest("hex"),
|
|
5507
|
+
filename: entry.name,
|
|
5508
|
+
originalName: entry.name,
|
|
5509
|
+
mimeType: getMimeType(entry.name),
|
|
5510
|
+
size: stats.size,
|
|
5511
|
+
url,
|
|
5512
|
+
provider: "local",
|
|
5513
|
+
createdAt: stats.birthtime.toISOString()
|
|
5514
|
+
});
|
|
5515
|
+
}
|
|
5516
|
+
}
|
|
5517
|
+
return files;
|
|
5518
|
+
},
|
|
5519
|
+
async exists(url) {
|
|
5520
|
+
const filepath = path.join(uploadDir, url.replace(baseUrl + "/", ""));
|
|
5521
|
+
return fs.existsSync(filepath);
|
|
5522
|
+
}
|
|
5523
|
+
};
|
|
5524
|
+
}
|
|
5525
|
+
function extractPublicDevUrlId(url) {
|
|
5526
|
+
if (!url) return "";
|
|
5527
|
+
if (url.startsWith("pub-")) return url;
|
|
5528
|
+
const match = url.match(/pub-[a-zA-Z0-9]+/i);
|
|
5529
|
+
return match ? match[0] : "";
|
|
5530
|
+
}
|
|
5531
|
+
function getPublicUrl(key, config) {
|
|
5532
|
+
const normalizedKey = key.startsWith("/") ? key.slice(1) : key;
|
|
5533
|
+
if (config.cdnUrl) {
|
|
5534
|
+
const cdn = config.cdnUrl.replace(/\/$/, "");
|
|
5535
|
+
return `${cdn}/${normalizedKey}`;
|
|
5536
|
+
}
|
|
5537
|
+
switch (config.provider) {
|
|
5538
|
+
case "r2": {
|
|
5539
|
+
const pubId = extractPublicDevUrlId(config.publicDevUrl);
|
|
5540
|
+
if (pubId) {
|
|
5541
|
+
return `https://${pubId}.r2.dev/${normalizedKey}`;
|
|
5542
|
+
}
|
|
5543
|
+
return `https://${config.bucket}.${config.accountId}.r2.cloudflarestorage.com/${normalizedKey}`;
|
|
5544
|
+
}
|
|
5545
|
+
case "gcs":
|
|
5546
|
+
return `https://storage.googleapis.com/${config.bucket}/${normalizedKey}`;
|
|
5547
|
+
case "digitalocean":
|
|
5548
|
+
return `https://${config.bucket}.${config.region}.cdn.digitaloceanspaces.com/${normalizedKey}`;
|
|
5549
|
+
case "backblaze":
|
|
5550
|
+
return `https://${config.bucket}.s3.backblazeb2.com/${normalizedKey}`;
|
|
5551
|
+
case "wasabi":
|
|
5552
|
+
return `https://${config.bucket}.s3.wasabisys.com/${normalizedKey}`;
|
|
5553
|
+
case "aws":
|
|
5554
|
+
default:
|
|
5555
|
+
return `https://${config.bucket}.s3.${config.region}.amazonaws.com/${normalizedKey}`;
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
function getUrlPrefix(config) {
|
|
5559
|
+
if (config.cdnUrl) {
|
|
5560
|
+
return config.cdnUrl.replace(/\/$/, "") + "/";
|
|
5561
|
+
}
|
|
5562
|
+
switch (config.provider) {
|
|
5563
|
+
case "r2": {
|
|
5564
|
+
const pubId = extractPublicDevUrlId(config.publicDevUrl);
|
|
5565
|
+
if (pubId) {
|
|
5566
|
+
return `https://${pubId}.r2.dev/`;
|
|
5567
|
+
}
|
|
5568
|
+
return `https://${config.bucket}.${config.accountId}.r2.cloudflarestorage.com/`;
|
|
5569
|
+
}
|
|
5570
|
+
case "gcs":
|
|
5571
|
+
return `https://storage.googleapis.com/${config.bucket}/`;
|
|
5572
|
+
case "digitalocean":
|
|
5573
|
+
return `https://${config.bucket}.${config.region}.cdn.digitaloceanspaces.com/`;
|
|
5574
|
+
case "backblaze":
|
|
5575
|
+
return `https://${config.bucket}.s3.backblazeb2.com/`;
|
|
5576
|
+
case "wasabi":
|
|
5577
|
+
return `https://${config.bucket}.s3.wasabisys.com/`;
|
|
5578
|
+
case "aws":
|
|
5579
|
+
default:
|
|
5580
|
+
return `https://${config.bucket}.s3.${config.region}.amazonaws.com/`;
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
function getDisplayName(provider) {
|
|
5584
|
+
switch (provider) {
|
|
5585
|
+
case "r2":
|
|
5586
|
+
return "Cloudflare R2";
|
|
5587
|
+
case "gcs":
|
|
5588
|
+
return "Google Cloud Storage";
|
|
5589
|
+
case "digitalocean":
|
|
5590
|
+
return "DigitalOcean Spaces";
|
|
5591
|
+
case "backblaze":
|
|
5592
|
+
return "Backblaze B2";
|
|
5593
|
+
case "wasabi":
|
|
5594
|
+
return "Wasabi";
|
|
5595
|
+
case "aws":
|
|
5596
|
+
default:
|
|
5597
|
+
return "AWS S3";
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
function createS3Storage(config) {
|
|
5601
|
+
console.log("[createS3Storage] Creating provider:", config.provider);
|
|
5602
|
+
console.log("[createS3Storage] Credentials:", {
|
|
5603
|
+
accessKeyId: config.accessKeyId ? "SET" : "UNDEFINED",
|
|
5604
|
+
secretAccessKey: config.secretAccessKey ? "SET" : "UNDEFINED",
|
|
5605
|
+
bucket: config.bucket,
|
|
5606
|
+
accountId: config.accountId,
|
|
5607
|
+
endpoint: config.endpoint
|
|
5608
|
+
});
|
|
5609
|
+
const client = new clientS3.S3Client({
|
|
5610
|
+
region: config.region || "auto",
|
|
5611
|
+
endpoint: config.endpoint,
|
|
5612
|
+
credentials: {
|
|
5613
|
+
accessKeyId: config.accessKeyId,
|
|
5614
|
+
secretAccessKey: config.secretAccessKey
|
|
5615
|
+
},
|
|
5616
|
+
forcePathStyle: true,
|
|
5617
|
+
tls: true,
|
|
5618
|
+
// R2 requires specific SSL configuration
|
|
5619
|
+
...config.provider === "r2" && {
|
|
5620
|
+
requestHandler: new (init_dist_es4(), chunkG7VZBCD6_cjs.__toCommonJS(dist_es_exports)).NodeHttpHandler({
|
|
5621
|
+
connectionTimeout: 1e4,
|
|
5622
|
+
socketTimeout: 1e4
|
|
5623
|
+
})
|
|
5624
|
+
}
|
|
5625
|
+
});
|
|
5626
|
+
const getKey = (path2) => {
|
|
5627
|
+
const prefix = config.prefix ? `${config.prefix}/` : "";
|
|
5628
|
+
return `${prefix}${path2}`.replace(/\/+/g, "/");
|
|
5629
|
+
};
|
|
5630
|
+
const getUrl = (key) => getPublicUrl(key, config);
|
|
5631
|
+
return {
|
|
5632
|
+
name: config.provider,
|
|
5633
|
+
displayName: getDisplayName(config.provider),
|
|
5634
|
+
supportsDynamicResize: true,
|
|
5635
|
+
async upload(file, options) {
|
|
5636
|
+
const key = getKey(
|
|
5637
|
+
`${options?.folder ? `${options.folder}/` : ""}${options?.filename || file.name}`
|
|
5638
|
+
);
|
|
5639
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
5640
|
+
await client.send(
|
|
5641
|
+
new clientS3.PutObjectCommand({
|
|
5642
|
+
Bucket: config.bucket,
|
|
5643
|
+
Key: key,
|
|
5644
|
+
Body: buffer,
|
|
5645
|
+
ContentType: file.type,
|
|
5646
|
+
Metadata: options?.metadata
|
|
5647
|
+
})
|
|
5648
|
+
);
|
|
5649
|
+
const head = await client.send(
|
|
5650
|
+
new clientS3.HeadObjectCommand({
|
|
5651
|
+
Bucket: config.bucket,
|
|
5652
|
+
Key: key
|
|
5653
|
+
})
|
|
5654
|
+
);
|
|
5655
|
+
return {
|
|
5656
|
+
id: Buffer.from(key).toString("base64url"),
|
|
5657
|
+
filename: options?.filename || file.name,
|
|
5658
|
+
originalName: file.name,
|
|
5659
|
+
mimeType: file.type,
|
|
5660
|
+
size: buffer.length,
|
|
5661
|
+
url: getUrl(key),
|
|
5662
|
+
thumbnailUrl: file.type.startsWith("image/") ? getUrl(key) : void 0,
|
|
5663
|
+
folder: options?.folder,
|
|
5664
|
+
provider: config.provider,
|
|
5665
|
+
metadata: {
|
|
5666
|
+
...options?.metadata,
|
|
5667
|
+
etag: head.ETag
|
|
5668
|
+
},
|
|
5669
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5670
|
+
};
|
|
5671
|
+
},
|
|
5672
|
+
async uploadFromUrl(url) {
|
|
5673
|
+
const response = await fetch(url);
|
|
5674
|
+
if (!response.ok) {
|
|
5675
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
5676
|
+
}
|
|
5677
|
+
const blob = await response.blob();
|
|
5678
|
+
const filename = url.split("/").pop() || "file";
|
|
5679
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
5680
|
+
return this.upload(file);
|
|
5681
|
+
},
|
|
5682
|
+
async delete(url) {
|
|
5683
|
+
const key = url.replace(getUrlPrefix(config), "");
|
|
5684
|
+
await client.send(
|
|
5685
|
+
new clientS3.DeleteObjectCommand({
|
|
5686
|
+
Bucket: config.bucket,
|
|
5687
|
+
Key: key
|
|
5688
|
+
})
|
|
5689
|
+
);
|
|
5690
|
+
},
|
|
5691
|
+
async rename(oldUrl, newKey) {
|
|
5692
|
+
const oldKey = oldUrl.replace(getUrlPrefix(config), "");
|
|
5693
|
+
const newKeyWithPrefix = config.prefix ? `${config.prefix}/${newKey}` : newKey;
|
|
5694
|
+
await client.send(
|
|
5695
|
+
new clientS3.CopyObjectCommand({
|
|
5696
|
+
Bucket: config.bucket,
|
|
5697
|
+
CopySource: `${config.bucket}/${oldKey}`,
|
|
5698
|
+
Key: newKeyWithPrefix
|
|
5699
|
+
})
|
|
5700
|
+
);
|
|
5701
|
+
await client.send(
|
|
5702
|
+
new clientS3.DeleteObjectCommand({
|
|
5703
|
+
Bucket: config.bucket,
|
|
5704
|
+
Key: oldKey
|
|
5705
|
+
})
|
|
5706
|
+
);
|
|
5707
|
+
return getUrl(newKeyWithPrefix);
|
|
5708
|
+
},
|
|
5709
|
+
getImageUrl(url, transforms) {
|
|
5710
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
5711
|
+
const params = new URLSearchParams({ url });
|
|
5712
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5713
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5714
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5715
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
5716
|
+
return `/api/media/resize?${params.toString()}`;
|
|
5717
|
+
},
|
|
5718
|
+
async generateThumbnail(file) {
|
|
5719
|
+
return this.getImageUrl(file.url, { width: 400, height: 400 });
|
|
5720
|
+
},
|
|
5721
|
+
async list(prefix) {
|
|
5722
|
+
const key = getKey(prefix || "");
|
|
5723
|
+
const response = await client.send(
|
|
5724
|
+
new clientS3.ListObjectsV2Command({
|
|
5725
|
+
Bucket: config.bucket,
|
|
5726
|
+
Prefix: key
|
|
5727
|
+
})
|
|
5728
|
+
);
|
|
5729
|
+
return (response.Contents || []).map((item) => ({
|
|
5730
|
+
id: Buffer.from(item.Key || "").toString("base64url"),
|
|
5731
|
+
filename: item.Key?.split("/").pop() || "",
|
|
5732
|
+
originalName: item.Key?.split("/").pop() || "",
|
|
5733
|
+
mimeType: "application/octet-stream",
|
|
5734
|
+
size: item.Size || 0,
|
|
5735
|
+
url: getUrl(item.Key || ""),
|
|
5736
|
+
provider: config.provider,
|
|
5737
|
+
createdAt: item.LastModified?.toISOString() || (/* @__PURE__ */ new Date()).toISOString()
|
|
5738
|
+
}));
|
|
5739
|
+
},
|
|
5740
|
+
async exists(url) {
|
|
5741
|
+
try {
|
|
5742
|
+
const key = url.replace(getUrlPrefix(config), "");
|
|
5743
|
+
await client.send(
|
|
5744
|
+
new clientS3.HeadObjectCommand({
|
|
5745
|
+
Bucket: config.bucket,
|
|
5746
|
+
Key: key
|
|
5747
|
+
})
|
|
5748
|
+
);
|
|
5749
|
+
return true;
|
|
5750
|
+
} catch {
|
|
5751
|
+
return false;
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
};
|
|
5755
|
+
}
|
|
5756
|
+
|
|
5757
|
+
// src/storage/cloudinary.ts
|
|
5758
|
+
function createCloudinaryStorage(config) {
|
|
5759
|
+
const getBaseUrl = () => `https://api.cloudinary.com/v1_1/${config.cloudName}/upload`;
|
|
5760
|
+
const generateSignature = async (params) => {
|
|
5761
|
+
const crypto = await import('crypto');
|
|
5762
|
+
const sortedParams = Object.keys(params).sort().map((key) => `${key}=${params[key]}`).join("&");
|
|
5763
|
+
return crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5764
|
+
};
|
|
5765
|
+
return {
|
|
5766
|
+
name: "cloudinary",
|
|
5767
|
+
displayName: "Cloudinary",
|
|
5768
|
+
supportsDynamicResize: true,
|
|
5769
|
+
async upload(file, options) {
|
|
5770
|
+
const formData = new FormData();
|
|
5771
|
+
formData.append("file", file);
|
|
5772
|
+
if (config.uploadPreset) {
|
|
5773
|
+
formData.append("upload_preset", config.uploadPreset);
|
|
5774
|
+
} else {
|
|
5775
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5776
|
+
const signatureParams = {
|
|
5777
|
+
timestamp: String(timestamp)
|
|
5778
|
+
};
|
|
5779
|
+
if (options?.folder || config.folder) {
|
|
5780
|
+
signatureParams.folder = options?.folder || config.folder || "";
|
|
5781
|
+
}
|
|
5782
|
+
const signature = await generateSignature(signatureParams);
|
|
5783
|
+
formData.append("timestamp", String(timestamp));
|
|
5784
|
+
formData.append("signature", signature);
|
|
5785
|
+
formData.append("api_key", config.apiKey);
|
|
5786
|
+
}
|
|
5787
|
+
if (options?.folder || config.folder) {
|
|
5788
|
+
formData.append("folder", options?.folder || config.folder || "");
|
|
5789
|
+
}
|
|
5790
|
+
const response = await fetch(getBaseUrl(), {
|
|
5791
|
+
method: "POST",
|
|
5792
|
+
body: formData
|
|
5793
|
+
});
|
|
5794
|
+
if (!response.ok) {
|
|
5795
|
+
const error = await response.json();
|
|
5796
|
+
throw new Error(
|
|
5797
|
+
`Cloudinary upload failed: ${error.error?.message || response.statusText}`
|
|
5798
|
+
);
|
|
5799
|
+
}
|
|
5800
|
+
const data = await response.json();
|
|
5801
|
+
return {
|
|
5802
|
+
id: data.public_id,
|
|
5803
|
+
filename: `${data.public_id}.${data.format}`,
|
|
5804
|
+
originalName: data.original_filename || file.name,
|
|
5805
|
+
mimeType: file.type || `image/${data.format}`,
|
|
5806
|
+
size: data.bytes,
|
|
5807
|
+
url: data.secure_url,
|
|
5808
|
+
thumbnailUrl: this.getImageUrl(data.secure_url, {
|
|
5809
|
+
width: 200,
|
|
5810
|
+
height: 200,
|
|
5811
|
+
fit: "crop"
|
|
5812
|
+
}),
|
|
5813
|
+
width: data.width,
|
|
5814
|
+
height: data.height,
|
|
5815
|
+
folder: options?.folder || config.folder,
|
|
5816
|
+
provider: "cloudinary",
|
|
5817
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5818
|
+
};
|
|
5819
|
+
},
|
|
5820
|
+
async uploadFromUrl(url, options) {
|
|
5821
|
+
const formData = new FormData();
|
|
5822
|
+
formData.append("file", url);
|
|
5823
|
+
formData.append("upload_preset", "ml_default");
|
|
5824
|
+
if (options?.folder || config.folder) {
|
|
5825
|
+
formData.append("folder", options?.folder || config.folder || "");
|
|
5826
|
+
}
|
|
5827
|
+
const response = await fetch(getBaseUrl(), {
|
|
5828
|
+
method: "POST",
|
|
5829
|
+
body: formData
|
|
5830
|
+
});
|
|
5831
|
+
if (!response.ok) throw new Error("Cloudinary upload failed");
|
|
5832
|
+
const data = await response.json();
|
|
5833
|
+
return {
|
|
5834
|
+
id: data.public_id,
|
|
5835
|
+
filename: `${data.public_id}.${data.format}`,
|
|
5836
|
+
originalName: data.original_filename || url.split("/").pop() || "file",
|
|
5837
|
+
mimeType: `image/${data.format}`,
|
|
5838
|
+
size: data.bytes,
|
|
5839
|
+
url: data.secure_url,
|
|
5840
|
+
thumbnailUrl: this.getImageUrl(data.secure_url, {
|
|
5841
|
+
width: 200,
|
|
5842
|
+
height: 200,
|
|
5843
|
+
fit: "crop"
|
|
5844
|
+
}),
|
|
5845
|
+
width: data.width,
|
|
5846
|
+
height: data.height,
|
|
5847
|
+
provider: "cloudinary",
|
|
5848
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5849
|
+
};
|
|
5850
|
+
},
|
|
5851
|
+
async delete(id) {
|
|
5852
|
+
try {
|
|
5853
|
+
const parts = id.split("/image/upload/");
|
|
5854
|
+
if (parts.length !== 2) {
|
|
5855
|
+
console.warn("[Cloudinary delete] Could not parse URL:", id);
|
|
5856
|
+
return;
|
|
5857
|
+
}
|
|
5858
|
+
const publicId = parts[1].replace(/^v\d+\//, "").replace(/\.[^.]+$/, "");
|
|
5859
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5860
|
+
const signatureParams = {
|
|
5861
|
+
timestamp: String(timestamp),
|
|
5862
|
+
public_id: publicId
|
|
5863
|
+
};
|
|
5864
|
+
const sortedParams = Object.keys(signatureParams).sort().map((key) => `${key}=${signatureParams[key]}`).join("&");
|
|
5865
|
+
const crypto = await import('crypto');
|
|
5866
|
+
const signature = crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5867
|
+
const deleteUrl = `https://api.cloudinary.com/v1_1/${config.cloudName}/image/destroy`;
|
|
5868
|
+
const formData = new FormData();
|
|
5869
|
+
formData.append("public_id", publicId);
|
|
5870
|
+
formData.append("timestamp", String(timestamp));
|
|
5871
|
+
formData.append("signature", signature);
|
|
5872
|
+
formData.append("api_key", config.apiKey);
|
|
5873
|
+
const response = await fetch(deleteUrl, {
|
|
5874
|
+
method: "POST",
|
|
5875
|
+
body: formData
|
|
5876
|
+
});
|
|
5877
|
+
if (!response.ok) {
|
|
5878
|
+
const error = await response.json();
|
|
5879
|
+
console.warn("[Cloudinary delete] Failed:", error);
|
|
5880
|
+
}
|
|
5881
|
+
} catch (e) {
|
|
5882
|
+
console.warn("[Cloudinary delete] Error:", e.message);
|
|
5883
|
+
}
|
|
5884
|
+
},
|
|
5885
|
+
async rename(oldUrl, newKey) {
|
|
5886
|
+
let version = "";
|
|
5887
|
+
let newPublicId = newKey.replace(/\.[^.]+$/, "");
|
|
5888
|
+
let folder = "";
|
|
5889
|
+
try {
|
|
5890
|
+
const parts = oldUrl.split("/image/upload/");
|
|
5891
|
+
if (parts.length !== 2) {
|
|
5892
|
+
console.warn("[Cloudinary rename] Could not parse old URL:", oldUrl);
|
|
5893
|
+
return oldUrl;
|
|
5894
|
+
}
|
|
5895
|
+
const urlPath = parts[1];
|
|
5896
|
+
const versionMatch = urlPath.match(/^(v\d+)\//);
|
|
5897
|
+
version = versionMatch ? versionMatch[1] : "";
|
|
5898
|
+
const publicIdWithoutVersion = urlPath.replace(/^v\d+\//, "").replace(/\.[^.]+$/, "");
|
|
5899
|
+
const folderParts = publicIdWithoutVersion.split("/");
|
|
5900
|
+
folder = folderParts.length > 1 ? folderParts.slice(0, -1).join("/") : "";
|
|
5901
|
+
const newFilename = newKey.replace(/\.[^.]+$/, "");
|
|
5902
|
+
newPublicId = folder ? `${folder}/${newFilename}` : newFilename;
|
|
5903
|
+
console.log("[Cloudinary rename]", {
|
|
5904
|
+
urlPath,
|
|
5905
|
+
version,
|
|
5906
|
+
publicIdWithoutVersion,
|
|
5907
|
+
folder,
|
|
5908
|
+
newPublicId
|
|
5909
|
+
});
|
|
5910
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5911
|
+
const signatureParams = {
|
|
5912
|
+
from_public_id: publicIdWithoutVersion,
|
|
5913
|
+
to_public_id: newPublicId,
|
|
5914
|
+
timestamp: String(timestamp)
|
|
5915
|
+
};
|
|
5916
|
+
const sortedParams = Object.keys(signatureParams).sort().map((key) => `${key}=${signatureParams[key]}`).join("&");
|
|
5917
|
+
const crypto = await import('crypto');
|
|
5918
|
+
const signature = crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5919
|
+
const formData = new FormData();
|
|
5920
|
+
formData.append("from_public_id", publicIdWithoutVersion);
|
|
5921
|
+
formData.append("to_public_id", newPublicId);
|
|
5922
|
+
formData.append("timestamp", String(timestamp));
|
|
5923
|
+
formData.append("signature", signature);
|
|
5924
|
+
formData.append("api_key", config.apiKey);
|
|
5925
|
+
const response = await fetch(
|
|
5926
|
+
`https://api.cloudinary.com/v1_1/${config.cloudName}/image/rename`,
|
|
5927
|
+
{
|
|
5928
|
+
method: "POST",
|
|
5929
|
+
body: formData
|
|
5930
|
+
}
|
|
5931
|
+
);
|
|
5932
|
+
if (response.ok) {
|
|
5933
|
+
const data = await response.json();
|
|
5934
|
+
console.log("[Cloudinary rename] Success:", data.secure_url);
|
|
5935
|
+
return data.secure_url;
|
|
5936
|
+
} else {
|
|
5937
|
+
const error = await response.json();
|
|
5938
|
+
console.warn("[Cloudinary rename] Failed:", error);
|
|
5939
|
+
const versionStr = version ? `/${version}/` : "/";
|
|
5940
|
+
return `https://res.cloudinary.com/${config.cloudName}/image/upload${versionStr}${newPublicId}.${newKey.split(".").pop()}`;
|
|
5941
|
+
}
|
|
5942
|
+
} catch (e) {
|
|
5943
|
+
console.warn("[Cloudinary rename] Error:", e.message);
|
|
5944
|
+
const versionStr = version ? `/${version}/` : "/";
|
|
5945
|
+
return `https://res.cloudinary.com/${config.cloudName}/image/upload${versionStr}${newPublicId}.${newKey.split(".").pop()}`;
|
|
5946
|
+
}
|
|
5947
|
+
},
|
|
5948
|
+
getImageUrl(url, transforms) {
|
|
5949
|
+
if (!transforms) return url;
|
|
5950
|
+
const parts = url.split("/upload/");
|
|
5951
|
+
if (parts.length !== 2) return url;
|
|
5952
|
+
const transformationArr = [];
|
|
5953
|
+
if (transforms.width) transformationArr.push(`w_${transforms.width}`);
|
|
5954
|
+
if (transforms.height) transformationArr.push(`h_${transforms.height}`);
|
|
5955
|
+
if (transforms.fit) {
|
|
5956
|
+
const fitMap = {
|
|
5957
|
+
crop: "c_fill",
|
|
5958
|
+
clip: "c_fit",
|
|
5959
|
+
scale: "c_scale",
|
|
5960
|
+
fill: "c_fill"
|
|
5961
|
+
};
|
|
5962
|
+
transformationArr.push(fitMap[transforms.fit] || "c_limit");
|
|
5963
|
+
}
|
|
5964
|
+
if (transforms.quality) transformationArr.push(`q_${transforms.quality}`);
|
|
5965
|
+
if (transforms.format) transformationArr.push(`f_${transforms.format}`);
|
|
5966
|
+
const transformationStr = transformationArr.join(",");
|
|
5967
|
+
return `${parts[0]}/upload/${transformationStr}/${parts[1]}`;
|
|
5968
|
+
},
|
|
5969
|
+
async generateThumbnail(file) {
|
|
5970
|
+
return this.getImageUrl(file.url, {
|
|
5971
|
+
width: 200,
|
|
5972
|
+
height: 200,
|
|
5973
|
+
fit: "crop"
|
|
5974
|
+
});
|
|
5975
|
+
},
|
|
5976
|
+
async list() {
|
|
5977
|
+
return [];
|
|
5978
|
+
},
|
|
5979
|
+
async exists(url) {
|
|
5980
|
+
const response = await fetch(url, { method: "HEAD" });
|
|
5981
|
+
return response.ok;
|
|
5982
|
+
}
|
|
5983
|
+
};
|
|
5984
|
+
}
|
|
5985
|
+
|
|
5986
|
+
// src/storage/imgix.ts
|
|
5987
|
+
function createImgixStorage(config) {
|
|
5988
|
+
const signUrl = (path2, params) => {
|
|
5989
|
+
if (!config.signKey) return path2;
|
|
5990
|
+
const signer = new TextEncoder();
|
|
5991
|
+
const key = signer.encode(config.signKey);
|
|
5992
|
+
const data = signer.encode(path2 + params.toString());
|
|
5993
|
+
let hash = 0;
|
|
5994
|
+
const combined = new Uint8Array(key.length + data.length);
|
|
5995
|
+
combined.set(key);
|
|
5996
|
+
combined.set(data, key.length);
|
|
5997
|
+
for (let i = 0; i < combined.length; i++) {
|
|
5998
|
+
hash = (hash << 5) - hash + combined[i] | 0;
|
|
5999
|
+
}
|
|
6000
|
+
params.set("s", Math.abs(hash).toString(16));
|
|
6001
|
+
return path2;
|
|
6002
|
+
};
|
|
6003
|
+
return {
|
|
6004
|
+
name: "imgix",
|
|
6005
|
+
displayName: "Imgix",
|
|
6006
|
+
supportsDynamicResize: true,
|
|
6007
|
+
async upload(_file, _options) {
|
|
6008
|
+
throw new Error(
|
|
6009
|
+
"Imgix is a transformation service. Use another provider for uploads."
|
|
6010
|
+
);
|
|
6011
|
+
},
|
|
6012
|
+
async uploadFromUrl(url, options) {
|
|
6013
|
+
const filename = options?.filename || url.split("/").pop() || "file";
|
|
6014
|
+
const response = await fetch(url);
|
|
6015
|
+
if (!response.ok) {
|
|
6016
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
6017
|
+
}
|
|
6018
|
+
const blob = await response.blob();
|
|
6019
|
+
new File([blob], filename, { type: blob.type });
|
|
6020
|
+
return {
|
|
6021
|
+
id: Buffer.from(url).toString("base64").slice(0, 20),
|
|
6022
|
+
filename,
|
|
6023
|
+
originalName: filename,
|
|
6024
|
+
mimeType: blob.type,
|
|
6025
|
+
size: blob.size,
|
|
6026
|
+
url: this.getImageUrl(url),
|
|
6027
|
+
thumbnailUrl: this.getImageUrl(url, {
|
|
6028
|
+
width: 200,
|
|
6029
|
+
height: 200,
|
|
6030
|
+
fit: "crop"
|
|
6031
|
+
}),
|
|
6032
|
+
provider: "imgix",
|
|
6033
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6034
|
+
};
|
|
6035
|
+
},
|
|
6036
|
+
async delete(_url) {
|
|
6037
|
+
},
|
|
6038
|
+
async rename(_oldUrl, newKey) {
|
|
6039
|
+
return `https://${config.domain}/${newKey}`;
|
|
6040
|
+
},
|
|
6041
|
+
getImageUrl(url, transforms) {
|
|
6042
|
+
const parsed = new URL(url);
|
|
6043
|
+
const params = new URLSearchParams(parsed.search);
|
|
6044
|
+
if (config.defaultParameters) {
|
|
6045
|
+
Object.entries(config.defaultParameters).forEach(([key, value]) => {
|
|
6046
|
+
if (!params.has(key)) {
|
|
6047
|
+
params.set(key, value);
|
|
6048
|
+
}
|
|
6049
|
+
});
|
|
6050
|
+
}
|
|
6051
|
+
if (transforms) {
|
|
6052
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
6053
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
6054
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
6055
|
+
if (transforms.format) params.set("fm", transforms.format);
|
|
6056
|
+
if (transforms.fit) params.set("fit", transforms.fit);
|
|
6057
|
+
if (transforms.blur) params.set("blur", String(transforms.blur));
|
|
6058
|
+
if (transforms.sharpen) params.set("sharp", String(transforms.sharpen));
|
|
6059
|
+
}
|
|
6060
|
+
params.set("auto", "compress,format");
|
|
6061
|
+
parsed.pathname + "?" + params.toString();
|
|
6062
|
+
if (config.signKey) {
|
|
6063
|
+
signUrl(parsed.pathname + params.toString(), params);
|
|
6064
|
+
}
|
|
6065
|
+
return `https://${config.domain}${parsed.pathname}${params.toString() ? "?" + params.toString() : ""}`;
|
|
6066
|
+
},
|
|
6067
|
+
async generateThumbnail(file) {
|
|
6068
|
+
return this.getImageUrl(file.url, {
|
|
6069
|
+
width: 200,
|
|
6070
|
+
height: 200,
|
|
6071
|
+
fit: "crop"
|
|
6072
|
+
});
|
|
6073
|
+
},
|
|
6074
|
+
async list() {
|
|
6075
|
+
return [];
|
|
6076
|
+
},
|
|
6077
|
+
async exists(url) {
|
|
6078
|
+
try {
|
|
6079
|
+
const response = await fetch(url, { method: "HEAD" });
|
|
6080
|
+
return response.ok;
|
|
6081
|
+
} catch {
|
|
6082
|
+
return false;
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
};
|
|
6086
|
+
}
|
|
6087
|
+
function createFtpStorage(config) {
|
|
6088
|
+
let client = null;
|
|
6089
|
+
async function getClient() {
|
|
6090
|
+
if (!client) {
|
|
6091
|
+
client = new basicFtp.Client(6e4, { allowSeparateTransferHost: true });
|
|
6092
|
+
client.ftp.verbose = false;
|
|
6093
|
+
await client.access({
|
|
6094
|
+
host: config.host,
|
|
6095
|
+
port: config.port || 21,
|
|
6096
|
+
user: config.user,
|
|
6097
|
+
password: config.password,
|
|
6098
|
+
secure: config.secure,
|
|
6099
|
+
secureOptions: {}
|
|
6100
|
+
});
|
|
6101
|
+
}
|
|
6102
|
+
return client;
|
|
6103
|
+
}
|
|
6104
|
+
const getKey = (path2) => {
|
|
6105
|
+
const prefix = config.prefix ? `${config.prefix}/` : "";
|
|
6106
|
+
return `${prefix}${path2}`.replace(/\/+/g, "/");
|
|
6107
|
+
};
|
|
6108
|
+
const getUrl = (key) => {
|
|
6109
|
+
const base = config.baseUrl.replace(/\/$/, "");
|
|
6110
|
+
return `${base}/${key}`;
|
|
6111
|
+
};
|
|
6112
|
+
const getUrlPrefix2 = () => {
|
|
6113
|
+
const base = config.baseUrl.replace(/\/$/, "");
|
|
6114
|
+
return base + "/";
|
|
6115
|
+
};
|
|
6116
|
+
return {
|
|
6117
|
+
name: config.type,
|
|
6118
|
+
displayName: config.type === "sftp" ? "SFTP Storage" : "FTP Storage",
|
|
6119
|
+
supportsDynamicResize: false,
|
|
6120
|
+
async upload(file, options) {
|
|
6121
|
+
const ftp = await getClient();
|
|
6122
|
+
const key = getKey(
|
|
6123
|
+
`${options?.folder ? `${options.folder}/` : ""}${options?.filename || file.name}`
|
|
6124
|
+
);
|
|
6125
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
6126
|
+
const parts = key.split("/").slice(0, -1);
|
|
6127
|
+
let currentPath = "";
|
|
6128
|
+
for (const part of parts) {
|
|
6129
|
+
currentPath = currentPath ? `${currentPath}/${part}` : part;
|
|
6130
|
+
try {
|
|
6131
|
+
await ftp.ensureDir(currentPath);
|
|
6132
|
+
} catch {
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
6135
|
+
const readable = stream.Readable.from(buffer);
|
|
6136
|
+
await ftp.uploadFrom(readable, key);
|
|
6137
|
+
return {
|
|
6138
|
+
id: Buffer.from(key).toString("base64url"),
|
|
6139
|
+
filename: options?.filename || file.name,
|
|
6140
|
+
originalName: file.name,
|
|
6141
|
+
mimeType: file.type,
|
|
6142
|
+
size: buffer.length,
|
|
6143
|
+
url: getUrl(key),
|
|
6144
|
+
thumbnailUrl: file.type.startsWith("image/") ? getUrl(key) : void 0,
|
|
6145
|
+
folder: options?.folder,
|
|
6146
|
+
provider: config.type,
|
|
6147
|
+
metadata: options?.metadata,
|
|
6148
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6149
|
+
};
|
|
6150
|
+
},
|
|
6151
|
+
async uploadFromUrl(url) {
|
|
6152
|
+
const response = await fetch(url);
|
|
6153
|
+
if (!response.ok) {
|
|
6154
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
6155
|
+
}
|
|
6156
|
+
const blob = await response.blob();
|
|
6157
|
+
const filename = url.split("/").pop() || "file";
|
|
6158
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
6159
|
+
return this.upload(file);
|
|
6160
|
+
},
|
|
6161
|
+
async delete(url) {
|
|
6162
|
+
const ftp = await getClient();
|
|
6163
|
+
const key = url.replace(getUrlPrefix2(), "");
|
|
6164
|
+
await ftp.remove(key);
|
|
6165
|
+
},
|
|
6166
|
+
async rename(oldUrl, newKey) {
|
|
6167
|
+
const ftp = await getClient();
|
|
6168
|
+
const oldKey = oldUrl.replace(getUrlPrefix2(), "");
|
|
6169
|
+
const fullPath = config.prefix ? `${config.prefix}/${newKey}` : newKey;
|
|
6170
|
+
await ftp.rename(oldKey, fullPath);
|
|
6171
|
+
return getUrl(fullPath);
|
|
6172
|
+
},
|
|
6173
|
+
getImageUrl(url, transforms) {
|
|
6174
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
6175
|
+
const params = new URLSearchParams({ url });
|
|
6176
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
6177
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
6178
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
6179
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
6180
|
+
return `/api/media/resize?${params.toString()}`;
|
|
6181
|
+
},
|
|
6182
|
+
async generateThumbnail(file) {
|
|
6183
|
+
return file.url;
|
|
6184
|
+
},
|
|
6185
|
+
async list(prefix) {
|
|
6186
|
+
const ftp = await getClient();
|
|
6187
|
+
const key = getKey(prefix || "");
|
|
6188
|
+
let items;
|
|
6189
|
+
try {
|
|
6190
|
+
items = await ftp.list(key);
|
|
6191
|
+
} catch {
|
|
6192
|
+
return [];
|
|
6193
|
+
}
|
|
6194
|
+
return items.filter((item) => item.type === 0).map((item) => ({
|
|
6195
|
+
id: Buffer.from(`${key}/${item.name}`).toString("base64url"),
|
|
6196
|
+
filename: item.name,
|
|
6197
|
+
originalName: item.name,
|
|
6198
|
+
mimeType: "application/octet-stream",
|
|
6199
|
+
size: Number(item.size) || 0,
|
|
6200
|
+
url: getUrl(`${key}/${item.name}`.replace(/\/+/g, "/")),
|
|
6201
|
+
provider: config.type,
|
|
6202
|
+
createdAt: item.modifiedAt ? item.modifiedAt.toISOString() : (/* @__PURE__ */ new Date()).toISOString()
|
|
6203
|
+
}));
|
|
6204
|
+
},
|
|
6205
|
+
async exists(url) {
|
|
6206
|
+
const ftp = await getClient();
|
|
6207
|
+
const key = url.replace(getUrlPrefix2(), "");
|
|
6208
|
+
try {
|
|
6209
|
+
await ftp.size(key);
|
|
6210
|
+
return true;
|
|
6211
|
+
} catch {
|
|
6212
|
+
return false;
|
|
6213
|
+
}
|
|
6214
|
+
}
|
|
6215
|
+
};
|
|
6216
|
+
}
|
|
6217
|
+
|
|
6218
|
+
// src/storage/index.ts
|
|
6219
|
+
async function resolveProvider(configService) {
|
|
6220
|
+
const config = configService.getStorageConfig();
|
|
6221
|
+
switch (config.type) {
|
|
6222
|
+
case "aws":
|
|
6223
|
+
return createS3Storage({
|
|
6224
|
+
provider: "aws",
|
|
6225
|
+
bucket: config.s3.bucket || "",
|
|
6226
|
+
region: config.s3.region || "us-east-1",
|
|
6227
|
+
accessKeyId: config.s3.accessKeyId || "",
|
|
6228
|
+
secretAccessKey: config.s3.secretAccessKey || "",
|
|
6229
|
+
endpoint: config.s3.endpoint,
|
|
6230
|
+
cdnUrl: config.s3.cdnUrl,
|
|
6231
|
+
prefix: config.s3.prefix
|
|
6232
|
+
});
|
|
6233
|
+
case "r2":
|
|
6234
|
+
return createS3Storage({
|
|
6235
|
+
provider: "r2",
|
|
6236
|
+
bucket: config.r2.bucket || "",
|
|
6237
|
+
region: "auto",
|
|
6238
|
+
accessKeyId: config.r2.accessKeyId || "",
|
|
6239
|
+
secretAccessKey: config.r2.secretAccessKey || "",
|
|
6240
|
+
accountId: config.r2.accountId || "",
|
|
6241
|
+
publicDevUrl: config.r2.publicDevUrl,
|
|
6242
|
+
endpoint: `https://${config.r2.accountId || ""}.r2.cloudflarestorage.com`,
|
|
6243
|
+
cdnUrl: config.r2.cdnUrl,
|
|
6244
|
+
prefix: config.r2.prefix
|
|
6245
|
+
});
|
|
6246
|
+
case "gcs":
|
|
6247
|
+
return createS3Storage({
|
|
6248
|
+
provider: "gcs",
|
|
6249
|
+
bucket: config.gcs.bucket || "",
|
|
6250
|
+
region: config.gcs.projectId || "auto",
|
|
6251
|
+
accessKeyId: config.gcs.clientEmail || "",
|
|
6252
|
+
secretAccessKey: config.gcs.privateKey || "",
|
|
6253
|
+
cdnUrl: config.gcs.cdnUrl,
|
|
6254
|
+
prefix: config.gcs.prefix
|
|
6255
|
+
});
|
|
6256
|
+
case "digitalocean":
|
|
6257
|
+
return createS3Storage({
|
|
6258
|
+
provider: "digitalocean",
|
|
6259
|
+
bucket: config.digitalocean.bucket || "",
|
|
6260
|
+
region: config.digitalocean.region || "nyc3",
|
|
6261
|
+
accessKeyId: config.digitalocean.accessKeyId || "",
|
|
6262
|
+
secretAccessKey: config.digitalocean.secretAccessKey || "",
|
|
6263
|
+
endpoint: `https://${config.digitalocean.region || "nyc3"}.digitaloceanspaces.com`,
|
|
6264
|
+
cdnUrl: config.digitalocean.cdnUrl,
|
|
6265
|
+
prefix: config.digitalocean.prefix
|
|
6266
|
+
});
|
|
6267
|
+
case "backblaze":
|
|
6268
|
+
return createS3Storage({
|
|
6269
|
+
provider: "backblaze",
|
|
6270
|
+
bucket: config.backblaze.bucket || "",
|
|
6271
|
+
region: "auto",
|
|
6272
|
+
accessKeyId: config.backblaze.applicationKeyId || "",
|
|
6273
|
+
secretAccessKey: config.backblaze.applicationKey || "",
|
|
6274
|
+
accountId: config.backblaze.accountId || "",
|
|
6275
|
+
endpoint: `https://s3.backblazeb2.com`,
|
|
6276
|
+
cdnUrl: config.backblaze.cdnUrl,
|
|
6277
|
+
prefix: config.backblaze.prefix
|
|
6278
|
+
});
|
|
6279
|
+
case "wasabi":
|
|
6280
|
+
return createS3Storage({
|
|
6281
|
+
provider: "wasabi",
|
|
6282
|
+
bucket: config.wasabi.bucket || "",
|
|
6283
|
+
region: config.wasabi.region || "us-east-1",
|
|
6284
|
+
accessKeyId: config.wasabi.accessKeyId || "",
|
|
6285
|
+
secretAccessKey: config.wasabi.secretAccessKey || "",
|
|
6286
|
+
endpoint: `https://s3.${config.wasabi.region || "us-east-1"}.wasabisys.com`,
|
|
6287
|
+
cdnUrl: config.wasabi.cdnUrl,
|
|
6288
|
+
prefix: config.wasabi.prefix
|
|
6289
|
+
});
|
|
6290
|
+
case "ftp":
|
|
6291
|
+
case "sftp":
|
|
6292
|
+
return createFtpStorage({
|
|
6293
|
+
host: config.ftp?.host || "",
|
|
6294
|
+
port: config.ftp?.port || 21,
|
|
6295
|
+
user: config.ftp?.user || "",
|
|
6296
|
+
password: config.ftp?.password || "",
|
|
6297
|
+
secure: config.ftp?.secure || false,
|
|
6298
|
+
baseUrl: config.ftp?.baseUrl || "",
|
|
6299
|
+
prefix: config.ftp?.prefix,
|
|
6300
|
+
type: "ftp"
|
|
6301
|
+
});
|
|
6302
|
+
case "cloudinary":
|
|
6303
|
+
return createCloudinaryStorage({
|
|
6304
|
+
cloudName: config.cloudinary.cloudName || "",
|
|
6305
|
+
apiKey: config.cloudinary.apiKey || "",
|
|
6306
|
+
apiSecret: config.cloudinary.apiSecret || "",
|
|
6307
|
+
folder: config.cloudinary.folder
|
|
6308
|
+
});
|
|
6309
|
+
case "imgix":
|
|
6310
|
+
return createImgixStorage({
|
|
6311
|
+
domain: config.imgix.domain || "",
|
|
6312
|
+
signKey: config.imgix.signKey
|
|
6313
|
+
});
|
|
6314
|
+
case "local":
|
|
6315
|
+
default:
|
|
6316
|
+
return createLocalStorage({
|
|
6317
|
+
uploadDir: config.local.uploadDir || path__default.default.join(process.cwd(), "public", "uploads"),
|
|
6318
|
+
baseUrl: config.local.baseUrl || "/uploads"
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
}
|
|
6322
|
+
async function resolveProviderWithConfig(config) {
|
|
6323
|
+
if (!config) {
|
|
6324
|
+
console.warn("[resolveProviderWithConfig] No config, using local");
|
|
6325
|
+
return createLocalStorage({
|
|
6326
|
+
uploadDir: path__default.default.join(process.cwd(), "public", "uploads"),
|
|
6327
|
+
baseUrl: "/uploads"
|
|
6328
|
+
});
|
|
6329
|
+
}
|
|
6330
|
+
console.log("[resolveProviderWithConfig] Creating provider:", config.type);
|
|
6331
|
+
switch (config.type) {
|
|
6332
|
+
case "aws":
|
|
6333
|
+
return createS3Storage({
|
|
6334
|
+
provider: "aws",
|
|
6335
|
+
bucket: config.s3?.bucket || "",
|
|
6336
|
+
region: config.s3?.region || "us-east-1",
|
|
6337
|
+
accessKeyId: config.s3?.accessKeyId || "",
|
|
6338
|
+
secretAccessKey: config.s3?.secretAccessKey || "",
|
|
6339
|
+
endpoint: config.s3?.endpoint,
|
|
6340
|
+
cdnUrl: config.s3?.cdnUrl,
|
|
6341
|
+
prefix: config.s3?.prefix
|
|
6342
|
+
});
|
|
6343
|
+
case "r2":
|
|
6344
|
+
return createS3Storage({
|
|
6345
|
+
provider: "r2",
|
|
6346
|
+
bucket: config.r2?.bucket || "",
|
|
6347
|
+
region: "auto",
|
|
6348
|
+
accessKeyId: config.r2?.accessKeyId || "",
|
|
6349
|
+
secretAccessKey: config.r2?.secretAccessKey || "",
|
|
6350
|
+
accountId: config.r2?.accountId || "",
|
|
6351
|
+
publicDevUrl: config.r2?.publicDevUrl,
|
|
6352
|
+
endpoint: `https://${config.r2?.accountId || ""}.r2.cloudflarestorage.com`,
|
|
6353
|
+
cdnUrl: config.r2?.cdnUrl,
|
|
6354
|
+
prefix: config.r2?.prefix
|
|
6355
|
+
});
|
|
6356
|
+
case "gcs":
|
|
6357
|
+
return createS3Storage({
|
|
6358
|
+
provider: "gcs",
|
|
6359
|
+
bucket: config.gcs?.bucket || "",
|
|
6360
|
+
region: config.gcs?.projectId || "auto",
|
|
6361
|
+
accessKeyId: config.gcs?.clientEmail || "",
|
|
6362
|
+
secretAccessKey: config.gcs?.privateKey || "",
|
|
6363
|
+
cdnUrl: config.gcs?.cdnUrl,
|
|
6364
|
+
prefix: config.gcs?.prefix
|
|
6365
|
+
});
|
|
6366
|
+
case "digitalocean":
|
|
6367
|
+
return createS3Storage({
|
|
6368
|
+
provider: "digitalocean",
|
|
6369
|
+
bucket: config.digitalocean?.bucket || "",
|
|
6370
|
+
region: config.digitalocean?.region || "nyc3",
|
|
6371
|
+
accessKeyId: config.digitalocean?.accessKeyId || "",
|
|
6372
|
+
secretAccessKey: config.digitalocean?.secretAccessKey || "",
|
|
6373
|
+
cdnUrl: config.digitalocean?.cdnUrl,
|
|
6374
|
+
prefix: config.digitalocean?.prefix
|
|
6375
|
+
});
|
|
6376
|
+
case "backblaze":
|
|
6377
|
+
return createS3Storage({
|
|
6378
|
+
provider: "backblaze",
|
|
6379
|
+
bucket: config.backblaze?.bucket || "",
|
|
6380
|
+
region: "auto",
|
|
6381
|
+
accessKeyId: config.backblaze?.applicationKeyId || "",
|
|
6382
|
+
secretAccessKey: config.backblaze?.applicationKey || "",
|
|
6383
|
+
cdnUrl: config.backblaze?.cdnUrl,
|
|
6384
|
+
prefix: config.backblaze?.prefix
|
|
6385
|
+
});
|
|
6386
|
+
case "wasabi":
|
|
6387
|
+
return createS3Storage({
|
|
6388
|
+
provider: "wasabi",
|
|
6389
|
+
bucket: config.wasabi?.bucket || "",
|
|
6390
|
+
region: config.wasabi?.region || "us-east-1",
|
|
6391
|
+
accessKeyId: config.wasabi?.accessKeyId || "",
|
|
6392
|
+
secretAccessKey: config.wasabi?.secretAccessKey || "",
|
|
6393
|
+
cdnUrl: config.wasabi?.cdnUrl,
|
|
6394
|
+
prefix: config.wasabi?.prefix
|
|
6395
|
+
});
|
|
6396
|
+
case "cloudinary":
|
|
6397
|
+
return createCloudinaryStorage({
|
|
6398
|
+
cloudName: config.cloudinary?.cloudName || "",
|
|
6399
|
+
apiKey: config.cloudinary?.apiKey || "",
|
|
6400
|
+
apiSecret: config.cloudinary?.apiSecret || "",
|
|
6401
|
+
folder: config.cloudinary?.folder
|
|
6402
|
+
});
|
|
6403
|
+
case "ftp":
|
|
6404
|
+
case "sftp": {
|
|
6405
|
+
const ftpConf = config.ftp || config;
|
|
6406
|
+
return createFtpStorage({
|
|
6407
|
+
type: "ftp",
|
|
6408
|
+
host: ftpConf.host || "",
|
|
6409
|
+
port: ftpConf.port || 21,
|
|
6410
|
+
user: ftpConf.user || "",
|
|
6411
|
+
password: ftpConf.password || "",
|
|
6412
|
+
secure: ftpConf.secure || false,
|
|
6413
|
+
baseUrl: ftpConf.baseUrl || "",
|
|
6414
|
+
prefix: ftpConf.prefix
|
|
6415
|
+
});
|
|
6416
|
+
}
|
|
6417
|
+
case "local":
|
|
6418
|
+
default: {
|
|
6419
|
+
const localConfig = config.local || {
|
|
6420
|
+
uploadDir: config["local.uploadDir"],
|
|
6421
|
+
baseUrl: config["local.baseUrl"]
|
|
6422
|
+
};
|
|
6423
|
+
const savedUploadDir = (localConfig?.uploadDir || "").trim();
|
|
6424
|
+
let uploadDir;
|
|
6425
|
+
if (savedUploadDir) {
|
|
6426
|
+
if (path__default.default.isAbsolute(savedUploadDir)) {
|
|
6427
|
+
uploadDir = savedUploadDir;
|
|
6428
|
+
} else if (savedUploadDir.includes("/") || savedUploadDir.includes("\\")) {
|
|
6429
|
+
uploadDir = path__default.default.resolve(process.cwd(), savedUploadDir);
|
|
6430
|
+
} else {
|
|
6431
|
+
uploadDir = path__default.default.join(process.cwd(), "public", savedUploadDir);
|
|
6432
|
+
}
|
|
6433
|
+
} else {
|
|
6434
|
+
uploadDir = path__default.default.join(process.cwd(), "public", "uploads");
|
|
6435
|
+
}
|
|
6436
|
+
const savedBaseUrl = (localConfig?.baseUrl || "").trim();
|
|
6437
|
+
let baseUrl;
|
|
6438
|
+
if (savedBaseUrl) {
|
|
6439
|
+
baseUrl = savedBaseUrl.startsWith("/") ? savedBaseUrl : `/${savedBaseUrl}`;
|
|
6440
|
+
} else {
|
|
6441
|
+
baseUrl = "/uploads";
|
|
6442
|
+
}
|
|
6443
|
+
return createLocalStorage({ uploadDir, baseUrl });
|
|
6444
|
+
}
|
|
6445
|
+
}
|
|
6446
|
+
}
|
|
6447
|
+
async function processImage(buffer) {
|
|
6448
|
+
const metadata = await sharp__default.default(buffer).metadata();
|
|
6449
|
+
const mainImage = sharp__default.default(buffer).webp({ quality: 85 });
|
|
6450
|
+
const thumbnail = sharp__default.default(buffer).resize({ width: 500, withoutEnlargement: true }).webp({ quality: 80 });
|
|
6451
|
+
return {
|
|
6452
|
+
buffer: await mainImage.toBuffer(),
|
|
6453
|
+
thumbnailBuffer: await thumbnail.toBuffer(),
|
|
6454
|
+
width: metadata.width,
|
|
6455
|
+
height: metadata.height,
|
|
6456
|
+
format: "webp"
|
|
6457
|
+
};
|
|
6458
|
+
}
|
|
6459
|
+
|
|
6460
|
+
// src/storage/MediaService.ts
|
|
6461
|
+
var MediaService = class _MediaService {
|
|
6462
|
+
db;
|
|
6463
|
+
storage;
|
|
6464
|
+
dialect;
|
|
6465
|
+
genId;
|
|
6466
|
+
mediaTable = "media";
|
|
6467
|
+
foldersTable = "media_folders";
|
|
6468
|
+
constructor(db, storage, options) {
|
|
6469
|
+
this.db = db;
|
|
6470
|
+
this.storage = storage;
|
|
6471
|
+
this.dialect = options?.dialect || "sqlite";
|
|
6472
|
+
this.genId = options?.genId || chunkGVFB5C6O_cjs.genId;
|
|
6473
|
+
}
|
|
6474
|
+
static async init(db, options) {
|
|
6475
|
+
let storage;
|
|
6476
|
+
if (options?.storageConfig) {
|
|
6477
|
+
console.log(
|
|
6478
|
+
"[MediaService.init] Using provided storageConfig:",
|
|
6479
|
+
options.storageConfig.type
|
|
6480
|
+
);
|
|
6481
|
+
storage = await resolveProviderWithConfig(options.storageConfig);
|
|
6482
|
+
} else {
|
|
6483
|
+
const configService = new chunkHVSQDZZJ_cjs.ConfigService(db);
|
|
6484
|
+
await configService.load();
|
|
6485
|
+
storage = await resolveProvider(configService);
|
|
6486
|
+
}
|
|
6487
|
+
return new _MediaService(db, storage, options);
|
|
6488
|
+
}
|
|
6489
|
+
now() {
|
|
6490
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
6491
|
+
}
|
|
6492
|
+
buildFindConditions(params) {
|
|
6493
|
+
const conditions = [];
|
|
6494
|
+
const p = [];
|
|
6495
|
+
const sortCol = params.sortBy === "name" ? "title" : params.sortBy || "created_at";
|
|
6496
|
+
const sortDir = params.sortDir === "asc" ? "ASC" : "DESC";
|
|
6497
|
+
if (params.search) {
|
|
6498
|
+
conditions.push(
|
|
6499
|
+
`(title LIKE ? OR filename LIKE ? OR original_name LIKE ? OR alt LIKE ?)`
|
|
6500
|
+
);
|
|
6501
|
+
const s = `%${params.search}%`;
|
|
6502
|
+
p.push(s, s, s, s);
|
|
6503
|
+
}
|
|
6504
|
+
if (params.type && params.type !== "all") {
|
|
6505
|
+
conditions.push(`mime_type LIKE ?`);
|
|
6506
|
+
p.push(`${params.type}/%`);
|
|
6507
|
+
}
|
|
6508
|
+
if (params.folder) {
|
|
6509
|
+
conditions.push(`(folder = ? OR folder LIKE ?)`);
|
|
6510
|
+
p.push(params.folder, `${params.folder}/%`);
|
|
6511
|
+
}
|
|
6512
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
6513
|
+
return { where, params: p, orderBy: sortDir, sortCol };
|
|
6514
|
+
}
|
|
6515
|
+
rowToMedia(row) {
|
|
6516
|
+
return {
|
|
6517
|
+
id: row.id,
|
|
6518
|
+
filename: row.filename,
|
|
6519
|
+
title: row.title ?? null,
|
|
6520
|
+
originalName: row.original_name ?? row.originalName,
|
|
6521
|
+
mimeType: row.mime_type ?? row.mimeType,
|
|
6522
|
+
fileSize: row.file_size ?? row.fileSize,
|
|
6523
|
+
width: row.width ?? null,
|
|
6524
|
+
height: row.height ?? null,
|
|
6525
|
+
url: row.url,
|
|
6526
|
+
thumbnailUrl: row.thumbnail_url ?? row.thumbnailUrl ?? null,
|
|
6527
|
+
folder: row.folder ?? null,
|
|
6528
|
+
provider: row.provider,
|
|
6529
|
+
alt: row.alt ?? null,
|
|
6530
|
+
caption: row.caption ?? null,
|
|
6531
|
+
metadata: row.metadata ?? null,
|
|
6532
|
+
createdAt: row.created_at ?? row.createdAt,
|
|
6533
|
+
updatedAt: row.updated_at ?? row.updatedAt
|
|
6534
|
+
};
|
|
6535
|
+
}
|
|
6536
|
+
async sqliteRun(sql, params = []) {
|
|
6537
|
+
const stmt = this.db.prepare(sql);
|
|
6538
|
+
const sqlLower = sql.trim().toLowerCase();
|
|
6539
|
+
if (sqlLower.startsWith("insert") || sqlLower.startsWith("update") || sqlLower.startsWith("delete")) {
|
|
6540
|
+
return stmt.run(...params);
|
|
6541
|
+
}
|
|
6542
|
+
return stmt.all(...params);
|
|
6543
|
+
}
|
|
6544
|
+
sqliteGet(sql, params = []) {
|
|
6545
|
+
const stmt = this.db.prepare(sql);
|
|
6546
|
+
return stmt.get(...params);
|
|
6547
|
+
}
|
|
6548
|
+
async upload(file, folder = "") {
|
|
6549
|
+
const isImage = file.type.startsWith("image/");
|
|
6550
|
+
let processed;
|
|
6551
|
+
let uploadFile = file;
|
|
6552
|
+
let filename = file.name;
|
|
6553
|
+
let width = null;
|
|
6554
|
+
let height = null;
|
|
6555
|
+
if (isImage && !file.type.includes("svg")) {
|
|
6556
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
6557
|
+
processed = await processImage(buffer);
|
|
6558
|
+
const originalName = file.name.replace(/\.[^/.]+$/, "");
|
|
6559
|
+
const safeName = originalName.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").substring(0, 50);
|
|
6560
|
+
filename = `${safeName}.webp`;
|
|
6561
|
+
width = processed.width ?? null;
|
|
6562
|
+
height = processed.height ?? null;
|
|
6563
|
+
uploadFile = new File([processed.buffer], filename, {
|
|
6564
|
+
type: "image/webp"
|
|
6565
|
+
});
|
|
6566
|
+
}
|
|
6567
|
+
const storageResult = await this.storage.upload(uploadFile, {
|
|
6568
|
+
folder,
|
|
6569
|
+
filename
|
|
6570
|
+
});
|
|
6571
|
+
const thumbnailUrl = await this.storage.generateThumbnail(
|
|
6572
|
+
{
|
|
6573
|
+
...storageResult,
|
|
6574
|
+
id: "",
|
|
6575
|
+
provider: this.storage.name,
|
|
6576
|
+
createdAt: this.now()
|
|
6577
|
+
},
|
|
6578
|
+
{ width: 400, height: 400 }
|
|
6579
|
+
);
|
|
6580
|
+
const id = this.genId();
|
|
6581
|
+
const now = this.now();
|
|
6582
|
+
if (this.dialect === "sqlite") {
|
|
6583
|
+
await this.sqliteRun(
|
|
6584
|
+
`INSERT INTO ${this.mediaTable}
|
|
6585
|
+
(id, filename, title, original_name, mime_type, file_size, width, height, url, thumbnail_url, folder, provider, alt, caption, metadata, created_at, updated_at)
|
|
6586
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6587
|
+
[
|
|
6588
|
+
id,
|
|
6589
|
+
storageResult.filename,
|
|
6590
|
+
file.name.replace(/\.[^/.]+$/, ""),
|
|
6591
|
+
file.name,
|
|
6592
|
+
storageResult.mimeType,
|
|
6593
|
+
storageResult.size,
|
|
6594
|
+
width,
|
|
6595
|
+
height,
|
|
6596
|
+
storageResult.url,
|
|
6597
|
+
thumbnailUrl,
|
|
6598
|
+
folder || null,
|
|
6599
|
+
this.storage.name,
|
|
6600
|
+
null,
|
|
6601
|
+
null,
|
|
6602
|
+
null,
|
|
6603
|
+
now,
|
|
6604
|
+
now
|
|
6605
|
+
]
|
|
6606
|
+
);
|
|
6607
|
+
} else {
|
|
6608
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6609
|
+
await this.db.insert(mediaSchema).values({
|
|
6610
|
+
id,
|
|
6611
|
+
filename: storageResult.filename,
|
|
6612
|
+
title: file.name.replace(/\.[^/.]+$/, ""),
|
|
6613
|
+
originalName: file.name,
|
|
6614
|
+
mimeType: storageResult.mimeType,
|
|
6615
|
+
fileSize: storageResult.size,
|
|
6616
|
+
width,
|
|
6617
|
+
height,
|
|
6618
|
+
url: storageResult.url,
|
|
6619
|
+
thumbnailUrl,
|
|
6620
|
+
folder: folder || "",
|
|
6621
|
+
provider: this.storage.name,
|
|
6622
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6623
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
6624
|
+
}).returning();
|
|
6625
|
+
}
|
|
6626
|
+
return {
|
|
6627
|
+
id,
|
|
6628
|
+
filename: storageResult.filename,
|
|
6629
|
+
title: file.name.replace(/\.[^/.]+$/, ""),
|
|
6630
|
+
originalName: file.name,
|
|
6631
|
+
mimeType: storageResult.mimeType,
|
|
6632
|
+
fileSize: storageResult.size,
|
|
6633
|
+
width,
|
|
6634
|
+
height,
|
|
6635
|
+
url: storageResult.url,
|
|
6636
|
+
thumbnailUrl,
|
|
6637
|
+
folder: folder || null,
|
|
6638
|
+
provider: this.storage.name,
|
|
6639
|
+
alt: null,
|
|
6640
|
+
caption: null,
|
|
6641
|
+
metadata: null,
|
|
6642
|
+
createdAt: now,
|
|
6643
|
+
updatedAt: now
|
|
6644
|
+
};
|
|
6645
|
+
}
|
|
6646
|
+
async delete(id) {
|
|
6647
|
+
let item = null;
|
|
6648
|
+
if (this.dialect === "sqlite") {
|
|
6649
|
+
item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
|
|
6650
|
+
id
|
|
6651
|
+
]);
|
|
6652
|
+
} else {
|
|
6653
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6654
|
+
const [row] = await this.db.select().from(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6655
|
+
if (row) item = this.rowToMedia(row);
|
|
6656
|
+
}
|
|
6657
|
+
if (!item) return;
|
|
6658
|
+
await this.deleteFile(item.url);
|
|
6659
|
+
if (item.thumbnailUrl && item.thumbnailUrl !== item.url && item.thumbnailUrl !== item.url + "?thumb") {
|
|
6660
|
+
try {
|
|
6661
|
+
await this.deleteFile(item.thumbnailUrl);
|
|
6662
|
+
} catch {
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6665
|
+
if (this.dialect === "sqlite") {
|
|
6666
|
+
await this.sqliteRun(`DELETE FROM ${this.mediaTable} WHERE id = ?`, [id]);
|
|
6667
|
+
} else {
|
|
6668
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6669
|
+
await this.db.delete(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
async deleteFile(url) {
|
|
6673
|
+
await this.storage.delete(url);
|
|
6674
|
+
}
|
|
6675
|
+
async rename(id, newKey) {
|
|
6676
|
+
let item = null;
|
|
6677
|
+
if (this.dialect === "sqlite") {
|
|
6678
|
+
item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
|
|
6679
|
+
id
|
|
6680
|
+
]);
|
|
6681
|
+
} else {
|
|
6682
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6683
|
+
const [row] = await this.db.select().from(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6684
|
+
if (row) item = this.rowToMedia(row);
|
|
6685
|
+
}
|
|
6686
|
+
if (!item) return null;
|
|
6687
|
+
const newUrl = await this.storage.rename(item.url, newKey);
|
|
6688
|
+
let newThumbnailUrl;
|
|
6689
|
+
if (item.thumbnailUrl || this.storage.name === "cloudinary") {
|
|
6690
|
+
const versionMatch = newUrl.match(/\/upload\/(v\d+)\//);
|
|
6691
|
+
const version = versionMatch ? versionMatch[1] + "/" : "";
|
|
6692
|
+
const baseUrlMatch = newUrl.match(/(.+?)\/upload\//);
|
|
6693
|
+
const baseUrl = baseUrlMatch ? baseUrlMatch[1] : "https://res.cloudinary.com/" + this.storage.config?.cloudName || "unknown";
|
|
6694
|
+
newThumbnailUrl = `${baseUrl}/upload/w_200,h_200,c_fill/${version}${newKey}`;
|
|
6695
|
+
}
|
|
6696
|
+
const ext = item.filename.split(".").pop();
|
|
6697
|
+
const newFilename = newKey.includes(".") ? newKey : `${newKey}.${ext}`;
|
|
6698
|
+
const updateData = {
|
|
6699
|
+
url: newUrl,
|
|
6700
|
+
filename: newFilename,
|
|
6701
|
+
thumbnailUrl: newThumbnailUrl
|
|
6702
|
+
};
|
|
6703
|
+
if (this.dialect === "sqlite") {
|
|
6704
|
+
const sqliteUpdateData = { ...updateData };
|
|
6705
|
+
if ("thumbnailUrl" in sqliteUpdateData) {
|
|
6706
|
+
sqliteUpdateData.thumbnail_url = sqliteUpdateData.thumbnailUrl;
|
|
6707
|
+
delete sqliteUpdateData.thumbnailUrl;
|
|
6708
|
+
}
|
|
6709
|
+
const sets = Object.keys(sqliteUpdateData).map((k) => `${k} = ?`).join(", ");
|
|
6710
|
+
const vals = Object.values(sqliteUpdateData);
|
|
6711
|
+
await this.sqliteRun(
|
|
6712
|
+
`UPDATE ${this.mediaTable} SET ${sets}, updated_at = ? WHERE id = ?`,
|
|
6713
|
+
[...vals, this.now(), id]
|
|
6714
|
+
);
|
|
6715
|
+
} else {
|
|
6716
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6717
|
+
await this.db.update(mediaSchema).set({ ...updateData, updatedAt: this.now() }).where(mediaSchema.id.equals(id));
|
|
6718
|
+
}
|
|
6719
|
+
return {
|
|
6720
|
+
...item,
|
|
6721
|
+
...updateData,
|
|
6722
|
+
updatedAt: this.now(),
|
|
6723
|
+
thumbnailUrl: updateData.thumbnailUrl ?? null
|
|
6724
|
+
};
|
|
6725
|
+
}
|
|
6726
|
+
async find(params = {}) {
|
|
6727
|
+
const {
|
|
6728
|
+
page = 1,
|
|
6729
|
+
limit = 30,
|
|
6730
|
+
search = "",
|
|
6731
|
+
type = "",
|
|
6732
|
+
folder = "",
|
|
6733
|
+
sortBy = "createdAt",
|
|
6734
|
+
sortDir = "desc"
|
|
6735
|
+
} = params;
|
|
6736
|
+
const {
|
|
6737
|
+
where,
|
|
6738
|
+
params: p,
|
|
6739
|
+
orderBy,
|
|
6740
|
+
sortCol
|
|
6741
|
+
} = this.buildFindConditions({
|
|
6742
|
+
page,
|
|
6743
|
+
limit,
|
|
6744
|
+
search,
|
|
6745
|
+
type,
|
|
6746
|
+
folder,
|
|
6747
|
+
sortBy,
|
|
6748
|
+
sortDir
|
|
6749
|
+
});
|
|
6750
|
+
const offset = (page - 1) * limit;
|
|
6751
|
+
if (this.dialect === "sqlite") {
|
|
6752
|
+
const countRow = this.sqliteGet(
|
|
6753
|
+
`SELECT COUNT(*) as cnt FROM ${this.mediaTable} ${where}`,
|
|
6754
|
+
p
|
|
6755
|
+
);
|
|
6756
|
+
const totalDocs2 = countRow?.cnt ?? 0;
|
|
6757
|
+
const rows = await this.sqliteRun(
|
|
6758
|
+
`SELECT * FROM ${this.mediaTable} ${where} ORDER BY ${sortCol} ${orderBy} LIMIT ? OFFSET ?`,
|
|
6759
|
+
[...p, limit, offset]
|
|
6760
|
+
);
|
|
6761
|
+
return {
|
|
6762
|
+
docs: rows.map((r) => this.rowToMedia(r)),
|
|
6763
|
+
totalDocs: totalDocs2,
|
|
6764
|
+
page,
|
|
6765
|
+
limit,
|
|
6766
|
+
totalPages: Math.ceil(totalDocs2 / limit)
|
|
6767
|
+
};
|
|
6768
|
+
}
|
|
6769
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6770
|
+
const { like, or, and, asc, desc, eq, sql } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6771
|
+
const conditions = [];
|
|
6772
|
+
if (search) {
|
|
6773
|
+
conditions.push(
|
|
6774
|
+
or(
|
|
6775
|
+
like(mediaSchema.title, `%${search}%`),
|
|
6776
|
+
like(mediaSchema.filename, `%${search}%`),
|
|
6777
|
+
like(mediaSchema.originalName, `%${search}%`),
|
|
6778
|
+
like(mediaSchema.alt, `%${search}%`)
|
|
6779
|
+
)
|
|
6780
|
+
);
|
|
6781
|
+
}
|
|
6782
|
+
if (type && type !== "all") {
|
|
6783
|
+
conditions.push(like(mediaSchema.mimeType, `${type}/%`));
|
|
6784
|
+
}
|
|
6785
|
+
if (folder) {
|
|
6786
|
+
conditions.push(
|
|
6787
|
+
or(
|
|
6788
|
+
eq(mediaSchema.folder, folder),
|
|
6789
|
+
like(mediaSchema.folder, `${folder}/%`)
|
|
6790
|
+
)
|
|
6791
|
+
);
|
|
6792
|
+
}
|
|
6793
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : void 0;
|
|
6794
|
+
const order = sortDir === "asc" ? asc(mediaSchema[sortCol]) : desc(mediaSchema[sortCol]);
|
|
6795
|
+
const docs = await this.db.select().from(mediaSchema).where(whereClause).orderBy(order).limit(limit).offset(offset);
|
|
6796
|
+
const [{ count }] = await this.db.select({ count: sql`count(*)` }).from(mediaSchema).where(whereClause);
|
|
6797
|
+
const totalDocs = Number(count);
|
|
6798
|
+
return {
|
|
6799
|
+
docs: docs.map((r) => this.rowToMedia(r)),
|
|
6800
|
+
totalDocs,
|
|
6801
|
+
page,
|
|
6802
|
+
limit,
|
|
6803
|
+
totalPages: Math.ceil(totalDocs / limit)
|
|
6804
|
+
};
|
|
6805
|
+
}
|
|
6806
|
+
async update(id, data) {
|
|
6807
|
+
const now = this.now();
|
|
6808
|
+
if (this.dialect === "sqlite") {
|
|
6809
|
+
const sets = ["updated_at = ?"];
|
|
6810
|
+
const p = [now];
|
|
6811
|
+
if (data.title !== void 0) {
|
|
6812
|
+
sets.push("title = ?");
|
|
6813
|
+
p.push(data.title);
|
|
6814
|
+
}
|
|
6815
|
+
if (data.alt !== void 0) {
|
|
6816
|
+
sets.push("alt = ?");
|
|
6817
|
+
p.push(data.alt);
|
|
6818
|
+
}
|
|
6819
|
+
if (data.caption !== void 0) {
|
|
6820
|
+
sets.push("caption = ?");
|
|
6821
|
+
p.push(data.caption);
|
|
6822
|
+
}
|
|
6823
|
+
if (data.folder !== void 0) {
|
|
6824
|
+
sets.push("folder = ?");
|
|
6825
|
+
p.push(data.folder || null);
|
|
6826
|
+
}
|
|
6827
|
+
p.push(id);
|
|
6828
|
+
await this.sqliteRun(
|
|
6829
|
+
`UPDATE ${this.mediaTable} SET ${sets.join(", ")} WHERE id = ?`,
|
|
6830
|
+
p
|
|
6831
|
+
);
|
|
6832
|
+
const row = this.sqliteGet(
|
|
6833
|
+
`SELECT * FROM ${this.mediaTable} WHERE id = ?`,
|
|
6834
|
+
[id]
|
|
6835
|
+
);
|
|
6836
|
+
return row ? this.rowToMedia(row) : null;
|
|
6837
|
+
}
|
|
6838
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6839
|
+
const [updated] = await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(mediaSchema.id.equals(id)).returning();
|
|
6840
|
+
return updated ? this.rowToMedia(updated) : null;
|
|
6841
|
+
}
|
|
6842
|
+
async updateMany(ids, data) {
|
|
6843
|
+
const now = this.now();
|
|
6844
|
+
if (this.dialect === "sqlite") {
|
|
6845
|
+
for (const id of ids) {
|
|
6846
|
+
const sets = ["updated_at = ?"];
|
|
6847
|
+
const p = [now];
|
|
6848
|
+
if (data.folder !== void 0) {
|
|
6849
|
+
sets.push("folder = ?");
|
|
6850
|
+
p.push(data.folder || null);
|
|
6851
|
+
}
|
|
6852
|
+
p.push(id);
|
|
6853
|
+
await this.sqliteRun(
|
|
6854
|
+
`UPDATE ${this.mediaTable} SET ${sets.join(", ")} WHERE id = ?`,
|
|
6855
|
+
p
|
|
6856
|
+
);
|
|
6857
|
+
}
|
|
6858
|
+
} else {
|
|
6859
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6860
|
+
for (const id of ids) {
|
|
6861
|
+
await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(mediaSchema.id.equals(id));
|
|
6862
|
+
}
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6865
|
+
async listFolders() {
|
|
6866
|
+
if (this.dialect === "sqlite") {
|
|
6867
|
+
const rows = await this.sqliteRun(
|
|
6868
|
+
`SELECT path FROM ${this.foldersTable} UNION
|
|
6869
|
+
SELECT folder as path FROM ${this.mediaTable} WHERE folder IS NOT NULL AND folder != ''`
|
|
6870
|
+
);
|
|
6871
|
+
return rows.map((r) => r.path).filter((f) => f && f !== "").sort();
|
|
6872
|
+
}
|
|
6873
|
+
const { media: mediaSchema, mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6874
|
+
const { eq, sql } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6875
|
+
const fromMedia = await this.db.select({ folder: mediaSchema.folder }).from(mediaSchema).groupBy(mediaSchema.folder);
|
|
6876
|
+
const fromFolders = await this.db.select({ path: folderSchema.path }).from(folderSchema);
|
|
6877
|
+
const allPaths = /* @__PURE__ */ new Set([
|
|
6878
|
+
...fromMedia.map((r) => r.folder),
|
|
6879
|
+
...fromFolders.map((r) => r.path)
|
|
6880
|
+
]);
|
|
6881
|
+
return Array.from(allPaths).filter((f) => f && f !== "").sort();
|
|
6882
|
+
}
|
|
6883
|
+
async createFolder(name, parentPath = "") {
|
|
6884
|
+
const fullPath = parentPath ? `${parentPath}/${name}` : name;
|
|
6885
|
+
if (this.storage.name === "local") {
|
|
6886
|
+
const { mkdir: mkdir2 } = await import('fs/promises');
|
|
6887
|
+
const { join: join2 } = await import('path');
|
|
6888
|
+
await mkdir2(join2(process.cwd(), "public", "uploads", fullPath), {
|
|
6889
|
+
recursive: true
|
|
6890
|
+
});
|
|
6891
|
+
}
|
|
6892
|
+
const now = this.now();
|
|
6893
|
+
if (this.dialect === "sqlite") {
|
|
6894
|
+
await this.sqliteRun(
|
|
6895
|
+
`INSERT OR IGNORE INTO ${this.foldersTable} (path, name, parent_path, created_at) VALUES (?, ?, ?, ?)`,
|
|
6896
|
+
[fullPath, name, parentPath || null, now]
|
|
6897
|
+
);
|
|
6898
|
+
} else {
|
|
6899
|
+
const { mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6900
|
+
await this.db.insert(folderSchema).values({
|
|
6901
|
+
path: fullPath,
|
|
6902
|
+
name,
|
|
6903
|
+
parentPath: parentPath || null,
|
|
6904
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
6905
|
+
}).onConflictDoNothing();
|
|
6906
|
+
}
|
|
6907
|
+
}
|
|
6908
|
+
async deleteFolder(folder) {
|
|
6909
|
+
const result = await this.find({ folder, limit: 1e4 });
|
|
6910
|
+
for (const item of result.docs) {
|
|
6911
|
+
await this.delete(item.id);
|
|
6912
|
+
}
|
|
6913
|
+
if (this.dialect === "sqlite") {
|
|
6914
|
+
await this.sqliteRun(
|
|
6915
|
+
`DELETE FROM ${this.foldersTable} WHERE path = ? OR path LIKE ?`,
|
|
6916
|
+
[folder, `${folder}/%`]
|
|
6917
|
+
);
|
|
6918
|
+
} else {
|
|
6919
|
+
const { mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6920
|
+
const { like, or, eq } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6921
|
+
await this.db.delete(folderSchema).where(
|
|
6922
|
+
or(
|
|
6923
|
+
eq(folderSchema.path, folder),
|
|
6924
|
+
like(folderSchema.path, `${folder}/%`)
|
|
6925
|
+
)
|
|
6926
|
+
);
|
|
6927
|
+
}
|
|
6928
|
+
if (this.storage.name === "local") {
|
|
6929
|
+
const { rm } = await import('fs/promises');
|
|
6930
|
+
const { join: join2 } = await import('path');
|
|
6931
|
+
try {
|
|
6932
|
+
await rm(join2(process.cwd(), "public", "uploads", folder), {
|
|
6933
|
+
recursive: true,
|
|
6934
|
+
force: true
|
|
6935
|
+
});
|
|
6936
|
+
} catch {
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
};
|
|
6941
|
+
|
|
6942
|
+
// src/registry/config.ts
|
|
6943
|
+
function normalizeCollections(collections) {
|
|
6944
|
+
if (!collections) return [];
|
|
6945
|
+
if (Array.isArray(collections)) return collections;
|
|
6946
|
+
return Object.values(collections);
|
|
6947
|
+
}
|
|
6948
|
+
function normalizeGlobals(globals) {
|
|
6949
|
+
if (!globals) return [];
|
|
6950
|
+
if (Array.isArray(globals)) return globals;
|
|
6951
|
+
return Object.values(globals);
|
|
6952
|
+
}
|
|
6953
|
+
function defineConfig(config) {
|
|
6954
|
+
return {
|
|
4053
6955
|
collections: normalizeCollections(config.collections),
|
|
4054
6956
|
globals: normalizeGlobals(config.globals),
|
|
4055
6957
|
adapter: config.adapter,
|
|
@@ -4068,139 +6970,195 @@ function defineConfig(config) {
|
|
|
4068
6970
|
|
|
4069
6971
|
Object.defineProperty(exports, "allSettingsGlobals", {
|
|
4070
6972
|
enumerable: true,
|
|
4071
|
-
get: function () { return
|
|
6973
|
+
get: function () { return chunkKDVDIZ4Y_cjs.allSettingsGlobals; }
|
|
4072
6974
|
});
|
|
4073
6975
|
Object.defineProperty(exports, "blogCollections", {
|
|
4074
6976
|
enumerable: true,
|
|
4075
|
-
get: function () { return
|
|
6977
|
+
get: function () { return chunkKDVDIZ4Y_cjs.blogCollections; }
|
|
4076
6978
|
});
|
|
4077
6979
|
Object.defineProperty(exports, "blogGlobals", {
|
|
4078
6980
|
enumerable: true,
|
|
4079
|
-
get: function () { return
|
|
6981
|
+
get: function () { return chunkKDVDIZ4Y_cjs.blogGlobals; }
|
|
4080
6982
|
});
|
|
4081
6983
|
Object.defineProperty(exports, "coreSettingsGlobals", {
|
|
4082
6984
|
enumerable: true,
|
|
4083
|
-
get: function () { return
|
|
6985
|
+
get: function () { return chunkKDVDIZ4Y_cjs.coreSettingsGlobals; }
|
|
4084
6986
|
});
|
|
4085
6987
|
Object.defineProperty(exports, "createTemplateConfig", {
|
|
4086
6988
|
enumerable: true,
|
|
4087
|
-
get: function () { return
|
|
6989
|
+
get: function () { return chunkKDVDIZ4Y_cjs.createTemplateConfig; }
|
|
4088
6990
|
});
|
|
4089
6991
|
Object.defineProperty(exports, "ecommerceCollections", {
|
|
4090
6992
|
enumerable: true,
|
|
4091
|
-
get: function () { return
|
|
6993
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceCollections; }
|
|
4092
6994
|
});
|
|
4093
6995
|
Object.defineProperty(exports, "ecommerceGlobals", {
|
|
4094
6996
|
enumerable: true,
|
|
4095
|
-
get: function () { return
|
|
6997
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceGlobals; }
|
|
4096
6998
|
});
|
|
4097
6999
|
Object.defineProperty(exports, "ecommerceSettingsGlobals", {
|
|
4098
7000
|
enumerable: true,
|
|
4099
|
-
get: function () { return
|
|
7001
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceSettingsGlobals; }
|
|
4100
7002
|
});
|
|
4101
7003
|
Object.defineProperty(exports, "kitchenSinkCollections", {
|
|
4102
7004
|
enumerable: true,
|
|
4103
|
-
get: function () { return
|
|
7005
|
+
get: function () { return chunkKDVDIZ4Y_cjs.kitchenSinkCollections; }
|
|
4104
7006
|
});
|
|
4105
7007
|
Object.defineProperty(exports, "mediaCollections", {
|
|
4106
7008
|
enumerable: true,
|
|
4107
|
-
get: function () { return
|
|
7009
|
+
get: function () { return chunkKDVDIZ4Y_cjs.mediaCollections; }
|
|
4108
7010
|
});
|
|
4109
7011
|
Object.defineProperty(exports, "minimalCollections", {
|
|
4110
7012
|
enumerable: true,
|
|
4111
|
-
get: function () { return
|
|
7013
|
+
get: function () { return chunkKDVDIZ4Y_cjs.minimalCollections; }
|
|
4112
7014
|
});
|
|
4113
7015
|
Object.defineProperty(exports, "RedisAuthAdapter", {
|
|
4114
7016
|
enumerable: true,
|
|
4115
|
-
get: function () { return
|
|
4116
|
-
});
|
|
4117
|
-
Object.defineProperty(exports, "EmailTransport", {
|
|
4118
|
-
enumerable: true,
|
|
4119
|
-
get: function () { return chunkMHS6CPO5_cjs.EmailTransport; }
|
|
7017
|
+
get: function () { return chunkBLMFBDBG_cjs.RedisAuthAdapter; }
|
|
4120
7018
|
});
|
|
4121
7019
|
Object.defineProperty(exports, "PasswordPolicy", {
|
|
4122
7020
|
enumerable: true,
|
|
4123
|
-
get: function () { return
|
|
7021
|
+
get: function () { return chunk4M5PHMUE_cjs.PasswordPolicy; }
|
|
4124
7022
|
});
|
|
4125
7023
|
Object.defineProperty(exports, "SQLiteAuthAdapter", {
|
|
4126
7024
|
enumerable: true,
|
|
4127
|
-
get: function () { return
|
|
7025
|
+
get: function () { return chunk4M5PHMUE_cjs.SQLiteAuthAdapter; }
|
|
4128
7026
|
});
|
|
4129
7027
|
Object.defineProperty(exports, "autoBootstrap", {
|
|
4130
7028
|
enumerable: true,
|
|
4131
|
-
get: function () { return
|
|
7029
|
+
get: function () { return chunk4M5PHMUE_cjs.autoBootstrap; }
|
|
4132
7030
|
});
|
|
4133
7031
|
Object.defineProperty(exports, "bootstrapAdmin", {
|
|
4134
7032
|
enumerable: true,
|
|
4135
|
-
get: function () { return
|
|
7033
|
+
get: function () { return chunk4M5PHMUE_cjs.bootstrapAdmin; }
|
|
4136
7034
|
});
|
|
4137
7035
|
Object.defineProperty(exports, "getBootstrapFromEnv", {
|
|
4138
7036
|
enumerable: true,
|
|
4139
|
-
get: function () { return
|
|
7037
|
+
get: function () { return chunk4M5PHMUE_cjs.getBootstrapFromEnv; }
|
|
4140
7038
|
});
|
|
4141
7039
|
Object.defineProperty(exports, "createContext", {
|
|
4142
7040
|
enumerable: true,
|
|
4143
|
-
get: function () { return
|
|
7041
|
+
get: function () { return chunk42JPONZU_cjs.createContext; }
|
|
4144
7042
|
});
|
|
4145
7043
|
Object.defineProperty(exports, "createCountProcedure", {
|
|
4146
7044
|
enumerable: true,
|
|
4147
|
-
get: function () { return
|
|
7045
|
+
get: function () { return chunk42JPONZU_cjs.createCountProcedure; }
|
|
4148
7046
|
});
|
|
4149
7047
|
Object.defineProperty(exports, "createCreateProcedure", {
|
|
4150
7048
|
enumerable: true,
|
|
4151
|
-
get: function () { return
|
|
7049
|
+
get: function () { return chunk42JPONZU_cjs.createCreateProcedure; }
|
|
4152
7050
|
});
|
|
4153
7051
|
Object.defineProperty(exports, "createDeleteProcedure", {
|
|
4154
7052
|
enumerable: true,
|
|
4155
|
-
get: function () { return
|
|
7053
|
+
get: function () { return chunk42JPONZU_cjs.createDeleteProcedure; }
|
|
4156
7054
|
});
|
|
4157
7055
|
Object.defineProperty(exports, "createDynamicRouter", {
|
|
4158
7056
|
enumerable: true,
|
|
4159
|
-
get: function () { return
|
|
7057
|
+
get: function () { return chunk42JPONZU_cjs.createDynamicRouter; }
|
|
4160
7058
|
});
|
|
4161
7059
|
Object.defineProperty(exports, "createFindByIDProcedure", {
|
|
4162
7060
|
enumerable: true,
|
|
4163
|
-
get: function () { return
|
|
7061
|
+
get: function () { return chunk42JPONZU_cjs.createFindByIDProcedure; }
|
|
4164
7062
|
});
|
|
4165
7063
|
Object.defineProperty(exports, "createFindProcedure", {
|
|
4166
7064
|
enumerable: true,
|
|
4167
|
-
get: function () { return
|
|
7065
|
+
get: function () { return chunk42JPONZU_cjs.createFindProcedure; }
|
|
4168
7066
|
});
|
|
4169
7067
|
Object.defineProperty(exports, "createKyroServer", {
|
|
4170
7068
|
enumerable: true,
|
|
4171
|
-
get: function () { return
|
|
7069
|
+
get: function () { return chunk42JPONZU_cjs.createKyroServer; }
|
|
4172
7070
|
});
|
|
4173
7071
|
Object.defineProperty(exports, "createUpdateProcedure", {
|
|
4174
7072
|
enumerable: true,
|
|
4175
|
-
get: function () { return
|
|
7073
|
+
get: function () { return chunk42JPONZU_cjs.createUpdateProcedure; }
|
|
4176
7074
|
});
|
|
4177
7075
|
Object.defineProperty(exports, "buildGraphQLSchema", {
|
|
4178
7076
|
enumerable: true,
|
|
4179
|
-
get: function () { return
|
|
7077
|
+
get: function () { return chunkFTSSDDZQ_cjs.buildGraphQLSchema; }
|
|
4180
7078
|
});
|
|
4181
7079
|
Object.defineProperty(exports, "createGraphQLSchema", {
|
|
4182
7080
|
enumerable: true,
|
|
4183
|
-
get: function () { return
|
|
7081
|
+
get: function () { return chunkFTSSDDZQ_cjs.createGraphQLSchema; }
|
|
7082
|
+
});
|
|
7083
|
+
Object.defineProperty(exports, "InMemoryRateLimiter", {
|
|
7084
|
+
enumerable: true,
|
|
7085
|
+
get: function () { return chunkE63IF3MD_cjs.InMemoryRateLimiter; }
|
|
4184
7086
|
});
|
|
4185
7087
|
Object.defineProperty(exports, "createHonoApp", {
|
|
4186
7088
|
enumerable: true,
|
|
4187
|
-
get: function () { return
|
|
7089
|
+
get: function () { return chunkE63IF3MD_cjs.createHonoApp; }
|
|
4188
7090
|
});
|
|
4189
7091
|
Object.defineProperty(exports, "createRESTAPI", {
|
|
4190
7092
|
enumerable: true,
|
|
4191
|
-
get: function () { return
|
|
7093
|
+
get: function () { return chunkE63IF3MD_cjs.createRESTAPI; }
|
|
7094
|
+
});
|
|
7095
|
+
Object.defineProperty(exports, "ConfigService", {
|
|
7096
|
+
enumerable: true,
|
|
7097
|
+
get: function () { return chunkHVSQDZZJ_cjs.ConfigService; }
|
|
7098
|
+
});
|
|
7099
|
+
Object.defineProperty(exports, "EmailTransport", {
|
|
7100
|
+
enumerable: true,
|
|
7101
|
+
get: function () { return chunkHVSQDZZJ_cjs.EmailTransport; }
|
|
7102
|
+
});
|
|
7103
|
+
Object.defineProperty(exports, "ALL_WEBHOOK_EVENTS", {
|
|
7104
|
+
enumerable: true,
|
|
7105
|
+
get: function () { return chunkVIONYQ2K_cjs.ALL_WEBHOOK_EVENTS; }
|
|
7106
|
+
});
|
|
7107
|
+
Object.defineProperty(exports, "WEBHOOK_COLLECTION", {
|
|
7108
|
+
enumerable: true,
|
|
7109
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_COLLECTION; }
|
|
7110
|
+
});
|
|
7111
|
+
Object.defineProperty(exports, "WEBHOOK_DELIVERY_COLLECTION", {
|
|
7112
|
+
enumerable: true,
|
|
7113
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_DELIVERY_COLLECTION; }
|
|
7114
|
+
});
|
|
7115
|
+
Object.defineProperty(exports, "WEBHOOK_EVENTS", {
|
|
7116
|
+
enumerable: true,
|
|
7117
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_EVENTS; }
|
|
7118
|
+
});
|
|
7119
|
+
Object.defineProperty(exports, "WebhookService", {
|
|
7120
|
+
enumerable: true,
|
|
7121
|
+
get: function () { return chunkVIONYQ2K_cjs.WebhookService; }
|
|
7122
|
+
});
|
|
7123
|
+
Object.defineProperty(exports, "buildDeliveryRecord", {
|
|
7124
|
+
enumerable: true,
|
|
7125
|
+
get: function () { return chunkVIONYQ2K_cjs.buildDeliveryRecord; }
|
|
7126
|
+
});
|
|
7127
|
+
Object.defineProperty(exports, "createTestPayload", {
|
|
7128
|
+
enumerable: true,
|
|
7129
|
+
get: function () { return chunkVIONYQ2K_cjs.createTestPayload; }
|
|
7130
|
+
});
|
|
7131
|
+
Object.defineProperty(exports, "createWebhookService", {
|
|
7132
|
+
enumerable: true,
|
|
7133
|
+
get: function () { return chunkVIONYQ2K_cjs.createWebhookService; }
|
|
7134
|
+
});
|
|
7135
|
+
Object.defineProperty(exports, "deliverWebhook", {
|
|
7136
|
+
enumerable: true,
|
|
7137
|
+
get: function () { return chunkVIONYQ2K_cjs.deliverWebhook; }
|
|
7138
|
+
});
|
|
7139
|
+
Object.defineProperty(exports, "deliverWithRetry", {
|
|
7140
|
+
enumerable: true,
|
|
7141
|
+
get: function () { return chunkVIONYQ2K_cjs.deliverWithRetry; }
|
|
4192
7142
|
});
|
|
4193
7143
|
Object.defineProperty(exports, "evaluateAccess", {
|
|
4194
7144
|
enumerable: true,
|
|
4195
|
-
get: function () { return
|
|
7145
|
+
get: function () { return chunkVIONYQ2K_cjs.evaluateAccess; }
|
|
7146
|
+
});
|
|
7147
|
+
Object.defineProperty(exports, "generateWebhookSecret", {
|
|
7148
|
+
enumerable: true,
|
|
7149
|
+
get: function () { return chunkVIONYQ2K_cjs.generateWebhookSecret; }
|
|
4196
7150
|
});
|
|
4197
7151
|
Object.defineProperty(exports, "getWhereClause", {
|
|
4198
7152
|
enumerable: true,
|
|
4199
|
-
get: function () { return
|
|
7153
|
+
get: function () { return chunkVIONYQ2K_cjs.getWhereClause; }
|
|
4200
7154
|
});
|
|
4201
7155
|
Object.defineProperty(exports, "mergeWhereClauses", {
|
|
4202
7156
|
enumerable: true,
|
|
4203
|
-
get: function () { return
|
|
7157
|
+
get: function () { return chunkVIONYQ2K_cjs.mergeWhereClauses; }
|
|
7158
|
+
});
|
|
7159
|
+
Object.defineProperty(exports, "signPayload", {
|
|
7160
|
+
enumerable: true,
|
|
7161
|
+
get: function () { return chunkVIONYQ2K_cjs.signPayload; }
|
|
4204
7162
|
});
|
|
4205
7163
|
Object.defineProperty(exports, "KyroPubSub", {
|
|
4206
7164
|
enumerable: true,
|
|
@@ -4220,35 +7178,35 @@ Object.defineProperty(exports, "createWSServer", {
|
|
|
4220
7178
|
});
|
|
4221
7179
|
Object.defineProperty(exports, "DrizzleAdapter", {
|
|
4222
7180
|
enumerable: true,
|
|
4223
|
-
get: function () { return
|
|
7181
|
+
get: function () { return chunkGVFB5C6O_cjs.DrizzleAdapter; }
|
|
4224
7182
|
});
|
|
4225
7183
|
Object.defineProperty(exports, "collectionToDrizzleSchema", {
|
|
4226
7184
|
enumerable: true,
|
|
4227
|
-
get: function () { return
|
|
7185
|
+
get: function () { return chunkGVFB5C6O_cjs.collectionToDrizzleSchema; }
|
|
4228
7186
|
});
|
|
4229
|
-
Object.defineProperty(exports, "
|
|
4230
|
-
enumerable: true,
|
|
4231
|
-
get: function () { return chunkV3B25QOK_cjs.createDrizzleAdapter; }
|
|
4232
|
-
});
|
|
4233
|
-
Object.defineProperty(exports, "fieldToDrizzleType", {
|
|
7187
|
+
Object.defineProperty(exports, "createDatabase", {
|
|
4234
7188
|
enumerable: true,
|
|
4235
|
-
get: function () { return
|
|
7189
|
+
get: function () { return chunkGVFB5C6O_cjs.createDatabase; }
|
|
4236
7190
|
});
|
|
4237
|
-
Object.defineProperty(exports, "
|
|
7191
|
+
Object.defineProperty(exports, "createDrizzleAdapter", {
|
|
4238
7192
|
enumerable: true,
|
|
4239
|
-
get: function () { return
|
|
7193
|
+
get: function () { return chunkGVFB5C6O_cjs.createDrizzleAdapter; }
|
|
4240
7194
|
});
|
|
4241
|
-
Object.defineProperty(exports, "
|
|
7195
|
+
Object.defineProperty(exports, "fieldToDrizzleType", {
|
|
4242
7196
|
enumerable: true,
|
|
4243
|
-
get: function () { return
|
|
7197
|
+
get: function () { return chunkGVFB5C6O_cjs.fieldToDrizzleType; }
|
|
4244
7198
|
});
|
|
4245
7199
|
Object.defineProperty(exports, "runMigrations", {
|
|
4246
7200
|
enumerable: true,
|
|
4247
|
-
get: function () { return
|
|
7201
|
+
get: function () { return chunkGVFB5C6O_cjs.runMigrations; }
|
|
4248
7202
|
});
|
|
4249
7203
|
Object.defineProperty(exports, "seedDefaultRoles", {
|
|
4250
7204
|
enumerable: true,
|
|
4251
|
-
get: function () { return
|
|
7205
|
+
get: function () { return chunkGVFB5C6O_cjs.seedDefaultRoles; }
|
|
7206
|
+
});
|
|
7207
|
+
Object.defineProperty(exports, "PostgresAuthAdapter", {
|
|
7208
|
+
enumerable: true,
|
|
7209
|
+
get: function () { return chunkLIJVWQKU_cjs.PostgresAuthAdapter; }
|
|
4252
7210
|
});
|
|
4253
7211
|
Object.defineProperty(exports, "MongoDBAdapter", {
|
|
4254
7212
|
enumerable: true,
|
|
@@ -4278,11 +7236,11 @@ exports.ConfigValidationError = ConfigValidationError;
|
|
|
4278
7236
|
exports.InMemoryAccountLockout = InMemoryAccountLockout;
|
|
4279
7237
|
exports.InMemoryAuditLogger = InMemoryAuditLogger;
|
|
4280
7238
|
exports.InMemoryAuthAdapter = InMemoryAuthAdapter;
|
|
4281
|
-
exports.InMemoryRateLimiter = InMemoryRateLimiter;
|
|
4282
7239
|
exports.Kyro = Kyro;
|
|
4283
7240
|
exports.KyroPlugin = KyroPlugin;
|
|
4284
7241
|
exports.LAYOUT_FIELD_TYPES = LAYOUT_FIELD_TYPES;
|
|
4285
7242
|
exports.LocalAdapter = LocalAdapter;
|
|
7243
|
+
exports.MediaService = MediaService;
|
|
4286
7244
|
exports.PRIMITIVE_FIELD_TYPES = PRIMITIVE_FIELD_TYPES;
|
|
4287
7245
|
exports.PluginManager = PluginManager;
|
|
4288
7246
|
exports.RELATIONAL_FIELD_TYPES = RELATIONAL_FIELD_TYPES;
|
|
@@ -4301,8 +7259,10 @@ exports.createAdminStyling = createAdminStyling;
|
|
|
4301
7259
|
exports.createAuditContext = createAuditContext;
|
|
4302
7260
|
exports.createAuth = createAuth;
|
|
4303
7261
|
exports.createAuthConfig = createAuthConfig;
|
|
7262
|
+
exports.createColumnsNode = createColumnsNode;
|
|
4304
7263
|
exports.createKyro = createKyro;
|
|
4305
7264
|
exports.createLocalAdapter = createLocalAdapter;
|
|
7265
|
+
exports.createLocalStorage = createLocalStorage;
|
|
4306
7266
|
exports.createRegistry = createRegistry;
|
|
4307
7267
|
exports.createVersionManager = createVersionManager;
|
|
4308
7268
|
exports.defaultDarkTheme = defaultDarkTheme;
|
|
@@ -4329,8 +7289,13 @@ exports.isRichTextField = isRichTextField;
|
|
|
4329
7289
|
exports.isSelectField = isSelectField;
|
|
4330
7290
|
exports.isTextField = isTextField;
|
|
4331
7291
|
exports.isUploadField = isUploadField;
|
|
7292
|
+
exports.normalizeRichTextDocument = normalizeRichTextDocument;
|
|
7293
|
+
exports.normalizeRichTextValue = normalizeRichTextValue;
|
|
4332
7294
|
exports.presetPlugins = presetPlugins;
|
|
7295
|
+
exports.renderRichText = renderRichText;
|
|
4333
7296
|
exports.resetRegistry = resetRegistry;
|
|
7297
|
+
exports.resolveProvider = resolveProvider;
|
|
7298
|
+
exports.richTextStyles = richTextStyles;
|
|
4334
7299
|
exports.runFieldHooks = runFieldHooks;
|
|
4335
7300
|
exports.runHooks = runHooks;
|
|
4336
7301
|
exports.validateCollection = validateCollection;
|