@kyro-cms/core 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -2
- package/dist/WebhookService-CXJ5oz6L.d.ts +112 -0
- package/dist/WebhookService-Dqx9Is7m.d.cts +112 -0
- package/dist/{base-CQkFzqQl.d.ts → base-CciYzoDF.d.ts} +1 -1
- package/dist/{base-DlhVlwnN.d.cts → base-Cfek4fp3.d.cts} +1 -1
- package/dist/bootstrap-BMWVB2T6.cjs +31 -0
- package/dist/{bootstrap-WMWQ4DBX.cjs.map → bootstrap-BMWVB2T6.cjs.map} +1 -1
- package/dist/bootstrap-LL6O7PWO.js +6 -0
- package/dist/{bootstrap-WOVGAKZP.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-3EVLFWH2.cjs → chunk-4M5PHMUE.cjs} +60 -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-EWP5AT6A.cjs +268 -0
- package/dist/chunk-EWP5AT6A.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-QKOFKITP.js +258 -0
- package/dist/chunk-QKOFKITP.js.map +1 -0
- package/dist/chunk-RONAX6UU.js +3456 -0
- package/dist/chunk-RONAX6UU.js.map +1 -0
- package/dist/{chunk-5Y7QGIHD.js → chunk-RRYXQMZG.js} +60 -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/client.cjs +45 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +11 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.js +4 -0
- package/dist/client.js.map +1 -0
- package/dist/drizzle/index.cjs +20 -17
- package/dist/drizzle/index.d.cts +115 -5
- package/dist/drizzle/index.d.ts +115 -5
- 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-4fJKLFK2.d.ts → index-BvZ1iWm2.d.ts} +1 -1
- package/dist/{index-DI0DRPNv.d.cts → index-CTLPjpMH.d.cts} +1 -1
- package/dist/index.cjs +3391 -649
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +368 -309
- package/dist/index.d.ts +368 -309
- package/dist/index.js +3253 -599
- 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/rate-limit-BvUAVCzw.d.cts +223 -0
- package/dist/rate-limit-CJnqG1mG.d.ts +223 -0
- 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-BSR91JFN.d.cts +159 -0
- package/dist/types-BSR91JFN.d.ts +159 -0
- package/dist/{types-BGM5MV_K.d.ts → types-Bt1OEk0S.d.cts} +78 -38
- package/dist/{types-BGM5MV_K.d.cts → types-Bt1OEk0S.d.ts} +78 -38
- package/dist/ws/index.cjs +1 -1
- package/dist/ws/index.js +1 -1
- package/package.json +19 -2
- package/dist/bootstrap-WMWQ4DBX.cjs +0 -29
- package/dist/bootstrap-WOVGAKZP.js +0 -4
- package/dist/chunk-3EVLFWH2.cjs.map +0 -1
- 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-5Y7QGIHD.js.map +0 -1
- 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-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-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/index-BMySjW6o.d.cts +0 -198
- package/dist/index-CMUNCIWQ.d.ts +0 -198
- 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,1025 @@
|
|
|
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 chunkEWP5AT6A_cjs = require('./chunk-EWP5AT6A.cjs');
|
|
7
|
+
var chunk42JPONZU_cjs = require('./chunk-42JPONZU.cjs');
|
|
8
|
+
var chunkFTSSDDZQ_cjs = require('./chunk-FTSSDDZQ.cjs');
|
|
9
|
+
var chunkE63IF3MD_cjs = require('./chunk-E63IF3MD.cjs');
|
|
10
|
+
var chunkHVSQDZZJ_cjs = require('./chunk-HVSQDZZJ.cjs');
|
|
11
|
+
require('./chunk-4PWRCMTQ.cjs');
|
|
12
|
+
var chunkVIONYQ2K_cjs = require('./chunk-VIONYQ2K.cjs');
|
|
10
13
|
var chunkDVD5P72E_cjs = require('./chunk-DVD5P72E.cjs');
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
require('./chunk-TZFJMPCH.cjs');
|
|
14
|
+
var chunkGVFB5C6O_cjs = require('./chunk-GVFB5C6O.cjs');
|
|
15
|
+
var chunkLIJVWQKU_cjs = require('./chunk-LIJVWQKU.cjs');
|
|
16
|
+
require('./chunk-7YITG2US.cjs');
|
|
15
17
|
var chunkHT6VE4NW_cjs = require('./chunk-HT6VE4NW.cjs');
|
|
16
18
|
var chunkRLTG4YZM_cjs = require('./chunk-RLTG4YZM.cjs');
|
|
17
|
-
var
|
|
19
|
+
var chunkG7VZBCD6_cjs = require('./chunk-G7VZBCD6.cjs');
|
|
20
|
+
var stream = require('stream');
|
|
21
|
+
var https = require('https');
|
|
22
|
+
var http2 = require('http2');
|
|
18
23
|
var zod = require('zod');
|
|
19
24
|
var bcrypt = require('bcrypt');
|
|
20
|
-
var
|
|
25
|
+
var jwt = require('jsonwebtoken');
|
|
21
26
|
var crypto = require('crypto');
|
|
27
|
+
var path = require('path');
|
|
28
|
+
var promises = require('fs/promises');
|
|
29
|
+
var fs = require('fs');
|
|
30
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
31
|
+
var basicFtp = require('basic-ftp');
|
|
32
|
+
var sharp = require('sharp');
|
|
22
33
|
|
|
23
34
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
35
|
|
|
36
|
+
var http2__default = /*#__PURE__*/_interopDefault(http2);
|
|
25
37
|
var bcrypt__default = /*#__PURE__*/_interopDefault(bcrypt);
|
|
26
|
-
var
|
|
38
|
+
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
39
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
40
|
+
var sharp__default = /*#__PURE__*/_interopDefault(sharp);
|
|
41
|
+
|
|
42
|
+
// node_modules/@smithy/protocol-http/dist-es/extensions/httpExtensionConfiguration.js
|
|
43
|
+
var init_httpExtensionConfiguration = chunkG7VZBCD6_cjs.__esm({
|
|
44
|
+
"node_modules/@smithy/protocol-http/dist-es/extensions/httpExtensionConfiguration.js"() {
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// node_modules/@smithy/protocol-http/dist-es/extensions/index.js
|
|
49
|
+
var init_extensions = chunkG7VZBCD6_cjs.__esm({
|
|
50
|
+
"node_modules/@smithy/protocol-http/dist-es/extensions/index.js"() {
|
|
51
|
+
init_httpExtensionConfiguration();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// node_modules/@smithy/protocol-http/dist-es/Field.js
|
|
56
|
+
var init_Field = chunkG7VZBCD6_cjs.__esm({
|
|
57
|
+
"node_modules/@smithy/protocol-http/dist-es/Field.js"() {
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// node_modules/@smithy/protocol-http/dist-es/Fields.js
|
|
62
|
+
var init_Fields = chunkG7VZBCD6_cjs.__esm({
|
|
63
|
+
"node_modules/@smithy/protocol-http/dist-es/Fields.js"() {
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// node_modules/@smithy/protocol-http/dist-es/httpHandler.js
|
|
68
|
+
var init_httpHandler = chunkG7VZBCD6_cjs.__esm({
|
|
69
|
+
"node_modules/@smithy/protocol-http/dist-es/httpHandler.js"() {
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// node_modules/@smithy/protocol-http/dist-es/httpRequest.js
|
|
74
|
+
var init_httpRequest = chunkG7VZBCD6_cjs.__esm({
|
|
75
|
+
"node_modules/@smithy/protocol-http/dist-es/httpRequest.js"() {
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// node_modules/@smithy/protocol-http/dist-es/httpResponse.js
|
|
80
|
+
var HttpResponse;
|
|
81
|
+
var init_httpResponse = chunkG7VZBCD6_cjs.__esm({
|
|
82
|
+
"node_modules/@smithy/protocol-http/dist-es/httpResponse.js"() {
|
|
83
|
+
HttpResponse = class {
|
|
84
|
+
statusCode;
|
|
85
|
+
reason;
|
|
86
|
+
headers;
|
|
87
|
+
body;
|
|
88
|
+
constructor(options) {
|
|
89
|
+
this.statusCode = options.statusCode;
|
|
90
|
+
this.reason = options.reason;
|
|
91
|
+
this.headers = options.headers || {};
|
|
92
|
+
this.body = options.body;
|
|
93
|
+
}
|
|
94
|
+
static isInstance(response) {
|
|
95
|
+
if (!response)
|
|
96
|
+
return false;
|
|
97
|
+
const resp = response;
|
|
98
|
+
return typeof resp.statusCode === "number" && typeof resp.headers === "object";
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// node_modules/@smithy/protocol-http/dist-es/isValidHostname.js
|
|
105
|
+
var init_isValidHostname = chunkG7VZBCD6_cjs.__esm({
|
|
106
|
+
"node_modules/@smithy/protocol-http/dist-es/isValidHostname.js"() {
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// node_modules/@smithy/protocol-http/dist-es/types.js
|
|
111
|
+
var init_types = chunkG7VZBCD6_cjs.__esm({
|
|
112
|
+
"node_modules/@smithy/protocol-http/dist-es/types.js"() {
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// node_modules/@smithy/protocol-http/dist-es/index.js
|
|
117
|
+
var init_dist_es = chunkG7VZBCD6_cjs.__esm({
|
|
118
|
+
"node_modules/@smithy/protocol-http/dist-es/index.js"() {
|
|
119
|
+
init_extensions();
|
|
120
|
+
init_Field();
|
|
121
|
+
init_Fields();
|
|
122
|
+
init_httpHandler();
|
|
123
|
+
init_httpRequest();
|
|
124
|
+
init_httpResponse();
|
|
125
|
+
init_isValidHostname();
|
|
126
|
+
init_types();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// node_modules/@smithy/util-uri-escape/dist-es/escape-uri.js
|
|
131
|
+
var escapeUri, hexEncode;
|
|
132
|
+
var init_escape_uri = chunkG7VZBCD6_cjs.__esm({
|
|
133
|
+
"node_modules/@smithy/util-uri-escape/dist-es/escape-uri.js"() {
|
|
134
|
+
escapeUri = (uri) => encodeURIComponent(uri).replace(/[!'()*]/g, hexEncode);
|
|
135
|
+
hexEncode = (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// node_modules/@smithy/util-uri-escape/dist-es/escape-uri-path.js
|
|
140
|
+
var init_escape_uri_path = chunkG7VZBCD6_cjs.__esm({
|
|
141
|
+
"node_modules/@smithy/util-uri-escape/dist-es/escape-uri-path.js"() {
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// node_modules/@smithy/util-uri-escape/dist-es/index.js
|
|
146
|
+
var init_dist_es2 = chunkG7VZBCD6_cjs.__esm({
|
|
147
|
+
"node_modules/@smithy/util-uri-escape/dist-es/index.js"() {
|
|
148
|
+
init_escape_uri();
|
|
149
|
+
init_escape_uri_path();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// node_modules/@smithy/querystring-builder/dist-es/index.js
|
|
154
|
+
function buildQueryString(query) {
|
|
155
|
+
const parts = [];
|
|
156
|
+
for (let key of Object.keys(query).sort()) {
|
|
157
|
+
const value = query[key];
|
|
158
|
+
key = escapeUri(key);
|
|
159
|
+
if (Array.isArray(value)) {
|
|
160
|
+
for (let i = 0, iLen = value.length; i < iLen; i++) {
|
|
161
|
+
parts.push(`${key}=${escapeUri(value[i])}`);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
let qsEntry = key;
|
|
165
|
+
if (value || typeof value === "string") {
|
|
166
|
+
qsEntry += `=${escapeUri(value)}`;
|
|
167
|
+
}
|
|
168
|
+
parts.push(qsEntry);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return parts.join("&");
|
|
172
|
+
}
|
|
173
|
+
var init_dist_es3 = chunkG7VZBCD6_cjs.__esm({
|
|
174
|
+
"node_modules/@smithy/querystring-builder/dist-es/index.js"() {
|
|
175
|
+
init_dist_es2();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js
|
|
180
|
+
function buildAbortError(abortSignal) {
|
|
181
|
+
const reason = abortSignal && typeof abortSignal === "object" && "reason" in abortSignal ? abortSignal.reason : void 0;
|
|
182
|
+
if (reason) {
|
|
183
|
+
if (reason instanceof Error) {
|
|
184
|
+
const abortError3 = new Error("Request aborted");
|
|
185
|
+
abortError3.name = "AbortError";
|
|
186
|
+
abortError3.cause = reason;
|
|
187
|
+
return abortError3;
|
|
188
|
+
}
|
|
189
|
+
const abortError2 = new Error(String(reason));
|
|
190
|
+
abortError2.name = "AbortError";
|
|
191
|
+
return abortError2;
|
|
192
|
+
}
|
|
193
|
+
const abortError = new Error("Request aborted");
|
|
194
|
+
abortError.name = "AbortError";
|
|
195
|
+
return abortError;
|
|
196
|
+
}
|
|
197
|
+
var init_build_abort_error = chunkG7VZBCD6_cjs.__esm({
|
|
198
|
+
"node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js"() {
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// node_modules/@smithy/node-http-handler/dist-es/constants.js
|
|
203
|
+
var NODEJS_TIMEOUT_ERROR_CODES;
|
|
204
|
+
var init_constants = chunkG7VZBCD6_cjs.__esm({
|
|
205
|
+
"node_modules/@smithy/node-http-handler/dist-es/constants.js"() {
|
|
206
|
+
NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "EPIPE", "ETIMEDOUT"];
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js
|
|
211
|
+
var getTransformedHeaders;
|
|
212
|
+
var init_get_transformed_headers = chunkG7VZBCD6_cjs.__esm({
|
|
213
|
+
"node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js"() {
|
|
214
|
+
getTransformedHeaders = (headers) => {
|
|
215
|
+
const transformedHeaders = {};
|
|
216
|
+
for (const name of Object.keys(headers)) {
|
|
217
|
+
const headerValues = headers[name];
|
|
218
|
+
transformedHeaders[name] = Array.isArray(headerValues) ? headerValues.join(",") : headerValues;
|
|
219
|
+
}
|
|
220
|
+
return transformedHeaders;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// node_modules/@smithy/node-http-handler/dist-es/timing.js
|
|
226
|
+
var timing;
|
|
227
|
+
var init_timing = chunkG7VZBCD6_cjs.__esm({
|
|
228
|
+
"node_modules/@smithy/node-http-handler/dist-es/timing.js"() {
|
|
229
|
+
timing = {
|
|
230
|
+
setTimeout: (cb, ms) => setTimeout(cb, ms),
|
|
231
|
+
clearTimeout: (timeoutId) => clearTimeout(timeoutId)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js
|
|
237
|
+
var DEFER_EVENT_LISTENER_TIME, setConnectionTimeout;
|
|
238
|
+
var init_set_connection_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
239
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js"() {
|
|
240
|
+
init_timing();
|
|
241
|
+
DEFER_EVENT_LISTENER_TIME = 1e3;
|
|
242
|
+
setConnectionTimeout = (request, reject, timeoutInMs = 0) => {
|
|
243
|
+
if (!timeoutInMs) {
|
|
244
|
+
return -1;
|
|
245
|
+
}
|
|
246
|
+
const registerTimeout = (offset) => {
|
|
247
|
+
const timeoutId = timing.setTimeout(() => {
|
|
248
|
+
request.destroy();
|
|
249
|
+
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.`), {
|
|
250
|
+
name: "TimeoutError"
|
|
251
|
+
}));
|
|
252
|
+
}, timeoutInMs - offset);
|
|
253
|
+
const doWithSocket = (socket) => {
|
|
254
|
+
if (socket?.connecting) {
|
|
255
|
+
socket.on("connect", () => {
|
|
256
|
+
timing.clearTimeout(timeoutId);
|
|
257
|
+
});
|
|
258
|
+
} else {
|
|
259
|
+
timing.clearTimeout(timeoutId);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
if (request.socket) {
|
|
263
|
+
doWithSocket(request.socket);
|
|
264
|
+
} else {
|
|
265
|
+
request.on("socket", doWithSocket);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
if (timeoutInMs < 2e3) {
|
|
269
|
+
registerTimeout(0);
|
|
270
|
+
return 0;
|
|
271
|
+
}
|
|
272
|
+
return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME);
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js
|
|
278
|
+
var setRequestTimeout;
|
|
279
|
+
var init_set_request_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
280
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js"() {
|
|
281
|
+
init_timing();
|
|
282
|
+
setRequestTimeout = (req, reject, timeoutInMs = 0, throwOnRequestTimeout, logger) => {
|
|
283
|
+
if (timeoutInMs) {
|
|
284
|
+
return timing.setTimeout(() => {
|
|
285
|
+
let msg = `@smithy/node-http-handler - [${throwOnRequestTimeout ? "ERROR" : "WARN"}] a request has exceeded the configured ${timeoutInMs} ms requestTimeout.`;
|
|
286
|
+
if (throwOnRequestTimeout) {
|
|
287
|
+
const error = Object.assign(new Error(msg), {
|
|
288
|
+
name: "TimeoutError",
|
|
289
|
+
code: "ETIMEDOUT"
|
|
290
|
+
});
|
|
291
|
+
req.destroy(error);
|
|
292
|
+
reject(error);
|
|
293
|
+
} else {
|
|
294
|
+
msg += ` Init client requestHandler with throwOnRequestTimeout=true to turn this into an error.`;
|
|
295
|
+
logger?.warn?.(msg);
|
|
296
|
+
}
|
|
297
|
+
}, timeoutInMs);
|
|
298
|
+
}
|
|
299
|
+
return -1;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js
|
|
305
|
+
var DEFER_EVENT_LISTENER_TIME2, setSocketKeepAlive;
|
|
306
|
+
var init_set_socket_keep_alive = chunkG7VZBCD6_cjs.__esm({
|
|
307
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js"() {
|
|
308
|
+
init_timing();
|
|
309
|
+
DEFER_EVENT_LISTENER_TIME2 = 3e3;
|
|
310
|
+
setSocketKeepAlive = (request, { keepAlive, keepAliveMsecs }, deferTimeMs = DEFER_EVENT_LISTENER_TIME2) => {
|
|
311
|
+
if (keepAlive !== true) {
|
|
312
|
+
return -1;
|
|
313
|
+
}
|
|
314
|
+
const registerListener = () => {
|
|
315
|
+
if (request.socket) {
|
|
316
|
+
request.socket.setKeepAlive(keepAlive, keepAliveMsecs || 0);
|
|
317
|
+
} else {
|
|
318
|
+
request.on("socket", (socket) => {
|
|
319
|
+
socket.setKeepAlive(keepAlive, keepAliveMsecs || 0);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
if (deferTimeMs === 0) {
|
|
324
|
+
registerListener();
|
|
325
|
+
return 0;
|
|
326
|
+
}
|
|
327
|
+
return timing.setTimeout(registerListener, deferTimeMs);
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js
|
|
333
|
+
var DEFER_EVENT_LISTENER_TIME3, setSocketTimeout;
|
|
334
|
+
var init_set_socket_timeout = chunkG7VZBCD6_cjs.__esm({
|
|
335
|
+
"node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js"() {
|
|
336
|
+
init_timing();
|
|
337
|
+
DEFER_EVENT_LISTENER_TIME3 = 3e3;
|
|
338
|
+
setSocketTimeout = (request, reject, timeoutInMs = 0) => {
|
|
339
|
+
const registerTimeout = (offset) => {
|
|
340
|
+
const timeout = timeoutInMs - offset;
|
|
341
|
+
const onTimeout = () => {
|
|
342
|
+
request.destroy();
|
|
343
|
+
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" }));
|
|
344
|
+
};
|
|
345
|
+
if (request.socket) {
|
|
346
|
+
request.socket.setTimeout(timeout, onTimeout);
|
|
347
|
+
request.on("close", () => request.socket?.removeListener("timeout", onTimeout));
|
|
348
|
+
} else {
|
|
349
|
+
request.setTimeout(timeout, onTimeout);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
if (0 < timeoutInMs && timeoutInMs < 6e3) {
|
|
353
|
+
registerTimeout(0);
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
return timing.setTimeout(registerTimeout.bind(null, timeoutInMs === 0 ? 0 : DEFER_EVENT_LISTENER_TIME3), DEFER_EVENT_LISTENER_TIME3);
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
async function writeRequestBody(httpRequest, request, maxContinueTimeoutMs = MIN_WAIT_TIME, externalAgent = false) {
|
|
361
|
+
const headers = request.headers ?? {};
|
|
362
|
+
const expect = headers.Expect || headers.expect;
|
|
363
|
+
let timeoutId = -1;
|
|
364
|
+
let sendBody = true;
|
|
365
|
+
if (!externalAgent && expect === "100-continue") {
|
|
366
|
+
sendBody = await Promise.race([
|
|
367
|
+
new Promise((resolve) => {
|
|
368
|
+
timeoutId = Number(timing.setTimeout(() => resolve(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
|
|
369
|
+
}),
|
|
370
|
+
new Promise((resolve) => {
|
|
371
|
+
httpRequest.on("continue", () => {
|
|
372
|
+
timing.clearTimeout(timeoutId);
|
|
373
|
+
resolve(true);
|
|
374
|
+
});
|
|
375
|
+
httpRequest.on("response", () => {
|
|
376
|
+
timing.clearTimeout(timeoutId);
|
|
377
|
+
resolve(false);
|
|
378
|
+
});
|
|
379
|
+
httpRequest.on("error", () => {
|
|
380
|
+
timing.clearTimeout(timeoutId);
|
|
381
|
+
resolve(false);
|
|
382
|
+
});
|
|
383
|
+
})
|
|
384
|
+
]);
|
|
385
|
+
}
|
|
386
|
+
if (sendBody) {
|
|
387
|
+
writeBody(httpRequest, request.body);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function writeBody(httpRequest, body) {
|
|
391
|
+
if (body instanceof stream.Readable) {
|
|
392
|
+
body.pipe(httpRequest);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (body) {
|
|
396
|
+
const isBuffer = Buffer.isBuffer(body);
|
|
397
|
+
const isString = typeof body === "string";
|
|
398
|
+
if (isBuffer || isString) {
|
|
399
|
+
if (isBuffer && body.byteLength === 0) {
|
|
400
|
+
httpRequest.end();
|
|
401
|
+
} else {
|
|
402
|
+
httpRequest.end(body);
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const uint8 = body;
|
|
407
|
+
if (typeof uint8 === "object" && uint8.buffer && typeof uint8.byteOffset === "number" && typeof uint8.byteLength === "number") {
|
|
408
|
+
httpRequest.end(Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
httpRequest.end(Buffer.from(body));
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
httpRequest.end();
|
|
415
|
+
}
|
|
416
|
+
var MIN_WAIT_TIME;
|
|
417
|
+
var init_write_request_body = chunkG7VZBCD6_cjs.__esm({
|
|
418
|
+
"node_modules/@smithy/node-http-handler/dist-es/write-request-body.js"() {
|
|
419
|
+
init_timing();
|
|
420
|
+
MIN_WAIT_TIME = 6e3;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
var DEFAULT_REQUEST_TIMEOUT, hAgent, hRequest, NodeHttpHandler;
|
|
424
|
+
var init_node_http_handler = chunkG7VZBCD6_cjs.__esm({
|
|
425
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js"() {
|
|
426
|
+
init_dist_es();
|
|
427
|
+
init_dist_es3();
|
|
428
|
+
init_build_abort_error();
|
|
429
|
+
init_constants();
|
|
430
|
+
init_get_transformed_headers();
|
|
431
|
+
init_set_connection_timeout();
|
|
432
|
+
init_set_request_timeout();
|
|
433
|
+
init_set_socket_keep_alive();
|
|
434
|
+
init_set_socket_timeout();
|
|
435
|
+
init_timing();
|
|
436
|
+
init_write_request_body();
|
|
437
|
+
DEFAULT_REQUEST_TIMEOUT = 0;
|
|
438
|
+
hAgent = void 0;
|
|
439
|
+
hRequest = void 0;
|
|
440
|
+
NodeHttpHandler = class _NodeHttpHandler {
|
|
441
|
+
config;
|
|
442
|
+
configProvider;
|
|
443
|
+
socketWarningTimestamp = 0;
|
|
444
|
+
externalAgent = false;
|
|
445
|
+
metadata = { handlerProtocol: "http/1.1" };
|
|
446
|
+
static create(instanceOrOptions) {
|
|
447
|
+
if (typeof instanceOrOptions?.handle === "function") {
|
|
448
|
+
return instanceOrOptions;
|
|
449
|
+
}
|
|
450
|
+
return new _NodeHttpHandler(instanceOrOptions);
|
|
451
|
+
}
|
|
452
|
+
static checkSocketUsage(agent, socketWarningTimestamp, logger = console) {
|
|
453
|
+
const { sockets, requests, maxSockets } = agent;
|
|
454
|
+
if (typeof maxSockets !== "number" || maxSockets === Infinity) {
|
|
455
|
+
return socketWarningTimestamp;
|
|
456
|
+
}
|
|
457
|
+
const interval = 15e3;
|
|
458
|
+
if (Date.now() - interval < socketWarningTimestamp) {
|
|
459
|
+
return socketWarningTimestamp;
|
|
460
|
+
}
|
|
461
|
+
if (sockets && requests) {
|
|
462
|
+
for (const origin in sockets) {
|
|
463
|
+
const socketsInUse = sockets[origin]?.length ?? 0;
|
|
464
|
+
const requestsEnqueued = requests[origin]?.length ?? 0;
|
|
465
|
+
if (socketsInUse >= maxSockets && requestsEnqueued >= 2 * maxSockets) {
|
|
466
|
+
logger?.warn?.(`@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued.
|
|
467
|
+
See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html
|
|
468
|
+
or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.`);
|
|
469
|
+
return Date.now();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return socketWarningTimestamp;
|
|
474
|
+
}
|
|
475
|
+
constructor(options) {
|
|
476
|
+
this.configProvider = new Promise((resolve, reject) => {
|
|
477
|
+
if (typeof options === "function") {
|
|
478
|
+
options().then((_options) => {
|
|
479
|
+
resolve(this.resolveDefaultConfig(_options));
|
|
480
|
+
}).catch(reject);
|
|
481
|
+
} else {
|
|
482
|
+
resolve(this.resolveDefaultConfig(options));
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
destroy() {
|
|
487
|
+
this.config?.httpAgent?.destroy();
|
|
488
|
+
this.config?.httpsAgent?.destroy();
|
|
489
|
+
}
|
|
490
|
+
async handle(request, { abortSignal, requestTimeout } = {}) {
|
|
491
|
+
if (!this.config) {
|
|
492
|
+
this.config = await this.configProvider;
|
|
493
|
+
}
|
|
494
|
+
const config = this.config;
|
|
495
|
+
const isSSL = request.protocol === "https:";
|
|
496
|
+
if (!isSSL && !this.config.httpAgent) {
|
|
497
|
+
this.config.httpAgent = await this.config.httpAgentProvider();
|
|
498
|
+
}
|
|
499
|
+
return new Promise((_resolve, _reject) => {
|
|
500
|
+
let writeRequestBodyPromise = void 0;
|
|
501
|
+
const timeouts = [];
|
|
502
|
+
const resolve = async (arg) => {
|
|
503
|
+
await writeRequestBodyPromise;
|
|
504
|
+
timeouts.forEach(timing.clearTimeout);
|
|
505
|
+
_resolve(arg);
|
|
506
|
+
};
|
|
507
|
+
const reject = async (arg) => {
|
|
508
|
+
await writeRequestBodyPromise;
|
|
509
|
+
timeouts.forEach(timing.clearTimeout);
|
|
510
|
+
_reject(arg);
|
|
511
|
+
};
|
|
512
|
+
if (abortSignal?.aborted) {
|
|
513
|
+
const abortError = buildAbortError(abortSignal);
|
|
514
|
+
reject(abortError);
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const headers = request.headers ?? {};
|
|
518
|
+
const expectContinue = (headers.Expect ?? headers.expect) === "100-continue";
|
|
519
|
+
let agent = isSSL ? config.httpsAgent : config.httpAgent;
|
|
520
|
+
if (expectContinue && !this.externalAgent) {
|
|
521
|
+
agent = new (isSSL ? https.Agent : hAgent)({
|
|
522
|
+
keepAlive: false,
|
|
523
|
+
maxSockets: Infinity
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
timeouts.push(timing.setTimeout(() => {
|
|
527
|
+
this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, config.logger);
|
|
528
|
+
}, config.socketAcquisitionWarningTimeout ?? (config.requestTimeout ?? 2e3) + (config.connectionTimeout ?? 1e3)));
|
|
529
|
+
const queryString = buildQueryString(request.query || {});
|
|
530
|
+
let auth = void 0;
|
|
531
|
+
if (request.username != null || request.password != null) {
|
|
532
|
+
const username = request.username ?? "";
|
|
533
|
+
const password = request.password ?? "";
|
|
534
|
+
auth = `${username}:${password}`;
|
|
535
|
+
}
|
|
536
|
+
let path2 = request.path;
|
|
537
|
+
if (queryString) {
|
|
538
|
+
path2 += `?${queryString}`;
|
|
539
|
+
}
|
|
540
|
+
if (request.fragment) {
|
|
541
|
+
path2 += `#${request.fragment}`;
|
|
542
|
+
}
|
|
543
|
+
let hostname = request.hostname ?? "";
|
|
544
|
+
if (hostname[0] === "[" && hostname.endsWith("]")) {
|
|
545
|
+
hostname = request.hostname.slice(1, -1);
|
|
546
|
+
} else {
|
|
547
|
+
hostname = request.hostname;
|
|
548
|
+
}
|
|
549
|
+
const nodeHttpsOptions = {
|
|
550
|
+
headers: request.headers,
|
|
551
|
+
host: hostname,
|
|
552
|
+
method: request.method,
|
|
553
|
+
path: path2,
|
|
554
|
+
port: request.port,
|
|
555
|
+
agent,
|
|
556
|
+
auth
|
|
557
|
+
};
|
|
558
|
+
const requestFunc = isSSL ? https.request : hRequest;
|
|
559
|
+
const req = requestFunc(nodeHttpsOptions, (res) => {
|
|
560
|
+
const httpResponse = new HttpResponse({
|
|
561
|
+
statusCode: res.statusCode || -1,
|
|
562
|
+
reason: res.statusMessage,
|
|
563
|
+
headers: getTransformedHeaders(res.headers),
|
|
564
|
+
body: res
|
|
565
|
+
});
|
|
566
|
+
resolve({ response: httpResponse });
|
|
567
|
+
});
|
|
568
|
+
req.on("error", (err) => {
|
|
569
|
+
if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
|
|
570
|
+
reject(Object.assign(err, { name: "TimeoutError" }));
|
|
571
|
+
} else {
|
|
572
|
+
reject(err);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
if (abortSignal) {
|
|
576
|
+
const onAbort = () => {
|
|
577
|
+
req.destroy();
|
|
578
|
+
const abortError = buildAbortError(abortSignal);
|
|
579
|
+
reject(abortError);
|
|
580
|
+
};
|
|
581
|
+
if (typeof abortSignal.addEventListener === "function") {
|
|
582
|
+
const signal = abortSignal;
|
|
583
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
584
|
+
req.once("close", () => signal.removeEventListener("abort", onAbort));
|
|
585
|
+
} else {
|
|
586
|
+
abortSignal.onabort = onAbort;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
const effectiveRequestTimeout = requestTimeout ?? config.requestTimeout;
|
|
590
|
+
timeouts.push(setConnectionTimeout(req, reject, config.connectionTimeout));
|
|
591
|
+
timeouts.push(setRequestTimeout(req, reject, effectiveRequestTimeout, config.throwOnRequestTimeout, config.logger ?? console));
|
|
592
|
+
timeouts.push(setSocketTimeout(req, reject, config.socketTimeout));
|
|
593
|
+
const httpAgent = nodeHttpsOptions.agent;
|
|
594
|
+
if (typeof httpAgent === "object" && "keepAlive" in httpAgent) {
|
|
595
|
+
timeouts.push(setSocketKeepAlive(req, {
|
|
596
|
+
keepAlive: httpAgent.keepAlive,
|
|
597
|
+
keepAliveMsecs: httpAgent.keepAliveMsecs
|
|
598
|
+
}));
|
|
599
|
+
}
|
|
600
|
+
writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout, this.externalAgent).catch((e) => {
|
|
601
|
+
timeouts.forEach(timing.clearTimeout);
|
|
602
|
+
return _reject(e);
|
|
603
|
+
});
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
updateHttpClientConfig(key, value) {
|
|
607
|
+
this.config = void 0;
|
|
608
|
+
this.configProvider = this.configProvider.then((config) => {
|
|
609
|
+
return {
|
|
610
|
+
...config,
|
|
611
|
+
[key]: value
|
|
612
|
+
};
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
httpHandlerConfigs() {
|
|
616
|
+
return this.config ?? {};
|
|
617
|
+
}
|
|
618
|
+
resolveDefaultConfig(options) {
|
|
619
|
+
const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent, throwOnRequestTimeout, logger } = options || {};
|
|
620
|
+
const keepAlive = true;
|
|
621
|
+
const maxSockets = 50;
|
|
622
|
+
return {
|
|
623
|
+
connectionTimeout,
|
|
624
|
+
requestTimeout,
|
|
625
|
+
socketTimeout,
|
|
626
|
+
socketAcquisitionWarningTimeout,
|
|
627
|
+
throwOnRequestTimeout,
|
|
628
|
+
httpAgentProvider: async () => {
|
|
629
|
+
const { Agent, request } = await import('http');
|
|
630
|
+
hRequest = request;
|
|
631
|
+
hAgent = Agent;
|
|
632
|
+
if (httpAgent instanceof hAgent || typeof httpAgent?.destroy === "function") {
|
|
633
|
+
this.externalAgent = true;
|
|
634
|
+
return httpAgent;
|
|
635
|
+
}
|
|
636
|
+
return new hAgent({ keepAlive, maxSockets, ...httpAgent });
|
|
637
|
+
},
|
|
638
|
+
httpsAgent: (() => {
|
|
639
|
+
if (httpsAgent instanceof https.Agent || typeof httpsAgent?.destroy === "function") {
|
|
640
|
+
this.externalAgent = true;
|
|
641
|
+
return httpsAgent;
|
|
642
|
+
}
|
|
643
|
+
return new https.Agent({ keepAlive, maxSockets, ...httpsAgent });
|
|
644
|
+
})(),
|
|
645
|
+
logger
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
// node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js
|
|
653
|
+
var NodeHttp2ConnectionPool;
|
|
654
|
+
var init_node_http2_connection_pool = chunkG7VZBCD6_cjs.__esm({
|
|
655
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js"() {
|
|
656
|
+
NodeHttp2ConnectionPool = class {
|
|
657
|
+
sessions = [];
|
|
658
|
+
constructor(sessions) {
|
|
659
|
+
this.sessions = sessions ?? [];
|
|
660
|
+
}
|
|
661
|
+
poll() {
|
|
662
|
+
if (this.sessions.length > 0) {
|
|
663
|
+
return this.sessions.shift();
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
offerLast(session) {
|
|
667
|
+
this.sessions.push(session);
|
|
668
|
+
}
|
|
669
|
+
contains(session) {
|
|
670
|
+
return this.sessions.includes(session);
|
|
671
|
+
}
|
|
672
|
+
remove(session) {
|
|
673
|
+
this.sessions = this.sessions.filter((s) => s !== session);
|
|
674
|
+
}
|
|
675
|
+
[Symbol.iterator]() {
|
|
676
|
+
return this.sessions[Symbol.iterator]();
|
|
677
|
+
}
|
|
678
|
+
destroy(connection) {
|
|
679
|
+
for (const session of this.sessions) {
|
|
680
|
+
if (session === connection) {
|
|
681
|
+
if (!session.destroyed) {
|
|
682
|
+
session.destroy();
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
var NodeHttp2ConnectionManager;
|
|
691
|
+
var init_node_http2_connection_manager = chunkG7VZBCD6_cjs.__esm({
|
|
692
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js"() {
|
|
693
|
+
init_node_http2_connection_pool();
|
|
694
|
+
NodeHttp2ConnectionManager = class {
|
|
695
|
+
constructor(config) {
|
|
696
|
+
this.config = config;
|
|
697
|
+
if (this.config.maxConcurrency && this.config.maxConcurrency <= 0) {
|
|
698
|
+
throw new RangeError("maxConcurrency must be greater than zero.");
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
config;
|
|
702
|
+
sessionCache = /* @__PURE__ */ new Map();
|
|
703
|
+
lease(requestContext, connectionConfiguration) {
|
|
704
|
+
const url = this.getUrlString(requestContext);
|
|
705
|
+
const existingPool = this.sessionCache.get(url);
|
|
706
|
+
if (existingPool) {
|
|
707
|
+
const existingSession = existingPool.poll();
|
|
708
|
+
if (existingSession && !this.config.disableConcurrency) {
|
|
709
|
+
return existingSession;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
const session = http2__default.default.connect(url);
|
|
713
|
+
if (this.config.maxConcurrency) {
|
|
714
|
+
session.settings({ maxConcurrentStreams: this.config.maxConcurrency }, (err) => {
|
|
715
|
+
if (err) {
|
|
716
|
+
throw new Error("Fail to set maxConcurrentStreams to " + this.config.maxConcurrency + "when creating new session for " + requestContext.destination.toString());
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
session.unref();
|
|
721
|
+
const destroySessionCb = () => {
|
|
722
|
+
session.destroy();
|
|
723
|
+
this.deleteSession(url, session);
|
|
724
|
+
};
|
|
725
|
+
session.on("goaway", destroySessionCb);
|
|
726
|
+
session.on("error", destroySessionCb);
|
|
727
|
+
session.on("frameError", destroySessionCb);
|
|
728
|
+
session.on("close", () => this.deleteSession(url, session));
|
|
729
|
+
if (connectionConfiguration.requestTimeout) {
|
|
730
|
+
session.setTimeout(connectionConfiguration.requestTimeout, destroySessionCb);
|
|
731
|
+
}
|
|
732
|
+
const connectionPool = this.sessionCache.get(url) || new NodeHttp2ConnectionPool();
|
|
733
|
+
connectionPool.offerLast(session);
|
|
734
|
+
this.sessionCache.set(url, connectionPool);
|
|
735
|
+
return session;
|
|
736
|
+
}
|
|
737
|
+
deleteSession(authority, session) {
|
|
738
|
+
const existingConnectionPool = this.sessionCache.get(authority);
|
|
739
|
+
if (!existingConnectionPool) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
if (!existingConnectionPool.contains(session)) {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
existingConnectionPool.remove(session);
|
|
746
|
+
this.sessionCache.set(authority, existingConnectionPool);
|
|
747
|
+
}
|
|
748
|
+
release(requestContext, session) {
|
|
749
|
+
const cacheKey = this.getUrlString(requestContext);
|
|
750
|
+
this.sessionCache.get(cacheKey)?.offerLast(session);
|
|
751
|
+
}
|
|
752
|
+
destroy() {
|
|
753
|
+
for (const [key, connectionPool] of this.sessionCache) {
|
|
754
|
+
for (const session of connectionPool) {
|
|
755
|
+
if (!session.destroyed) {
|
|
756
|
+
session.destroy();
|
|
757
|
+
}
|
|
758
|
+
connectionPool.remove(session);
|
|
759
|
+
}
|
|
760
|
+
this.sessionCache.delete(key);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
setMaxConcurrentStreams(maxConcurrentStreams) {
|
|
764
|
+
if (maxConcurrentStreams && maxConcurrentStreams <= 0) {
|
|
765
|
+
throw new RangeError("maxConcurrentStreams must be greater than zero.");
|
|
766
|
+
}
|
|
767
|
+
this.config.maxConcurrency = maxConcurrentStreams;
|
|
768
|
+
}
|
|
769
|
+
setDisableConcurrentStreams(disableConcurrentStreams) {
|
|
770
|
+
this.config.disableConcurrency = disableConcurrentStreams;
|
|
771
|
+
}
|
|
772
|
+
getUrlString(request) {
|
|
773
|
+
return request.destination.toString();
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
var NodeHttp2Handler;
|
|
779
|
+
var init_node_http2_handler = chunkG7VZBCD6_cjs.__esm({
|
|
780
|
+
"node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js"() {
|
|
781
|
+
init_dist_es();
|
|
782
|
+
init_dist_es3();
|
|
783
|
+
init_build_abort_error();
|
|
784
|
+
init_get_transformed_headers();
|
|
785
|
+
init_node_http2_connection_manager();
|
|
786
|
+
init_write_request_body();
|
|
787
|
+
NodeHttp2Handler = class _NodeHttp2Handler {
|
|
788
|
+
config;
|
|
789
|
+
configProvider;
|
|
790
|
+
metadata = { handlerProtocol: "h2" };
|
|
791
|
+
connectionManager = new NodeHttp2ConnectionManager({});
|
|
792
|
+
static create(instanceOrOptions) {
|
|
793
|
+
if (typeof instanceOrOptions?.handle === "function") {
|
|
794
|
+
return instanceOrOptions;
|
|
795
|
+
}
|
|
796
|
+
return new _NodeHttp2Handler(instanceOrOptions);
|
|
797
|
+
}
|
|
798
|
+
constructor(options) {
|
|
799
|
+
this.configProvider = new Promise((resolve, reject) => {
|
|
800
|
+
if (typeof options === "function") {
|
|
801
|
+
options().then((opts) => {
|
|
802
|
+
resolve(opts || {});
|
|
803
|
+
}).catch(reject);
|
|
804
|
+
} else {
|
|
805
|
+
resolve(options || {});
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
destroy() {
|
|
810
|
+
this.connectionManager.destroy();
|
|
811
|
+
}
|
|
812
|
+
async handle(request, { abortSignal, requestTimeout } = {}) {
|
|
813
|
+
if (!this.config) {
|
|
814
|
+
this.config = await this.configProvider;
|
|
815
|
+
this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams || false);
|
|
816
|
+
if (this.config.maxConcurrentStreams) {
|
|
817
|
+
this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
const { requestTimeout: configRequestTimeout, disableConcurrentStreams } = this.config;
|
|
821
|
+
const effectiveRequestTimeout = requestTimeout ?? configRequestTimeout;
|
|
822
|
+
return new Promise((_resolve, _reject) => {
|
|
823
|
+
let fulfilled = false;
|
|
824
|
+
let writeRequestBodyPromise = void 0;
|
|
825
|
+
const resolve = async (arg) => {
|
|
826
|
+
await writeRequestBodyPromise;
|
|
827
|
+
_resolve(arg);
|
|
828
|
+
};
|
|
829
|
+
const reject = async (arg) => {
|
|
830
|
+
await writeRequestBodyPromise;
|
|
831
|
+
_reject(arg);
|
|
832
|
+
};
|
|
833
|
+
if (abortSignal?.aborted) {
|
|
834
|
+
fulfilled = true;
|
|
835
|
+
const abortError = buildAbortError(abortSignal);
|
|
836
|
+
reject(abortError);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const { hostname, method, port, protocol, query } = request;
|
|
840
|
+
let auth = "";
|
|
841
|
+
if (request.username != null || request.password != null) {
|
|
842
|
+
const username = request.username ?? "";
|
|
843
|
+
const password = request.password ?? "";
|
|
844
|
+
auth = `${username}:${password}@`;
|
|
845
|
+
}
|
|
846
|
+
const authority = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`;
|
|
847
|
+
const requestContext = { destination: new URL(authority) };
|
|
848
|
+
const session = this.connectionManager.lease(requestContext, {
|
|
849
|
+
requestTimeout: this.config?.sessionTimeout,
|
|
850
|
+
disableConcurrentStreams: disableConcurrentStreams || false
|
|
851
|
+
});
|
|
852
|
+
const rejectWithDestroy = (err) => {
|
|
853
|
+
if (disableConcurrentStreams) {
|
|
854
|
+
this.destroySession(session);
|
|
855
|
+
}
|
|
856
|
+
fulfilled = true;
|
|
857
|
+
reject(err);
|
|
858
|
+
};
|
|
859
|
+
const queryString = buildQueryString(query || {});
|
|
860
|
+
let path2 = request.path;
|
|
861
|
+
if (queryString) {
|
|
862
|
+
path2 += `?${queryString}`;
|
|
863
|
+
}
|
|
864
|
+
if (request.fragment) {
|
|
865
|
+
path2 += `#${request.fragment}`;
|
|
866
|
+
}
|
|
867
|
+
const req = session.request({
|
|
868
|
+
...request.headers,
|
|
869
|
+
[http2.constants.HTTP2_HEADER_PATH]: path2,
|
|
870
|
+
[http2.constants.HTTP2_HEADER_METHOD]: method
|
|
871
|
+
});
|
|
872
|
+
session.ref();
|
|
873
|
+
req.on("response", (headers) => {
|
|
874
|
+
const httpResponse = new HttpResponse({
|
|
875
|
+
statusCode: headers[":status"] || -1,
|
|
876
|
+
headers: getTransformedHeaders(headers),
|
|
877
|
+
body: req
|
|
878
|
+
});
|
|
879
|
+
fulfilled = true;
|
|
880
|
+
resolve({ response: httpResponse });
|
|
881
|
+
if (disableConcurrentStreams) {
|
|
882
|
+
session.close();
|
|
883
|
+
this.connectionManager.deleteSession(authority, session);
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
if (effectiveRequestTimeout) {
|
|
887
|
+
req.setTimeout(effectiveRequestTimeout, () => {
|
|
888
|
+
req.close();
|
|
889
|
+
const timeoutError = new Error(`Stream timed out because of no activity for ${effectiveRequestTimeout} ms`);
|
|
890
|
+
timeoutError.name = "TimeoutError";
|
|
891
|
+
rejectWithDestroy(timeoutError);
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
if (abortSignal) {
|
|
895
|
+
const onAbort = () => {
|
|
896
|
+
req.close();
|
|
897
|
+
const abortError = buildAbortError(abortSignal);
|
|
898
|
+
rejectWithDestroy(abortError);
|
|
899
|
+
};
|
|
900
|
+
if (typeof abortSignal.addEventListener === "function") {
|
|
901
|
+
const signal = abortSignal;
|
|
902
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
903
|
+
req.once("close", () => signal.removeEventListener("abort", onAbort));
|
|
904
|
+
} else {
|
|
905
|
+
abortSignal.onabort = onAbort;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
req.on("frameError", (type, code, id) => {
|
|
909
|
+
rejectWithDestroy(new Error(`Frame type id ${type} in stream id ${id} has failed with code ${code}.`));
|
|
910
|
+
});
|
|
911
|
+
req.on("error", rejectWithDestroy);
|
|
912
|
+
req.on("aborted", () => {
|
|
913
|
+
rejectWithDestroy(new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${req.rstCode}.`));
|
|
914
|
+
});
|
|
915
|
+
req.on("close", () => {
|
|
916
|
+
session.unref();
|
|
917
|
+
if (disableConcurrentStreams) {
|
|
918
|
+
session.destroy();
|
|
919
|
+
}
|
|
920
|
+
if (!fulfilled) {
|
|
921
|
+
rejectWithDestroy(new Error("Unexpected error: http2 request did not get a response"));
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout);
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
updateHttpClientConfig(key, value) {
|
|
928
|
+
this.config = void 0;
|
|
929
|
+
this.configProvider = this.configProvider.then((config) => {
|
|
930
|
+
return {
|
|
931
|
+
...config,
|
|
932
|
+
[key]: value
|
|
933
|
+
};
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
httpHandlerConfigs() {
|
|
937
|
+
return this.config ?? {};
|
|
938
|
+
}
|
|
939
|
+
destroySession(session) {
|
|
940
|
+
if (!session.destroyed) {
|
|
941
|
+
session.destroy();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
var Collector;
|
|
948
|
+
var init_collector = chunkG7VZBCD6_cjs.__esm({
|
|
949
|
+
"node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js"() {
|
|
950
|
+
Collector = class extends stream.Writable {
|
|
951
|
+
bufferedBytes = [];
|
|
952
|
+
_write(chunk, encoding, callback) {
|
|
953
|
+
this.bufferedBytes.push(chunk);
|
|
954
|
+
callback();
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
// node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js
|
|
961
|
+
async function collectReadableStream(stream) {
|
|
962
|
+
const chunks = [];
|
|
963
|
+
const reader = stream.getReader();
|
|
964
|
+
let isDone = false;
|
|
965
|
+
let length = 0;
|
|
966
|
+
while (!isDone) {
|
|
967
|
+
const { done, value } = await reader.read();
|
|
968
|
+
if (value) {
|
|
969
|
+
chunks.push(value);
|
|
970
|
+
length += value.length;
|
|
971
|
+
}
|
|
972
|
+
isDone = done;
|
|
973
|
+
}
|
|
974
|
+
const collected = new Uint8Array(length);
|
|
975
|
+
let offset = 0;
|
|
976
|
+
for (const chunk of chunks) {
|
|
977
|
+
collected.set(chunk, offset);
|
|
978
|
+
offset += chunk.length;
|
|
979
|
+
}
|
|
980
|
+
return collected;
|
|
981
|
+
}
|
|
982
|
+
var streamCollector, isReadableStreamInstance;
|
|
983
|
+
var init_stream_collector = chunkG7VZBCD6_cjs.__esm({
|
|
984
|
+
"node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js"() {
|
|
985
|
+
init_collector();
|
|
986
|
+
streamCollector = (stream) => {
|
|
987
|
+
if (isReadableStreamInstance(stream)) {
|
|
988
|
+
return collectReadableStream(stream);
|
|
989
|
+
}
|
|
990
|
+
return new Promise((resolve, reject) => {
|
|
991
|
+
const collector = new Collector();
|
|
992
|
+
stream.pipe(collector);
|
|
993
|
+
stream.on("error", (err) => {
|
|
994
|
+
collector.end();
|
|
995
|
+
reject(err);
|
|
996
|
+
});
|
|
997
|
+
collector.on("error", reject);
|
|
998
|
+
collector.on("finish", function() {
|
|
999
|
+
const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
|
|
1000
|
+
resolve(bytes);
|
|
1001
|
+
});
|
|
1002
|
+
});
|
|
1003
|
+
};
|
|
1004
|
+
isReadableStreamInstance = (stream) => typeof ReadableStream === "function" && stream instanceof ReadableStream;
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
// node_modules/@smithy/node-http-handler/dist-es/index.js
|
|
1009
|
+
var dist_es_exports = {};
|
|
1010
|
+
chunkG7VZBCD6_cjs.__export(dist_es_exports, {
|
|
1011
|
+
DEFAULT_REQUEST_TIMEOUT: () => DEFAULT_REQUEST_TIMEOUT,
|
|
1012
|
+
NodeHttp2Handler: () => NodeHttp2Handler,
|
|
1013
|
+
NodeHttpHandler: () => NodeHttpHandler,
|
|
1014
|
+
streamCollector: () => streamCollector
|
|
1015
|
+
});
|
|
1016
|
+
var init_dist_es4 = chunkG7VZBCD6_cjs.__esm({
|
|
1017
|
+
"node_modules/@smithy/node-http-handler/dist-es/index.js"() {
|
|
1018
|
+
init_node_http_handler();
|
|
1019
|
+
init_node_http2_handler();
|
|
1020
|
+
init_stream_collector();
|
|
1021
|
+
}
|
|
1022
|
+
});
|
|
27
1023
|
|
|
28
1024
|
// src/registry/validator.ts
|
|
29
1025
|
var ConfigValidationError = class extends Error {
|
|
@@ -377,10 +1373,7 @@ function checkboxToZod(field) {
|
|
|
377
1373
|
return schema;
|
|
378
1374
|
}
|
|
379
1375
|
function dateToZod(field) {
|
|
380
|
-
let schema = zod.z.string().refine(
|
|
381
|
-
(val) => !isNaN(Date.parse(val)),
|
|
382
|
-
"Invalid date format"
|
|
383
|
-
);
|
|
1376
|
+
let schema = zod.z.string().refine((val) => !isNaN(Date.parse(val)), "Invalid date format");
|
|
384
1377
|
if (field.minDate) {
|
|
385
1378
|
schema = schema.refine(
|
|
386
1379
|
(val) => new Date(val) >= new Date(field.minDate),
|
|
@@ -438,19 +1431,28 @@ function radioToZod(field) {
|
|
|
438
1431
|
}
|
|
439
1432
|
function colorToZod(field) {
|
|
440
1433
|
let schema = zod.z.string();
|
|
441
|
-
if (field.format === "hex")
|
|
442
|
-
|
|
443
|
-
if (field.format === "
|
|
1434
|
+
if (field.format === "hex")
|
|
1435
|
+
schema = schema.regex(/^#[0-9A-Fa-f]{6}$/);
|
|
1436
|
+
if (field.format === "rgb")
|
|
1437
|
+
schema = schema.regex(
|
|
1438
|
+
/^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/
|
|
1439
|
+
);
|
|
1440
|
+
if (field.format === "hsl")
|
|
1441
|
+
schema = schema.regex(
|
|
1442
|
+
/^hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\)$/
|
|
1443
|
+
);
|
|
444
1444
|
if (!field.required) schema = schema.optional();
|
|
445
1445
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
446
1446
|
return schema;
|
|
447
1447
|
}
|
|
448
1448
|
function richTextToZod(field) {
|
|
449
|
-
let schema = zod.z.array(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
1449
|
+
let schema = zod.z.array(
|
|
1450
|
+
zod.z.object({
|
|
1451
|
+
type: zod.z.string(),
|
|
1452
|
+
data: zod.z.record(zod.z.any()),
|
|
1453
|
+
children: zod.z.array(zod.z.any()).optional()
|
|
1454
|
+
})
|
|
1455
|
+
);
|
|
454
1456
|
if (!field.required) schema = schema.optional();
|
|
455
1457
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
456
1458
|
return schema;
|
|
@@ -516,7 +1518,8 @@ function groupToZod(field) {
|
|
|
516
1518
|
return schema;
|
|
517
1519
|
}
|
|
518
1520
|
function blocksToZod(field) {
|
|
519
|
-
const
|
|
1521
|
+
const blocks = field.blocks || [];
|
|
1522
|
+
const blockSchemas = blocks.map((block) => {
|
|
520
1523
|
return zod.z.object({
|
|
521
1524
|
blockType: zod.z.literal(block.slug),
|
|
522
1525
|
...Object.fromEntries(
|
|
@@ -524,7 +1527,9 @@ function blocksToZod(field) {
|
|
|
524
1527
|
)
|
|
525
1528
|
});
|
|
526
1529
|
});
|
|
527
|
-
let schema = zod.z.array(
|
|
1530
|
+
let schema = zod.z.array(
|
|
1531
|
+
zod.z.discriminatedUnion("blockType", blockSchemas)
|
|
1532
|
+
);
|
|
528
1533
|
if (field.minRows) schema = schema.min(field.minRows);
|
|
529
1534
|
if (field.maxRows) schema = schema.max(field.maxRows);
|
|
530
1535
|
if (!field.required) schema = schema.optional();
|
|
@@ -984,6 +1989,7 @@ var Kyro = class {
|
|
|
984
1989
|
registry;
|
|
985
1990
|
db;
|
|
986
1991
|
pubsub;
|
|
1992
|
+
settings;
|
|
987
1993
|
wsServer;
|
|
988
1994
|
config;
|
|
989
1995
|
constructor(config) {
|
|
@@ -1005,7 +2011,10 @@ var Kyro = class {
|
|
|
1005
2011
|
}
|
|
1006
2012
|
async init() {
|
|
1007
2013
|
await this.registry.init();
|
|
1008
|
-
await this.db.init(
|
|
2014
|
+
await this.db.init(
|
|
2015
|
+
this.registry.getCollections(),
|
|
2016
|
+
this.registry.getGlobals()
|
|
2017
|
+
);
|
|
1009
2018
|
this.pubsub.autoRegisterHooks();
|
|
1010
2019
|
console.log("\u2705 Kyro CMS initialized");
|
|
1011
2020
|
console.log(` Collections: ${this.registry.getCollections().length}`);
|
|
@@ -1014,34 +2023,58 @@ var Kyro = class {
|
|
|
1014
2023
|
// ============================================================================
|
|
1015
2024
|
// API Methods
|
|
1016
2025
|
// ============================================================================
|
|
2026
|
+
// Load settings from globals if not already loaded
|
|
2027
|
+
async loadSettings() {
|
|
2028
|
+
if (this.settings) return this.settings;
|
|
2029
|
+
try {
|
|
2030
|
+
const accessSettings = await this.db.findOne({
|
|
2031
|
+
collection: "_globals",
|
|
2032
|
+
where: { slug: "access-settings" }
|
|
2033
|
+
});
|
|
2034
|
+
if (accessSettings) {
|
|
2035
|
+
this.settings = accessSettings.data;
|
|
2036
|
+
}
|
|
2037
|
+
} catch (e) {
|
|
2038
|
+
console.log("\u26A0\uFE0F No access-settings found, using defaults");
|
|
2039
|
+
}
|
|
2040
|
+
return this.settings || {};
|
|
2041
|
+
}
|
|
1017
2042
|
getREST(options) {
|
|
1018
|
-
return
|
|
2043
|
+
return chunkE63IF3MD_cjs.createHonoApp({
|
|
1019
2044
|
registry: this.registry,
|
|
1020
2045
|
db: this.db,
|
|
1021
2046
|
...options,
|
|
1022
|
-
cors: this.config.cors
|
|
2047
|
+
cors: this.config.cors,
|
|
2048
|
+
settings: this.settings
|
|
1023
2049
|
});
|
|
1024
2050
|
}
|
|
1025
2051
|
getGraphQL(options) {
|
|
1026
|
-
return
|
|
2052
|
+
return chunkFTSSDDZQ_cjs.buildGraphQLSchema({
|
|
1027
2053
|
registry: this.registry,
|
|
1028
2054
|
db: this.db,
|
|
1029
|
-
...options
|
|
2055
|
+
...options,
|
|
2056
|
+
settings: this.settings
|
|
1030
2057
|
});
|
|
1031
2058
|
}
|
|
1032
2059
|
getTRPC(options) {
|
|
1033
|
-
return
|
|
2060
|
+
return chunk42JPONZU_cjs.createKyroServer({
|
|
1034
2061
|
registry: this.registry,
|
|
1035
2062
|
db: this.db,
|
|
1036
2063
|
req: options?.req || { headers: {} },
|
|
1037
|
-
...options
|
|
2064
|
+
...options,
|
|
2065
|
+
settings: this.settings
|
|
1038
2066
|
});
|
|
1039
2067
|
}
|
|
1040
2068
|
async startWebSocket(options) {
|
|
2069
|
+
const apiAccess = this.settings?.access?.apiAccess;
|
|
2070
|
+
if (apiAccess?.websocketEnabled === false) {
|
|
2071
|
+
console.log("\u26A0\uFE0F WebSocket is disabled in settings");
|
|
2072
|
+
return null;
|
|
2073
|
+
}
|
|
1041
2074
|
this.wsServer = chunkDVD5P72E_cjs.createWSServer({
|
|
1042
2075
|
pubsub: this.pubsub,
|
|
1043
2076
|
port: options?.port || 8080,
|
|
1044
|
-
requireAuth: options?.requireAuth,
|
|
2077
|
+
requireAuth: options?.requireAuth ?? apiAccess?.requireAuth,
|
|
1045
2078
|
verifyToken: options?.verifyToken
|
|
1046
2079
|
});
|
|
1047
2080
|
console.log(`\u{1F50C} WebSocket server started on port ${options?.port || 8080}`);
|
|
@@ -1084,6 +2117,9 @@ function isBlocksField(field) {
|
|
|
1084
2117
|
function isUploadField(field) {
|
|
1085
2118
|
return field.type === "upload";
|
|
1086
2119
|
}
|
|
2120
|
+
function isImageField(field) {
|
|
2121
|
+
return field.type === "image";
|
|
2122
|
+
}
|
|
1087
2123
|
function isRichTextField(field) {
|
|
1088
2124
|
return field.type === "richtext";
|
|
1089
2125
|
}
|
|
@@ -1110,6 +2146,7 @@ var COMPLEX_FIELD_TYPES = [
|
|
|
1110
2146
|
"json",
|
|
1111
2147
|
"code",
|
|
1112
2148
|
"upload",
|
|
2149
|
+
"image",
|
|
1113
2150
|
"markdown"
|
|
1114
2151
|
];
|
|
1115
2152
|
var RELATIONAL_FIELD_TYPES = [
|
|
@@ -1118,11 +2155,7 @@ var RELATIONAL_FIELD_TYPES = [
|
|
|
1118
2155
|
"group",
|
|
1119
2156
|
"blocks"
|
|
1120
2157
|
];
|
|
1121
|
-
var LAYOUT_FIELD_TYPES = [
|
|
1122
|
-
"row",
|
|
1123
|
-
"collapsible",
|
|
1124
|
-
"tabs"
|
|
1125
|
-
];
|
|
2158
|
+
var LAYOUT_FIELD_TYPES = ["row", "collapsible", "tabs"];
|
|
1126
2159
|
var ALL_FIELD_TYPES = [
|
|
1127
2160
|
...PRIMITIVE_FIELD_TYPES,
|
|
1128
2161
|
...COMPLEX_FIELD_TYPES,
|
|
@@ -1130,6 +2163,414 @@ var ALL_FIELD_TYPES = [
|
|
|
1130
2163
|
...LAYOUT_FIELD_TYPES
|
|
1131
2164
|
];
|
|
1132
2165
|
|
|
2166
|
+
// src/fields/richtext.ts
|
|
2167
|
+
var MIN_COLUMNS = 1;
|
|
2168
|
+
var MAX_COLUMNS = 6;
|
|
2169
|
+
var richTextStyles = `
|
|
2170
|
+
.kyro-richtext {
|
|
2171
|
+
color: inherit;
|
|
2172
|
+
line-height: 1.7;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
.kyro-richtext > *:first-child {
|
|
2176
|
+
margin-top: 0;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
.kyro-richtext > *:last-child {
|
|
2180
|
+
margin-bottom: 0;
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
.kyro-richtext p,
|
|
2184
|
+
.kyro-richtext ul,
|
|
2185
|
+
.kyro-richtext ol,
|
|
2186
|
+
.kyro-richtext blockquote,
|
|
2187
|
+
.kyro-richtext pre,
|
|
2188
|
+
.kyro-richtext kyro-callout,
|
|
2189
|
+
.kyro-richtext kyro-hero,
|
|
2190
|
+
.kyro-richtext kyro-heading,
|
|
2191
|
+
.kyro-richtext kyro-stack,
|
|
2192
|
+
.kyro-richtext kyro-columns {
|
|
2193
|
+
margin: 0 0 1rem;
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
.kyro-richtext h1,
|
|
2197
|
+
.kyro-richtext h2,
|
|
2198
|
+
.kyro-richtext h3,
|
|
2199
|
+
.kyro-richtext h4,
|
|
2200
|
+
.kyro-richtext h5,
|
|
2201
|
+
.kyro-richtext h6 {
|
|
2202
|
+
margin: 0 0 0.75rem;
|
|
2203
|
+
line-height: 1.2;
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
.kyro-richtext ul,
|
|
2207
|
+
.kyro-richtext ol {
|
|
2208
|
+
padding-left: 1.5rem;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
.kyro-richtext blockquote {
|
|
2212
|
+
border-left: 4px solid rgba(148, 163, 184, 0.5);
|
|
2213
|
+
margin-left: 0;
|
|
2214
|
+
padding-left: 1rem;
|
|
2215
|
+
font-style: italic;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
.kyro-richtext pre {
|
|
2219
|
+
overflow-x: auto;
|
|
2220
|
+
border-radius: 0.75rem;
|
|
2221
|
+
background: rgba(15, 23, 42, 0.92);
|
|
2222
|
+
color: #f8fafc;
|
|
2223
|
+
padding: 1rem;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
.kyro-richtext code {
|
|
2227
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
.kyro-richtext img {
|
|
2231
|
+
display: block;
|
|
2232
|
+
max-width: 100%;
|
|
2233
|
+
height: auto;
|
|
2234
|
+
border-radius: 0.75rem;
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
.kyro-richtext kyro-columns {
|
|
2238
|
+
display: grid;
|
|
2239
|
+
grid-template-columns: repeat(var(--kyro-columns-count, 1), minmax(0, 1fr));
|
|
2240
|
+
gap: 1rem;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
.kyro-richtext kyro-column {
|
|
2244
|
+
display: block;
|
|
2245
|
+
min-width: 0;
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
.kyro-richtext kyro-column > *:last-child {
|
|
2249
|
+
margin-bottom: 0;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
.kyro-richtext kyro-hero,
|
|
2253
|
+
.kyro-richtext kyro-callout,
|
|
2254
|
+
.kyro-richtext kyro-stack,
|
|
2255
|
+
.kyro-richtext kyro-heading {
|
|
2256
|
+
display: block;
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
.kyro-richtext kyro-hero {
|
|
2260
|
+
border: 1px solid rgba(148, 163, 184, 0.25);
|
|
2261
|
+
border-radius: 1rem;
|
|
2262
|
+
padding: 1.5rem;
|
|
2263
|
+
text-align: center;
|
|
2264
|
+
background: linear-gradient(to bottom, rgba(148, 163, 184, 0.12), transparent);
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
.kyro-richtext kyro-heading {
|
|
2268
|
+
font-size: 1.125rem;
|
|
2269
|
+
font-weight: 700;
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
.kyro-richtext kyro-callout {
|
|
2273
|
+
border: 1px solid rgba(59, 130, 246, 0.25);
|
|
2274
|
+
border-radius: 0.875rem;
|
|
2275
|
+
padding: 0.875rem 1rem;
|
|
2276
|
+
background: rgba(59, 130, 246, 0.06);
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
@media (max-width: 720px) {
|
|
2280
|
+
.kyro-richtext kyro-columns {
|
|
2281
|
+
grid-template-columns: 1fr;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
`.trim();
|
|
2285
|
+
function createEmptyParagraphNode() {
|
|
2286
|
+
return {
|
|
2287
|
+
type: "paragraph",
|
|
2288
|
+
content: []
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
function createColumnNode(content = [createEmptyParagraphNode()]) {
|
|
2292
|
+
return {
|
|
2293
|
+
type: "kyroColumn",
|
|
2294
|
+
content: content.length > 0 ? content : [createEmptyParagraphNode()]
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
function createColumnsNode(columns = 2) {
|
|
2298
|
+
const count = clampColumns(columns);
|
|
2299
|
+
return {
|
|
2300
|
+
type: "kyroColumns",
|
|
2301
|
+
attrs: { columns: count },
|
|
2302
|
+
content: Array.from({ length: count }, () => createColumnNode())
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
function normalizeRichTextDocument(value) {
|
|
2306
|
+
const documentNode = toRichTextDocument(value);
|
|
2307
|
+
return {
|
|
2308
|
+
type: "doc",
|
|
2309
|
+
content: normalizeNodes(documentNode.content)
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
function normalizeRichTextValue(value) {
|
|
2313
|
+
if (Array.isArray(value)) {
|
|
2314
|
+
return normalizeRichTextDocument(value).content;
|
|
2315
|
+
}
|
|
2316
|
+
if (isObject(value) && value.type === "doc") {
|
|
2317
|
+
return normalizeRichTextDocument(value);
|
|
2318
|
+
}
|
|
2319
|
+
return value;
|
|
2320
|
+
}
|
|
2321
|
+
function renderRichText(value) {
|
|
2322
|
+
if (typeof value === "string") {
|
|
2323
|
+
return `<div class="kyro-richtext">${value}</div>`;
|
|
2324
|
+
}
|
|
2325
|
+
const documentNode = normalizeRichTextDocument(value);
|
|
2326
|
+
return `<div class="kyro-richtext">${renderNodes(documentNode.content)}</div>`;
|
|
2327
|
+
}
|
|
2328
|
+
function toRichTextDocument(value) {
|
|
2329
|
+
if (Array.isArray(value)) {
|
|
2330
|
+
return {
|
|
2331
|
+
type: "doc",
|
|
2332
|
+
content: normalizeNodes(value)
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
if (isObject(value) && value.type === "doc") {
|
|
2336
|
+
const doc = value;
|
|
2337
|
+
return {
|
|
2338
|
+
type: "doc",
|
|
2339
|
+
content: normalizeNodes(doc.content ?? [])
|
|
2340
|
+
};
|
|
2341
|
+
}
|
|
2342
|
+
return {
|
|
2343
|
+
type: "doc",
|
|
2344
|
+
content: []
|
|
2345
|
+
};
|
|
2346
|
+
}
|
|
2347
|
+
function normalizeNodes(nodes) {
|
|
2348
|
+
return nodes.filter((node) => isObject(node) && typeof node.type === "string").map((node) => normalizeNode(node));
|
|
2349
|
+
}
|
|
2350
|
+
function normalizeNode(node) {
|
|
2351
|
+
if (node.type === "kyroColumns") {
|
|
2352
|
+
return normalizeColumnsNode(node);
|
|
2353
|
+
}
|
|
2354
|
+
if (node.type === "kyroColumn") {
|
|
2355
|
+
const normalizedContent = normalizeNodes(
|
|
2356
|
+
Array.isArray(node.content) ? node.content : []
|
|
2357
|
+
).filter((child) => child.type !== "kyroColumns");
|
|
2358
|
+
return {
|
|
2359
|
+
...node,
|
|
2360
|
+
content: normalizedContent.length > 0 ? normalizedContent : [createEmptyParagraphNode()]
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
if (Array.isArray(node.content)) {
|
|
2364
|
+
return {
|
|
2365
|
+
...node,
|
|
2366
|
+
content: normalizeNodes(node.content)
|
|
2367
|
+
};
|
|
2368
|
+
}
|
|
2369
|
+
return {
|
|
2370
|
+
...node
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
function normalizeColumnsNode(node) {
|
|
2374
|
+
const rawChildren = Array.isArray(node.content) ? node.content : [];
|
|
2375
|
+
const hasStructuredColumns = rawChildren.every((child) => child?.type === "kyroColumn");
|
|
2376
|
+
const targetColumns = clampColumns(
|
|
2377
|
+
typeof node.attrs?.columns === "number" ? node.attrs.columns : hasStructuredColumns && rawChildren.length > 0 ? rawChildren.length : 2
|
|
2378
|
+
);
|
|
2379
|
+
const content = hasStructuredColumns ? normalizeStructuredColumns(rawChildren, targetColumns) : normalizeLegacyColumns(rawChildren, targetColumns);
|
|
2380
|
+
return {
|
|
2381
|
+
...node,
|
|
2382
|
+
attrs: {
|
|
2383
|
+
...node.attrs ?? {},
|
|
2384
|
+
columns: content.length
|
|
2385
|
+
},
|
|
2386
|
+
content
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
function normalizeStructuredColumns(columns, targetColumns) {
|
|
2390
|
+
const normalized = columns.slice(0, MAX_COLUMNS).map((column) => normalizeNode(column)).filter((column) => column.type === "kyroColumn");
|
|
2391
|
+
if (normalized.length === 0) {
|
|
2392
|
+
return Array.from({ length: targetColumns }, () => createColumnNode());
|
|
2393
|
+
}
|
|
2394
|
+
if (normalized.length > targetColumns) {
|
|
2395
|
+
const kept = normalized.slice(0, targetColumns);
|
|
2396
|
+
const extras = normalized.slice(targetColumns);
|
|
2397
|
+
const mergedTail = extras.flatMap(
|
|
2398
|
+
(column) => normalizeColumnChildren(column.content)
|
|
2399
|
+
);
|
|
2400
|
+
const lastIndex = kept.length - 1;
|
|
2401
|
+
kept[lastIndex] = createColumnNode([
|
|
2402
|
+
...normalizeColumnChildren(kept[lastIndex].content),
|
|
2403
|
+
...mergedTail
|
|
2404
|
+
]);
|
|
2405
|
+
return kept;
|
|
2406
|
+
}
|
|
2407
|
+
if (normalized.length < targetColumns) {
|
|
2408
|
+
return [
|
|
2409
|
+
...normalized,
|
|
2410
|
+
...Array.from(
|
|
2411
|
+
{ length: targetColumns - normalized.length },
|
|
2412
|
+
() => createColumnNode()
|
|
2413
|
+
)
|
|
2414
|
+
];
|
|
2415
|
+
}
|
|
2416
|
+
return normalized;
|
|
2417
|
+
}
|
|
2418
|
+
function normalizeLegacyColumns(blocks, targetColumns) {
|
|
2419
|
+
const normalizedBlocks = normalizeNodes(blocks);
|
|
2420
|
+
return Array.from({ length: targetColumns }, (_, index) => {
|
|
2421
|
+
if (index < targetColumns - 1) {
|
|
2422
|
+
const block = normalizedBlocks[index];
|
|
2423
|
+
return block ? createColumnNode([block]) : createColumnNode();
|
|
2424
|
+
}
|
|
2425
|
+
const tail = normalizedBlocks.slice(index);
|
|
2426
|
+
return createColumnNode(tail.length > 0 ? tail : [createEmptyParagraphNode()]);
|
|
2427
|
+
});
|
|
2428
|
+
}
|
|
2429
|
+
function normalizeColumnChildren(content) {
|
|
2430
|
+
const children = Array.isArray(content) ? normalizeNodes(content) : [];
|
|
2431
|
+
const filtered = children.filter((child) => child.type !== "kyroColumns");
|
|
2432
|
+
return filtered.length > 0 ? filtered : [createEmptyParagraphNode()];
|
|
2433
|
+
}
|
|
2434
|
+
function renderNodes(nodes) {
|
|
2435
|
+
return nodes.map((node) => renderNode(node)).join("");
|
|
2436
|
+
}
|
|
2437
|
+
function renderNode(node) {
|
|
2438
|
+
switch (node.type) {
|
|
2439
|
+
case "paragraph":
|
|
2440
|
+
return `<p>${renderInlineContent(node.content)}</p>`;
|
|
2441
|
+
case "text":
|
|
2442
|
+
return renderTextNode(node);
|
|
2443
|
+
case "heading": {
|
|
2444
|
+
const level = clampHeadingLevel(node.attrs?.level);
|
|
2445
|
+
return `<h${level}>${renderInlineContent(node.content)}</h${level}>`;
|
|
2446
|
+
}
|
|
2447
|
+
case "bulletList":
|
|
2448
|
+
return `<ul>${renderNodes(node.content ?? [])}</ul>`;
|
|
2449
|
+
case "orderedList":
|
|
2450
|
+
return `<ol>${renderNodes(node.content ?? [])}</ol>`;
|
|
2451
|
+
case "listItem":
|
|
2452
|
+
return `<li>${renderNodes(node.content ?? [])}</li>`;
|
|
2453
|
+
case "blockquote":
|
|
2454
|
+
return `<blockquote>${renderNodes(node.content ?? [])}</blockquote>`;
|
|
2455
|
+
case "codeBlock":
|
|
2456
|
+
return `<pre><code>${escapeHtml(extractText(node.content ?? []))}</code></pre>`;
|
|
2457
|
+
case "horizontalRule":
|
|
2458
|
+
return "<hr />";
|
|
2459
|
+
case "hardBreak":
|
|
2460
|
+
return "<br />";
|
|
2461
|
+
case "image":
|
|
2462
|
+
return renderImageNode(node);
|
|
2463
|
+
case "kyroColumns": {
|
|
2464
|
+
const columns = clampColumns(
|
|
2465
|
+
Array.isArray(node.content) ? node.content.length : 1
|
|
2466
|
+
);
|
|
2467
|
+
return `<kyro-columns data-columns="${columns}" style="--kyro-columns-count:${columns}">${renderNodes(node.content ?? [])}</kyro-columns>`;
|
|
2468
|
+
}
|
|
2469
|
+
case "kyroColumn":
|
|
2470
|
+
return `<kyro-column>${renderNodes(node.content ?? [])}</kyro-column>`;
|
|
2471
|
+
case "kyroHero":
|
|
2472
|
+
return `<kyro-hero>${renderInlineContent(node.content)}</kyro-hero>`;
|
|
2473
|
+
case "kyroHeading":
|
|
2474
|
+
return `<kyro-heading>${renderInlineContent(node.content)}</kyro-heading>`;
|
|
2475
|
+
case "kyroDivider":
|
|
2476
|
+
return '<hr class="kyro-divider" />';
|
|
2477
|
+
case "kyroCallout":
|
|
2478
|
+
return `<kyro-callout>${renderInlineContent(node.content)}</kyro-callout>`;
|
|
2479
|
+
case "kyroStack":
|
|
2480
|
+
return `<kyro-stack>${renderNodes(node.content ?? [])}</kyro-stack>`;
|
|
2481
|
+
case "kyroImage":
|
|
2482
|
+
return renderCustomMediaNode("kyro-image", node);
|
|
2483
|
+
case "kyroVideo":
|
|
2484
|
+
return renderCustomMediaNode("kyro-video", node);
|
|
2485
|
+
default:
|
|
2486
|
+
return renderNodes(node.content ?? []);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
function renderInlineContent(content) {
|
|
2490
|
+
const nodes = content ?? [];
|
|
2491
|
+
if (nodes.length === 0) {
|
|
2492
|
+
return "<br />";
|
|
2493
|
+
}
|
|
2494
|
+
return nodes.map((node) => renderNode(node)).join("");
|
|
2495
|
+
}
|
|
2496
|
+
function renderTextNode(node) {
|
|
2497
|
+
const text = typeof node.text === "string" ? escapeHtml(node.text) : "";
|
|
2498
|
+
return (node.marks ?? []).reduce((acc, mark) => applyMark(acc, mark), text);
|
|
2499
|
+
}
|
|
2500
|
+
function renderImageNode(node) {
|
|
2501
|
+
const src = typeof node.attrs?.src === "string" ? node.attrs.src : "";
|
|
2502
|
+
if (!src) {
|
|
2503
|
+
return "";
|
|
2504
|
+
}
|
|
2505
|
+
const alt = typeof node.attrs?.alt === "string" ? node.attrs.alt : "";
|
|
2506
|
+
return `<img src="${escapeAttribute(src)}" alt="${escapeAttribute(alt)}" />`;
|
|
2507
|
+
}
|
|
2508
|
+
function renderCustomMediaNode(tagName, node) {
|
|
2509
|
+
const attrs = renderAttributes(node.attrs);
|
|
2510
|
+
return `<${tagName}${attrs}></${tagName}>`;
|
|
2511
|
+
}
|
|
2512
|
+
function renderAttributes(attrs, keysToSkip = []) {
|
|
2513
|
+
if (!attrs) {
|
|
2514
|
+
return "";
|
|
2515
|
+
}
|
|
2516
|
+
const entries = Object.entries(attrs).filter(([key, value]) => !keysToSkip.includes(key) && value !== void 0 && value !== null).map(([key, value]) => `${key}="${escapeAttribute(String(value))}"`);
|
|
2517
|
+
return entries.length > 0 ? ` ${entries.join(" ")}` : "";
|
|
2518
|
+
}
|
|
2519
|
+
function applyMark(content, mark) {
|
|
2520
|
+
switch (mark.type) {
|
|
2521
|
+
case "bold":
|
|
2522
|
+
return `<strong>${content}</strong>`;
|
|
2523
|
+
case "italic":
|
|
2524
|
+
return `<em>${content}</em>`;
|
|
2525
|
+
case "underline":
|
|
2526
|
+
return `<u>${content}</u>`;
|
|
2527
|
+
case "strike":
|
|
2528
|
+
return `<s>${content}</s>`;
|
|
2529
|
+
case "code":
|
|
2530
|
+
return `<code>${content}</code>`;
|
|
2531
|
+
case "link": {
|
|
2532
|
+
const href = typeof mark.attrs?.href === "string" ? escapeAttribute(mark.attrs.href) : "#";
|
|
2533
|
+
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${content}</a>`;
|
|
2534
|
+
}
|
|
2535
|
+
default:
|
|
2536
|
+
return content;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
function extractText(nodes) {
|
|
2540
|
+
return nodes.map((node) => {
|
|
2541
|
+
if (node.type === "text") {
|
|
2542
|
+
return typeof node.text === "string" ? node.text : "";
|
|
2543
|
+
}
|
|
2544
|
+
if (node.type === "hardBreak") {
|
|
2545
|
+
return "\n";
|
|
2546
|
+
}
|
|
2547
|
+
return extractText(node.content ?? []);
|
|
2548
|
+
}).join("");
|
|
2549
|
+
}
|
|
2550
|
+
function clampColumns(value) {
|
|
2551
|
+
const numericValue = typeof value === "number" ? value : Number(value);
|
|
2552
|
+
if (!Number.isFinite(numericValue)) {
|
|
2553
|
+
return 2;
|
|
2554
|
+
}
|
|
2555
|
+
return Math.max(MIN_COLUMNS, Math.min(MAX_COLUMNS, Math.round(numericValue)));
|
|
2556
|
+
}
|
|
2557
|
+
function clampHeadingLevel(level) {
|
|
2558
|
+
const numericLevel = typeof level === "number" ? level : Number(level);
|
|
2559
|
+
if (!Number.isFinite(numericLevel)) {
|
|
2560
|
+
return 2;
|
|
2561
|
+
}
|
|
2562
|
+
return Math.max(1, Math.min(6, Math.round(numericLevel)));
|
|
2563
|
+
}
|
|
2564
|
+
function escapeHtml(value) {
|
|
2565
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
2566
|
+
}
|
|
2567
|
+
function escapeAttribute(value) {
|
|
2568
|
+
return escapeHtml(value).replaceAll('"', """);
|
|
2569
|
+
}
|
|
2570
|
+
function isObject(value) {
|
|
2571
|
+
return typeof value === "object" && value !== null;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
1133
2574
|
// src/hooks/types.ts
|
|
1134
2575
|
async function runHooks(hooks, args) {
|
|
1135
2576
|
let result = args.data;
|
|
@@ -1649,9 +3090,19 @@ var SEOPLugin = class extends KyroPlugin {
|
|
|
1649
3090
|
slug: "seo-settings",
|
|
1650
3091
|
label: "SEO Settings",
|
|
1651
3092
|
fields: [
|
|
1652
|
-
{
|
|
1653
|
-
|
|
1654
|
-
|
|
3093
|
+
{
|
|
3094
|
+
name: "sitemap",
|
|
3095
|
+
type: "checkbox",
|
|
3096
|
+
label: "Enable Sitemap",
|
|
3097
|
+
defaultValue: true
|
|
3098
|
+
},
|
|
3099
|
+
{ name: "robotsTxt", type: "richtext", label: "robots.txt Content" },
|
|
3100
|
+
{
|
|
3101
|
+
name: "canonicalUrl",
|
|
3102
|
+
type: "text",
|
|
3103
|
+
variant: "url",
|
|
3104
|
+
label: "Canonical URL"
|
|
3105
|
+
},
|
|
1655
3106
|
{ name: "ogImage", type: "text", label: "Default OG Image URL" }
|
|
1656
3107
|
]
|
|
1657
3108
|
});
|
|
@@ -1683,7 +3134,7 @@ var CommentsPlugin = class extends KyroPlugin {
|
|
|
1683
3134
|
slug: "comments",
|
|
1684
3135
|
label: "Comments",
|
|
1685
3136
|
fields: [
|
|
1686
|
-
{ name: "content", type: "
|
|
3137
|
+
{ name: "content", type: "richtext", required: true },
|
|
1687
3138
|
{ name: "author", type: "text", required: true },
|
|
1688
3139
|
{ name: "email", type: "email" },
|
|
1689
3140
|
{ name: "approved", type: "checkbox", defaultValue: false },
|
|
@@ -1705,12 +3156,22 @@ var ReviewsPlugin = class extends KyroPlugin {
|
|
|
1705
3156
|
fields: [
|
|
1706
3157
|
{ name: "rating", type: "number", required: true, min: 1, max: 5 },
|
|
1707
3158
|
{ name: "title", type: "text" },
|
|
1708
|
-
{ name: "content", type: "
|
|
3159
|
+
{ name: "content", type: "richtext", required: true },
|
|
1709
3160
|
{ name: "author", type: "relationship", relationTo: "customers" },
|
|
1710
|
-
{
|
|
3161
|
+
{
|
|
3162
|
+
name: "product",
|
|
3163
|
+
type: "relationship",
|
|
3164
|
+
relationTo: "products",
|
|
3165
|
+
required: true
|
|
3166
|
+
},
|
|
1711
3167
|
{ name: "approved", type: "checkbox", defaultValue: false },
|
|
1712
3168
|
{ name: "verified", type: "checkbox", label: "Verified Purchase" },
|
|
1713
|
-
{
|
|
3169
|
+
{
|
|
3170
|
+
name: "helpful",
|
|
3171
|
+
type: "number",
|
|
3172
|
+
label: "Helpful Count",
|
|
3173
|
+
defaultValue: 0
|
|
3174
|
+
}
|
|
1714
3175
|
]
|
|
1715
3176
|
});
|
|
1716
3177
|
this.adminComponents["ReviewModeration"] = {};
|
|
@@ -1724,24 +3185,47 @@ var WishlistPlugin = class extends KyroPlugin {
|
|
|
1724
3185
|
slug: "wishlists",
|
|
1725
3186
|
label: "Wishlists",
|
|
1726
3187
|
fields: [
|
|
1727
|
-
{
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
3188
|
+
{
|
|
3189
|
+
name: "customer",
|
|
3190
|
+
type: "relationship",
|
|
3191
|
+
relationTo: "customers",
|
|
3192
|
+
required: true
|
|
3193
|
+
},
|
|
3194
|
+
{
|
|
3195
|
+
name: "name",
|
|
3196
|
+
type: "text",
|
|
3197
|
+
label: "Wishlist Name",
|
|
3198
|
+
defaultValue: "My Wishlist"
|
|
3199
|
+
},
|
|
3200
|
+
{
|
|
3201
|
+
name: "items",
|
|
3202
|
+
type: "blocks",
|
|
3203
|
+
label: "Items",
|
|
3204
|
+
blocks: [
|
|
3205
|
+
{
|
|
3206
|
+
slug: "wishlist-item",
|
|
3207
|
+
label: "Item",
|
|
3208
|
+
fields: [
|
|
3209
|
+
{
|
|
3210
|
+
name: "product",
|
|
3211
|
+
type: "relationship",
|
|
3212
|
+
relationTo: "products"
|
|
3213
|
+
},
|
|
3214
|
+
{ name: "quantity", type: "number", defaultValue: 1 },
|
|
3215
|
+
{ name: "addedAt", type: "date" },
|
|
3216
|
+
{
|
|
3217
|
+
name: "priority",
|
|
3218
|
+
type: "select",
|
|
3219
|
+
options: [
|
|
3220
|
+
{ label: "Low", value: "low" },
|
|
3221
|
+
{ label: "Medium", value: "medium" },
|
|
3222
|
+
{ label: "High", value: "high" }
|
|
3223
|
+
]
|
|
3224
|
+
}
|
|
3225
|
+
]
|
|
3226
|
+
}
|
|
3227
|
+
]
|
|
3228
|
+
}
|
|
1745
3229
|
]
|
|
1746
3230
|
});
|
|
1747
3231
|
}
|
|
@@ -1754,253 +3238,6 @@ var presetPlugins = {
|
|
|
1754
3238
|
Wishlist: WishlistPlugin
|
|
1755
3239
|
};
|
|
1756
3240
|
|
|
1757
|
-
// src/styling/index.ts
|
|
1758
|
-
var CSSGenerator = class {
|
|
1759
|
-
constructor(config) {
|
|
1760
|
-
this.config = config;
|
|
1761
|
-
}
|
|
1762
|
-
config;
|
|
1763
|
-
css = [];
|
|
1764
|
-
addRule(selector, properties) {
|
|
1765
|
-
const props = Object.entries(properties).map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
1766
|
-
this.css.push(`${selector} {
|
|
1767
|
-
${props}
|
|
1768
|
-
}`);
|
|
1769
|
-
return this;
|
|
1770
|
-
}
|
|
1771
|
-
addMediaQuery(breakpoint, rules) {
|
|
1772
|
-
this.css.push(`@media (min-width: ${breakpoint}) {
|
|
1773
|
-
${rules.join("\n ")}
|
|
1774
|
-
}`);
|
|
1775
|
-
return this;
|
|
1776
|
-
}
|
|
1777
|
-
generate() {
|
|
1778
|
-
return this.css.join("\n\n");
|
|
1779
|
-
}
|
|
1780
|
-
};
|
|
1781
|
-
function generateTailwindConfig(theme) {
|
|
1782
|
-
return {
|
|
1783
|
-
theme: {
|
|
1784
|
-
extend: {
|
|
1785
|
-
colors: theme.colors || {},
|
|
1786
|
-
fontFamily: theme.fonts || {},
|
|
1787
|
-
spacing: theme.spacing || {},
|
|
1788
|
-
borderRadius: theme.borderRadius || {},
|
|
1789
|
-
boxShadow: theme.shadows || {},
|
|
1790
|
-
screens: theme.breakpoints || {}
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
var defaultLightTheme = {
|
|
1796
|
-
colors: {
|
|
1797
|
-
primary: "#3b82f6",
|
|
1798
|
-
secondary: "#6366f1",
|
|
1799
|
-
accent: "#ec4899",
|
|
1800
|
-
background: "#ffffff",
|
|
1801
|
-
surface: "#f9fafb",
|
|
1802
|
-
text: "#111827",
|
|
1803
|
-
textMuted: "#6b7280",
|
|
1804
|
-
border: "#e5e7eb",
|
|
1805
|
-
error: "#ef4444",
|
|
1806
|
-
warning: "#f59e0b",
|
|
1807
|
-
success: "#10b981",
|
|
1808
|
-
info: "#3b82f6"
|
|
1809
|
-
},
|
|
1810
|
-
fonts: {
|
|
1811
|
-
sans: "system-ui, -apple-system, sans-serif",
|
|
1812
|
-
serif: "Georgia, serif",
|
|
1813
|
-
mono: "Menlo, monospace"
|
|
1814
|
-
},
|
|
1815
|
-
spacing: {
|
|
1816
|
-
xs: "0.25rem",
|
|
1817
|
-
sm: "0.5rem",
|
|
1818
|
-
md: "1rem",
|
|
1819
|
-
lg: "1.5rem",
|
|
1820
|
-
xl: "2rem",
|
|
1821
|
-
"2xl": "3rem",
|
|
1822
|
-
"3xl": "4rem"
|
|
1823
|
-
},
|
|
1824
|
-
borderRadius: {
|
|
1825
|
-
sm: "0.125rem",
|
|
1826
|
-
md: "0.375rem",
|
|
1827
|
-
lg: "0.5rem",
|
|
1828
|
-
xl: "0.75rem",
|
|
1829
|
-
full: "9999px"
|
|
1830
|
-
},
|
|
1831
|
-
shadows: {
|
|
1832
|
-
sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
1833
|
-
md: "0 4px 6px -1px rgb(0 0 0 / 0.1)",
|
|
1834
|
-
lg: "0 10px 15px -3px rgb(0 0 0 / 0.1)",
|
|
1835
|
-
xl: "0 20px 25px -5px rgb(0 0 0 / 0.1)"
|
|
1836
|
-
}
|
|
1837
|
-
};
|
|
1838
|
-
var defaultDarkTheme = {
|
|
1839
|
-
colors: {
|
|
1840
|
-
primary: "#60a5fa",
|
|
1841
|
-
secondary: "#818cf8",
|
|
1842
|
-
accent: "#f472b6",
|
|
1843
|
-
background: "#111827",
|
|
1844
|
-
surface: "#1f2937",
|
|
1845
|
-
text: "#f9fafb",
|
|
1846
|
-
textMuted: "#9ca3af",
|
|
1847
|
-
border: "#374151",
|
|
1848
|
-
error: "#f87171",
|
|
1849
|
-
warning: "#fbbf24",
|
|
1850
|
-
success: "#34d399",
|
|
1851
|
-
info: "#60a5fa"
|
|
1852
|
-
},
|
|
1853
|
-
fonts: defaultLightTheme.fonts,
|
|
1854
|
-
spacing: defaultLightTheme.spacing,
|
|
1855
|
-
borderRadius: defaultLightTheme.borderRadius,
|
|
1856
|
-
shadows: {
|
|
1857
|
-
sm: "0 1px 2px 0 rgb(0 0 0 / 0.3)",
|
|
1858
|
-
md: "0 4px 6px -1px rgb(0 0 0 / 0.4)",
|
|
1859
|
-
lg: "0 10px 15px -3px rgb(0 0 0 / 0.5)",
|
|
1860
|
-
xl: "0 20px 25px -5px rgb(0 0 0 / 0.6)"
|
|
1861
|
-
}
|
|
1862
|
-
};
|
|
1863
|
-
var ecommerce2026Theme = {
|
|
1864
|
-
colors: {
|
|
1865
|
-
primary: "#FF6B35",
|
|
1866
|
-
secondary: "#1A1A2E",
|
|
1867
|
-
accent: "#16C79A",
|
|
1868
|
-
background: "#FFFFFF",
|
|
1869
|
-
surface: "#F8F9FA",
|
|
1870
|
-
text: "#1A1A2E",
|
|
1871
|
-
textMuted: "#6B7280",
|
|
1872
|
-
border: "#E5E7EB",
|
|
1873
|
-
error: "#EF4444",
|
|
1874
|
-
warning: "#F59E0B",
|
|
1875
|
-
success: "#16C79A",
|
|
1876
|
-
info: "#3B82F6"
|
|
1877
|
-
},
|
|
1878
|
-
fonts: {
|
|
1879
|
-
sans: '"Inter", "Satoshi", system-ui, sans-serif',
|
|
1880
|
-
serif: '"Playfair Display", Georgia, serif',
|
|
1881
|
-
mono: '"JetBrains Mono", monospace'
|
|
1882
|
-
},
|
|
1883
|
-
spacing: {
|
|
1884
|
-
xs: "0.125rem",
|
|
1885
|
-
sm: "0.25rem",
|
|
1886
|
-
md: "0.5rem",
|
|
1887
|
-
lg: "1rem",
|
|
1888
|
-
xl: "1.5rem",
|
|
1889
|
-
"2xl": "2rem",
|
|
1890
|
-
"3xl": "3rem",
|
|
1891
|
-
"4xl": "4rem"
|
|
1892
|
-
},
|
|
1893
|
-
borderRadius: {
|
|
1894
|
-
sm: "0",
|
|
1895
|
-
md: "0",
|
|
1896
|
-
lg: "0",
|
|
1897
|
-
xl: "0",
|
|
1898
|
-
full: "9999px"
|
|
1899
|
-
},
|
|
1900
|
-
shadows: {
|
|
1901
|
-
sm: "0 1px 2px rgba(0,0,0,0.05)",
|
|
1902
|
-
md: "0 4px 6px rgba(0,0,0,0.07)",
|
|
1903
|
-
lg: "0 10px 15px rgba(0,0,0,0.1)",
|
|
1904
|
-
xl: "0 20px 25px rgba(0,0,0,0.15)"
|
|
1905
|
-
}
|
|
1906
|
-
};
|
|
1907
|
-
function generateCSSVariables(theme) {
|
|
1908
|
-
const variables = [];
|
|
1909
|
-
if (theme.colors) {
|
|
1910
|
-
for (const [key, value] of Object.entries(theme.colors)) {
|
|
1911
|
-
variables.push(` --color-${key}: ${value};`);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
if (theme.fonts) {
|
|
1915
|
-
for (const [key, value] of Object.entries(theme.fonts)) {
|
|
1916
|
-
variables.push(` --font-${key}: ${value};`);
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
if (theme.spacing) {
|
|
1920
|
-
for (const [key, value] of Object.entries(theme.spacing)) {
|
|
1921
|
-
variables.push(` --spacing-${key}: ${value};`);
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
if (theme.borderRadius) {
|
|
1925
|
-
for (const [key, value] of Object.entries(theme.borderRadius)) {
|
|
1926
|
-
variables.push(` --radius-${key}: ${value};`);
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
if (theme.shadows) {
|
|
1930
|
-
for (const [key, value] of Object.entries(theme.shadows)) {
|
|
1931
|
-
variables.push(` --shadow-${key}: ${value};`);
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
return `:root {
|
|
1935
|
-
${variables.join("\n")}
|
|
1936
|
-
}`;
|
|
1937
|
-
}
|
|
1938
|
-
function createAdminStyling(config) {
|
|
1939
|
-
const cssVars = generateCSSVariables(config.theme || defaultLightTheme);
|
|
1940
|
-
const componentStyles = [];
|
|
1941
|
-
if (config.componentOverrides) {
|
|
1942
|
-
for (const [selector, styles] of Object.entries(config.componentOverrides)) {
|
|
1943
|
-
const props = Object.entries(styles).map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
1944
|
-
componentStyles.push(`${selector} {
|
|
1945
|
-
${props}
|
|
1946
|
-
}`);
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
return `
|
|
1950
|
-
${cssVars}
|
|
1951
|
-
${config.customStyles || ""}
|
|
1952
|
-
${componentStyles.join("\n")}
|
|
1953
|
-
`;
|
|
1954
|
-
}
|
|
1955
|
-
var defaultFieldStyling = {
|
|
1956
|
-
text: {
|
|
1957
|
-
wrapper: { marginBottom: "var(--spacing-md)" },
|
|
1958
|
-
label: {
|
|
1959
|
-
display: "block",
|
|
1960
|
-
marginBottom: "var(--spacing-xs)",
|
|
1961
|
-
fontWeight: "500",
|
|
1962
|
-
color: "var(--color-text)"
|
|
1963
|
-
},
|
|
1964
|
-
input: {
|
|
1965
|
-
width: "100%",
|
|
1966
|
-
padding: "var(--spacing-sm) var(--spacing-md)",
|
|
1967
|
-
border: "1px solid var(--color-border)",
|
|
1968
|
-
borderRadius: "var(--radius-md)",
|
|
1969
|
-
fontSize: "0.875rem"
|
|
1970
|
-
},
|
|
1971
|
-
error: {
|
|
1972
|
-
color: "var(--color-error)",
|
|
1973
|
-
fontSize: "0.75rem",
|
|
1974
|
-
marginTop: "var(--spacing-xs)"
|
|
1975
|
-
}
|
|
1976
|
-
},
|
|
1977
|
-
number: {
|
|
1978
|
-
wrapper: { marginBottom: "var(--spacing-md)" },
|
|
1979
|
-
label: { display: "block", marginBottom: "var(--spacing-xs)", fontWeight: "500" },
|
|
1980
|
-
input: {
|
|
1981
|
-
width: "100%",
|
|
1982
|
-
padding: "var(--spacing-sm) var(--spacing-md)",
|
|
1983
|
-
border: "1px solid var(--color-border)",
|
|
1984
|
-
borderRadius: "var(--radius-md)"
|
|
1985
|
-
}
|
|
1986
|
-
},
|
|
1987
|
-
checkbox: {
|
|
1988
|
-
wrapper: { display: "flex", alignItems: "center", gap: "var(--spacing-sm)" },
|
|
1989
|
-
input: { width: "1rem", height: "1rem" },
|
|
1990
|
-
label: { cursor: "pointer" }
|
|
1991
|
-
},
|
|
1992
|
-
select: {
|
|
1993
|
-
wrapper: { marginBottom: "var(--spacing-md)" },
|
|
1994
|
-
input: {
|
|
1995
|
-
width: "100%",
|
|
1996
|
-
padding: "var(--spacing-sm) var(--spacing-md)",
|
|
1997
|
-
border: "1px solid var(--color-border)",
|
|
1998
|
-
borderRadius: "var(--radius-md)",
|
|
1999
|
-
backgroundColor: "white"
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
};
|
|
2003
|
-
|
|
2004
3241
|
// src/auth/security/lockout.ts
|
|
2005
3242
|
var DEFAULT_LOCKOUT_CONFIG = {
|
|
2006
3243
|
maxAttempts: 5,
|
|
@@ -2492,7 +3729,7 @@ var AuditLogger = class {
|
|
|
2492
3729
|
};
|
|
2493
3730
|
}
|
|
2494
3731
|
};
|
|
2495
|
-
function
|
|
3732
|
+
function createAuditContext2(req) {
|
|
2496
3733
|
return {
|
|
2497
3734
|
ipAddress: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || req.headers.get("x-real-ip") || "unknown",
|
|
2498
3735
|
userAgent: req.headers.get("user-agent") || "unknown"
|
|
@@ -2502,10 +3739,9 @@ var InMemoryAuthAdapter = class {
|
|
|
2502
3739
|
users = /* @__PURE__ */ new Map();
|
|
2503
3740
|
sessions = /* @__PURE__ */ new Map();
|
|
2504
3741
|
refreshTokens = /* @__PURE__ */ new Map();
|
|
2505
|
-
// refreshToken -> sessionId
|
|
2506
3742
|
emailToUserId = /* @__PURE__ */ new Map();
|
|
2507
3743
|
passwordHistory = /* @__PURE__ */ new Map();
|
|
2508
|
-
|
|
3744
|
+
auditLogs = [];
|
|
2509
3745
|
externalDb = false;
|
|
2510
3746
|
constructor() {
|
|
2511
3747
|
}
|
|
@@ -2521,10 +3757,11 @@ var InMemoryAuthAdapter = class {
|
|
|
2521
3757
|
async createUser(data) {
|
|
2522
3758
|
const userId = crypto.randomBytes(16).toString("hex");
|
|
2523
3759
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3760
|
+
const passwordHash = await this.hashPassword(data.password);
|
|
2524
3761
|
const user = {
|
|
2525
3762
|
id: userId,
|
|
2526
3763
|
email: data.email.toLowerCase(),
|
|
2527
|
-
passwordHash
|
|
3764
|
+
passwordHash,
|
|
2528
3765
|
role: data.role || "customer",
|
|
2529
3766
|
tenantId: data.tenantId,
|
|
2530
3767
|
createdAt: now,
|
|
@@ -2582,9 +3819,12 @@ var InMemoryAuthAdapter = class {
|
|
|
2582
3819
|
const bcrypt2 = (await import('bcryptjs')).default;
|
|
2583
3820
|
return bcrypt2.hash(password, 12);
|
|
2584
3821
|
}
|
|
2585
|
-
async verifyPassword(
|
|
3822
|
+
async verifyPassword(email, password) {
|
|
3823
|
+
const user = await this.findUserByEmail(email);
|
|
3824
|
+
if (!user || !user.passwordHash) return null;
|
|
2586
3825
|
const bcrypt2 = (await import('bcryptjs')).default;
|
|
2587
|
-
|
|
3826
|
+
const valid = await bcrypt2.compare(password, user.passwordHash);
|
|
3827
|
+
return valid ? user : null;
|
|
2588
3828
|
}
|
|
2589
3829
|
async createSession(userId, data = {}) {
|
|
2590
3830
|
const sessionId = crypto.randomBytes(32).toString("hex");
|
|
@@ -2655,197 +3895,83 @@ var InMemoryAuthAdapter = class {
|
|
|
2655
3895
|
async hasAnyUsers() {
|
|
2656
3896
|
return this.users.size > 0;
|
|
2657
3897
|
}
|
|
3898
|
+
async findAuditLogs(filter) {
|
|
3899
|
+
const { limit = 50, offset = 0 } = filter;
|
|
3900
|
+
let logs = this.auditLogs.slice().reverse();
|
|
3901
|
+
if (filter.userId) logs = logs.filter((l) => l.userId === filter.userId);
|
|
3902
|
+
if (filter.action) {
|
|
3903
|
+
if (Array.isArray(filter.action)) {
|
|
3904
|
+
logs = logs.filter((l) => filter.action.includes(String(l.action)));
|
|
3905
|
+
} else {
|
|
3906
|
+
logs = logs.filter((l) => l.action === filter.action);
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
if (filter.resource)
|
|
3910
|
+
logs = logs.filter((l) => l.resource === filter.resource);
|
|
3911
|
+
if (filter.success !== void 0)
|
|
3912
|
+
logs = logs.filter((l) => l.success === filter.success);
|
|
3913
|
+
return { logs: logs.slice(offset, offset + limit), total: logs.length };
|
|
3914
|
+
}
|
|
3915
|
+
async createAuditLog(data) {
|
|
3916
|
+
const id = crypto.randomBytes(16).toString("hex");
|
|
3917
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
3918
|
+
const log = { ...data, id, timestamp };
|
|
3919
|
+
this.auditLogs.push(log);
|
|
3920
|
+
return log;
|
|
3921
|
+
}
|
|
2658
3922
|
};
|
|
2659
3923
|
|
|
2660
|
-
// src/auth/security/in-memory-
|
|
2661
|
-
var
|
|
3924
|
+
// src/auth/security/in-memory-lockout.ts
|
|
3925
|
+
var InMemoryAccountLockout = class {
|
|
2662
3926
|
storage = /* @__PURE__ */ new Map();
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
constructor(
|
|
2667
|
-
this.
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
3927
|
+
history = /* @__PURE__ */ new Map();
|
|
3928
|
+
// userId -> attempt timestamps
|
|
3929
|
+
config;
|
|
3930
|
+
constructor(config = {}) {
|
|
3931
|
+
this.config = {
|
|
3932
|
+
maxAttempts: 5,
|
|
3933
|
+
lockDuration: 9e5,
|
|
3934
|
+
// 15 minutes
|
|
3935
|
+
notifyUser: true,
|
|
3936
|
+
notifyAdmin: true,
|
|
3937
|
+
adminNotifyAfter: 3,
|
|
3938
|
+
...config
|
|
2671
3939
|
};
|
|
2672
3940
|
}
|
|
2673
|
-
|
|
2674
|
-
return `${type}:${identifier}`;
|
|
2675
|
-
}
|
|
2676
|
-
getUserKey(type, userId, identifier) {
|
|
2677
|
-
return `user:${type}:${userId}:${identifier}`;
|
|
2678
|
-
}
|
|
2679
|
-
cleanupOldEntries(entries, window) {
|
|
3941
|
+
async checkLockout(userId) {
|
|
2680
3942
|
const now = Date.now();
|
|
2681
|
-
const
|
|
2682
|
-
|
|
2683
|
-
|
|
3943
|
+
const record = this.storage.get(userId);
|
|
3944
|
+
if (record && record.lockedUntil !== null && record.lockedUntil <= now) {
|
|
3945
|
+
await this.resetAttempts(userId);
|
|
3946
|
+
return {
|
|
3947
|
+
locked: false,
|
|
3948
|
+
attemptsRemaining: this.config.maxAttempts,
|
|
3949
|
+
totalAttempts: 0
|
|
3950
|
+
};
|
|
2684
3951
|
}
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
entries = [];
|
|
2692
|
-
this.storage.set(key, entries);
|
|
3952
|
+
if (!record) {
|
|
3953
|
+
return {
|
|
3954
|
+
locked: false,
|
|
3955
|
+
attemptsRemaining: this.config.maxAttempts,
|
|
3956
|
+
totalAttempts: 0
|
|
3957
|
+
};
|
|
2693
3958
|
}
|
|
2694
|
-
|
|
2695
|
-
|
|
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;
|
|
3959
|
+
const { attempts, lockedUntil } = record;
|
|
3960
|
+
if (lockedUntil !== null && lockedUntil > now) {
|
|
2704
3961
|
return {
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
3962
|
+
locked: true,
|
|
3963
|
+
attemptsRemaining: 0,
|
|
3964
|
+
lockedUntil: new Date(lockedUntil),
|
|
3965
|
+
totalAttempts: attempts
|
|
2709
3966
|
};
|
|
2710
3967
|
}
|
|
2711
3968
|
return {
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
3969
|
+
locked: false,
|
|
3970
|
+
attemptsRemaining: Math.max(0, this.config.maxAttempts - attempts),
|
|
3971
|
+
totalAttempts: attempts
|
|
2715
3972
|
};
|
|
2716
3973
|
}
|
|
2717
|
-
async
|
|
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());
|
|
2726
|
-
}
|
|
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
|
-
}
|
|
2771
|
-
this.cleanupOldEntries(entries, config.window);
|
|
2772
|
-
const now = Date.now();
|
|
2773
|
-
const count = entries.reduce((sum, entry) => sum + entry.count, 0);
|
|
2774
|
-
return {
|
|
2775
|
-
count,
|
|
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;
|
|
2783
|
-
}
|
|
2784
|
-
setUserLimit(type, config) {
|
|
2785
|
-
this.userLimits[type] = config;
|
|
2786
|
-
}
|
|
2787
|
-
};
|
|
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
|
-
|
|
2798
|
-
// src/auth/security/in-memory-lockout.ts
|
|
2799
|
-
var InMemoryAccountLockout = class {
|
|
2800
|
-
storage = /* @__PURE__ */ new Map();
|
|
2801
|
-
history = /* @__PURE__ */ new Map();
|
|
2802
|
-
// userId -> attempt timestamps
|
|
2803
|
-
config;
|
|
2804
|
-
constructor(config = {}) {
|
|
2805
|
-
this.config = {
|
|
2806
|
-
maxAttempts: 5,
|
|
2807
|
-
lockDuration: 9e5,
|
|
2808
|
-
// 15 minutes
|
|
2809
|
-
notifyUser: true,
|
|
2810
|
-
notifyAdmin: true,
|
|
2811
|
-
adminNotifyAfter: 3,
|
|
2812
|
-
...config
|
|
2813
|
-
};
|
|
2814
|
-
}
|
|
2815
|
-
async checkLockout(userId) {
|
|
2816
|
-
const now = Date.now();
|
|
2817
|
-
const record = this.storage.get(userId);
|
|
2818
|
-
if (record && record.lockedUntil !== null && record.lockedUntil <= now) {
|
|
2819
|
-
await this.resetAttempts(userId);
|
|
2820
|
-
return {
|
|
2821
|
-
locked: false,
|
|
2822
|
-
attemptsRemaining: this.config.maxAttempts,
|
|
2823
|
-
totalAttempts: 0
|
|
2824
|
-
};
|
|
2825
|
-
}
|
|
2826
|
-
if (!record) {
|
|
2827
|
-
return {
|
|
2828
|
-
locked: false,
|
|
2829
|
-
attemptsRemaining: this.config.maxAttempts,
|
|
2830
|
-
totalAttempts: 0
|
|
2831
|
-
};
|
|
2832
|
-
}
|
|
2833
|
-
const { attempts, lockedUntil } = record;
|
|
2834
|
-
if (lockedUntil !== null && lockedUntil > now) {
|
|
2835
|
-
return {
|
|
2836
|
-
locked: true,
|
|
2837
|
-
attemptsRemaining: 0,
|
|
2838
|
-
lockedUntil: new Date(lockedUntil),
|
|
2839
|
-
totalAttempts: attempts
|
|
2840
|
-
};
|
|
2841
|
-
}
|
|
2842
|
-
return {
|
|
2843
|
-
locked: false,
|
|
2844
|
-
attemptsRemaining: Math.max(0, this.config.maxAttempts - attempts),
|
|
2845
|
-
totalAttempts: attempts
|
|
2846
|
-
};
|
|
2847
|
-
}
|
|
2848
|
-
async recordFailedAttempt(userId) {
|
|
3974
|
+
async recordFailedAttempt(userId) {
|
|
2849
3975
|
const now = Date.now();
|
|
2850
3976
|
const record = this.storage.get(userId) || {
|
|
2851
3977
|
attempts: 0,
|
|
@@ -3058,38 +4184,6 @@ var InMemoryAuditLogger = class {
|
|
|
3058
4184
|
this.logs = this.logs.filter((log) => log.timestamp >= cutoffDate);
|
|
3059
4185
|
}
|
|
3060
4186
|
};
|
|
3061
|
-
function createAuditContext2(req) {
|
|
3062
|
-
return {
|
|
3063
|
-
ipAddress: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || req.headers.get("x-real-ip") || "unknown",
|
|
3064
|
-
userAgent: req.headers.get("user-agent") || "unknown"
|
|
3065
|
-
};
|
|
3066
|
-
}
|
|
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
4187
|
var AuthRoutes = class {
|
|
3094
4188
|
authAdapter;
|
|
3095
4189
|
email;
|
|
@@ -3110,7 +4204,7 @@ var AuthRoutes = class {
|
|
|
3110
4204
|
this.jwtExpiresIn = config.jwtExpiresIn || "24h";
|
|
3111
4205
|
this.jwtIssuer = config.jwtIssuer;
|
|
3112
4206
|
this.jwtAudience = config.jwtAudience;
|
|
3113
|
-
this.passwordPolicy = config.passwordPolicy || new
|
|
4207
|
+
this.passwordPolicy = config.passwordPolicy || new chunk4M5PHMUE_cjs.PasswordPolicy();
|
|
3114
4208
|
this.lockout = config.lockout;
|
|
3115
4209
|
this.rateLimiter = config.rateLimiter;
|
|
3116
4210
|
this.auditLogger = config.auditLogger;
|
|
@@ -3118,7 +4212,7 @@ var AuthRoutes = class {
|
|
|
3118
4212
|
this.emailVerificationRequired = config.emailVerificationRequired ?? true;
|
|
3119
4213
|
}
|
|
3120
4214
|
async register(req) {
|
|
3121
|
-
const { ipAddress, userAgent } =
|
|
4215
|
+
const { ipAddress, userAgent } = chunkEWP5AT6A_cjs.createAuditContext(req);
|
|
3122
4216
|
if (this.rateLimiter) {
|
|
3123
4217
|
const limit = await this.rateLimiter.check("auth:register", ipAddress);
|
|
3124
4218
|
if (!limit.allowed) {
|
|
@@ -3141,10 +4235,9 @@ var AuthRoutes = class {
|
|
|
3141
4235
|
if (existingUser) {
|
|
3142
4236
|
return this.errorResponse("Email already registered", 400);
|
|
3143
4237
|
}
|
|
3144
|
-
const passwordHash = await this.authAdapter.hashPassword(body.password);
|
|
3145
4238
|
const user = await this.authAdapter.createUser({
|
|
3146
4239
|
email: body.email,
|
|
3147
|
-
|
|
4240
|
+
password: body.password,
|
|
3148
4241
|
role: body.role || "customer",
|
|
3149
4242
|
tenantId: body.tenantId
|
|
3150
4243
|
});
|
|
@@ -3180,7 +4273,7 @@ var AuthRoutes = class {
|
|
|
3180
4273
|
}
|
|
3181
4274
|
}
|
|
3182
4275
|
async login(req) {
|
|
3183
|
-
const { ipAddress, userAgent } =
|
|
4276
|
+
const { ipAddress, userAgent } = chunkEWP5AT6A_cjs.createAuditContext(req);
|
|
3184
4277
|
if (this.rateLimiter) {
|
|
3185
4278
|
const limit = await this.rateLimiter.check("auth:login", ipAddress);
|
|
3186
4279
|
if (!limit.allowed) {
|
|
@@ -3241,7 +4334,7 @@ var AuthRoutes = class {
|
|
|
3241
4334
|
iat: Math.floor(Date.now() / 1e3),
|
|
3242
4335
|
exp: Math.floor(Date.now() / 1e3) + 86400
|
|
3243
4336
|
};
|
|
3244
|
-
const accessToken = generateToken(payload, this.jwtSecret, {
|
|
4337
|
+
const accessToken = chunkE63IF3MD_cjs.generateToken(payload, this.jwtSecret, {
|
|
3245
4338
|
expiresIn: this.jwtExpiresIn,
|
|
3246
4339
|
issuer: this.jwtIssuer,
|
|
3247
4340
|
audience: this.jwtAudience
|
|
@@ -3273,13 +4366,13 @@ var AuthRoutes = class {
|
|
|
3273
4366
|
}
|
|
3274
4367
|
}
|
|
3275
4368
|
async logout(req) {
|
|
3276
|
-
const token = defaultExtractToken(req);
|
|
4369
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3277
4370
|
if (!token) {
|
|
3278
4371
|
return this.errorResponse("No session to logout", 401);
|
|
3279
4372
|
}
|
|
3280
|
-
const { ipAddress, userAgent } =
|
|
4373
|
+
const { ipAddress, userAgent } = chunkEWP5AT6A_cjs.createAuditContext(req);
|
|
3281
4374
|
try {
|
|
3282
|
-
const payload =
|
|
4375
|
+
const payload = jwt__default.default.decode(token);
|
|
3283
4376
|
if (payload && payload.sub) {
|
|
3284
4377
|
await this.authAdapter.deleteUserSessions(payload.sub);
|
|
3285
4378
|
if (this.auditLogger) {
|
|
@@ -3315,12 +4408,12 @@ var AuthRoutes = class {
|
|
|
3315
4408
|
}
|
|
3316
4409
|
}
|
|
3317
4410
|
async me(req) {
|
|
3318
|
-
const token = defaultExtractToken(req);
|
|
4411
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3319
4412
|
if (!token) {
|
|
3320
4413
|
return this.errorResponse("Not authenticated", 401);
|
|
3321
4414
|
}
|
|
3322
4415
|
try {
|
|
3323
|
-
const payload =
|
|
4416
|
+
const payload = jwt__default.default.verify(token, this.jwtSecret, {
|
|
3324
4417
|
issuer: this.jwtIssuer,
|
|
3325
4418
|
audience: this.jwtAudience
|
|
3326
4419
|
});
|
|
@@ -3337,13 +4430,13 @@ var AuthRoutes = class {
|
|
|
3337
4430
|
}
|
|
3338
4431
|
}
|
|
3339
4432
|
async changePassword(req) {
|
|
3340
|
-
const token = defaultExtractToken(req);
|
|
4433
|
+
const token = chunkE63IF3MD_cjs.defaultExtractToken(req);
|
|
3341
4434
|
if (!token) {
|
|
3342
4435
|
return this.errorResponse("Not authenticated", 401);
|
|
3343
4436
|
}
|
|
3344
|
-
const { ipAddress, userAgent } =
|
|
4437
|
+
const { ipAddress, userAgent } = chunkEWP5AT6A_cjs.createAuditContext(req);
|
|
3345
4438
|
try {
|
|
3346
|
-
const payload =
|
|
4439
|
+
const payload = jwt__default.default.verify(token, this.jwtSecret);
|
|
3347
4440
|
const body = await req.json();
|
|
3348
4441
|
const { currentPassword, newPassword, confirmPassword } = body;
|
|
3349
4442
|
if (!currentPassword || !newPassword) {
|
|
@@ -3417,7 +4510,7 @@ var AuthRoutes = class {
|
|
|
3417
4510
|
}
|
|
3418
4511
|
}
|
|
3419
4512
|
async forgotPassword(req) {
|
|
3420
|
-
const { ipAddress, userAgent } =
|
|
4513
|
+
const { ipAddress, userAgent } = chunkEWP5AT6A_cjs.createAuditContext(req);
|
|
3421
4514
|
if (this.rateLimiter) {
|
|
3422
4515
|
const limit = await this.rateLimiter.check("auth:forgot", ipAddress);
|
|
3423
4516
|
if (!limit.allowed) {
|
|
@@ -3549,9 +4642,9 @@ function detectDatabaseType() {
|
|
|
3549
4642
|
return envDb;
|
|
3550
4643
|
}
|
|
3551
4644
|
try {
|
|
3552
|
-
const { readFileSync } =
|
|
3553
|
-
const { join } =
|
|
3554
|
-
const configPath =
|
|
4645
|
+
const { readFileSync } = chunkG7VZBCD6_cjs.__require("fs");
|
|
4646
|
+
const { join: join2 } = chunkG7VZBCD6_cjs.__require("path");
|
|
4647
|
+
const configPath = join2(process.cwd(), "kyro.config.ts");
|
|
3555
4648
|
const configContent = readFileSync(configPath, "utf8");
|
|
3556
4649
|
if (configContent.includes("createLocalAdapter")) {
|
|
3557
4650
|
return "sqlite";
|
|
@@ -3572,16 +4665,16 @@ function detectDatabaseType() {
|
|
|
3572
4665
|
async function createAuthAdapter(databaseType) {
|
|
3573
4666
|
switch (databaseType) {
|
|
3574
4667
|
case "sqlite":
|
|
3575
|
-
return new
|
|
4668
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3576
4669
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3577
4670
|
});
|
|
3578
4671
|
case "postgres":
|
|
3579
4672
|
case "mysql":
|
|
3580
|
-
return new
|
|
4673
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3581
4674
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3582
4675
|
});
|
|
3583
4676
|
case "mongodb":
|
|
3584
|
-
return new
|
|
4677
|
+
return new chunk4M5PHMUE_cjs.SQLiteAuthAdapter({
|
|
3585
4678
|
path: getEnv("KYRO_AUTH_DB_PATH", "./data/auth.db")
|
|
3586
4679
|
});
|
|
3587
4680
|
case "memory":
|
|
@@ -3593,7 +4686,7 @@ async function createAuthConfig(databaseType) {
|
|
|
3593
4686
|
const distributed = getEnvBool("KYRO_DISTRIBUTED", false);
|
|
3594
4687
|
let authAdapter;
|
|
3595
4688
|
if (distributed) {
|
|
3596
|
-
const { RedisAuthAdapter: RedisAuthAdapter2 } = await import('./redis-adapter-
|
|
4689
|
+
const { RedisAuthAdapter: RedisAuthAdapter2 } = await import('./redis-adapter-2N6VA7BI.cjs');
|
|
3597
4690
|
const redisUrl = getEnv("REDIS_URL", "redis://localhost:6379");
|
|
3598
4691
|
const redisTls = getEnvBool("REDIS_TLS", false);
|
|
3599
4692
|
const redisAdapter = new RedisAuthAdapter2({ url: redisUrl, tls: redisTls });
|
|
@@ -3606,9 +4699,8 @@ async function createAuthConfig(databaseType) {
|
|
|
3606
4699
|
await authAdapter.connect();
|
|
3607
4700
|
}
|
|
3608
4701
|
}
|
|
3609
|
-
const
|
|
3610
|
-
const
|
|
3611
|
-
const passwordPolicy = new chunk3EVLFWH2_cjs.PasswordPolicy({
|
|
4702
|
+
const email = chunkHVSQDZZJ_cjs.EmailTransport.fromEnv() || void 0;
|
|
4703
|
+
const passwordPolicy = new chunk4M5PHMUE_cjs.PasswordPolicy({
|
|
3612
4704
|
minLength: getEnvNum("PASSWORD_MIN_LENGTH", 12),
|
|
3613
4705
|
requireUppercase: getEnvBool("PASSWORD_REQUIRE_UPPERCASE", true),
|
|
3614
4706
|
requireLowercase: getEnvBool("PASSWORD_REQUIRE_LOWERCASE", true),
|
|
@@ -3646,7 +4738,7 @@ async function createAuthConfig(databaseType) {
|
|
|
3646
4738
|
maxAttempts: getEnvNum("LOCKOUT_MAX_ATTEMPTS", 5),
|
|
3647
4739
|
lockDuration: getEnvNum("LOCKOUT_DURATION_MINUTES", 15) * 60 * 1e3
|
|
3648
4740
|
});
|
|
3649
|
-
rateLimiter = new InMemoryRateLimiter({
|
|
4741
|
+
rateLimiter = new chunkE63IF3MD_cjs.InMemoryRateLimiter({
|
|
3650
4742
|
"auth:login": {
|
|
3651
4743
|
window: getEnvNum("RATE_LIMIT_AUTH_WINDOW_MS", 9e5),
|
|
3652
4744
|
max: getEnvNum("RATE_LIMIT_AUTH_MAX_REQUESTS", 10)
|
|
@@ -3684,21 +4776,6 @@ async function createAuthConfig(databaseType) {
|
|
|
3684
4776
|
routes
|
|
3685
4777
|
};
|
|
3686
4778
|
}
|
|
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
4779
|
var authConfig = createAuthConfig();
|
|
3703
4780
|
|
|
3704
4781
|
// src/auth/index.ts
|
|
@@ -3725,10 +4802,9 @@ var Auth = class {
|
|
|
3725
4802
|
if (existing) {
|
|
3726
4803
|
return { success: false, error: "Email already registered" };
|
|
3727
4804
|
}
|
|
3728
|
-
const passwordHash = await this.hashPassword(data.password);
|
|
3729
4805
|
const user = await this.adapter.createUser({
|
|
3730
4806
|
email: data.email,
|
|
3731
|
-
|
|
4807
|
+
password: data.password,
|
|
3732
4808
|
role: data.role ?? "customer",
|
|
3733
4809
|
tenantId: data.tenantId
|
|
3734
4810
|
});
|
|
@@ -3739,15 +4815,11 @@ var Auth = class {
|
|
|
3739
4815
|
}
|
|
3740
4816
|
async login(credentials) {
|
|
3741
4817
|
try {
|
|
3742
|
-
const user = await this.adapter.
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
}
|
|
3746
|
-
const valid = await this.adapter.verifyPassword(
|
|
3747
|
-
credentials.password,
|
|
3748
|
-
user.passwordHash
|
|
4818
|
+
const user = await this.adapter.verifyPassword(
|
|
4819
|
+
credentials.email,
|
|
4820
|
+
credentials.password
|
|
3749
4821
|
);
|
|
3750
|
-
if (!
|
|
4822
|
+
if (!user) {
|
|
3751
4823
|
return { success: false, error: "Invalid credentials" };
|
|
3752
4824
|
}
|
|
3753
4825
|
return this.createSessionForUser(user);
|
|
@@ -3776,7 +4848,7 @@ var Auth = class {
|
|
|
3776
4848
|
}
|
|
3777
4849
|
async verifyToken(token) {
|
|
3778
4850
|
try {
|
|
3779
|
-
const decoded =
|
|
4851
|
+
const decoded = jwt__default.default.verify(token, this.config.secret, {
|
|
3780
4852
|
issuer: this.config.issuer,
|
|
3781
4853
|
audience: this.config.audience.length > 0 ? this.config.audience[0] : void 0
|
|
3782
4854
|
});
|
|
@@ -3793,18 +4865,17 @@ var Auth = class {
|
|
|
3793
4865
|
async changePassword(userId, currentPassword, newPassword) {
|
|
3794
4866
|
try {
|
|
3795
4867
|
const user = await this.adapter.findUserById(userId);
|
|
3796
|
-
if (!user
|
|
4868
|
+
if (!user) {
|
|
3797
4869
|
return { success: false, error: "User not found" };
|
|
3798
4870
|
}
|
|
3799
4871
|
const valid = await this.adapter.verifyPassword(
|
|
3800
|
-
|
|
3801
|
-
|
|
4872
|
+
user.email,
|
|
4873
|
+
currentPassword
|
|
3802
4874
|
);
|
|
3803
4875
|
if (!valid) {
|
|
3804
4876
|
return { success: false, error: "Current password is incorrect" };
|
|
3805
4877
|
}
|
|
3806
|
-
|
|
3807
|
-
await this.adapter.updateUser(userId, { passwordHash: newHash });
|
|
4878
|
+
await this.adapter.updateUser(userId, { password: newPassword });
|
|
3808
4879
|
await this.adapter.deleteUserSessions(userId);
|
|
3809
4880
|
return { success: true, user };
|
|
3810
4881
|
} catch (error) {
|
|
@@ -3817,8 +4888,7 @@ var Auth = class {
|
|
|
3817
4888
|
if (!user) {
|
|
3818
4889
|
return { success: false, error: "User not found" };
|
|
3819
4890
|
}
|
|
3820
|
-
|
|
3821
|
-
await this.adapter.updateUser(user.id, { passwordHash });
|
|
4891
|
+
await this.adapter.updateUser(user.id, { password: newPassword });
|
|
3822
4892
|
await this.adapter.deleteUserSessions(user.id);
|
|
3823
4893
|
return { success: true, user };
|
|
3824
4894
|
} catch (error) {
|
|
@@ -3862,7 +4932,7 @@ var Auth = class {
|
|
|
3862
4932
|
if (this.config.audience.length > 0) {
|
|
3863
4933
|
signOptions.audience = this.config.audience[0];
|
|
3864
4934
|
}
|
|
3865
|
-
return
|
|
4935
|
+
return jwt__default.default.sign(payload, this.config.secret, signOptions);
|
|
3866
4936
|
}
|
|
3867
4937
|
async hashPassword(password) {
|
|
3868
4938
|
return bcrypt__default.default.hash(password, this.config.saltRounds);
|
|
@@ -4036,6 +5106,1590 @@ function isDraft(status) {
|
|
|
4036
5106
|
function isArchived(status) {
|
|
4037
5107
|
return status === "archived";
|
|
4038
5108
|
}
|
|
5109
|
+
function createLocalStorage(config) {
|
|
5110
|
+
const { uploadDir, baseUrl = "/uploads" } = config;
|
|
5111
|
+
async function ensureDir(dir) {
|
|
5112
|
+
if (!fs.existsSync(dir)) {
|
|
5113
|
+
await promises.mkdir(dir, { recursive: true });
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
5116
|
+
function getMimeType(filename) {
|
|
5117
|
+
const ext = path.extname(filename).toLowerCase();
|
|
5118
|
+
const mimeTypes = {
|
|
5119
|
+
".jpg": "image/jpeg",
|
|
5120
|
+
".jpeg": "image/jpeg",
|
|
5121
|
+
".png": "image/png",
|
|
5122
|
+
".gif": "image/gif",
|
|
5123
|
+
".webp": "image/webp",
|
|
5124
|
+
".svg": "image/svg+xml",
|
|
5125
|
+
".mp4": "video/mp4",
|
|
5126
|
+
".webm": "video/webm",
|
|
5127
|
+
".pdf": "application/pdf",
|
|
5128
|
+
".doc": "application/msword",
|
|
5129
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
5130
|
+
".xls": "application/vnd.ms-excel",
|
|
5131
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
5132
|
+
".zip": "application/zip"
|
|
5133
|
+
};
|
|
5134
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
5135
|
+
}
|
|
5136
|
+
async function getImageDimensions(buffer) {
|
|
5137
|
+
try {
|
|
5138
|
+
const header = buffer.toString("hex", 0, 8);
|
|
5139
|
+
if (header.startsWith("89504e47")) {
|
|
5140
|
+
const width = buffer.readUInt32BE(16);
|
|
5141
|
+
const height = buffer.readUInt32BE(20);
|
|
5142
|
+
return { width, height };
|
|
5143
|
+
}
|
|
5144
|
+
if (header.startsWith("ffd8")) {
|
|
5145
|
+
let offset = 2;
|
|
5146
|
+
while (offset < buffer.length) {
|
|
5147
|
+
if (buffer[offset] !== 255) break;
|
|
5148
|
+
const marker = buffer[offset + 1];
|
|
5149
|
+
if (marker === 192 || marker === 194) {
|
|
5150
|
+
const height = buffer.readUInt16BE(offset + 5);
|
|
5151
|
+
const width = buffer.readUInt16BE(offset + 7);
|
|
5152
|
+
return { width, height };
|
|
5153
|
+
}
|
|
5154
|
+
offset += 2 + buffer.readUInt16BE(offset + 2);
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
} catch {
|
|
5158
|
+
}
|
|
5159
|
+
return {};
|
|
5160
|
+
}
|
|
5161
|
+
return {
|
|
5162
|
+
name: "local",
|
|
5163
|
+
displayName: "Local Storage",
|
|
5164
|
+
supportsDynamicResize: true,
|
|
5165
|
+
async upload(file, options) {
|
|
5166
|
+
await ensureDir(uploadDir);
|
|
5167
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
5168
|
+
const hash = crypto.createHash("md5").update(buffer).digest("hex");
|
|
5169
|
+
const ext = path.extname(file.name);
|
|
5170
|
+
const filename = options?.filename || `${hash}${ext}`;
|
|
5171
|
+
const folder = options?.folder || "";
|
|
5172
|
+
const targetDir = folder ? path.join(uploadDir, folder) : uploadDir;
|
|
5173
|
+
await ensureDir(targetDir);
|
|
5174
|
+
const filepath = path.join(targetDir, filename);
|
|
5175
|
+
await promises.writeFile(filepath, buffer);
|
|
5176
|
+
const dimensions = file.type.startsWith("image/") ? await getImageDimensions(buffer) : {};
|
|
5177
|
+
const normalizedBaseUrl = baseUrl || "/uploads";
|
|
5178
|
+
const urlPath = folder ? `/${folder}/${filename}` : `/${filename}`;
|
|
5179
|
+
const url = normalizedBaseUrl + urlPath;
|
|
5180
|
+
return {
|
|
5181
|
+
id: hash,
|
|
5182
|
+
filename,
|
|
5183
|
+
originalName: file.name,
|
|
5184
|
+
mimeType: file.type || getMimeType(file.name),
|
|
5185
|
+
size: buffer.length,
|
|
5186
|
+
url,
|
|
5187
|
+
thumbnailUrl: file.type.startsWith("image/") ? url : void 0,
|
|
5188
|
+
folder: folder || void 0,
|
|
5189
|
+
provider: "local",
|
|
5190
|
+
metadata: {
|
|
5191
|
+
...dimensions,
|
|
5192
|
+
...options?.metadata
|
|
5193
|
+
},
|
|
5194
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5195
|
+
};
|
|
5196
|
+
},
|
|
5197
|
+
async uploadFromUrl(url, options) {
|
|
5198
|
+
const response = await fetch(url);
|
|
5199
|
+
if (!response.ok) {
|
|
5200
|
+
throw new Error(`Failed to fetch file: ${response.statusText}`);
|
|
5201
|
+
}
|
|
5202
|
+
const blob = await response.blob();
|
|
5203
|
+
const contentDisposition = response.headers.get("content-disposition");
|
|
5204
|
+
let filename = options?.filename;
|
|
5205
|
+
if (!filename && contentDisposition) {
|
|
5206
|
+
const match = contentDisposition.match(
|
|
5207
|
+
/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
|
|
5208
|
+
);
|
|
5209
|
+
if (match) {
|
|
5210
|
+
filename = match[1].replace(/['"]/g, "");
|
|
5211
|
+
}
|
|
5212
|
+
}
|
|
5213
|
+
if (!filename) {
|
|
5214
|
+
filename = path.basename(new URL(url).pathname);
|
|
5215
|
+
}
|
|
5216
|
+
const file = new File([blob], filename, {
|
|
5217
|
+
type: blob.type || getMimeType(filename)
|
|
5218
|
+
});
|
|
5219
|
+
return this.upload(file, options);
|
|
5220
|
+
},
|
|
5221
|
+
async delete(url) {
|
|
5222
|
+
const filepath = path.join(uploadDir, url.replace(baseUrl + "/", ""));
|
|
5223
|
+
try {
|
|
5224
|
+
await promises.unlink(filepath);
|
|
5225
|
+
} catch {
|
|
5226
|
+
}
|
|
5227
|
+
},
|
|
5228
|
+
async rename(oldUrl, newFilename) {
|
|
5229
|
+
const oldPath = path.join(uploadDir, oldUrl.replace(baseUrl + "/", ""));
|
|
5230
|
+
const newPath = path.join(uploadDir, newFilename);
|
|
5231
|
+
await promises.rename(oldPath, newPath);
|
|
5232
|
+
return `${baseUrl}/${newFilename}`;
|
|
5233
|
+
},
|
|
5234
|
+
getImageUrl(url, transforms) {
|
|
5235
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
5236
|
+
const params = new URLSearchParams({ url });
|
|
5237
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5238
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5239
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5240
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
5241
|
+
return `/api/media/resize?${params.toString()}`;
|
|
5242
|
+
},
|
|
5243
|
+
async generateThumbnail(file) {
|
|
5244
|
+
if (!file.mimeType.startsWith("image/")) return "";
|
|
5245
|
+
return this.getImageUrl(file.url, { width: 400, height: 400 });
|
|
5246
|
+
},
|
|
5247
|
+
async list(prefix) {
|
|
5248
|
+
const dir = prefix ? path.join(uploadDir, prefix) : uploadDir;
|
|
5249
|
+
if (!fs.existsSync(dir)) return [];
|
|
5250
|
+
const files = [];
|
|
5251
|
+
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
5252
|
+
for (const entry of entries) {
|
|
5253
|
+
if (entry.isFile()) {
|
|
5254
|
+
const filepath = path.join(dir, entry.name);
|
|
5255
|
+
const stats = await promises.stat(filepath);
|
|
5256
|
+
const url = `${baseUrl}${prefix ? `/${prefix}` : ""}/${entry.name}`;
|
|
5257
|
+
files.push({
|
|
5258
|
+
id: crypto.createHash("md5").update(entry.name).digest("hex"),
|
|
5259
|
+
filename: entry.name,
|
|
5260
|
+
originalName: entry.name,
|
|
5261
|
+
mimeType: getMimeType(entry.name),
|
|
5262
|
+
size: stats.size,
|
|
5263
|
+
url,
|
|
5264
|
+
provider: "local",
|
|
5265
|
+
createdAt: stats.birthtime.toISOString()
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
return files;
|
|
5270
|
+
},
|
|
5271
|
+
async exists(url) {
|
|
5272
|
+
const filepath = path.join(uploadDir, url.replace(baseUrl + "/", ""));
|
|
5273
|
+
return fs.existsSync(filepath);
|
|
5274
|
+
}
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5277
|
+
function extractPublicDevUrlId(url) {
|
|
5278
|
+
if (!url) return "";
|
|
5279
|
+
if (url.startsWith("pub-")) return url;
|
|
5280
|
+
const match = url.match(/pub-[a-zA-Z0-9]+/i);
|
|
5281
|
+
return match ? match[0] : "";
|
|
5282
|
+
}
|
|
5283
|
+
function getPublicUrl(key, config) {
|
|
5284
|
+
const normalizedKey = key.startsWith("/") ? key.slice(1) : key;
|
|
5285
|
+
if (config.cdnUrl) {
|
|
5286
|
+
const cdn = config.cdnUrl.replace(/\/$/, "");
|
|
5287
|
+
return `${cdn}/${normalizedKey}`;
|
|
5288
|
+
}
|
|
5289
|
+
switch (config.provider) {
|
|
5290
|
+
case "r2": {
|
|
5291
|
+
const pubId = extractPublicDevUrlId(config.publicDevUrl);
|
|
5292
|
+
if (pubId) {
|
|
5293
|
+
return `https://${pubId}.r2.dev/${normalizedKey}`;
|
|
5294
|
+
}
|
|
5295
|
+
return `https://${config.bucket}.${config.accountId}.r2.cloudflarestorage.com/${normalizedKey}`;
|
|
5296
|
+
}
|
|
5297
|
+
case "gcs":
|
|
5298
|
+
return `https://storage.googleapis.com/${config.bucket}/${normalizedKey}`;
|
|
5299
|
+
case "digitalocean":
|
|
5300
|
+
return `https://${config.bucket}.${config.region}.cdn.digitaloceanspaces.com/${normalizedKey}`;
|
|
5301
|
+
case "backblaze":
|
|
5302
|
+
return `https://${config.bucket}.s3.backblazeb2.com/${normalizedKey}`;
|
|
5303
|
+
case "wasabi":
|
|
5304
|
+
return `https://${config.bucket}.s3.wasabisys.com/${normalizedKey}`;
|
|
5305
|
+
case "aws":
|
|
5306
|
+
default:
|
|
5307
|
+
return `https://${config.bucket}.s3.${config.region}.amazonaws.com/${normalizedKey}`;
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
5310
|
+
function getUrlPrefix(config) {
|
|
5311
|
+
if (config.cdnUrl) {
|
|
5312
|
+
return config.cdnUrl.replace(/\/$/, "") + "/";
|
|
5313
|
+
}
|
|
5314
|
+
switch (config.provider) {
|
|
5315
|
+
case "r2": {
|
|
5316
|
+
const pubId = extractPublicDevUrlId(config.publicDevUrl);
|
|
5317
|
+
if (pubId) {
|
|
5318
|
+
return `https://${pubId}.r2.dev/`;
|
|
5319
|
+
}
|
|
5320
|
+
return `https://${config.bucket}.${config.accountId}.r2.cloudflarestorage.com/`;
|
|
5321
|
+
}
|
|
5322
|
+
case "gcs":
|
|
5323
|
+
return `https://storage.googleapis.com/${config.bucket}/`;
|
|
5324
|
+
case "digitalocean":
|
|
5325
|
+
return `https://${config.bucket}.${config.region}.cdn.digitaloceanspaces.com/`;
|
|
5326
|
+
case "backblaze":
|
|
5327
|
+
return `https://${config.bucket}.s3.backblazeb2.com/`;
|
|
5328
|
+
case "wasabi":
|
|
5329
|
+
return `https://${config.bucket}.s3.wasabisys.com/`;
|
|
5330
|
+
case "aws":
|
|
5331
|
+
default:
|
|
5332
|
+
return `https://${config.bucket}.s3.${config.region}.amazonaws.com/`;
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
function getDisplayName(provider) {
|
|
5336
|
+
switch (provider) {
|
|
5337
|
+
case "r2":
|
|
5338
|
+
return "Cloudflare R2";
|
|
5339
|
+
case "gcs":
|
|
5340
|
+
return "Google Cloud Storage";
|
|
5341
|
+
case "digitalocean":
|
|
5342
|
+
return "DigitalOcean Spaces";
|
|
5343
|
+
case "backblaze":
|
|
5344
|
+
return "Backblaze B2";
|
|
5345
|
+
case "wasabi":
|
|
5346
|
+
return "Wasabi";
|
|
5347
|
+
case "aws":
|
|
5348
|
+
default:
|
|
5349
|
+
return "AWS S3";
|
|
5350
|
+
}
|
|
5351
|
+
}
|
|
5352
|
+
function createS3Storage(config) {
|
|
5353
|
+
console.log("[createS3Storage] Creating provider:", config.provider);
|
|
5354
|
+
console.log("[createS3Storage] Credentials:", {
|
|
5355
|
+
accessKeyId: config.accessKeyId ? "SET" : "UNDEFINED",
|
|
5356
|
+
secretAccessKey: config.secretAccessKey ? "SET" : "UNDEFINED",
|
|
5357
|
+
bucket: config.bucket,
|
|
5358
|
+
accountId: config.accountId,
|
|
5359
|
+
endpoint: config.endpoint
|
|
5360
|
+
});
|
|
5361
|
+
const client = new clientS3.S3Client({
|
|
5362
|
+
region: config.region || "auto",
|
|
5363
|
+
endpoint: config.endpoint,
|
|
5364
|
+
credentials: {
|
|
5365
|
+
accessKeyId: config.accessKeyId,
|
|
5366
|
+
secretAccessKey: config.secretAccessKey
|
|
5367
|
+
},
|
|
5368
|
+
forcePathStyle: true,
|
|
5369
|
+
tls: true,
|
|
5370
|
+
// R2 requires specific SSL configuration
|
|
5371
|
+
...config.provider === "r2" && {
|
|
5372
|
+
requestHandler: new (init_dist_es4(), chunkG7VZBCD6_cjs.__toCommonJS(dist_es_exports)).NodeHttpHandler({
|
|
5373
|
+
connectionTimeout: 1e4,
|
|
5374
|
+
socketTimeout: 1e4
|
|
5375
|
+
})
|
|
5376
|
+
}
|
|
5377
|
+
});
|
|
5378
|
+
const getKey = (path2) => {
|
|
5379
|
+
const prefix = config.prefix ? `${config.prefix}/` : "";
|
|
5380
|
+
return `${prefix}${path2}`.replace(/\/+/g, "/");
|
|
5381
|
+
};
|
|
5382
|
+
const getUrl = (key) => getPublicUrl(key, config);
|
|
5383
|
+
return {
|
|
5384
|
+
name: config.provider,
|
|
5385
|
+
displayName: getDisplayName(config.provider),
|
|
5386
|
+
supportsDynamicResize: true,
|
|
5387
|
+
async upload(file, options) {
|
|
5388
|
+
const key = getKey(
|
|
5389
|
+
`${options?.folder ? `${options.folder}/` : ""}${options?.filename || file.name}`
|
|
5390
|
+
);
|
|
5391
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
5392
|
+
await client.send(
|
|
5393
|
+
new clientS3.PutObjectCommand({
|
|
5394
|
+
Bucket: config.bucket,
|
|
5395
|
+
Key: key,
|
|
5396
|
+
Body: buffer,
|
|
5397
|
+
ContentType: file.type,
|
|
5398
|
+
Metadata: options?.metadata
|
|
5399
|
+
})
|
|
5400
|
+
);
|
|
5401
|
+
const head = await client.send(
|
|
5402
|
+
new clientS3.HeadObjectCommand({
|
|
5403
|
+
Bucket: config.bucket,
|
|
5404
|
+
Key: key
|
|
5405
|
+
})
|
|
5406
|
+
);
|
|
5407
|
+
return {
|
|
5408
|
+
id: Buffer.from(key).toString("base64url"),
|
|
5409
|
+
filename: options?.filename || file.name,
|
|
5410
|
+
originalName: file.name,
|
|
5411
|
+
mimeType: file.type,
|
|
5412
|
+
size: buffer.length,
|
|
5413
|
+
url: getUrl(key),
|
|
5414
|
+
thumbnailUrl: file.type.startsWith("image/") ? getUrl(key) : void 0,
|
|
5415
|
+
folder: options?.folder,
|
|
5416
|
+
provider: config.provider,
|
|
5417
|
+
metadata: {
|
|
5418
|
+
...options?.metadata,
|
|
5419
|
+
etag: head.ETag
|
|
5420
|
+
},
|
|
5421
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5422
|
+
};
|
|
5423
|
+
},
|
|
5424
|
+
async uploadFromUrl(url) {
|
|
5425
|
+
const response = await fetch(url);
|
|
5426
|
+
if (!response.ok) {
|
|
5427
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
5428
|
+
}
|
|
5429
|
+
const blob = await response.blob();
|
|
5430
|
+
const filename = url.split("/").pop() || "file";
|
|
5431
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
5432
|
+
return this.upload(file);
|
|
5433
|
+
},
|
|
5434
|
+
async delete(url) {
|
|
5435
|
+
const key = url.replace(getUrlPrefix(config), "");
|
|
5436
|
+
await client.send(
|
|
5437
|
+
new clientS3.DeleteObjectCommand({
|
|
5438
|
+
Bucket: config.bucket,
|
|
5439
|
+
Key: key
|
|
5440
|
+
})
|
|
5441
|
+
);
|
|
5442
|
+
},
|
|
5443
|
+
async rename(oldUrl, newKey) {
|
|
5444
|
+
const oldKey = oldUrl.replace(getUrlPrefix(config), "");
|
|
5445
|
+
const newKeyWithPrefix = config.prefix ? `${config.prefix}/${newKey}` : newKey;
|
|
5446
|
+
await client.send(
|
|
5447
|
+
new clientS3.CopyObjectCommand({
|
|
5448
|
+
Bucket: config.bucket,
|
|
5449
|
+
CopySource: `${config.bucket}/${oldKey}`,
|
|
5450
|
+
Key: newKeyWithPrefix
|
|
5451
|
+
})
|
|
5452
|
+
);
|
|
5453
|
+
await client.send(
|
|
5454
|
+
new clientS3.DeleteObjectCommand({
|
|
5455
|
+
Bucket: config.bucket,
|
|
5456
|
+
Key: oldKey
|
|
5457
|
+
})
|
|
5458
|
+
);
|
|
5459
|
+
return getUrl(newKeyWithPrefix);
|
|
5460
|
+
},
|
|
5461
|
+
getImageUrl(url, transforms) {
|
|
5462
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
5463
|
+
const params = new URLSearchParams({ url });
|
|
5464
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5465
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5466
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5467
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
5468
|
+
return `/api/media/resize?${params.toString()}`;
|
|
5469
|
+
},
|
|
5470
|
+
async generateThumbnail(file) {
|
|
5471
|
+
return this.getImageUrl(file.url, { width: 400, height: 400 });
|
|
5472
|
+
},
|
|
5473
|
+
async list(prefix) {
|
|
5474
|
+
const key = getKey(prefix || "");
|
|
5475
|
+
const response = await client.send(
|
|
5476
|
+
new clientS3.ListObjectsV2Command({
|
|
5477
|
+
Bucket: config.bucket,
|
|
5478
|
+
Prefix: key
|
|
5479
|
+
})
|
|
5480
|
+
);
|
|
5481
|
+
return (response.Contents || []).map((item) => ({
|
|
5482
|
+
id: Buffer.from(item.Key || "").toString("base64url"),
|
|
5483
|
+
filename: item.Key?.split("/").pop() || "",
|
|
5484
|
+
originalName: item.Key?.split("/").pop() || "",
|
|
5485
|
+
mimeType: "application/octet-stream",
|
|
5486
|
+
size: item.Size || 0,
|
|
5487
|
+
url: getUrl(item.Key || ""),
|
|
5488
|
+
provider: config.provider,
|
|
5489
|
+
createdAt: item.LastModified?.toISOString() || (/* @__PURE__ */ new Date()).toISOString()
|
|
5490
|
+
}));
|
|
5491
|
+
},
|
|
5492
|
+
async exists(url) {
|
|
5493
|
+
try {
|
|
5494
|
+
const key = url.replace(getUrlPrefix(config), "");
|
|
5495
|
+
await client.send(
|
|
5496
|
+
new clientS3.HeadObjectCommand({
|
|
5497
|
+
Bucket: config.bucket,
|
|
5498
|
+
Key: key
|
|
5499
|
+
})
|
|
5500
|
+
);
|
|
5501
|
+
return true;
|
|
5502
|
+
} catch {
|
|
5503
|
+
return false;
|
|
5504
|
+
}
|
|
5505
|
+
}
|
|
5506
|
+
};
|
|
5507
|
+
}
|
|
5508
|
+
|
|
5509
|
+
// src/storage/cloudinary.ts
|
|
5510
|
+
function createCloudinaryStorage(config) {
|
|
5511
|
+
const getBaseUrl = () => `https://api.cloudinary.com/v1_1/${config.cloudName}/upload`;
|
|
5512
|
+
const generateSignature = async (params) => {
|
|
5513
|
+
const crypto = await import('crypto');
|
|
5514
|
+
const sortedParams = Object.keys(params).sort().map((key) => `${key}=${params[key]}`).join("&");
|
|
5515
|
+
return crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5516
|
+
};
|
|
5517
|
+
return {
|
|
5518
|
+
name: "cloudinary",
|
|
5519
|
+
displayName: "Cloudinary",
|
|
5520
|
+
supportsDynamicResize: true,
|
|
5521
|
+
async upload(file, options) {
|
|
5522
|
+
const formData = new FormData();
|
|
5523
|
+
formData.append("file", file);
|
|
5524
|
+
if (config.uploadPreset) {
|
|
5525
|
+
formData.append("upload_preset", config.uploadPreset);
|
|
5526
|
+
} else {
|
|
5527
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5528
|
+
const signatureParams = {
|
|
5529
|
+
timestamp: String(timestamp)
|
|
5530
|
+
};
|
|
5531
|
+
if (options?.folder || config.folder) {
|
|
5532
|
+
signatureParams.folder = options?.folder || config.folder || "";
|
|
5533
|
+
}
|
|
5534
|
+
const signature = await generateSignature(signatureParams);
|
|
5535
|
+
formData.append("timestamp", String(timestamp));
|
|
5536
|
+
formData.append("signature", signature);
|
|
5537
|
+
formData.append("api_key", config.apiKey);
|
|
5538
|
+
}
|
|
5539
|
+
if (options?.folder || config.folder) {
|
|
5540
|
+
formData.append("folder", options?.folder || config.folder || "");
|
|
5541
|
+
}
|
|
5542
|
+
const response = await fetch(getBaseUrl(), {
|
|
5543
|
+
method: "POST",
|
|
5544
|
+
body: formData
|
|
5545
|
+
});
|
|
5546
|
+
if (!response.ok) {
|
|
5547
|
+
const error = await response.json();
|
|
5548
|
+
throw new Error(
|
|
5549
|
+
`Cloudinary upload failed: ${error.error?.message || response.statusText}`
|
|
5550
|
+
);
|
|
5551
|
+
}
|
|
5552
|
+
const data = await response.json();
|
|
5553
|
+
return {
|
|
5554
|
+
id: data.public_id,
|
|
5555
|
+
filename: `${data.public_id}.${data.format}`,
|
|
5556
|
+
originalName: data.original_filename || file.name,
|
|
5557
|
+
mimeType: file.type || `image/${data.format}`,
|
|
5558
|
+
size: data.bytes,
|
|
5559
|
+
url: data.secure_url,
|
|
5560
|
+
thumbnailUrl: this.getImageUrl(data.secure_url, {
|
|
5561
|
+
width: 200,
|
|
5562
|
+
height: 200,
|
|
5563
|
+
fit: "crop"
|
|
5564
|
+
}),
|
|
5565
|
+
width: data.width,
|
|
5566
|
+
height: data.height,
|
|
5567
|
+
folder: options?.folder || config.folder,
|
|
5568
|
+
provider: "cloudinary",
|
|
5569
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5570
|
+
};
|
|
5571
|
+
},
|
|
5572
|
+
async uploadFromUrl(url, options) {
|
|
5573
|
+
const formData = new FormData();
|
|
5574
|
+
formData.append("file", url);
|
|
5575
|
+
formData.append("upload_preset", "ml_default");
|
|
5576
|
+
if (options?.folder || config.folder) {
|
|
5577
|
+
formData.append("folder", options?.folder || config.folder || "");
|
|
5578
|
+
}
|
|
5579
|
+
const response = await fetch(getBaseUrl(), {
|
|
5580
|
+
method: "POST",
|
|
5581
|
+
body: formData
|
|
5582
|
+
});
|
|
5583
|
+
if (!response.ok) throw new Error("Cloudinary upload failed");
|
|
5584
|
+
const data = await response.json();
|
|
5585
|
+
return {
|
|
5586
|
+
id: data.public_id,
|
|
5587
|
+
filename: `${data.public_id}.${data.format}`,
|
|
5588
|
+
originalName: data.original_filename || url.split("/").pop() || "file",
|
|
5589
|
+
mimeType: `image/${data.format}`,
|
|
5590
|
+
size: data.bytes,
|
|
5591
|
+
url: data.secure_url,
|
|
5592
|
+
thumbnailUrl: this.getImageUrl(data.secure_url, {
|
|
5593
|
+
width: 200,
|
|
5594
|
+
height: 200,
|
|
5595
|
+
fit: "crop"
|
|
5596
|
+
}),
|
|
5597
|
+
width: data.width,
|
|
5598
|
+
height: data.height,
|
|
5599
|
+
provider: "cloudinary",
|
|
5600
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5601
|
+
};
|
|
5602
|
+
},
|
|
5603
|
+
async delete(id) {
|
|
5604
|
+
try {
|
|
5605
|
+
const parts = id.split("/image/upload/");
|
|
5606
|
+
if (parts.length !== 2) {
|
|
5607
|
+
console.warn("[Cloudinary delete] Could not parse URL:", id);
|
|
5608
|
+
return;
|
|
5609
|
+
}
|
|
5610
|
+
const publicId = parts[1].replace(/^v\d+\//, "").replace(/\.[^.]+$/, "");
|
|
5611
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5612
|
+
const signatureParams = {
|
|
5613
|
+
timestamp: String(timestamp),
|
|
5614
|
+
public_id: publicId
|
|
5615
|
+
};
|
|
5616
|
+
const sortedParams = Object.keys(signatureParams).sort().map((key) => `${key}=${signatureParams[key]}`).join("&");
|
|
5617
|
+
const crypto = await import('crypto');
|
|
5618
|
+
const signature = crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5619
|
+
const deleteUrl = `https://api.cloudinary.com/v1_1/${config.cloudName}/image/destroy`;
|
|
5620
|
+
const formData = new FormData();
|
|
5621
|
+
formData.append("public_id", publicId);
|
|
5622
|
+
formData.append("timestamp", String(timestamp));
|
|
5623
|
+
formData.append("signature", signature);
|
|
5624
|
+
formData.append("api_key", config.apiKey);
|
|
5625
|
+
const response = await fetch(deleteUrl, {
|
|
5626
|
+
method: "POST",
|
|
5627
|
+
body: formData
|
|
5628
|
+
});
|
|
5629
|
+
if (!response.ok) {
|
|
5630
|
+
const error = await response.json();
|
|
5631
|
+
console.warn("[Cloudinary delete] Failed:", error);
|
|
5632
|
+
}
|
|
5633
|
+
} catch (e) {
|
|
5634
|
+
console.warn("[Cloudinary delete] Error:", e.message);
|
|
5635
|
+
}
|
|
5636
|
+
},
|
|
5637
|
+
async rename(oldUrl, newKey) {
|
|
5638
|
+
let version = "";
|
|
5639
|
+
let newPublicId = newKey.replace(/\.[^.]+$/, "");
|
|
5640
|
+
let folder = "";
|
|
5641
|
+
try {
|
|
5642
|
+
const parts = oldUrl.split("/image/upload/");
|
|
5643
|
+
if (parts.length !== 2) {
|
|
5644
|
+
console.warn("[Cloudinary rename] Could not parse old URL:", oldUrl);
|
|
5645
|
+
return oldUrl;
|
|
5646
|
+
}
|
|
5647
|
+
const urlPath = parts[1];
|
|
5648
|
+
const versionMatch = urlPath.match(/^(v\d+)\//);
|
|
5649
|
+
version = versionMatch ? versionMatch[1] : "";
|
|
5650
|
+
const publicIdWithoutVersion = urlPath.replace(/^v\d+\//, "").replace(/\.[^.]+$/, "");
|
|
5651
|
+
const folderParts = publicIdWithoutVersion.split("/");
|
|
5652
|
+
folder = folderParts.length > 1 ? folderParts.slice(0, -1).join("/") : "";
|
|
5653
|
+
const newFilename = newKey.replace(/\.[^.]+$/, "");
|
|
5654
|
+
newPublicId = folder ? `${folder}/${newFilename}` : newFilename;
|
|
5655
|
+
console.log("[Cloudinary rename]", {
|
|
5656
|
+
urlPath,
|
|
5657
|
+
version,
|
|
5658
|
+
publicIdWithoutVersion,
|
|
5659
|
+
folder,
|
|
5660
|
+
newPublicId
|
|
5661
|
+
});
|
|
5662
|
+
const timestamp = Math.round(Date.now() / 1e3);
|
|
5663
|
+
const signatureParams = {
|
|
5664
|
+
from_public_id: publicIdWithoutVersion,
|
|
5665
|
+
to_public_id: newPublicId,
|
|
5666
|
+
timestamp: String(timestamp)
|
|
5667
|
+
};
|
|
5668
|
+
const sortedParams = Object.keys(signatureParams).sort().map((key) => `${key}=${signatureParams[key]}`).join("&");
|
|
5669
|
+
const crypto = await import('crypto');
|
|
5670
|
+
const signature = crypto.createHash("sha256").update(sortedParams + config.apiSecret).digest("hex");
|
|
5671
|
+
const formData = new FormData();
|
|
5672
|
+
formData.append("from_public_id", publicIdWithoutVersion);
|
|
5673
|
+
formData.append("to_public_id", newPublicId);
|
|
5674
|
+
formData.append("timestamp", String(timestamp));
|
|
5675
|
+
formData.append("signature", signature);
|
|
5676
|
+
formData.append("api_key", config.apiKey);
|
|
5677
|
+
const response = await fetch(
|
|
5678
|
+
`https://api.cloudinary.com/v1_1/${config.cloudName}/image/rename`,
|
|
5679
|
+
{
|
|
5680
|
+
method: "POST",
|
|
5681
|
+
body: formData
|
|
5682
|
+
}
|
|
5683
|
+
);
|
|
5684
|
+
if (response.ok) {
|
|
5685
|
+
const data = await response.json();
|
|
5686
|
+
console.log("[Cloudinary rename] Success:", data.secure_url);
|
|
5687
|
+
return data.secure_url;
|
|
5688
|
+
} else {
|
|
5689
|
+
const error = await response.json();
|
|
5690
|
+
console.warn("[Cloudinary rename] Failed:", error);
|
|
5691
|
+
const versionStr = version ? `/${version}/` : "/";
|
|
5692
|
+
return `https://res.cloudinary.com/${config.cloudName}/image/upload${versionStr}${newPublicId}.${newKey.split(".").pop()}`;
|
|
5693
|
+
}
|
|
5694
|
+
} catch (e) {
|
|
5695
|
+
console.warn("[Cloudinary rename] Error:", e.message);
|
|
5696
|
+
const versionStr = version ? `/${version}/` : "/";
|
|
5697
|
+
return `https://res.cloudinary.com/${config.cloudName}/image/upload${versionStr}${newPublicId}.${newKey.split(".").pop()}`;
|
|
5698
|
+
}
|
|
5699
|
+
},
|
|
5700
|
+
getImageUrl(url, transforms) {
|
|
5701
|
+
if (!transforms) return url;
|
|
5702
|
+
const parts = url.split("/upload/");
|
|
5703
|
+
if (parts.length !== 2) return url;
|
|
5704
|
+
const transformationArr = [];
|
|
5705
|
+
if (transforms.width) transformationArr.push(`w_${transforms.width}`);
|
|
5706
|
+
if (transforms.height) transformationArr.push(`h_${transforms.height}`);
|
|
5707
|
+
if (transforms.fit) {
|
|
5708
|
+
const fitMap = {
|
|
5709
|
+
crop: "c_fill",
|
|
5710
|
+
clip: "c_fit",
|
|
5711
|
+
scale: "c_scale",
|
|
5712
|
+
fill: "c_fill"
|
|
5713
|
+
};
|
|
5714
|
+
transformationArr.push(fitMap[transforms.fit] || "c_limit");
|
|
5715
|
+
}
|
|
5716
|
+
if (transforms.quality) transformationArr.push(`q_${transforms.quality}`);
|
|
5717
|
+
if (transforms.format) transformationArr.push(`f_${transforms.format}`);
|
|
5718
|
+
const transformationStr = transformationArr.join(",");
|
|
5719
|
+
return `${parts[0]}/upload/${transformationStr}/${parts[1]}`;
|
|
5720
|
+
},
|
|
5721
|
+
async generateThumbnail(file) {
|
|
5722
|
+
return this.getImageUrl(file.url, {
|
|
5723
|
+
width: 200,
|
|
5724
|
+
height: 200,
|
|
5725
|
+
fit: "crop"
|
|
5726
|
+
});
|
|
5727
|
+
},
|
|
5728
|
+
async list() {
|
|
5729
|
+
return [];
|
|
5730
|
+
},
|
|
5731
|
+
async exists(url) {
|
|
5732
|
+
const response = await fetch(url, { method: "HEAD" });
|
|
5733
|
+
return response.ok;
|
|
5734
|
+
}
|
|
5735
|
+
};
|
|
5736
|
+
}
|
|
5737
|
+
|
|
5738
|
+
// src/storage/imgix.ts
|
|
5739
|
+
function createImgixStorage(config) {
|
|
5740
|
+
const signUrl = (path2, params) => {
|
|
5741
|
+
if (!config.signKey) return path2;
|
|
5742
|
+
const signer = new TextEncoder();
|
|
5743
|
+
const key = signer.encode(config.signKey);
|
|
5744
|
+
const data = signer.encode(path2 + params.toString());
|
|
5745
|
+
let hash = 0;
|
|
5746
|
+
const combined = new Uint8Array(key.length + data.length);
|
|
5747
|
+
combined.set(key);
|
|
5748
|
+
combined.set(data, key.length);
|
|
5749
|
+
for (let i = 0; i < combined.length; i++) {
|
|
5750
|
+
hash = (hash << 5) - hash + combined[i] | 0;
|
|
5751
|
+
}
|
|
5752
|
+
params.set("s", Math.abs(hash).toString(16));
|
|
5753
|
+
return path2;
|
|
5754
|
+
};
|
|
5755
|
+
return {
|
|
5756
|
+
name: "imgix",
|
|
5757
|
+
displayName: "Imgix",
|
|
5758
|
+
supportsDynamicResize: true,
|
|
5759
|
+
async upload(_file, _options) {
|
|
5760
|
+
throw new Error(
|
|
5761
|
+
"Imgix is a transformation service. Use another provider for uploads."
|
|
5762
|
+
);
|
|
5763
|
+
},
|
|
5764
|
+
async uploadFromUrl(url, options) {
|
|
5765
|
+
const filename = options?.filename || url.split("/").pop() || "file";
|
|
5766
|
+
const response = await fetch(url);
|
|
5767
|
+
if (!response.ok) {
|
|
5768
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
5769
|
+
}
|
|
5770
|
+
const blob = await response.blob();
|
|
5771
|
+
new File([blob], filename, { type: blob.type });
|
|
5772
|
+
return {
|
|
5773
|
+
id: Buffer.from(url).toString("base64").slice(0, 20),
|
|
5774
|
+
filename,
|
|
5775
|
+
originalName: filename,
|
|
5776
|
+
mimeType: blob.type,
|
|
5777
|
+
size: blob.size,
|
|
5778
|
+
url: this.getImageUrl(url),
|
|
5779
|
+
thumbnailUrl: this.getImageUrl(url, {
|
|
5780
|
+
width: 200,
|
|
5781
|
+
height: 200,
|
|
5782
|
+
fit: "crop"
|
|
5783
|
+
}),
|
|
5784
|
+
provider: "imgix",
|
|
5785
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5786
|
+
};
|
|
5787
|
+
},
|
|
5788
|
+
async delete(_url) {
|
|
5789
|
+
},
|
|
5790
|
+
async rename(_oldUrl, newKey) {
|
|
5791
|
+
return `https://${config.domain}/${newKey}`;
|
|
5792
|
+
},
|
|
5793
|
+
getImageUrl(url, transforms) {
|
|
5794
|
+
const parsed = new URL(url);
|
|
5795
|
+
const params = new URLSearchParams(parsed.search);
|
|
5796
|
+
if (config.defaultParameters) {
|
|
5797
|
+
Object.entries(config.defaultParameters).forEach(([key, value]) => {
|
|
5798
|
+
if (!params.has(key)) {
|
|
5799
|
+
params.set(key, value);
|
|
5800
|
+
}
|
|
5801
|
+
});
|
|
5802
|
+
}
|
|
5803
|
+
if (transforms) {
|
|
5804
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5805
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5806
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5807
|
+
if (transforms.format) params.set("fm", transforms.format);
|
|
5808
|
+
if (transforms.fit) params.set("fit", transforms.fit);
|
|
5809
|
+
if (transforms.blur) params.set("blur", String(transforms.blur));
|
|
5810
|
+
if (transforms.sharpen) params.set("sharp", String(transforms.sharpen));
|
|
5811
|
+
}
|
|
5812
|
+
params.set("auto", "compress,format");
|
|
5813
|
+
parsed.pathname + "?" + params.toString();
|
|
5814
|
+
if (config.signKey) {
|
|
5815
|
+
signUrl(parsed.pathname + params.toString(), params);
|
|
5816
|
+
}
|
|
5817
|
+
return `https://${config.domain}${parsed.pathname}${params.toString() ? "?" + params.toString() : ""}`;
|
|
5818
|
+
},
|
|
5819
|
+
async generateThumbnail(file) {
|
|
5820
|
+
return this.getImageUrl(file.url, {
|
|
5821
|
+
width: 200,
|
|
5822
|
+
height: 200,
|
|
5823
|
+
fit: "crop"
|
|
5824
|
+
});
|
|
5825
|
+
},
|
|
5826
|
+
async list() {
|
|
5827
|
+
return [];
|
|
5828
|
+
},
|
|
5829
|
+
async exists(url) {
|
|
5830
|
+
try {
|
|
5831
|
+
const response = await fetch(url, { method: "HEAD" });
|
|
5832
|
+
return response.ok;
|
|
5833
|
+
} catch {
|
|
5834
|
+
return false;
|
|
5835
|
+
}
|
|
5836
|
+
}
|
|
5837
|
+
};
|
|
5838
|
+
}
|
|
5839
|
+
function createFtpStorage(config) {
|
|
5840
|
+
let client = null;
|
|
5841
|
+
async function getClient() {
|
|
5842
|
+
if (!client) {
|
|
5843
|
+
client = new basicFtp.Client(6e4, { allowSeparateTransferHost: true });
|
|
5844
|
+
client.ftp.verbose = false;
|
|
5845
|
+
await client.access({
|
|
5846
|
+
host: config.host,
|
|
5847
|
+
port: config.port || 21,
|
|
5848
|
+
user: config.user,
|
|
5849
|
+
password: config.password,
|
|
5850
|
+
secure: config.secure,
|
|
5851
|
+
secureOptions: {}
|
|
5852
|
+
});
|
|
5853
|
+
}
|
|
5854
|
+
return client;
|
|
5855
|
+
}
|
|
5856
|
+
const getKey = (path2) => {
|
|
5857
|
+
const prefix = config.prefix ? `${config.prefix}/` : "";
|
|
5858
|
+
return `${prefix}${path2}`.replace(/\/+/g, "/");
|
|
5859
|
+
};
|
|
5860
|
+
const getUrl = (key) => {
|
|
5861
|
+
const base = config.baseUrl.replace(/\/$/, "");
|
|
5862
|
+
return `${base}/${key}`;
|
|
5863
|
+
};
|
|
5864
|
+
const getUrlPrefix2 = () => {
|
|
5865
|
+
const base = config.baseUrl.replace(/\/$/, "");
|
|
5866
|
+
return base + "/";
|
|
5867
|
+
};
|
|
5868
|
+
return {
|
|
5869
|
+
name: config.type,
|
|
5870
|
+
displayName: config.type === "sftp" ? "SFTP Storage" : "FTP Storage",
|
|
5871
|
+
supportsDynamicResize: false,
|
|
5872
|
+
async upload(file, options) {
|
|
5873
|
+
const ftp = await getClient();
|
|
5874
|
+
const key = getKey(
|
|
5875
|
+
`${options?.folder ? `${options.folder}/` : ""}${options?.filename || file.name}`
|
|
5876
|
+
);
|
|
5877
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
5878
|
+
const parts = key.split("/").slice(0, -1);
|
|
5879
|
+
let currentPath = "";
|
|
5880
|
+
for (const part of parts) {
|
|
5881
|
+
currentPath = currentPath ? `${currentPath}/${part}` : part;
|
|
5882
|
+
try {
|
|
5883
|
+
await ftp.ensureDir(currentPath);
|
|
5884
|
+
} catch {
|
|
5885
|
+
}
|
|
5886
|
+
}
|
|
5887
|
+
const readable = stream.Readable.from(buffer);
|
|
5888
|
+
await ftp.uploadFrom(readable, key);
|
|
5889
|
+
return {
|
|
5890
|
+
id: Buffer.from(key).toString("base64url"),
|
|
5891
|
+
filename: options?.filename || file.name,
|
|
5892
|
+
originalName: file.name,
|
|
5893
|
+
mimeType: file.type,
|
|
5894
|
+
size: buffer.length,
|
|
5895
|
+
url: getUrl(key),
|
|
5896
|
+
thumbnailUrl: file.type.startsWith("image/") ? getUrl(key) : void 0,
|
|
5897
|
+
folder: options?.folder,
|
|
5898
|
+
provider: config.type,
|
|
5899
|
+
metadata: options?.metadata,
|
|
5900
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5901
|
+
};
|
|
5902
|
+
},
|
|
5903
|
+
async uploadFromUrl(url) {
|
|
5904
|
+
const response = await fetch(url);
|
|
5905
|
+
if (!response.ok) {
|
|
5906
|
+
throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
5907
|
+
}
|
|
5908
|
+
const blob = await response.blob();
|
|
5909
|
+
const filename = url.split("/").pop() || "file";
|
|
5910
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
5911
|
+
return this.upload(file);
|
|
5912
|
+
},
|
|
5913
|
+
async delete(url) {
|
|
5914
|
+
const ftp = await getClient();
|
|
5915
|
+
const key = url.replace(getUrlPrefix2(), "");
|
|
5916
|
+
await ftp.remove(key);
|
|
5917
|
+
},
|
|
5918
|
+
async rename(oldUrl, newKey) {
|
|
5919
|
+
const ftp = await getClient();
|
|
5920
|
+
const oldKey = oldUrl.replace(getUrlPrefix2(), "");
|
|
5921
|
+
const fullPath = config.prefix ? `${config.prefix}/${newKey}` : newKey;
|
|
5922
|
+
await ftp.rename(oldKey, fullPath);
|
|
5923
|
+
return getUrl(fullPath);
|
|
5924
|
+
},
|
|
5925
|
+
getImageUrl(url, transforms) {
|
|
5926
|
+
if (!transforms || Object.keys(transforms).length === 0) return url;
|
|
5927
|
+
const params = new URLSearchParams({ url });
|
|
5928
|
+
if (transforms.width) params.set("w", String(transforms.width));
|
|
5929
|
+
if (transforms.height) params.set("h", String(transforms.height));
|
|
5930
|
+
if (transforms.quality) params.set("q", String(transforms.quality));
|
|
5931
|
+
if (transforms.format) params.set("f", transforms.format);
|
|
5932
|
+
return `/api/media/resize?${params.toString()}`;
|
|
5933
|
+
},
|
|
5934
|
+
async generateThumbnail(file) {
|
|
5935
|
+
return file.url;
|
|
5936
|
+
},
|
|
5937
|
+
async list(prefix) {
|
|
5938
|
+
const ftp = await getClient();
|
|
5939
|
+
const key = getKey(prefix || "");
|
|
5940
|
+
let items;
|
|
5941
|
+
try {
|
|
5942
|
+
items = await ftp.list(key);
|
|
5943
|
+
} catch {
|
|
5944
|
+
return [];
|
|
5945
|
+
}
|
|
5946
|
+
return items.filter((item) => item.type === 0).map((item) => ({
|
|
5947
|
+
id: Buffer.from(`${key}/${item.name}`).toString("base64url"),
|
|
5948
|
+
filename: item.name,
|
|
5949
|
+
originalName: item.name,
|
|
5950
|
+
mimeType: "application/octet-stream",
|
|
5951
|
+
size: Number(item.size) || 0,
|
|
5952
|
+
url: getUrl(`${key}/${item.name}`.replace(/\/+/g, "/")),
|
|
5953
|
+
provider: config.type,
|
|
5954
|
+
createdAt: item.modifiedAt ? item.modifiedAt.toISOString() : (/* @__PURE__ */ new Date()).toISOString()
|
|
5955
|
+
}));
|
|
5956
|
+
},
|
|
5957
|
+
async exists(url) {
|
|
5958
|
+
const ftp = await getClient();
|
|
5959
|
+
const key = url.replace(getUrlPrefix2(), "");
|
|
5960
|
+
try {
|
|
5961
|
+
await ftp.size(key);
|
|
5962
|
+
return true;
|
|
5963
|
+
} catch {
|
|
5964
|
+
return false;
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
};
|
|
5968
|
+
}
|
|
5969
|
+
|
|
5970
|
+
// src/storage/index.ts
|
|
5971
|
+
async function resolveProvider(configService) {
|
|
5972
|
+
const config = configService.getStorageConfig();
|
|
5973
|
+
switch (config.type) {
|
|
5974
|
+
case "aws":
|
|
5975
|
+
return createS3Storage({
|
|
5976
|
+
provider: "aws",
|
|
5977
|
+
bucket: config.s3.bucket || "",
|
|
5978
|
+
region: config.s3.region || "us-east-1",
|
|
5979
|
+
accessKeyId: config.s3.accessKeyId || "",
|
|
5980
|
+
secretAccessKey: config.s3.secretAccessKey || "",
|
|
5981
|
+
endpoint: config.s3.endpoint,
|
|
5982
|
+
cdnUrl: config.s3.cdnUrl,
|
|
5983
|
+
prefix: config.s3.prefix
|
|
5984
|
+
});
|
|
5985
|
+
case "r2":
|
|
5986
|
+
return createS3Storage({
|
|
5987
|
+
provider: "r2",
|
|
5988
|
+
bucket: config.r2.bucket || "",
|
|
5989
|
+
region: "auto",
|
|
5990
|
+
accessKeyId: config.r2.accessKeyId || "",
|
|
5991
|
+
secretAccessKey: config.r2.secretAccessKey || "",
|
|
5992
|
+
accountId: config.r2.accountId || "",
|
|
5993
|
+
publicDevUrl: config.r2.publicDevUrl,
|
|
5994
|
+
endpoint: `https://${config.r2.accountId || ""}.r2.cloudflarestorage.com`,
|
|
5995
|
+
cdnUrl: config.r2.cdnUrl,
|
|
5996
|
+
prefix: config.r2.prefix
|
|
5997
|
+
});
|
|
5998
|
+
case "gcs":
|
|
5999
|
+
return createS3Storage({
|
|
6000
|
+
provider: "gcs",
|
|
6001
|
+
bucket: config.gcs.bucket || "",
|
|
6002
|
+
region: config.gcs.projectId || "auto",
|
|
6003
|
+
accessKeyId: config.gcs.clientEmail || "",
|
|
6004
|
+
secretAccessKey: config.gcs.privateKey || "",
|
|
6005
|
+
cdnUrl: config.gcs.cdnUrl,
|
|
6006
|
+
prefix: config.gcs.prefix
|
|
6007
|
+
});
|
|
6008
|
+
case "digitalocean":
|
|
6009
|
+
return createS3Storage({
|
|
6010
|
+
provider: "digitalocean",
|
|
6011
|
+
bucket: config.digitalocean.bucket || "",
|
|
6012
|
+
region: config.digitalocean.region || "nyc3",
|
|
6013
|
+
accessKeyId: config.digitalocean.accessKeyId || "",
|
|
6014
|
+
secretAccessKey: config.digitalocean.secretAccessKey || "",
|
|
6015
|
+
endpoint: `https://${config.digitalocean.region || "nyc3"}.digitaloceanspaces.com`,
|
|
6016
|
+
cdnUrl: config.digitalocean.cdnUrl,
|
|
6017
|
+
prefix: config.digitalocean.prefix
|
|
6018
|
+
});
|
|
6019
|
+
case "backblaze":
|
|
6020
|
+
return createS3Storage({
|
|
6021
|
+
provider: "backblaze",
|
|
6022
|
+
bucket: config.backblaze.bucket || "",
|
|
6023
|
+
region: "auto",
|
|
6024
|
+
accessKeyId: config.backblaze.applicationKeyId || "",
|
|
6025
|
+
secretAccessKey: config.backblaze.applicationKey || "",
|
|
6026
|
+
accountId: config.backblaze.accountId || "",
|
|
6027
|
+
endpoint: `https://s3.backblazeb2.com`,
|
|
6028
|
+
cdnUrl: config.backblaze.cdnUrl,
|
|
6029
|
+
prefix: config.backblaze.prefix
|
|
6030
|
+
});
|
|
6031
|
+
case "wasabi":
|
|
6032
|
+
return createS3Storage({
|
|
6033
|
+
provider: "wasabi",
|
|
6034
|
+
bucket: config.wasabi.bucket || "",
|
|
6035
|
+
region: config.wasabi.region || "us-east-1",
|
|
6036
|
+
accessKeyId: config.wasabi.accessKeyId || "",
|
|
6037
|
+
secretAccessKey: config.wasabi.secretAccessKey || "",
|
|
6038
|
+
endpoint: `https://s3.${config.wasabi.region || "us-east-1"}.wasabisys.com`,
|
|
6039
|
+
cdnUrl: config.wasabi.cdnUrl,
|
|
6040
|
+
prefix: config.wasabi.prefix
|
|
6041
|
+
});
|
|
6042
|
+
case "ftp":
|
|
6043
|
+
case "sftp":
|
|
6044
|
+
return createFtpStorage({
|
|
6045
|
+
host: config.ftp?.host || "",
|
|
6046
|
+
port: config.ftp?.port || 21,
|
|
6047
|
+
user: config.ftp?.user || "",
|
|
6048
|
+
password: config.ftp?.password || "",
|
|
6049
|
+
secure: config.ftp?.secure || false,
|
|
6050
|
+
baseUrl: config.ftp?.baseUrl || "",
|
|
6051
|
+
prefix: config.ftp?.prefix,
|
|
6052
|
+
type: "ftp"
|
|
6053
|
+
});
|
|
6054
|
+
case "cloudinary":
|
|
6055
|
+
return createCloudinaryStorage({
|
|
6056
|
+
cloudName: config.cloudinary.cloudName || "",
|
|
6057
|
+
apiKey: config.cloudinary.apiKey || "",
|
|
6058
|
+
apiSecret: config.cloudinary.apiSecret || "",
|
|
6059
|
+
folder: config.cloudinary.folder
|
|
6060
|
+
});
|
|
6061
|
+
case "imgix":
|
|
6062
|
+
return createImgixStorage({
|
|
6063
|
+
domain: config.imgix.domain || "",
|
|
6064
|
+
signKey: config.imgix.signKey
|
|
6065
|
+
});
|
|
6066
|
+
case "local":
|
|
6067
|
+
default:
|
|
6068
|
+
return createLocalStorage({
|
|
6069
|
+
uploadDir: config.local.uploadDir || path__default.default.join(process.cwd(), "public", "uploads"),
|
|
6070
|
+
baseUrl: config.local.baseUrl || "/uploads"
|
|
6071
|
+
});
|
|
6072
|
+
}
|
|
6073
|
+
}
|
|
6074
|
+
async function resolveProviderWithConfig(config) {
|
|
6075
|
+
if (!config) {
|
|
6076
|
+
console.warn("[resolveProviderWithConfig] No config, using local");
|
|
6077
|
+
return createLocalStorage({
|
|
6078
|
+
uploadDir: path__default.default.join(process.cwd(), "public", "uploads"),
|
|
6079
|
+
baseUrl: "/uploads"
|
|
6080
|
+
});
|
|
6081
|
+
}
|
|
6082
|
+
console.log("[resolveProviderWithConfig] Creating provider:", config.type);
|
|
6083
|
+
switch (config.type) {
|
|
6084
|
+
case "aws":
|
|
6085
|
+
return createS3Storage({
|
|
6086
|
+
provider: "aws",
|
|
6087
|
+
bucket: config.s3?.bucket || "",
|
|
6088
|
+
region: config.s3?.region || "us-east-1",
|
|
6089
|
+
accessKeyId: config.s3?.accessKeyId || "",
|
|
6090
|
+
secretAccessKey: config.s3?.secretAccessKey || "",
|
|
6091
|
+
endpoint: config.s3?.endpoint,
|
|
6092
|
+
cdnUrl: config.s3?.cdnUrl,
|
|
6093
|
+
prefix: config.s3?.prefix
|
|
6094
|
+
});
|
|
6095
|
+
case "r2":
|
|
6096
|
+
return createS3Storage({
|
|
6097
|
+
provider: "r2",
|
|
6098
|
+
bucket: config.r2?.bucket || "",
|
|
6099
|
+
region: "auto",
|
|
6100
|
+
accessKeyId: config.r2?.accessKeyId || "",
|
|
6101
|
+
secretAccessKey: config.r2?.secretAccessKey || "",
|
|
6102
|
+
accountId: config.r2?.accountId || "",
|
|
6103
|
+
publicDevUrl: config.r2?.publicDevUrl,
|
|
6104
|
+
endpoint: `https://${config.r2?.accountId || ""}.r2.cloudflarestorage.com`,
|
|
6105
|
+
cdnUrl: config.r2?.cdnUrl,
|
|
6106
|
+
prefix: config.r2?.prefix
|
|
6107
|
+
});
|
|
6108
|
+
case "gcs":
|
|
6109
|
+
return createS3Storage({
|
|
6110
|
+
provider: "gcs",
|
|
6111
|
+
bucket: config.gcs?.bucket || "",
|
|
6112
|
+
region: config.gcs?.projectId || "auto",
|
|
6113
|
+
accessKeyId: config.gcs?.clientEmail || "",
|
|
6114
|
+
secretAccessKey: config.gcs?.privateKey || "",
|
|
6115
|
+
cdnUrl: config.gcs?.cdnUrl,
|
|
6116
|
+
prefix: config.gcs?.prefix
|
|
6117
|
+
});
|
|
6118
|
+
case "digitalocean":
|
|
6119
|
+
return createS3Storage({
|
|
6120
|
+
provider: "digitalocean",
|
|
6121
|
+
bucket: config.digitalocean?.bucket || "",
|
|
6122
|
+
region: config.digitalocean?.region || "nyc3",
|
|
6123
|
+
accessKeyId: config.digitalocean?.accessKeyId || "",
|
|
6124
|
+
secretAccessKey: config.digitalocean?.secretAccessKey || "",
|
|
6125
|
+
cdnUrl: config.digitalocean?.cdnUrl,
|
|
6126
|
+
prefix: config.digitalocean?.prefix
|
|
6127
|
+
});
|
|
6128
|
+
case "backblaze":
|
|
6129
|
+
return createS3Storage({
|
|
6130
|
+
provider: "backblaze",
|
|
6131
|
+
bucket: config.backblaze?.bucket || "",
|
|
6132
|
+
region: "auto",
|
|
6133
|
+
accessKeyId: config.backblaze?.applicationKeyId || "",
|
|
6134
|
+
secretAccessKey: config.backblaze?.applicationKey || "",
|
|
6135
|
+
cdnUrl: config.backblaze?.cdnUrl,
|
|
6136
|
+
prefix: config.backblaze?.prefix
|
|
6137
|
+
});
|
|
6138
|
+
case "wasabi":
|
|
6139
|
+
return createS3Storage({
|
|
6140
|
+
provider: "wasabi",
|
|
6141
|
+
bucket: config.wasabi?.bucket || "",
|
|
6142
|
+
region: config.wasabi?.region || "us-east-1",
|
|
6143
|
+
accessKeyId: config.wasabi?.accessKeyId || "",
|
|
6144
|
+
secretAccessKey: config.wasabi?.secretAccessKey || "",
|
|
6145
|
+
cdnUrl: config.wasabi?.cdnUrl,
|
|
6146
|
+
prefix: config.wasabi?.prefix
|
|
6147
|
+
});
|
|
6148
|
+
case "cloudinary":
|
|
6149
|
+
return createCloudinaryStorage({
|
|
6150
|
+
cloudName: config.cloudinary?.cloudName || "",
|
|
6151
|
+
apiKey: config.cloudinary?.apiKey || "",
|
|
6152
|
+
apiSecret: config.cloudinary?.apiSecret || "",
|
|
6153
|
+
folder: config.cloudinary?.folder
|
|
6154
|
+
});
|
|
6155
|
+
case "ftp":
|
|
6156
|
+
case "sftp": {
|
|
6157
|
+
const ftpConf = config.ftp || config;
|
|
6158
|
+
return createFtpStorage({
|
|
6159
|
+
type: "ftp",
|
|
6160
|
+
host: ftpConf.host || "",
|
|
6161
|
+
port: ftpConf.port || 21,
|
|
6162
|
+
user: ftpConf.user || "",
|
|
6163
|
+
password: ftpConf.password || "",
|
|
6164
|
+
secure: ftpConf.secure || false,
|
|
6165
|
+
baseUrl: ftpConf.baseUrl || "",
|
|
6166
|
+
prefix: ftpConf.prefix
|
|
6167
|
+
});
|
|
6168
|
+
}
|
|
6169
|
+
case "local":
|
|
6170
|
+
default: {
|
|
6171
|
+
const localConfig = config.local || {
|
|
6172
|
+
uploadDir: config["local.uploadDir"],
|
|
6173
|
+
baseUrl: config["local.baseUrl"]
|
|
6174
|
+
};
|
|
6175
|
+
const savedUploadDir = (localConfig?.uploadDir || "").trim();
|
|
6176
|
+
let uploadDir;
|
|
6177
|
+
if (savedUploadDir) {
|
|
6178
|
+
if (path__default.default.isAbsolute(savedUploadDir)) {
|
|
6179
|
+
uploadDir = savedUploadDir;
|
|
6180
|
+
} else if (savedUploadDir.includes("/") || savedUploadDir.includes("\\")) {
|
|
6181
|
+
uploadDir = path__default.default.resolve(process.cwd(), savedUploadDir);
|
|
6182
|
+
} else {
|
|
6183
|
+
uploadDir = path__default.default.join(process.cwd(), "public", savedUploadDir);
|
|
6184
|
+
}
|
|
6185
|
+
} else {
|
|
6186
|
+
uploadDir = path__default.default.join(process.cwd(), "public", "uploads");
|
|
6187
|
+
}
|
|
6188
|
+
const savedBaseUrl = (localConfig?.baseUrl || "").trim();
|
|
6189
|
+
let baseUrl;
|
|
6190
|
+
if (savedBaseUrl) {
|
|
6191
|
+
baseUrl = savedBaseUrl.startsWith("/") ? savedBaseUrl : `/${savedBaseUrl}`;
|
|
6192
|
+
} else {
|
|
6193
|
+
baseUrl = "/uploads";
|
|
6194
|
+
}
|
|
6195
|
+
return createLocalStorage({ uploadDir, baseUrl });
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
async function processImage(buffer) {
|
|
6200
|
+
const metadata = await sharp__default.default(buffer).metadata();
|
|
6201
|
+
const mainImage = sharp__default.default(buffer).webp({ quality: 85 });
|
|
6202
|
+
const thumbnail = sharp__default.default(buffer).resize({ width: 500, withoutEnlargement: true }).webp({ quality: 80 });
|
|
6203
|
+
return {
|
|
6204
|
+
buffer: await mainImage.toBuffer(),
|
|
6205
|
+
thumbnailBuffer: await thumbnail.toBuffer(),
|
|
6206
|
+
width: metadata.width,
|
|
6207
|
+
height: metadata.height,
|
|
6208
|
+
format: "webp"
|
|
6209
|
+
};
|
|
6210
|
+
}
|
|
6211
|
+
|
|
6212
|
+
// src/storage/MediaService.ts
|
|
6213
|
+
var MediaService = class _MediaService {
|
|
6214
|
+
db;
|
|
6215
|
+
storage;
|
|
6216
|
+
dialect;
|
|
6217
|
+
genId;
|
|
6218
|
+
mediaTable = "media";
|
|
6219
|
+
foldersTable = "media_folders";
|
|
6220
|
+
constructor(db, storage, options) {
|
|
6221
|
+
this.db = db;
|
|
6222
|
+
this.storage = storage;
|
|
6223
|
+
this.dialect = options?.dialect || "sqlite";
|
|
6224
|
+
this.genId = options?.genId || chunkGVFB5C6O_cjs.genId;
|
|
6225
|
+
}
|
|
6226
|
+
static async init(db, options) {
|
|
6227
|
+
let storage;
|
|
6228
|
+
if (options?.storageConfig) {
|
|
6229
|
+
console.log(
|
|
6230
|
+
"[MediaService.init] Using provided storageConfig:",
|
|
6231
|
+
options.storageConfig.type
|
|
6232
|
+
);
|
|
6233
|
+
storage = await resolveProviderWithConfig(options.storageConfig);
|
|
6234
|
+
} else {
|
|
6235
|
+
const configService = new chunkHVSQDZZJ_cjs.ConfigService(db);
|
|
6236
|
+
await configService.load();
|
|
6237
|
+
storage = await resolveProvider(configService);
|
|
6238
|
+
}
|
|
6239
|
+
return new _MediaService(db, storage, options);
|
|
6240
|
+
}
|
|
6241
|
+
now() {
|
|
6242
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
6243
|
+
}
|
|
6244
|
+
buildFindConditions(params) {
|
|
6245
|
+
const conditions = [];
|
|
6246
|
+
const p = [];
|
|
6247
|
+
const sortCol = params.sortBy === "name" ? "title" : params.sortBy || "created_at";
|
|
6248
|
+
const sortDir = params.sortDir === "asc" ? "ASC" : "DESC";
|
|
6249
|
+
if (params.search) {
|
|
6250
|
+
conditions.push(
|
|
6251
|
+
`(title LIKE ? OR filename LIKE ? OR original_name LIKE ? OR alt LIKE ?)`
|
|
6252
|
+
);
|
|
6253
|
+
const s = `%${params.search}%`;
|
|
6254
|
+
p.push(s, s, s, s);
|
|
6255
|
+
}
|
|
6256
|
+
if (params.type && params.type !== "all") {
|
|
6257
|
+
conditions.push(`mime_type LIKE ?`);
|
|
6258
|
+
p.push(`${params.type}/%`);
|
|
6259
|
+
}
|
|
6260
|
+
if (params.folder) {
|
|
6261
|
+
conditions.push(`(folder = ? OR folder LIKE ?)`);
|
|
6262
|
+
p.push(params.folder, `${params.folder}/%`);
|
|
6263
|
+
}
|
|
6264
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
6265
|
+
return { where, params: p, orderBy: sortDir, sortCol };
|
|
6266
|
+
}
|
|
6267
|
+
rowToMedia(row) {
|
|
6268
|
+
return {
|
|
6269
|
+
id: row.id,
|
|
6270
|
+
filename: row.filename,
|
|
6271
|
+
title: row.title ?? null,
|
|
6272
|
+
originalName: row.original_name ?? row.originalName,
|
|
6273
|
+
mimeType: row.mime_type ?? row.mimeType,
|
|
6274
|
+
fileSize: row.file_size ?? row.fileSize,
|
|
6275
|
+
width: row.width ?? null,
|
|
6276
|
+
height: row.height ?? null,
|
|
6277
|
+
url: row.url,
|
|
6278
|
+
thumbnailUrl: row.thumbnail_url ?? row.thumbnailUrl ?? null,
|
|
6279
|
+
folder: row.folder ?? null,
|
|
6280
|
+
provider: row.provider,
|
|
6281
|
+
alt: row.alt ?? null,
|
|
6282
|
+
caption: row.caption ?? null,
|
|
6283
|
+
metadata: row.metadata ?? null,
|
|
6284
|
+
createdAt: row.created_at ?? row.createdAt,
|
|
6285
|
+
updatedAt: row.updated_at ?? row.updatedAt
|
|
6286
|
+
};
|
|
6287
|
+
}
|
|
6288
|
+
async sqliteRun(sql, params = []) {
|
|
6289
|
+
const stmt = this.db.prepare(sql);
|
|
6290
|
+
const sqlLower = sql.trim().toLowerCase();
|
|
6291
|
+
if (sqlLower.startsWith("insert") || sqlLower.startsWith("update") || sqlLower.startsWith("delete")) {
|
|
6292
|
+
return stmt.run(...params);
|
|
6293
|
+
}
|
|
6294
|
+
return stmt.all(...params);
|
|
6295
|
+
}
|
|
6296
|
+
sqliteGet(sql, params = []) {
|
|
6297
|
+
const stmt = this.db.prepare(sql);
|
|
6298
|
+
return stmt.get(...params);
|
|
6299
|
+
}
|
|
6300
|
+
async upload(file, folder = "") {
|
|
6301
|
+
const isImage = file.type.startsWith("image/");
|
|
6302
|
+
let processed;
|
|
6303
|
+
let uploadFile = file;
|
|
6304
|
+
let filename = file.name;
|
|
6305
|
+
let width = null;
|
|
6306
|
+
let height = null;
|
|
6307
|
+
if (isImage && !file.type.includes("svg")) {
|
|
6308
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
6309
|
+
processed = await processImage(buffer);
|
|
6310
|
+
const originalName = file.name.replace(/\.[^/.]+$/, "");
|
|
6311
|
+
const safeName = originalName.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").substring(0, 50);
|
|
6312
|
+
filename = `${safeName}.webp`;
|
|
6313
|
+
width = processed.width ?? null;
|
|
6314
|
+
height = processed.height ?? null;
|
|
6315
|
+
uploadFile = new File([processed.buffer], filename, {
|
|
6316
|
+
type: "image/webp"
|
|
6317
|
+
});
|
|
6318
|
+
}
|
|
6319
|
+
const storageResult = await this.storage.upload(uploadFile, {
|
|
6320
|
+
folder,
|
|
6321
|
+
filename
|
|
6322
|
+
});
|
|
6323
|
+
const thumbnailUrl = await this.storage.generateThumbnail(
|
|
6324
|
+
{
|
|
6325
|
+
...storageResult,
|
|
6326
|
+
id: "",
|
|
6327
|
+
provider: this.storage.name,
|
|
6328
|
+
createdAt: this.now()
|
|
6329
|
+
},
|
|
6330
|
+
{ width: 400, height: 400 }
|
|
6331
|
+
);
|
|
6332
|
+
const id = this.genId();
|
|
6333
|
+
const now = this.now();
|
|
6334
|
+
if (this.dialect === "sqlite") {
|
|
6335
|
+
await this.sqliteRun(
|
|
6336
|
+
`INSERT INTO ${this.mediaTable}
|
|
6337
|
+
(id, filename, title, original_name, mime_type, file_size, width, height, url, thumbnail_url, folder, provider, alt, caption, metadata, created_at, updated_at)
|
|
6338
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6339
|
+
[
|
|
6340
|
+
id,
|
|
6341
|
+
storageResult.filename,
|
|
6342
|
+
file.name.replace(/\.[^/.]+$/, ""),
|
|
6343
|
+
file.name,
|
|
6344
|
+
storageResult.mimeType,
|
|
6345
|
+
storageResult.size,
|
|
6346
|
+
width,
|
|
6347
|
+
height,
|
|
6348
|
+
storageResult.url,
|
|
6349
|
+
thumbnailUrl,
|
|
6350
|
+
folder || null,
|
|
6351
|
+
this.storage.name,
|
|
6352
|
+
null,
|
|
6353
|
+
null,
|
|
6354
|
+
null,
|
|
6355
|
+
now,
|
|
6356
|
+
now
|
|
6357
|
+
]
|
|
6358
|
+
);
|
|
6359
|
+
} else {
|
|
6360
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6361
|
+
await this.db.insert(mediaSchema).values({
|
|
6362
|
+
id,
|
|
6363
|
+
filename: storageResult.filename,
|
|
6364
|
+
title: file.name.replace(/\.[^/.]+$/, ""),
|
|
6365
|
+
originalName: file.name,
|
|
6366
|
+
mimeType: storageResult.mimeType,
|
|
6367
|
+
fileSize: storageResult.size,
|
|
6368
|
+
width,
|
|
6369
|
+
height,
|
|
6370
|
+
url: storageResult.url,
|
|
6371
|
+
thumbnailUrl,
|
|
6372
|
+
folder: folder || "",
|
|
6373
|
+
provider: this.storage.name,
|
|
6374
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6375
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
6376
|
+
}).returning();
|
|
6377
|
+
}
|
|
6378
|
+
return {
|
|
6379
|
+
id,
|
|
6380
|
+
filename: storageResult.filename,
|
|
6381
|
+
title: file.name.replace(/\.[^/.]+$/, ""),
|
|
6382
|
+
originalName: file.name,
|
|
6383
|
+
mimeType: storageResult.mimeType,
|
|
6384
|
+
fileSize: storageResult.size,
|
|
6385
|
+
width,
|
|
6386
|
+
height,
|
|
6387
|
+
url: storageResult.url,
|
|
6388
|
+
thumbnailUrl,
|
|
6389
|
+
folder: folder || null,
|
|
6390
|
+
provider: this.storage.name,
|
|
6391
|
+
alt: null,
|
|
6392
|
+
caption: null,
|
|
6393
|
+
metadata: null,
|
|
6394
|
+
createdAt: now,
|
|
6395
|
+
updatedAt: now
|
|
6396
|
+
};
|
|
6397
|
+
}
|
|
6398
|
+
async delete(id) {
|
|
6399
|
+
let item = null;
|
|
6400
|
+
if (this.dialect === "sqlite") {
|
|
6401
|
+
item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
|
|
6402
|
+
id
|
|
6403
|
+
]);
|
|
6404
|
+
} else {
|
|
6405
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6406
|
+
const [row] = await this.db.select().from(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6407
|
+
if (row) item = this.rowToMedia(row);
|
|
6408
|
+
}
|
|
6409
|
+
if (!item) return;
|
|
6410
|
+
await this.deleteFile(item.url);
|
|
6411
|
+
if (item.thumbnailUrl && item.thumbnailUrl !== item.url && item.thumbnailUrl !== item.url + "?thumb") {
|
|
6412
|
+
try {
|
|
6413
|
+
await this.deleteFile(item.thumbnailUrl);
|
|
6414
|
+
} catch {
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
if (this.dialect === "sqlite") {
|
|
6418
|
+
await this.sqliteRun(`DELETE FROM ${this.mediaTable} WHERE id = ?`, [id]);
|
|
6419
|
+
} else {
|
|
6420
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6421
|
+
await this.db.delete(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6422
|
+
}
|
|
6423
|
+
}
|
|
6424
|
+
async deleteFile(url) {
|
|
6425
|
+
await this.storage.delete(url);
|
|
6426
|
+
}
|
|
6427
|
+
async rename(id, newKey) {
|
|
6428
|
+
let item = null;
|
|
6429
|
+
if (this.dialect === "sqlite") {
|
|
6430
|
+
item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
|
|
6431
|
+
id
|
|
6432
|
+
]);
|
|
6433
|
+
} else {
|
|
6434
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6435
|
+
const [row] = await this.db.select().from(mediaSchema).where(mediaSchema.id.equals(id));
|
|
6436
|
+
if (row) item = this.rowToMedia(row);
|
|
6437
|
+
}
|
|
6438
|
+
if (!item) return null;
|
|
6439
|
+
const newUrl = await this.storage.rename(item.url, newKey);
|
|
6440
|
+
let newThumbnailUrl;
|
|
6441
|
+
if (item.thumbnailUrl || this.storage.name === "cloudinary") {
|
|
6442
|
+
const versionMatch = newUrl.match(/\/upload\/(v\d+)\//);
|
|
6443
|
+
const version = versionMatch ? versionMatch[1] + "/" : "";
|
|
6444
|
+
const baseUrlMatch = newUrl.match(/(.+?)\/upload\//);
|
|
6445
|
+
const baseUrl = baseUrlMatch ? baseUrlMatch[1] : "https://res.cloudinary.com/" + this.storage.config?.cloudName || "unknown";
|
|
6446
|
+
newThumbnailUrl = `${baseUrl}/upload/w_200,h_200,c_fill/${version}${newKey}`;
|
|
6447
|
+
}
|
|
6448
|
+
const ext = item.filename.split(".").pop();
|
|
6449
|
+
const newFilename = newKey.includes(".") ? newKey : `${newKey}.${ext}`;
|
|
6450
|
+
const updateData = {
|
|
6451
|
+
url: newUrl,
|
|
6452
|
+
filename: newFilename,
|
|
6453
|
+
thumbnailUrl: newThumbnailUrl
|
|
6454
|
+
};
|
|
6455
|
+
if (this.dialect === "sqlite") {
|
|
6456
|
+
const sqliteUpdateData = { ...updateData };
|
|
6457
|
+
if ("thumbnailUrl" in sqliteUpdateData) {
|
|
6458
|
+
sqliteUpdateData.thumbnail_url = sqliteUpdateData.thumbnailUrl;
|
|
6459
|
+
delete sqliteUpdateData.thumbnailUrl;
|
|
6460
|
+
}
|
|
6461
|
+
const sets = Object.keys(sqliteUpdateData).map((k) => `${k} = ?`).join(", ");
|
|
6462
|
+
const vals = Object.values(sqliteUpdateData);
|
|
6463
|
+
await this.sqliteRun(
|
|
6464
|
+
`UPDATE ${this.mediaTable} SET ${sets}, updated_at = ? WHERE id = ?`,
|
|
6465
|
+
[...vals, this.now(), id]
|
|
6466
|
+
);
|
|
6467
|
+
} else {
|
|
6468
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6469
|
+
await this.db.update(mediaSchema).set({ ...updateData, updatedAt: this.now() }).where(mediaSchema.id.equals(id));
|
|
6470
|
+
}
|
|
6471
|
+
return {
|
|
6472
|
+
...item,
|
|
6473
|
+
...updateData,
|
|
6474
|
+
updatedAt: this.now(),
|
|
6475
|
+
thumbnailUrl: updateData.thumbnailUrl ?? null
|
|
6476
|
+
};
|
|
6477
|
+
}
|
|
6478
|
+
async find(params = {}) {
|
|
6479
|
+
const {
|
|
6480
|
+
page = 1,
|
|
6481
|
+
limit = 30,
|
|
6482
|
+
search = "",
|
|
6483
|
+
type = "",
|
|
6484
|
+
folder = "",
|
|
6485
|
+
sortBy = "createdAt",
|
|
6486
|
+
sortDir = "desc"
|
|
6487
|
+
} = params;
|
|
6488
|
+
const {
|
|
6489
|
+
where,
|
|
6490
|
+
params: p,
|
|
6491
|
+
orderBy,
|
|
6492
|
+
sortCol
|
|
6493
|
+
} = this.buildFindConditions({
|
|
6494
|
+
page,
|
|
6495
|
+
limit,
|
|
6496
|
+
search,
|
|
6497
|
+
type,
|
|
6498
|
+
folder,
|
|
6499
|
+
sortBy,
|
|
6500
|
+
sortDir
|
|
6501
|
+
});
|
|
6502
|
+
const offset = (page - 1) * limit;
|
|
6503
|
+
if (this.dialect === "sqlite") {
|
|
6504
|
+
const countRow = this.sqliteGet(
|
|
6505
|
+
`SELECT COUNT(*) as cnt FROM ${this.mediaTable} ${where}`,
|
|
6506
|
+
p
|
|
6507
|
+
);
|
|
6508
|
+
const totalDocs2 = countRow?.cnt ?? 0;
|
|
6509
|
+
const rows = await this.sqliteRun(
|
|
6510
|
+
`SELECT * FROM ${this.mediaTable} ${where} ORDER BY ${sortCol} ${orderBy} LIMIT ? OFFSET ?`,
|
|
6511
|
+
[...p, limit, offset]
|
|
6512
|
+
);
|
|
6513
|
+
return {
|
|
6514
|
+
docs: rows.map((r) => this.rowToMedia(r)),
|
|
6515
|
+
totalDocs: totalDocs2,
|
|
6516
|
+
page,
|
|
6517
|
+
limit,
|
|
6518
|
+
totalPages: Math.ceil(totalDocs2 / limit)
|
|
6519
|
+
};
|
|
6520
|
+
}
|
|
6521
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6522
|
+
const { like, or, and, asc, desc, eq, sql } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6523
|
+
const conditions = [];
|
|
6524
|
+
if (search) {
|
|
6525
|
+
conditions.push(
|
|
6526
|
+
or(
|
|
6527
|
+
like(mediaSchema.title, `%${search}%`),
|
|
6528
|
+
like(mediaSchema.filename, `%${search}%`),
|
|
6529
|
+
like(mediaSchema.originalName, `%${search}%`),
|
|
6530
|
+
like(mediaSchema.alt, `%${search}%`)
|
|
6531
|
+
)
|
|
6532
|
+
);
|
|
6533
|
+
}
|
|
6534
|
+
if (type && type !== "all") {
|
|
6535
|
+
conditions.push(like(mediaSchema.mimeType, `${type}/%`));
|
|
6536
|
+
}
|
|
6537
|
+
if (folder) {
|
|
6538
|
+
conditions.push(
|
|
6539
|
+
or(
|
|
6540
|
+
eq(mediaSchema.folder, folder),
|
|
6541
|
+
like(mediaSchema.folder, `${folder}/%`)
|
|
6542
|
+
)
|
|
6543
|
+
);
|
|
6544
|
+
}
|
|
6545
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : void 0;
|
|
6546
|
+
const order = sortDir === "asc" ? asc(mediaSchema[sortCol]) : desc(mediaSchema[sortCol]);
|
|
6547
|
+
const docs = await this.db.select().from(mediaSchema).where(whereClause).orderBy(order).limit(limit).offset(offset);
|
|
6548
|
+
const [{ count }] = await this.db.select({ count: sql`count(*)` }).from(mediaSchema).where(whereClause);
|
|
6549
|
+
const totalDocs = Number(count);
|
|
6550
|
+
return {
|
|
6551
|
+
docs: docs.map((r) => this.rowToMedia(r)),
|
|
6552
|
+
totalDocs,
|
|
6553
|
+
page,
|
|
6554
|
+
limit,
|
|
6555
|
+
totalPages: Math.ceil(totalDocs / limit)
|
|
6556
|
+
};
|
|
6557
|
+
}
|
|
6558
|
+
async update(id, data) {
|
|
6559
|
+
const now = this.now();
|
|
6560
|
+
if (this.dialect === "sqlite") {
|
|
6561
|
+
const sets = ["updated_at = ?"];
|
|
6562
|
+
const p = [now];
|
|
6563
|
+
if (data.title !== void 0) {
|
|
6564
|
+
sets.push("title = ?");
|
|
6565
|
+
p.push(data.title);
|
|
6566
|
+
}
|
|
6567
|
+
if (data.alt !== void 0) {
|
|
6568
|
+
sets.push("alt = ?");
|
|
6569
|
+
p.push(data.alt);
|
|
6570
|
+
}
|
|
6571
|
+
if (data.caption !== void 0) {
|
|
6572
|
+
sets.push("caption = ?");
|
|
6573
|
+
p.push(data.caption);
|
|
6574
|
+
}
|
|
6575
|
+
if (data.folder !== void 0) {
|
|
6576
|
+
sets.push("folder = ?");
|
|
6577
|
+
p.push(data.folder || null);
|
|
6578
|
+
}
|
|
6579
|
+
p.push(id);
|
|
6580
|
+
await this.sqliteRun(
|
|
6581
|
+
`UPDATE ${this.mediaTable} SET ${sets.join(", ")} WHERE id = ?`,
|
|
6582
|
+
p
|
|
6583
|
+
);
|
|
6584
|
+
const row = this.sqliteGet(
|
|
6585
|
+
`SELECT * FROM ${this.mediaTable} WHERE id = ?`,
|
|
6586
|
+
[id]
|
|
6587
|
+
);
|
|
6588
|
+
return row ? this.rowToMedia(row) : null;
|
|
6589
|
+
}
|
|
6590
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6591
|
+
const [updated] = await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(mediaSchema.id.equals(id)).returning();
|
|
6592
|
+
return updated ? this.rowToMedia(updated) : null;
|
|
6593
|
+
}
|
|
6594
|
+
async updateMany(ids, data) {
|
|
6595
|
+
const now = this.now();
|
|
6596
|
+
if (this.dialect === "sqlite") {
|
|
6597
|
+
for (const id of ids) {
|
|
6598
|
+
const sets = ["updated_at = ?"];
|
|
6599
|
+
const p = [now];
|
|
6600
|
+
if (data.folder !== void 0) {
|
|
6601
|
+
sets.push("folder = ?");
|
|
6602
|
+
p.push(data.folder || null);
|
|
6603
|
+
}
|
|
6604
|
+
p.push(id);
|
|
6605
|
+
await this.sqliteRun(
|
|
6606
|
+
`UPDATE ${this.mediaTable} SET ${sets.join(", ")} WHERE id = ?`,
|
|
6607
|
+
p
|
|
6608
|
+
);
|
|
6609
|
+
}
|
|
6610
|
+
} else {
|
|
6611
|
+
const { media: mediaSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6612
|
+
for (const id of ids) {
|
|
6613
|
+
await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(mediaSchema.id.equals(id));
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
async listFolders() {
|
|
6618
|
+
if (this.dialect === "sqlite") {
|
|
6619
|
+
const rows = await this.sqliteRun(
|
|
6620
|
+
`SELECT path FROM ${this.foldersTable} UNION
|
|
6621
|
+
SELECT folder as path FROM ${this.mediaTable} WHERE folder IS NOT NULL AND folder != ''`
|
|
6622
|
+
);
|
|
6623
|
+
return rows.map((r) => r.path).filter((f) => f && f !== "").sort();
|
|
6624
|
+
}
|
|
6625
|
+
const { media: mediaSchema, mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6626
|
+
const { eq, sql } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6627
|
+
const fromMedia = await this.db.select({ folder: mediaSchema.folder }).from(mediaSchema).groupBy(mediaSchema.folder);
|
|
6628
|
+
const fromFolders = await this.db.select({ path: folderSchema.path }).from(folderSchema);
|
|
6629
|
+
const allPaths = /* @__PURE__ */ new Set([
|
|
6630
|
+
...fromMedia.map((r) => r.folder),
|
|
6631
|
+
...fromFolders.map((r) => r.path)
|
|
6632
|
+
]);
|
|
6633
|
+
return Array.from(allPaths).filter((f) => f && f !== "").sort();
|
|
6634
|
+
}
|
|
6635
|
+
async createFolder(name, parentPath = "") {
|
|
6636
|
+
const fullPath = parentPath ? `${parentPath}/${name}` : name;
|
|
6637
|
+
if (this.storage.name === "local") {
|
|
6638
|
+
const { mkdir: mkdir2 } = await import('fs/promises');
|
|
6639
|
+
const { join: join2 } = await import('path');
|
|
6640
|
+
await mkdir2(join2(process.cwd(), "public", "uploads", fullPath), {
|
|
6641
|
+
recursive: true
|
|
6642
|
+
});
|
|
6643
|
+
}
|
|
6644
|
+
const now = this.now();
|
|
6645
|
+
if (this.dialect === "sqlite") {
|
|
6646
|
+
await this.sqliteRun(
|
|
6647
|
+
`INSERT OR IGNORE INTO ${this.foldersTable} (path, name, parent_path, created_at) VALUES (?, ?, ?, ?)`,
|
|
6648
|
+
[fullPath, name, parentPath || null, now]
|
|
6649
|
+
);
|
|
6650
|
+
} else {
|
|
6651
|
+
const { mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6652
|
+
await this.db.insert(folderSchema).values({
|
|
6653
|
+
path: fullPath,
|
|
6654
|
+
name,
|
|
6655
|
+
parentPath: parentPath || null,
|
|
6656
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
6657
|
+
}).onConflictDoNothing();
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
async deleteFolder(folder) {
|
|
6661
|
+
const result = await this.find({ folder, limit: 1e4 });
|
|
6662
|
+
for (const item of result.docs) {
|
|
6663
|
+
await this.delete(item.id);
|
|
6664
|
+
}
|
|
6665
|
+
if (this.dialect === "sqlite") {
|
|
6666
|
+
await this.sqliteRun(
|
|
6667
|
+
`DELETE FROM ${this.foldersTable} WHERE path = ? OR path LIKE ?`,
|
|
6668
|
+
[folder, `${folder}/%`]
|
|
6669
|
+
);
|
|
6670
|
+
} else {
|
|
6671
|
+
const { mediaFolders: folderSchema } = await (this.dialect === "mysql" ? import('./mysql-media-AI6YK767.cjs') : import('./media-WKP5AOX2.cjs'));
|
|
6672
|
+
const { like, or, eq } = await (this.dialect === "mysql" ? import('drizzle-orm/mysql-core') : import('drizzle-orm/pg-core'));
|
|
6673
|
+
await this.db.delete(folderSchema).where(
|
|
6674
|
+
or(
|
|
6675
|
+
eq(folderSchema.path, folder),
|
|
6676
|
+
like(folderSchema.path, `${folder}/%`)
|
|
6677
|
+
)
|
|
6678
|
+
);
|
|
6679
|
+
}
|
|
6680
|
+
if (this.storage.name === "local") {
|
|
6681
|
+
const { rm } = await import('fs/promises');
|
|
6682
|
+
const { join: join2 } = await import('path');
|
|
6683
|
+
try {
|
|
6684
|
+
await rm(join2(process.cwd(), "public", "uploads", folder), {
|
|
6685
|
+
recursive: true,
|
|
6686
|
+
force: true
|
|
6687
|
+
});
|
|
6688
|
+
} catch {
|
|
6689
|
+
}
|
|
6690
|
+
}
|
|
6691
|
+
}
|
|
6692
|
+
};
|
|
4039
6693
|
|
|
4040
6694
|
// src/registry/config.ts
|
|
4041
6695
|
function normalizeCollections(collections) {
|
|
@@ -4068,139 +6722,227 @@ function defineConfig(config) {
|
|
|
4068
6722
|
|
|
4069
6723
|
Object.defineProperty(exports, "allSettingsGlobals", {
|
|
4070
6724
|
enumerable: true,
|
|
4071
|
-
get: function () { return
|
|
6725
|
+
get: function () { return chunkKDVDIZ4Y_cjs.allSettingsGlobals; }
|
|
4072
6726
|
});
|
|
4073
6727
|
Object.defineProperty(exports, "blogCollections", {
|
|
4074
6728
|
enumerable: true,
|
|
4075
|
-
get: function () { return
|
|
6729
|
+
get: function () { return chunkKDVDIZ4Y_cjs.blogCollections; }
|
|
4076
6730
|
});
|
|
4077
6731
|
Object.defineProperty(exports, "blogGlobals", {
|
|
4078
6732
|
enumerable: true,
|
|
4079
|
-
get: function () { return
|
|
6733
|
+
get: function () { return chunkKDVDIZ4Y_cjs.blogGlobals; }
|
|
4080
6734
|
});
|
|
4081
6735
|
Object.defineProperty(exports, "coreSettingsGlobals", {
|
|
4082
6736
|
enumerable: true,
|
|
4083
|
-
get: function () { return
|
|
6737
|
+
get: function () { return chunkKDVDIZ4Y_cjs.coreSettingsGlobals; }
|
|
4084
6738
|
});
|
|
4085
6739
|
Object.defineProperty(exports, "createTemplateConfig", {
|
|
4086
6740
|
enumerable: true,
|
|
4087
|
-
get: function () { return
|
|
6741
|
+
get: function () { return chunkKDVDIZ4Y_cjs.createTemplateConfig; }
|
|
4088
6742
|
});
|
|
4089
6743
|
Object.defineProperty(exports, "ecommerceCollections", {
|
|
4090
6744
|
enumerable: true,
|
|
4091
|
-
get: function () { return
|
|
6745
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceCollections; }
|
|
4092
6746
|
});
|
|
4093
6747
|
Object.defineProperty(exports, "ecommerceGlobals", {
|
|
4094
6748
|
enumerable: true,
|
|
4095
|
-
get: function () { return
|
|
6749
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceGlobals; }
|
|
4096
6750
|
});
|
|
4097
6751
|
Object.defineProperty(exports, "ecommerceSettingsGlobals", {
|
|
4098
6752
|
enumerable: true,
|
|
4099
|
-
get: function () { return
|
|
6753
|
+
get: function () { return chunkKDVDIZ4Y_cjs.ecommerceSettingsGlobals; }
|
|
4100
6754
|
});
|
|
4101
6755
|
Object.defineProperty(exports, "kitchenSinkCollections", {
|
|
4102
6756
|
enumerable: true,
|
|
4103
|
-
get: function () { return
|
|
6757
|
+
get: function () { return chunkKDVDIZ4Y_cjs.kitchenSinkCollections; }
|
|
4104
6758
|
});
|
|
4105
6759
|
Object.defineProperty(exports, "mediaCollections", {
|
|
4106
6760
|
enumerable: true,
|
|
4107
|
-
get: function () { return
|
|
6761
|
+
get: function () { return chunkKDVDIZ4Y_cjs.mediaCollections; }
|
|
4108
6762
|
});
|
|
4109
6763
|
Object.defineProperty(exports, "minimalCollections", {
|
|
4110
6764
|
enumerable: true,
|
|
4111
|
-
get: function () { return
|
|
6765
|
+
get: function () { return chunkKDVDIZ4Y_cjs.minimalCollections; }
|
|
4112
6766
|
});
|
|
4113
6767
|
Object.defineProperty(exports, "RedisAuthAdapter", {
|
|
4114
6768
|
enumerable: true,
|
|
4115
|
-
get: function () { return
|
|
4116
|
-
});
|
|
4117
|
-
Object.defineProperty(exports, "EmailTransport", {
|
|
4118
|
-
enumerable: true,
|
|
4119
|
-
get: function () { return chunk3EVLFWH2_cjs.EmailTransport; }
|
|
6769
|
+
get: function () { return chunkBLMFBDBG_cjs.RedisAuthAdapter; }
|
|
4120
6770
|
});
|
|
4121
6771
|
Object.defineProperty(exports, "PasswordPolicy", {
|
|
4122
6772
|
enumerable: true,
|
|
4123
|
-
get: function () { return
|
|
6773
|
+
get: function () { return chunk4M5PHMUE_cjs.PasswordPolicy; }
|
|
4124
6774
|
});
|
|
4125
6775
|
Object.defineProperty(exports, "SQLiteAuthAdapter", {
|
|
4126
6776
|
enumerable: true,
|
|
4127
|
-
get: function () { return
|
|
6777
|
+
get: function () { return chunk4M5PHMUE_cjs.SQLiteAuthAdapter; }
|
|
4128
6778
|
});
|
|
4129
6779
|
Object.defineProperty(exports, "autoBootstrap", {
|
|
4130
6780
|
enumerable: true,
|
|
4131
|
-
get: function () { return
|
|
6781
|
+
get: function () { return chunk4M5PHMUE_cjs.autoBootstrap; }
|
|
4132
6782
|
});
|
|
4133
6783
|
Object.defineProperty(exports, "bootstrapAdmin", {
|
|
4134
6784
|
enumerable: true,
|
|
4135
|
-
get: function () { return
|
|
6785
|
+
get: function () { return chunk4M5PHMUE_cjs.bootstrapAdmin; }
|
|
4136
6786
|
});
|
|
4137
6787
|
Object.defineProperty(exports, "getBootstrapFromEnv", {
|
|
4138
6788
|
enumerable: true,
|
|
4139
|
-
get: function () { return
|
|
6789
|
+
get: function () { return chunk4M5PHMUE_cjs.getBootstrapFromEnv; }
|
|
6790
|
+
});
|
|
6791
|
+
Object.defineProperty(exports, "CSSGenerator", {
|
|
6792
|
+
enumerable: true,
|
|
6793
|
+
get: function () { return chunkEWP5AT6A_cjs.CSSGenerator; }
|
|
6794
|
+
});
|
|
6795
|
+
Object.defineProperty(exports, "createAdminStyling", {
|
|
6796
|
+
enumerable: true,
|
|
6797
|
+
get: function () { return chunkEWP5AT6A_cjs.createAdminStyling; }
|
|
6798
|
+
});
|
|
6799
|
+
Object.defineProperty(exports, "defaultDarkTheme", {
|
|
6800
|
+
enumerable: true,
|
|
6801
|
+
get: function () { return chunkEWP5AT6A_cjs.defaultDarkTheme; }
|
|
6802
|
+
});
|
|
6803
|
+
Object.defineProperty(exports, "defaultFieldStyling", {
|
|
6804
|
+
enumerable: true,
|
|
6805
|
+
get: function () { return chunkEWP5AT6A_cjs.defaultFieldStyling; }
|
|
6806
|
+
});
|
|
6807
|
+
Object.defineProperty(exports, "defaultLightTheme", {
|
|
6808
|
+
enumerable: true,
|
|
6809
|
+
get: function () { return chunkEWP5AT6A_cjs.defaultLightTheme; }
|
|
6810
|
+
});
|
|
6811
|
+
Object.defineProperty(exports, "ecommerce2026Theme", {
|
|
6812
|
+
enumerable: true,
|
|
6813
|
+
get: function () { return chunkEWP5AT6A_cjs.ecommerce2026Theme; }
|
|
6814
|
+
});
|
|
6815
|
+
Object.defineProperty(exports, "generateCSSVariables", {
|
|
6816
|
+
enumerable: true,
|
|
6817
|
+
get: function () { return chunkEWP5AT6A_cjs.generateCSSVariables; }
|
|
6818
|
+
});
|
|
6819
|
+
Object.defineProperty(exports, "generateTailwindConfig", {
|
|
6820
|
+
enumerable: true,
|
|
6821
|
+
get: function () { return chunkEWP5AT6A_cjs.generateTailwindConfig; }
|
|
4140
6822
|
});
|
|
4141
6823
|
Object.defineProperty(exports, "createContext", {
|
|
4142
6824
|
enumerable: true,
|
|
4143
|
-
get: function () { return
|
|
6825
|
+
get: function () { return chunk42JPONZU_cjs.createContext; }
|
|
4144
6826
|
});
|
|
4145
6827
|
Object.defineProperty(exports, "createCountProcedure", {
|
|
4146
6828
|
enumerable: true,
|
|
4147
|
-
get: function () { return
|
|
6829
|
+
get: function () { return chunk42JPONZU_cjs.createCountProcedure; }
|
|
4148
6830
|
});
|
|
4149
6831
|
Object.defineProperty(exports, "createCreateProcedure", {
|
|
4150
6832
|
enumerable: true,
|
|
4151
|
-
get: function () { return
|
|
6833
|
+
get: function () { return chunk42JPONZU_cjs.createCreateProcedure; }
|
|
4152
6834
|
});
|
|
4153
6835
|
Object.defineProperty(exports, "createDeleteProcedure", {
|
|
4154
6836
|
enumerable: true,
|
|
4155
|
-
get: function () { return
|
|
6837
|
+
get: function () { return chunk42JPONZU_cjs.createDeleteProcedure; }
|
|
4156
6838
|
});
|
|
4157
6839
|
Object.defineProperty(exports, "createDynamicRouter", {
|
|
4158
6840
|
enumerable: true,
|
|
4159
|
-
get: function () { return
|
|
6841
|
+
get: function () { return chunk42JPONZU_cjs.createDynamicRouter; }
|
|
4160
6842
|
});
|
|
4161
6843
|
Object.defineProperty(exports, "createFindByIDProcedure", {
|
|
4162
6844
|
enumerable: true,
|
|
4163
|
-
get: function () { return
|
|
6845
|
+
get: function () { return chunk42JPONZU_cjs.createFindByIDProcedure; }
|
|
4164
6846
|
});
|
|
4165
6847
|
Object.defineProperty(exports, "createFindProcedure", {
|
|
4166
6848
|
enumerable: true,
|
|
4167
|
-
get: function () { return
|
|
6849
|
+
get: function () { return chunk42JPONZU_cjs.createFindProcedure; }
|
|
4168
6850
|
});
|
|
4169
6851
|
Object.defineProperty(exports, "createKyroServer", {
|
|
4170
6852
|
enumerable: true,
|
|
4171
|
-
get: function () { return
|
|
6853
|
+
get: function () { return chunk42JPONZU_cjs.createKyroServer; }
|
|
4172
6854
|
});
|
|
4173
6855
|
Object.defineProperty(exports, "createUpdateProcedure", {
|
|
4174
6856
|
enumerable: true,
|
|
4175
|
-
get: function () { return
|
|
6857
|
+
get: function () { return chunk42JPONZU_cjs.createUpdateProcedure; }
|
|
4176
6858
|
});
|
|
4177
6859
|
Object.defineProperty(exports, "buildGraphQLSchema", {
|
|
4178
6860
|
enumerable: true,
|
|
4179
|
-
get: function () { return
|
|
6861
|
+
get: function () { return chunkFTSSDDZQ_cjs.buildGraphQLSchema; }
|
|
4180
6862
|
});
|
|
4181
6863
|
Object.defineProperty(exports, "createGraphQLSchema", {
|
|
4182
6864
|
enumerable: true,
|
|
4183
|
-
get: function () { return
|
|
6865
|
+
get: function () { return chunkFTSSDDZQ_cjs.createGraphQLSchema; }
|
|
6866
|
+
});
|
|
6867
|
+
Object.defineProperty(exports, "InMemoryRateLimiter", {
|
|
6868
|
+
enumerable: true,
|
|
6869
|
+
get: function () { return chunkE63IF3MD_cjs.InMemoryRateLimiter; }
|
|
4184
6870
|
});
|
|
4185
6871
|
Object.defineProperty(exports, "createHonoApp", {
|
|
4186
6872
|
enumerable: true,
|
|
4187
|
-
get: function () { return
|
|
6873
|
+
get: function () { return chunkE63IF3MD_cjs.createHonoApp; }
|
|
4188
6874
|
});
|
|
4189
6875
|
Object.defineProperty(exports, "createRESTAPI", {
|
|
4190
6876
|
enumerable: true,
|
|
4191
|
-
get: function () { return
|
|
6877
|
+
get: function () { return chunkE63IF3MD_cjs.createRESTAPI; }
|
|
6878
|
+
});
|
|
6879
|
+
Object.defineProperty(exports, "ConfigService", {
|
|
6880
|
+
enumerable: true,
|
|
6881
|
+
get: function () { return chunkHVSQDZZJ_cjs.ConfigService; }
|
|
6882
|
+
});
|
|
6883
|
+
Object.defineProperty(exports, "EmailTransport", {
|
|
6884
|
+
enumerable: true,
|
|
6885
|
+
get: function () { return chunkHVSQDZZJ_cjs.EmailTransport; }
|
|
6886
|
+
});
|
|
6887
|
+
Object.defineProperty(exports, "ALL_WEBHOOK_EVENTS", {
|
|
6888
|
+
enumerable: true,
|
|
6889
|
+
get: function () { return chunkVIONYQ2K_cjs.ALL_WEBHOOK_EVENTS; }
|
|
6890
|
+
});
|
|
6891
|
+
Object.defineProperty(exports, "WEBHOOK_COLLECTION", {
|
|
6892
|
+
enumerable: true,
|
|
6893
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_COLLECTION; }
|
|
6894
|
+
});
|
|
6895
|
+
Object.defineProperty(exports, "WEBHOOK_DELIVERY_COLLECTION", {
|
|
6896
|
+
enumerable: true,
|
|
6897
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_DELIVERY_COLLECTION; }
|
|
6898
|
+
});
|
|
6899
|
+
Object.defineProperty(exports, "WEBHOOK_EVENTS", {
|
|
6900
|
+
enumerable: true,
|
|
6901
|
+
get: function () { return chunkVIONYQ2K_cjs.WEBHOOK_EVENTS; }
|
|
6902
|
+
});
|
|
6903
|
+
Object.defineProperty(exports, "WebhookService", {
|
|
6904
|
+
enumerable: true,
|
|
6905
|
+
get: function () { return chunkVIONYQ2K_cjs.WebhookService; }
|
|
6906
|
+
});
|
|
6907
|
+
Object.defineProperty(exports, "buildDeliveryRecord", {
|
|
6908
|
+
enumerable: true,
|
|
6909
|
+
get: function () { return chunkVIONYQ2K_cjs.buildDeliveryRecord; }
|
|
6910
|
+
});
|
|
6911
|
+
Object.defineProperty(exports, "createTestPayload", {
|
|
6912
|
+
enumerable: true,
|
|
6913
|
+
get: function () { return chunkVIONYQ2K_cjs.createTestPayload; }
|
|
6914
|
+
});
|
|
6915
|
+
Object.defineProperty(exports, "createWebhookService", {
|
|
6916
|
+
enumerable: true,
|
|
6917
|
+
get: function () { return chunkVIONYQ2K_cjs.createWebhookService; }
|
|
6918
|
+
});
|
|
6919
|
+
Object.defineProperty(exports, "deliverWebhook", {
|
|
6920
|
+
enumerable: true,
|
|
6921
|
+
get: function () { return chunkVIONYQ2K_cjs.deliverWebhook; }
|
|
6922
|
+
});
|
|
6923
|
+
Object.defineProperty(exports, "deliverWithRetry", {
|
|
6924
|
+
enumerable: true,
|
|
6925
|
+
get: function () { return chunkVIONYQ2K_cjs.deliverWithRetry; }
|
|
4192
6926
|
});
|
|
4193
6927
|
Object.defineProperty(exports, "evaluateAccess", {
|
|
4194
6928
|
enumerable: true,
|
|
4195
|
-
get: function () { return
|
|
6929
|
+
get: function () { return chunkVIONYQ2K_cjs.evaluateAccess; }
|
|
6930
|
+
});
|
|
6931
|
+
Object.defineProperty(exports, "generateWebhookSecret", {
|
|
6932
|
+
enumerable: true,
|
|
6933
|
+
get: function () { return chunkVIONYQ2K_cjs.generateWebhookSecret; }
|
|
4196
6934
|
});
|
|
4197
6935
|
Object.defineProperty(exports, "getWhereClause", {
|
|
4198
6936
|
enumerable: true,
|
|
4199
|
-
get: function () { return
|
|
6937
|
+
get: function () { return chunkVIONYQ2K_cjs.getWhereClause; }
|
|
4200
6938
|
});
|
|
4201
6939
|
Object.defineProperty(exports, "mergeWhereClauses", {
|
|
4202
6940
|
enumerable: true,
|
|
4203
|
-
get: function () { return
|
|
6941
|
+
get: function () { return chunkVIONYQ2K_cjs.mergeWhereClauses; }
|
|
6942
|
+
});
|
|
6943
|
+
Object.defineProperty(exports, "signPayload", {
|
|
6944
|
+
enumerable: true,
|
|
6945
|
+
get: function () { return chunkVIONYQ2K_cjs.signPayload; }
|
|
4204
6946
|
});
|
|
4205
6947
|
Object.defineProperty(exports, "KyroPubSub", {
|
|
4206
6948
|
enumerable: true,
|
|
@@ -4220,35 +6962,35 @@ Object.defineProperty(exports, "createWSServer", {
|
|
|
4220
6962
|
});
|
|
4221
6963
|
Object.defineProperty(exports, "DrizzleAdapter", {
|
|
4222
6964
|
enumerable: true,
|
|
4223
|
-
get: function () { return
|
|
6965
|
+
get: function () { return chunkGVFB5C6O_cjs.DrizzleAdapter; }
|
|
4224
6966
|
});
|
|
4225
6967
|
Object.defineProperty(exports, "collectionToDrizzleSchema", {
|
|
4226
6968
|
enumerable: true,
|
|
4227
|
-
get: function () { return
|
|
4228
|
-
});
|
|
4229
|
-
Object.defineProperty(exports, "createDrizzleAdapter", {
|
|
4230
|
-
enumerable: true,
|
|
4231
|
-
get: function () { return chunkV3B25QOK_cjs.createDrizzleAdapter; }
|
|
6969
|
+
get: function () { return chunkGVFB5C6O_cjs.collectionToDrizzleSchema; }
|
|
4232
6970
|
});
|
|
4233
|
-
Object.defineProperty(exports, "
|
|
6971
|
+
Object.defineProperty(exports, "createDatabase", {
|
|
4234
6972
|
enumerable: true,
|
|
4235
|
-
get: function () { return
|
|
6973
|
+
get: function () { return chunkGVFB5C6O_cjs.createDatabase; }
|
|
4236
6974
|
});
|
|
4237
|
-
Object.defineProperty(exports, "
|
|
6975
|
+
Object.defineProperty(exports, "createDrizzleAdapter", {
|
|
4238
6976
|
enumerable: true,
|
|
4239
|
-
get: function () { return
|
|
6977
|
+
get: function () { return chunkGVFB5C6O_cjs.createDrizzleAdapter; }
|
|
4240
6978
|
});
|
|
4241
|
-
Object.defineProperty(exports, "
|
|
6979
|
+
Object.defineProperty(exports, "fieldToDrizzleType", {
|
|
4242
6980
|
enumerable: true,
|
|
4243
|
-
get: function () { return
|
|
6981
|
+
get: function () { return chunkGVFB5C6O_cjs.fieldToDrizzleType; }
|
|
4244
6982
|
});
|
|
4245
6983
|
Object.defineProperty(exports, "runMigrations", {
|
|
4246
6984
|
enumerable: true,
|
|
4247
|
-
get: function () { return
|
|
6985
|
+
get: function () { return chunkGVFB5C6O_cjs.runMigrations; }
|
|
4248
6986
|
});
|
|
4249
6987
|
Object.defineProperty(exports, "seedDefaultRoles", {
|
|
4250
6988
|
enumerable: true,
|
|
4251
|
-
get: function () { return
|
|
6989
|
+
get: function () { return chunkGVFB5C6O_cjs.seedDefaultRoles; }
|
|
6990
|
+
});
|
|
6991
|
+
Object.defineProperty(exports, "PostgresAuthAdapter", {
|
|
6992
|
+
enumerable: true,
|
|
6993
|
+
get: function () { return chunkLIJVWQKU_cjs.PostgresAuthAdapter; }
|
|
4252
6994
|
});
|
|
4253
6995
|
Object.defineProperty(exports, "MongoDBAdapter", {
|
|
4254
6996
|
enumerable: true,
|
|
@@ -4272,17 +7014,16 @@ exports.AnalyticsPlugin = AnalyticsPlugin;
|
|
|
4272
7014
|
exports.AuditLogger = AuditLogger;
|
|
4273
7015
|
exports.Auth = Auth;
|
|
4274
7016
|
exports.COMPLEX_FIELD_TYPES = COMPLEX_FIELD_TYPES;
|
|
4275
|
-
exports.CSSGenerator = CSSGenerator;
|
|
4276
7017
|
exports.CommentsPlugin = CommentsPlugin;
|
|
4277
7018
|
exports.ConfigValidationError = ConfigValidationError;
|
|
4278
7019
|
exports.InMemoryAccountLockout = InMemoryAccountLockout;
|
|
4279
7020
|
exports.InMemoryAuditLogger = InMemoryAuditLogger;
|
|
4280
7021
|
exports.InMemoryAuthAdapter = InMemoryAuthAdapter;
|
|
4281
|
-
exports.InMemoryRateLimiter = InMemoryRateLimiter;
|
|
4282
7022
|
exports.Kyro = Kyro;
|
|
4283
7023
|
exports.KyroPlugin = KyroPlugin;
|
|
4284
7024
|
exports.LAYOUT_FIELD_TYPES = LAYOUT_FIELD_TYPES;
|
|
4285
7025
|
exports.LocalAdapter = LocalAdapter;
|
|
7026
|
+
exports.MediaService = MediaService;
|
|
4286
7027
|
exports.PRIMITIVE_FIELD_TYPES = PRIMITIVE_FIELD_TYPES;
|
|
4287
7028
|
exports.PluginManager = PluginManager;
|
|
4288
7029
|
exports.RELATIONAL_FIELD_TYPES = RELATIONAL_FIELD_TYPES;
|
|
@@ -4297,22 +7038,17 @@ exports.collectionToCreateZod = collectionToCreateZod;
|
|
|
4297
7038
|
exports.collectionToUpdateZod = collectionToUpdateZod;
|
|
4298
7039
|
exports.collectionToWhereZod = collectionToWhereZod;
|
|
4299
7040
|
exports.collectionToZod = collectionToZod;
|
|
4300
|
-
exports.
|
|
4301
|
-
exports.createAuditContext = createAuditContext;
|
|
7041
|
+
exports.createAuditContext = createAuditContext2;
|
|
4302
7042
|
exports.createAuth = createAuth;
|
|
4303
7043
|
exports.createAuthConfig = createAuthConfig;
|
|
7044
|
+
exports.createColumnsNode = createColumnsNode;
|
|
4304
7045
|
exports.createKyro = createKyro;
|
|
4305
7046
|
exports.createLocalAdapter = createLocalAdapter;
|
|
7047
|
+
exports.createLocalStorage = createLocalStorage;
|
|
4306
7048
|
exports.createRegistry = createRegistry;
|
|
4307
7049
|
exports.createVersionManager = createVersionManager;
|
|
4308
|
-
exports.defaultDarkTheme = defaultDarkTheme;
|
|
4309
|
-
exports.defaultFieldStyling = defaultFieldStyling;
|
|
4310
|
-
exports.defaultLightTheme = defaultLightTheme;
|
|
4311
7050
|
exports.defineConfig = defineConfig;
|
|
4312
|
-
exports.ecommerce2026Theme = ecommerce2026Theme;
|
|
4313
7051
|
exports.fieldToZod = fieldToZod;
|
|
4314
|
-
exports.generateCSSVariables = generateCSSVariables;
|
|
4315
|
-
exports.generateTailwindConfig = generateTailwindConfig;
|
|
4316
7052
|
exports.getDefaultDraftPublishConfig = getDefaultDraftPublishConfig;
|
|
4317
7053
|
exports.getRegistry = getRegistry;
|
|
4318
7054
|
exports.globalToZod = globalToZod;
|
|
@@ -4321,6 +7057,7 @@ exports.isArrayField = isArrayField;
|
|
|
4321
7057
|
exports.isBlocksField = isBlocksField;
|
|
4322
7058
|
exports.isDraft = isDraft;
|
|
4323
7059
|
exports.isGroupField = isGroupField;
|
|
7060
|
+
exports.isImageField = isImageField;
|
|
4324
7061
|
exports.isLayoutField = isLayoutField;
|
|
4325
7062
|
exports.isNumberField = isNumberField;
|
|
4326
7063
|
exports.isPublished = isPublished;
|
|
@@ -4329,8 +7066,13 @@ exports.isRichTextField = isRichTextField;
|
|
|
4329
7066
|
exports.isSelectField = isSelectField;
|
|
4330
7067
|
exports.isTextField = isTextField;
|
|
4331
7068
|
exports.isUploadField = isUploadField;
|
|
7069
|
+
exports.normalizeRichTextDocument = normalizeRichTextDocument;
|
|
7070
|
+
exports.normalizeRichTextValue = normalizeRichTextValue;
|
|
4332
7071
|
exports.presetPlugins = presetPlugins;
|
|
7072
|
+
exports.renderRichText = renderRichText;
|
|
4333
7073
|
exports.resetRegistry = resetRegistry;
|
|
7074
|
+
exports.resolveProvider = resolveProvider;
|
|
7075
|
+
exports.richTextStyles = richTextStyles;
|
|
4334
7076
|
exports.runFieldHooks = runFieldHooks;
|
|
4335
7077
|
exports.runHooks = runHooks;
|
|
4336
7078
|
exports.validateCollection = validateCollection;
|