s3db.js 13.4.0 → 13.6.0
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 -10
- package/dist/{s3db.cjs.js → s3db.cjs} +38801 -32446
- package/dist/s3db.cjs.map +1 -0
- package/dist/s3db.es.js +38653 -32291
- package/dist/s3db.es.js.map +1 -1
- package/package.json +218 -22
- package/src/concerns/id.js +90 -6
- package/src/concerns/index.js +2 -1
- package/src/concerns/password-hashing.js +150 -0
- package/src/database.class.js +6 -2
- package/src/plugins/api/auth/basic-auth.js +40 -10
- package/src/plugins/api/auth/index.js +49 -3
- package/src/plugins/api/auth/oauth2-auth.js +171 -0
- package/src/plugins/api/auth/oidc-auth.js +789 -0
- package/src/plugins/api/auth/oidc-client.js +462 -0
- package/src/plugins/api/auth/path-auth-matcher.js +284 -0
- package/src/plugins/api/concerns/event-emitter.js +134 -0
- package/src/plugins/api/concerns/failban-manager.js +651 -0
- package/src/plugins/api/concerns/guards-helpers.js +402 -0
- package/src/plugins/api/concerns/metrics-collector.js +346 -0
- package/src/plugins/api/index.js +510 -57
- package/src/plugins/api/middlewares/failban.js +305 -0
- package/src/plugins/api/middlewares/rate-limit.js +301 -0
- package/src/plugins/api/middlewares/request-id.js +74 -0
- package/src/plugins/api/middlewares/security-headers.js +120 -0
- package/src/plugins/api/middlewares/session-tracking.js +194 -0
- package/src/plugins/api/routes/auth-routes.js +119 -78
- package/src/plugins/api/routes/resource-routes.js +73 -30
- package/src/plugins/api/server.js +1139 -45
- package/src/plugins/api/utils/custom-routes.js +102 -0
- package/src/plugins/api/utils/guards.js +213 -0
- package/src/plugins/api/utils/mime-types.js +154 -0
- package/src/plugins/api/utils/openapi-generator.js +91 -12
- package/src/plugins/api/utils/path-matcher.js +173 -0
- package/src/plugins/api/utils/static-filesystem.js +262 -0
- package/src/plugins/api/utils/static-s3.js +231 -0
- package/src/plugins/api/utils/template-engine.js +188 -0
- package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +853 -0
- package/src/plugins/cloud-inventory/drivers/aws-driver.js +2554 -0
- package/src/plugins/cloud-inventory/drivers/azure-driver.js +637 -0
- package/src/plugins/cloud-inventory/drivers/base-driver.js +99 -0
- package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +620 -0
- package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +698 -0
- package/src/plugins/cloud-inventory/drivers/gcp-driver.js +645 -0
- package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +559 -0
- package/src/plugins/cloud-inventory/drivers/linode-driver.js +614 -0
- package/src/plugins/cloud-inventory/drivers/mock-drivers.js +449 -0
- package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +771 -0
- package/src/plugins/cloud-inventory/drivers/oracle-driver.js +768 -0
- package/src/plugins/cloud-inventory/drivers/vultr-driver.js +636 -0
- package/src/plugins/cloud-inventory/index.js +20 -0
- package/src/plugins/cloud-inventory/registry.js +146 -0
- package/src/plugins/cloud-inventory/terraform-exporter.js +362 -0
- package/src/plugins/cloud-inventory.plugin.js +1333 -0
- package/src/plugins/concerns/plugin-dependencies.js +62 -2
- package/src/plugins/eventual-consistency/analytics.js +1 -0
- package/src/plugins/eventual-consistency/consolidation.js +2 -2
- package/src/plugins/eventual-consistency/garbage-collection.js +2 -2
- package/src/plugins/eventual-consistency/install.js +2 -2
- package/src/plugins/identity/README.md +335 -0
- package/src/plugins/identity/concerns/mfa-manager.js +204 -0
- package/src/plugins/identity/concerns/password.js +138 -0
- package/src/plugins/identity/concerns/resource-schemas.js +273 -0
- package/src/plugins/identity/concerns/token-generator.js +172 -0
- package/src/plugins/identity/email-service.js +422 -0
- package/src/plugins/identity/index.js +1052 -0
- package/src/plugins/identity/oauth2-server.js +1033 -0
- package/src/plugins/identity/oidc-discovery.js +285 -0
- package/src/plugins/identity/rsa-keys.js +323 -0
- package/src/plugins/identity/server.js +500 -0
- package/src/plugins/identity/session-manager.js +453 -0
- package/src/plugins/identity/ui/layouts/base.js +251 -0
- package/src/plugins/identity/ui/middleware.js +135 -0
- package/src/plugins/identity/ui/pages/admin/client-form.js +247 -0
- package/src/plugins/identity/ui/pages/admin/clients.js +179 -0
- package/src/plugins/identity/ui/pages/admin/dashboard.js +181 -0
- package/src/plugins/identity/ui/pages/admin/user-form.js +283 -0
- package/src/plugins/identity/ui/pages/admin/users.js +263 -0
- package/src/plugins/identity/ui/pages/consent.js +262 -0
- package/src/plugins/identity/ui/pages/forgot-password.js +104 -0
- package/src/plugins/identity/ui/pages/login.js +144 -0
- package/src/plugins/identity/ui/pages/mfa-backup-codes.js +180 -0
- package/src/plugins/identity/ui/pages/mfa-enrollment.js +187 -0
- package/src/plugins/identity/ui/pages/mfa-verification.js +178 -0
- package/src/plugins/identity/ui/pages/oauth-error.js +225 -0
- package/src/plugins/identity/ui/pages/profile.js +361 -0
- package/src/plugins/identity/ui/pages/register.js +226 -0
- package/src/plugins/identity/ui/pages/reset-password.js +128 -0
- package/src/plugins/identity/ui/pages/verify-email.js +172 -0
- package/src/plugins/identity/ui/routes.js +2541 -0
- package/src/plugins/identity/ui/styles/main.css +465 -0
- package/src/plugins/index.js +4 -1
- package/src/plugins/ml/base-model.class.js +65 -16
- package/src/plugins/ml/classification-model.class.js +1 -1
- package/src/plugins/ml/timeseries-model.class.js +3 -1
- package/src/plugins/ml.plugin.js +584 -31
- package/src/plugins/shared/error-handler.js +147 -0
- package/src/plugins/shared/index.js +9 -0
- package/src/plugins/shared/middlewares/compression.js +117 -0
- package/src/plugins/shared/middlewares/cors.js +49 -0
- package/src/plugins/shared/middlewares/index.js +11 -0
- package/src/plugins/shared/middlewares/logging.js +54 -0
- package/src/plugins/shared/middlewares/rate-limit.js +73 -0
- package/src/plugins/shared/middlewares/security.js +158 -0
- package/src/plugins/shared/response-formatter.js +264 -0
- package/src/plugins/state-machine.plugin.js +57 -2
- package/src/resource.class.js +140 -12
- package/src/schema.class.js +30 -1
- package/src/validator.class.js +57 -6
- package/dist/s3db.cjs.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "s3db.js",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.6.0",
|
|
4
4
|
"description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
|
|
5
|
-
"main": "dist/s3db.cjs
|
|
5
|
+
"main": "dist/s3db.cjs",
|
|
6
6
|
"module": "dist/s3db.es.js",
|
|
7
7
|
"types": "dist/s3db.d.ts",
|
|
8
8
|
"author": "@stone/martech",
|
|
@@ -51,12 +51,16 @@
|
|
|
51
51
|
".": {
|
|
52
52
|
"types": "./dist/s3db.d.ts",
|
|
53
53
|
"import": "./dist/s3db.es.js",
|
|
54
|
-
"require": "./dist/s3db.cjs
|
|
54
|
+
"require": "./dist/s3db.cjs"
|
|
55
55
|
},
|
|
56
56
|
"./typescript-generator": {
|
|
57
57
|
"types": "./src/concerns/typescript-generator.d.ts",
|
|
58
58
|
"import": "./src/concerns/typescript-generator.js",
|
|
59
59
|
"require": "./src/concerns/typescript-generator.js"
|
|
60
|
+
},
|
|
61
|
+
"./concerns/guards-helpers": {
|
|
62
|
+
"import": "./src/concerns/guards-helpers.js",
|
|
63
|
+
"require": "./src/concerns/guards-helpers.js"
|
|
60
64
|
}
|
|
61
65
|
},
|
|
62
66
|
"files": [
|
|
@@ -70,12 +74,13 @@
|
|
|
70
74
|
"UNLICENSE"
|
|
71
75
|
],
|
|
72
76
|
"dependencies": {
|
|
73
|
-
"@aws-sdk/client-s3": "^3.
|
|
74
|
-
"@
|
|
75
|
-
"@
|
|
77
|
+
"@aws-sdk/client-s3": "^3.920.0",
|
|
78
|
+
"@aws-sdk/credential-providers": "^3.920.0",
|
|
79
|
+
"@aws-sdk/s3-request-presigner": "^3.920.0",
|
|
80
|
+
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
81
|
+
"@smithy/node-http-handler": "^4.4.3",
|
|
76
82
|
"@supercharge/promise-pool": "^3.2.0",
|
|
77
83
|
"dotenv": "^17.2.3",
|
|
78
|
-
"express": "^5.1.0",
|
|
79
84
|
"fastest-validator": "^1.19.1",
|
|
80
85
|
"flat": "^6.0.1",
|
|
81
86
|
"glob": "^11.0.3",
|
|
@@ -84,25 +89,165 @@
|
|
|
84
89
|
"nanoid": "5.1.6"
|
|
85
90
|
},
|
|
86
91
|
"peerDependencies": {
|
|
92
|
+
"@aws-sdk/client-acm": "^3.0.0",
|
|
93
|
+
"@aws-sdk/client-api-gateway": "^3.0.0",
|
|
94
|
+
"@aws-sdk/client-apigatewayv2": "^3.0.0",
|
|
95
|
+
"@aws-sdk/client-backup": "^3.0.0",
|
|
96
|
+
"@aws-sdk/client-cloudfront": "^3.0.0",
|
|
97
|
+
"@aws-sdk/client-cloudtrail": "^3.0.0",
|
|
98
|
+
"@aws-sdk/client-cloudwatch": "^3.0.0",
|
|
99
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.0.0",
|
|
100
|
+
"@aws-sdk/client-cognito-identity-provider": "^3.0.0",
|
|
101
|
+
"@aws-sdk/client-config-service": "^3.0.0",
|
|
102
|
+
"@aws-sdk/client-dynamodb": "^3.0.0",
|
|
103
|
+
"@aws-sdk/client-ec2": "^3.0.0",
|
|
104
|
+
"@aws-sdk/client-ecr": "^3.0.0",
|
|
105
|
+
"@aws-sdk/client-ecs": "^3.0.0",
|
|
106
|
+
"@aws-sdk/client-efs": "^3.0.0",
|
|
107
|
+
"@aws-sdk/client-eks": "^3.0.0",
|
|
108
|
+
"@aws-sdk/client-elastic-load-balancing": "^3.0.0",
|
|
109
|
+
"@aws-sdk/client-elastic-load-balancing-v2": "^3.0.0",
|
|
110
|
+
"@aws-sdk/client-elasticache": "^3.0.0",
|
|
111
|
+
"@aws-sdk/client-eventbridge": "^3.0.0",
|
|
112
|
+
"@aws-sdk/client-iam": "^3.0.0",
|
|
113
|
+
"@aws-sdk/client-kinesis": "^3.0.0",
|
|
114
|
+
"@aws-sdk/client-kms": "^3.0.0",
|
|
115
|
+
"@aws-sdk/client-lambda": "^3.0.0",
|
|
116
|
+
"@aws-sdk/client-rds": "^3.0.0",
|
|
117
|
+
"@aws-sdk/client-route-53": "^3.0.0",
|
|
118
|
+
"@aws-sdk/client-secrets-manager": "^3.0.0",
|
|
119
|
+
"@aws-sdk/client-sfn": "^3.0.0",
|
|
120
|
+
"@aws-sdk/client-sns": "^3.0.0",
|
|
87
121
|
"@aws-sdk/client-sqs": "^3.0.0",
|
|
122
|
+
"@aws-sdk/client-ssm": "^3.0.0",
|
|
123
|
+
"@aws-sdk/client-sts": "^3.0.0",
|
|
124
|
+
"@aws-sdk/client-waf": "^3.0.0",
|
|
125
|
+
"@aws-sdk/client-wafv2": "^3.0.0",
|
|
88
126
|
"@google-cloud/bigquery": "^7.0.0",
|
|
127
|
+
"google-auth-library": "^9.0.0 || ^10.0.0",
|
|
89
128
|
"@hono/node-server": "^1.0.0",
|
|
90
|
-
"@hono/swagger-ui": "^0.5.
|
|
129
|
+
"@hono/swagger-ui": "^0.5.2",
|
|
91
130
|
"@libsql/client": "^0.14.0",
|
|
92
131
|
"@planetscale/database": "^1.0.0",
|
|
93
132
|
"@tensorflow/tfjs-node": "^4.0.0",
|
|
94
133
|
"amqplib": "^0.10.8",
|
|
134
|
+
"bcrypt": "^5.0.0 || ^6.0.0",
|
|
135
|
+
"express": "^4.0.0 || ^5.0.0",
|
|
95
136
|
"hono": "^4.0.0",
|
|
137
|
+
"jose": "^5.0.0 || ^6.0.0",
|
|
96
138
|
"node-cron": "^4.0.0",
|
|
139
|
+
"nodemailer": "^6.0.0 || ^7.0.0",
|
|
97
140
|
"pg": "^8.0.0"
|
|
98
141
|
},
|
|
99
142
|
"peerDependenciesMeta": {
|
|
143
|
+
"@aws-sdk/client-acm": {
|
|
144
|
+
"optional": true
|
|
145
|
+
},
|
|
146
|
+
"@aws-sdk/client-api-gateway": {
|
|
147
|
+
"optional": true
|
|
148
|
+
},
|
|
149
|
+
"@aws-sdk/client-apigatewayv2": {
|
|
150
|
+
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"@aws-sdk/client-backup": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
155
|
+
"@aws-sdk/client-cloudfront": {
|
|
156
|
+
"optional": true
|
|
157
|
+
},
|
|
158
|
+
"@aws-sdk/client-cloudtrail": {
|
|
159
|
+
"optional": true
|
|
160
|
+
},
|
|
161
|
+
"@aws-sdk/client-cloudwatch": {
|
|
162
|
+
"optional": true
|
|
163
|
+
},
|
|
164
|
+
"@aws-sdk/client-cloudwatch-logs": {
|
|
165
|
+
"optional": true
|
|
166
|
+
},
|
|
167
|
+
"@aws-sdk/client-cognito-identity-provider": {
|
|
168
|
+
"optional": true
|
|
169
|
+
},
|
|
170
|
+
"@aws-sdk/client-config-service": {
|
|
171
|
+
"optional": true
|
|
172
|
+
},
|
|
173
|
+
"@aws-sdk/client-dynamodb": {
|
|
174
|
+
"optional": true
|
|
175
|
+
},
|
|
176
|
+
"@aws-sdk/client-ec2": {
|
|
177
|
+
"optional": true
|
|
178
|
+
},
|
|
179
|
+
"@aws-sdk/client-ecr": {
|
|
180
|
+
"optional": true
|
|
181
|
+
},
|
|
182
|
+
"@aws-sdk/client-ecs": {
|
|
183
|
+
"optional": true
|
|
184
|
+
},
|
|
185
|
+
"@aws-sdk/client-efs": {
|
|
186
|
+
"optional": true
|
|
187
|
+
},
|
|
188
|
+
"@aws-sdk/client-eks": {
|
|
189
|
+
"optional": true
|
|
190
|
+
},
|
|
191
|
+
"@aws-sdk/client-elasticache": {
|
|
192
|
+
"optional": true
|
|
193
|
+
},
|
|
194
|
+
"@aws-sdk/client-elastic-load-balancing": {
|
|
195
|
+
"optional": true
|
|
196
|
+
},
|
|
197
|
+
"@aws-sdk/client-elastic-load-balancing-v2": {
|
|
198
|
+
"optional": true
|
|
199
|
+
},
|
|
200
|
+
"@aws-sdk/client-eventbridge": {
|
|
201
|
+
"optional": true
|
|
202
|
+
},
|
|
203
|
+
"@aws-sdk/client-iam": {
|
|
204
|
+
"optional": true
|
|
205
|
+
},
|
|
206
|
+
"@aws-sdk/client-kinesis": {
|
|
207
|
+
"optional": true
|
|
208
|
+
},
|
|
209
|
+
"@aws-sdk/client-kms": {
|
|
210
|
+
"optional": true
|
|
211
|
+
},
|
|
212
|
+
"@aws-sdk/client-lambda": {
|
|
213
|
+
"optional": true
|
|
214
|
+
},
|
|
215
|
+
"@aws-sdk/client-rds": {
|
|
216
|
+
"optional": true
|
|
217
|
+
},
|
|
218
|
+
"@aws-sdk/client-route-53": {
|
|
219
|
+
"optional": true
|
|
220
|
+
},
|
|
221
|
+
"@aws-sdk/client-secrets-manager": {
|
|
222
|
+
"optional": true
|
|
223
|
+
},
|
|
224
|
+
"@aws-sdk/client-sfn": {
|
|
225
|
+
"optional": true
|
|
226
|
+
},
|
|
227
|
+
"@aws-sdk/client-sns": {
|
|
228
|
+
"optional": true
|
|
229
|
+
},
|
|
100
230
|
"@aws-sdk/client-sqs": {
|
|
101
231
|
"optional": true
|
|
102
232
|
},
|
|
233
|
+
"@aws-sdk/client-ssm": {
|
|
234
|
+
"optional": true
|
|
235
|
+
},
|
|
236
|
+
"@aws-sdk/client-sts": {
|
|
237
|
+
"optional": true
|
|
238
|
+
},
|
|
239
|
+
"@aws-sdk/client-waf": {
|
|
240
|
+
"optional": true
|
|
241
|
+
},
|
|
242
|
+
"@aws-sdk/client-wafv2": {
|
|
243
|
+
"optional": true
|
|
244
|
+
},
|
|
103
245
|
"@google-cloud/bigquery": {
|
|
104
246
|
"optional": true
|
|
105
247
|
},
|
|
248
|
+
"google-auth-library": {
|
|
249
|
+
"optional": true
|
|
250
|
+
},
|
|
106
251
|
"@hono/node-server": {
|
|
107
252
|
"optional": true
|
|
108
253
|
},
|
|
@@ -118,48 +263,99 @@
|
|
|
118
263
|
"@tensorflow/tfjs-node": {
|
|
119
264
|
"optional": true
|
|
120
265
|
},
|
|
121
|
-
"
|
|
266
|
+
"amqplib": {
|
|
122
267
|
"optional": true
|
|
123
268
|
},
|
|
124
|
-
"
|
|
269
|
+
"bcrypt": {
|
|
270
|
+
"optional": true
|
|
271
|
+
},
|
|
272
|
+
"express": {
|
|
125
273
|
"optional": true
|
|
126
274
|
},
|
|
127
275
|
"hono": {
|
|
128
276
|
"optional": true
|
|
129
277
|
},
|
|
278
|
+
"jose": {
|
|
279
|
+
"optional": true
|
|
280
|
+
},
|
|
130
281
|
"node-cron": {
|
|
131
282
|
"optional": true
|
|
283
|
+
},
|
|
284
|
+
"nodemailer": {
|
|
285
|
+
"optional": true
|
|
286
|
+
},
|
|
287
|
+
"pg": {
|
|
288
|
+
"optional": true
|
|
132
289
|
}
|
|
133
290
|
},
|
|
134
291
|
"devDependencies": {
|
|
135
|
-
"@aws-sdk/client-
|
|
136
|
-
"@
|
|
137
|
-
"@
|
|
292
|
+
"@aws-sdk/client-acm": "^3.920.0",
|
|
293
|
+
"@aws-sdk/client-api-gateway": "^3.920.0",
|
|
294
|
+
"@aws-sdk/client-apigatewayv2": "^3.920.0",
|
|
295
|
+
"@aws-sdk/client-backup": "^3.920.0",
|
|
296
|
+
"@aws-sdk/client-cloudfront": "^3.920.0",
|
|
297
|
+
"@aws-sdk/client-cloudtrail": "^3.920.0",
|
|
298
|
+
"@aws-sdk/client-cloudwatch": "^3.920.0",
|
|
299
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.920.0",
|
|
300
|
+
"@aws-sdk/client-cognito-identity-provider": "^3.920.0",
|
|
301
|
+
"@aws-sdk/client-config-service": "^3.920.0",
|
|
302
|
+
"@aws-sdk/client-dynamodb": "^3.920.0",
|
|
303
|
+
"@aws-sdk/client-ec2": "^3.920.0",
|
|
304
|
+
"@aws-sdk/client-ecr": "^3.920.0",
|
|
305
|
+
"@aws-sdk/client-ecs": "^3.920.0",
|
|
306
|
+
"@aws-sdk/client-efs": "^3.920.0",
|
|
307
|
+
"@aws-sdk/client-eks": "^3.920.0",
|
|
308
|
+
"@aws-sdk/client-elastic-load-balancing": "^3.920.0",
|
|
309
|
+
"@aws-sdk/client-elastic-load-balancing-v2": "^3.920.0",
|
|
310
|
+
"@aws-sdk/client-elasticache": "^3.920.0",
|
|
311
|
+
"@aws-sdk/client-eventbridge": "^3.920.0",
|
|
312
|
+
"@aws-sdk/client-iam": "^3.920.0",
|
|
313
|
+
"@aws-sdk/client-kinesis": "^3.920.0",
|
|
314
|
+
"@aws-sdk/client-kms": "^3.920.0",
|
|
315
|
+
"@aws-sdk/client-lambda": "^3.920.0",
|
|
316
|
+
"@aws-sdk/client-rds": "^3.920.0",
|
|
317
|
+
"@aws-sdk/client-route-53": "^3.920.0",
|
|
318
|
+
"@aws-sdk/client-secrets-manager": "^3.920.0",
|
|
319
|
+
"@aws-sdk/client-sfn": "^3.920.0",
|
|
320
|
+
"@aws-sdk/client-sns": "^3.920.0",
|
|
321
|
+
"@aws-sdk/client-sqs": "^3.920.0",
|
|
322
|
+
"@aws-sdk/client-ssm": "^3.920.0",
|
|
323
|
+
"@aws-sdk/client-sts": "^3.920.0",
|
|
324
|
+
"@aws-sdk/client-waf": "^3.920.0",
|
|
325
|
+
"@aws-sdk/client-wafv2": "^3.920.0",
|
|
326
|
+
"@babel/core": "^7.28.5",
|
|
327
|
+
"@babel/preset-env": "^7.28.5",
|
|
138
328
|
"@google-cloud/bigquery": "^7.9.4",
|
|
139
|
-
"@hono/node-server": "^1.
|
|
140
|
-
"@hono/swagger-ui": "^0.5.
|
|
329
|
+
"@hono/node-server": "^1.19.5",
|
|
330
|
+
"@hono/swagger-ui": "^0.5.2",
|
|
141
331
|
"@libsql/client": "^0.14.0",
|
|
142
332
|
"@planetscale/database": "^1.19.0",
|
|
143
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
333
|
+
"@rollup/plugin-commonjs": "^28.0.9",
|
|
144
334
|
"@rollup/plugin-json": "^6.1.0",
|
|
145
335
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
146
|
-
"@rollup/plugin-replace": "^6.0.
|
|
336
|
+
"@rollup/plugin-replace": "^6.0.3",
|
|
147
337
|
"@rollup/plugin-terser": "^0.4.4",
|
|
148
338
|
"@tensorflow/tfjs-node": "^4.22.0",
|
|
149
339
|
"@types/node": "24.7.0",
|
|
150
340
|
"@xenova/transformers": "^2.17.2",
|
|
151
|
-
"@yao-pkg/pkg": "^6.
|
|
341
|
+
"@yao-pkg/pkg": "^6.10.0",
|
|
152
342
|
"amqplib": "^0.10.9",
|
|
153
343
|
"babel-loader": "^10.0.0",
|
|
344
|
+
"bcrypt": "^6.0.0",
|
|
154
345
|
"chalk": "^5.6.2",
|
|
155
346
|
"cli-table3": "^0.6.5",
|
|
156
|
-
"commander": "^14.0.
|
|
347
|
+
"commander": "^14.0.2",
|
|
157
348
|
"esbuild": "^0.25.11",
|
|
158
|
-
"
|
|
349
|
+
"express": "^5.1.0",
|
|
350
|
+
"google-auth-library": "^10.4.2",
|
|
351
|
+
"hono": "^4.10.4",
|
|
159
352
|
"inquirer": "^12.10.0",
|
|
160
353
|
"jest": "^30.2.0",
|
|
354
|
+
"jose": "^6.1.0",
|
|
161
355
|
"node-cron": "^4.2.1",
|
|
162
356
|
"node-loader": "^2.1.0",
|
|
357
|
+
"nodemailer": "^7.0.10",
|
|
358
|
+
"nodemon": "^3.1.10",
|
|
163
359
|
"ora": "^9.0.0",
|
|
164
360
|
"pg": "^8.16.3",
|
|
165
361
|
"rollup": "^4.52.5",
|
|
@@ -188,7 +384,7 @@
|
|
|
188
384
|
"test:js": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
189
385
|
"test:quick": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --maxWorkers=2 --bail",
|
|
190
386
|
"test:ts": "tsc --noEmit --project tests/typescript/tsconfig.json",
|
|
191
|
-
"test:coverage": "
|
|
387
|
+
"test:coverage": "pnpm run test:js -- --coverage --runInBand && pnpm run test:ts",
|
|
192
388
|
"test:serial": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand",
|
|
193
389
|
"test:plugins": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js tests/plugins/ --testTimeout=60000",
|
|
194
390
|
"test:full": "pnpm run test:js && pnpm run test:ts",
|
|
@@ -198,7 +394,7 @@
|
|
|
198
394
|
"validate:types": "pnpm run test:ts && echo 'TypeScript definitions are valid!'",
|
|
199
395
|
"test:ts:runtime": "tsx tests/typescript/types-runtime-simple.ts",
|
|
200
396
|
"test:mcp": "node mcp/entrypoint.js --help",
|
|
201
|
-
"install:peers": "pnpm add -D @aws-sdk/client-sqs @google-cloud/bigquery @hono/node-server @hono/swagger-ui @libsql/client @planetscale/database @tensorflow/tfjs-node amqplib hono node-cron pg",
|
|
397
|
+
"install:peers": "pnpm add -D @aws-sdk/client-acm @aws-sdk/client-api-gateway @aws-sdk/client-apigatewayv2 @aws-sdk/client-backup @aws-sdk/client-cloudfront @aws-sdk/client-cloudtrail @aws-sdk/client-cloudwatch @aws-sdk/client-cloudwatch-logs @aws-sdk/client-cognito-identity-provider @aws-sdk/client-config-service @aws-sdk/client-dynamodb @aws-sdk/client-ec2 @aws-sdk/client-ecr @aws-sdk/client-ecs @aws-sdk/client-efs @aws-sdk/client-eks @aws-sdk/client-elasticache @aws-sdk/client-elastic-load-balancing @aws-sdk/client-elastic-load-balancing-v2 @aws-sdk/client-eventbridge @aws-sdk/client-iam @aws-sdk/client-kinesis @aws-sdk/client-kms @aws-sdk/client-lambda @aws-sdk/client-rds @aws-sdk/client-route-53 @aws-sdk/client-secrets-manager @aws-sdk/client-sfn @aws-sdk/client-sns @aws-sdk/client-sqs @aws-sdk/client-ssm @aws-sdk/client-sts @aws-sdk/client-waf @aws-sdk/client-wafv2 @google-cloud/bigquery google-auth-library @hono/node-server @hono/swagger-ui @libsql/client @planetscale/database @tensorflow/tfjs-node amqplib bcrypt express hono jose node-cron nodemailer pg",
|
|
202
398
|
"install:peers:script": "./scripts/install-peer-deps.sh"
|
|
203
399
|
}
|
|
204
400
|
}
|
package/src/concerns/id.js
CHANGED
|
@@ -1,8 +1,92 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomFillSync } from 'node:crypto';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// Fallback URL alphabet taken from nanoid's source. Using it keeps generated IDs stable
|
|
4
|
+
// even while we await the official nanoid implementation to load.
|
|
5
|
+
const FALLBACK_URL_ALPHABET =
|
|
6
|
+
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
|
|
4
7
|
|
|
5
|
-
// Password generator using nanoid
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
// Password generator using nanoid-style alphabet, excluding visually similar characters.
|
|
9
|
+
const PASSWORD_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';
|
|
10
|
+
|
|
11
|
+
const POOL_SIZE_MULTIPLIER = 128;
|
|
12
|
+
let pool;
|
|
13
|
+
let poolOffset = 0;
|
|
14
|
+
|
|
15
|
+
function fillPool(bytes) {
|
|
16
|
+
if (!pool || pool.length < bytes) {
|
|
17
|
+
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
18
|
+
randomFillSync(pool);
|
|
19
|
+
poolOffset = 0;
|
|
20
|
+
} else if (poolOffset + bytes > pool.length) {
|
|
21
|
+
randomFillSync(pool);
|
|
22
|
+
poolOffset = 0;
|
|
23
|
+
}
|
|
24
|
+
poolOffset += bytes;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function randomFromPool(bytes) {
|
|
28
|
+
fillPool((bytes |= 0));
|
|
29
|
+
return pool.subarray(poolOffset - bytes, poolOffset);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function customRandomFallback(alphabet, defaultSize, getRandom) {
|
|
33
|
+
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1;
|
|
34
|
+
const step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length);
|
|
35
|
+
|
|
36
|
+
return (size = defaultSize) => {
|
|
37
|
+
if (!size) return '';
|
|
38
|
+
|
|
39
|
+
let id = '';
|
|
40
|
+
while (true) {
|
|
41
|
+
const bytes = getRandom(step);
|
|
42
|
+
let i = step;
|
|
43
|
+
while (i--) {
|
|
44
|
+
id += alphabet[bytes[i] & mask] || '';
|
|
45
|
+
if (id.length >= size) return id;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function customAlphabetFallback(alphabet, size = 21) {
|
|
52
|
+
return customRandomFallback(alphabet, size, randomFromPool);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let activeCustomAlphabet = customAlphabetFallback;
|
|
56
|
+
let activeUrlAlphabet = FALLBACK_URL_ALPHABET;
|
|
57
|
+
let idGeneratorImpl = activeCustomAlphabet(activeUrlAlphabet, 22);
|
|
58
|
+
let passwordGeneratorImpl = activeCustomAlphabet(PASSWORD_ALPHABET, 16);
|
|
59
|
+
let nanoidInitializationError = null;
|
|
60
|
+
|
|
61
|
+
const nanoidReadyPromise = import('nanoid')
|
|
62
|
+
.then((mod) => {
|
|
63
|
+
const resolvedCustomAlphabet = mod?.customAlphabet ?? activeCustomAlphabet;
|
|
64
|
+
const resolvedUrlAlphabet = mod?.urlAlphabet ?? activeUrlAlphabet;
|
|
65
|
+
|
|
66
|
+
activeCustomAlphabet = resolvedCustomAlphabet;
|
|
67
|
+
activeUrlAlphabet = resolvedUrlAlphabet;
|
|
68
|
+
idGeneratorImpl = activeCustomAlphabet(activeUrlAlphabet, 22);
|
|
69
|
+
passwordGeneratorImpl = activeCustomAlphabet(PASSWORD_ALPHABET, 16);
|
|
70
|
+
})
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
nanoidInitializationError = error;
|
|
73
|
+
if (typeof process !== 'undefined' && process?.env?.S3DB_DEBUG) {
|
|
74
|
+
console.warn('[s3db] Failed to dynamically import "nanoid". Using fallback implementation.', error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export function initializeNanoid() {
|
|
79
|
+
return nanoidReadyPromise;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getNanoidInitializationError() {
|
|
83
|
+
return nanoidInitializationError;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const idGenerator = (...args) => idGeneratorImpl(...args);
|
|
87
|
+
|
|
88
|
+
export const passwordGenerator = (...args) => passwordGeneratorImpl(...args);
|
|
89
|
+
|
|
90
|
+
export const getUrlAlphabet = () => activeUrlAlphabet;
|
|
91
|
+
|
|
92
|
+
export const createCustomGenerator = (alphabet, size) => activeCustomAlphabet(alphabet, size);
|
package/src/concerns/index.js
CHANGED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Password Hashing with bcrypt
|
|
3
|
+
*
|
|
4
|
+
* Provides secure one-way password hashing with space optimization.
|
|
5
|
+
* Bcrypt hashes are 60 bytes, but we compact them to 52 bytes by removing
|
|
6
|
+
* the version/rounds prefix ($2b$10$) which we can reconstruct.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import bcrypt from 'bcrypt';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Hash a password using bcrypt (synchronous)
|
|
13
|
+
* @param {string} password - Plaintext password
|
|
14
|
+
* @param {number} [rounds=10] - Bcrypt cost factor (4-31, default 10)
|
|
15
|
+
* @returns {string} Bcrypt hash (60 bytes)
|
|
16
|
+
*/
|
|
17
|
+
export function hashPasswordSync(password, rounds = 10) {
|
|
18
|
+
if (!password || typeof password !== 'string') {
|
|
19
|
+
throw new Error('Password must be a non-empty string');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (rounds < 4 || rounds > 31) {
|
|
23
|
+
throw new Error('Bcrypt rounds must be between 4 and 31');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return bcrypt.hashSync(password, rounds);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Hash a password using bcrypt
|
|
31
|
+
* @param {string} password - Plaintext password
|
|
32
|
+
* @param {number} [rounds=10] - Bcrypt cost factor (4-31, default 10)
|
|
33
|
+
* @returns {Promise<string>} Bcrypt hash (60 bytes)
|
|
34
|
+
*/
|
|
35
|
+
export async function hashPassword(password, rounds = 10) {
|
|
36
|
+
if (!password || typeof password !== 'string') {
|
|
37
|
+
throw new Error('Password must be a non-empty string');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (rounds < 4 || rounds > 31) {
|
|
41
|
+
throw new Error('Bcrypt rounds must be between 4 and 31');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return await bcrypt.hash(password, rounds);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Verify a password against a bcrypt hash
|
|
49
|
+
* @param {string} plaintext - Plaintext password to verify
|
|
50
|
+
* @param {string} hash - Bcrypt hash (can be full 60-byte or compact 52-byte)
|
|
51
|
+
* @returns {Promise<boolean>} True if password matches
|
|
52
|
+
*/
|
|
53
|
+
export async function verifyPassword(plaintext, hash) {
|
|
54
|
+
if (!plaintext || typeof plaintext !== 'string') {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!hash || typeof hash !== 'string') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
// If hash doesn't start with $, it's compacted - expand it first
|
|
64
|
+
const fullHash = hash.startsWith('$') ? hash : expandHash(hash);
|
|
65
|
+
return await bcrypt.compare(plaintext, fullHash);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
// Invalid hash format
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Compact a bcrypt hash by removing the prefix
|
|
74
|
+
*
|
|
75
|
+
* Bcrypt format: $2b$10$saltsaltsaltsaltsalthashhashhashhashhashhashhashh
|
|
76
|
+
* Compacted: saltsaltsaltsaltsalthashhashhashhashhashhashhashh
|
|
77
|
+
*
|
|
78
|
+
* Saves 7 bytes (11.6% reduction: 60 → 53 bytes)
|
|
79
|
+
*
|
|
80
|
+
* @param {string} bcryptHash - Full bcrypt hash (60 bytes)
|
|
81
|
+
* @returns {string} Compacted hash (53 bytes)
|
|
82
|
+
*/
|
|
83
|
+
export function compactHash(bcryptHash) {
|
|
84
|
+
if (!bcryptHash || typeof bcryptHash !== 'string') {
|
|
85
|
+
throw new Error('Invalid bcrypt hash');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Bcrypt format: $2a$10$ or $2b$10$ or $2y$10$
|
|
89
|
+
if (!bcryptHash.startsWith('$2')) {
|
|
90
|
+
throw new Error('Not a valid bcrypt hash');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Remove prefix (e.g., "$2b$10$")
|
|
94
|
+
const parts = bcryptHash.split('$');
|
|
95
|
+
if (parts.length !== 4) {
|
|
96
|
+
throw new Error('Invalid bcrypt hash format');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Return just the salt+hash part (last element after split)
|
|
100
|
+
return parts[3];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Expand a compacted bcrypt hash by restoring the prefix
|
|
105
|
+
*
|
|
106
|
+
* @param {string} compactHash - Compacted hash (53 bytes)
|
|
107
|
+
* @param {number} [rounds=10] - Bcrypt rounds used (default 10)
|
|
108
|
+
* @returns {string} Full bcrypt hash (60 bytes)
|
|
109
|
+
*/
|
|
110
|
+
export function expandHash(compactHash, rounds = 10) {
|
|
111
|
+
if (!compactHash || typeof compactHash !== 'string') {
|
|
112
|
+
throw new Error('Invalid compacted hash');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// If it's already a full hash, return as-is
|
|
116
|
+
if (compactHash.startsWith('$')) {
|
|
117
|
+
return compactHash;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Reconstruct prefix: $2b${rounds}$
|
|
121
|
+
const roundsStr = rounds.toString().padStart(2, '0');
|
|
122
|
+
return `$2b$${roundsStr}$${compactHash}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Check if a string is a bcrypt hash (full or compact)
|
|
127
|
+
* @param {string} str - String to check
|
|
128
|
+
* @returns {boolean} True if it looks like a bcrypt hash
|
|
129
|
+
*/
|
|
130
|
+
export function isBcryptHash(str) {
|
|
131
|
+
if (!str || typeof str !== 'string') {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Full hash: starts with $2
|
|
136
|
+
if (str.startsWith('$2')) {
|
|
137
|
+
return str.length === 60;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Compact hash: 53 characters (22 salt + 31 hash)
|
|
141
|
+
return str.length === 53;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default {
|
|
145
|
+
hashPassword,
|
|
146
|
+
verifyPassword,
|
|
147
|
+
compactHash,
|
|
148
|
+
expandHash,
|
|
149
|
+
isBcryptHash
|
|
150
|
+
};
|
package/src/database.class.js
CHANGED
|
@@ -66,6 +66,7 @@ export class Database extends EventEmitter {
|
|
|
66
66
|
this.plugins = this.pluginRegistry; // Alias for plugin registry
|
|
67
67
|
this.cache = options.cache;
|
|
68
68
|
this.passphrase = options.passphrase || "secret";
|
|
69
|
+
this.bcryptRounds = options.bcryptRounds || 10;
|
|
69
70
|
this.versioningEnabled = options.versioningEnabled || false;
|
|
70
71
|
this.persistHooks = options.persistHooks || false; // New configuration for hook persistence
|
|
71
72
|
this.strictValidation = options.strictValidation !== false; // Enable strict validation by default
|
|
@@ -235,6 +236,7 @@ export class Database extends EventEmitter {
|
|
|
235
236
|
behavior: versionData.behavior || 'user-managed',
|
|
236
237
|
parallelism: this.parallelism,
|
|
237
238
|
passphrase: this.passphrase,
|
|
239
|
+
bcryptRounds: this.bcryptRounds,
|
|
238
240
|
observers: [this],
|
|
239
241
|
cache: this.cache,
|
|
240
242
|
timestamps: versionData.timestamps !== undefined ? versionData.timestamps : false,
|
|
@@ -967,6 +969,7 @@ export class Database extends EventEmitter {
|
|
|
967
969
|
client: this.client,
|
|
968
970
|
version: existingResource.version,
|
|
969
971
|
passphrase: this.passphrase,
|
|
972
|
+
bcryptRounds: this.bcryptRounds,
|
|
970
973
|
versioningEnabled: this.versioningEnabled
|
|
971
974
|
});
|
|
972
975
|
|
|
@@ -1091,7 +1094,7 @@ export class Database extends EventEmitter {
|
|
|
1091
1094
|
if (!existingVersionData || existingVersionData.hash !== newHash) {
|
|
1092
1095
|
await this.uploadMetadataFile();
|
|
1093
1096
|
}
|
|
1094
|
-
this.emit("
|
|
1097
|
+
this.emit("db:resource-updated", name);
|
|
1095
1098
|
return existingResource;
|
|
1096
1099
|
}
|
|
1097
1100
|
const existingMetadata = this.savedMetadata?.resources?.[name];
|
|
@@ -1104,6 +1107,7 @@ export class Database extends EventEmitter {
|
|
|
1104
1107
|
behavior,
|
|
1105
1108
|
parallelism: this.parallelism,
|
|
1106
1109
|
passphrase: config.passphrase !== undefined ? config.passphrase : this.passphrase,
|
|
1110
|
+
bcryptRounds: config.bcryptRounds !== undefined ? config.bcryptRounds : this.bcryptRounds,
|
|
1107
1111
|
observers: [this],
|
|
1108
1112
|
cache: config.cache !== undefined ? config.cache : this.cache,
|
|
1109
1113
|
timestamps: config.timestamps !== undefined ? config.timestamps : false,
|
|
@@ -1131,7 +1135,7 @@ export class Database extends EventEmitter {
|
|
|
1131
1135
|
}
|
|
1132
1136
|
|
|
1133
1137
|
await this.uploadMetadataFile();
|
|
1134
|
-
this.emit("
|
|
1138
|
+
this.emit("db:resource-created", name);
|
|
1135
1139
|
return resource;
|
|
1136
1140
|
}
|
|
1137
1141
|
|