boltstore 0.5.1 → 0.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 +65 -23
- package/dist/admin/api-keys.d.ts +87 -0
- package/dist/admin/api-keys.d.ts.map +1 -0
- package/dist/admin/api-keys.js +267 -0
- package/dist/admin/api-keys.js.map +1 -0
- package/dist/admin/backup.d.ts +76 -0
- package/dist/admin/backup.d.ts.map +1 -0
- package/dist/admin/backup.js +255 -0
- package/dist/admin/backup.js.map +1 -0
- package/dist/admin/import-export/csv.d.ts +4 -0
- package/dist/admin/import-export/csv.d.ts.map +1 -0
- package/dist/admin/import-export/csv.js +123 -0
- package/dist/admin/import-export/csv.js.map +1 -0
- package/dist/admin/import-export/export.d.ts +4 -0
- package/dist/admin/import-export/export.d.ts.map +1 -0
- package/dist/admin/import-export/export.js +66 -0
- package/dist/admin/import-export/export.js.map +1 -0
- package/dist/admin/import-export/import.d.ts +4 -0
- package/dist/admin/import-export/import.d.ts.map +1 -0
- package/dist/admin/import-export/import.js +253 -0
- package/dist/admin/import-export/import.js.map +1 -0
- package/dist/admin/import-export/index.d.ts +7 -0
- package/dist/admin/import-export/index.d.ts.map +1 -0
- package/dist/admin/import-export/index.js +7 -0
- package/dist/admin/import-export/index.js.map +1 -0
- package/dist/admin/import-export/json-input.d.ts +2 -0
- package/dist/admin/import-export/json-input.d.ts.map +1 -0
- package/dist/admin/import-export/json-input.js +42 -0
- package/dist/admin/import-export/json-input.js.map +1 -0
- package/dist/admin/import-export/schema-inference.d.ts +6 -0
- package/dist/admin/import-export/schema-inference.d.ts.map +1 -0
- package/dist/admin/import-export/schema-inference.js +34 -0
- package/dist/admin/import-export/schema-inference.js.map +1 -0
- package/dist/admin/import-export/types.d.ts +40 -0
- package/dist/admin/import-export/types.d.ts.map +1 -0
- package/dist/admin/import-export/types.js +2 -0
- package/dist/admin/import-export/types.js.map +1 -0
- package/dist/admin/oauth/github.d.ts +12 -0
- package/dist/admin/oauth/github.d.ts.map +1 -0
- package/dist/admin/oauth/github.js +78 -0
- package/dist/admin/oauth/github.js.map +1 -0
- package/dist/admin/oauth/google.d.ts +12 -0
- package/dist/admin/oauth/google.d.ts.map +1 -0
- package/dist/admin/oauth/google.js +55 -0
- package/dist/admin/oauth/google.js.map +1 -0
- package/dist/admin/oauth/handler.d.ts +5 -0
- package/dist/admin/oauth/handler.d.ts.map +1 -0
- package/dist/admin/oauth/handler.js +37 -0
- package/dist/admin/oauth/handler.js.map +1 -0
- package/dist/admin/oauth/index.d.ts +5 -0
- package/dist/admin/oauth/index.d.ts.map +1 -0
- package/dist/admin/oauth/index.js +5 -0
- package/dist/admin/oauth/index.js.map +1 -0
- package/dist/admin/oauth/registry.d.ts +16 -0
- package/dist/admin/oauth/registry.d.ts.map +1 -0
- package/dist/admin/oauth/registry.js +37 -0
- package/dist/admin/oauth/registry.js.map +1 -0
- package/dist/admin/oauth/types.d.ts +14 -0
- package/dist/admin/oauth/types.d.ts.map +1 -0
- package/dist/admin/oauth/types.js +2 -0
- package/dist/admin/oauth/types.js.map +1 -0
- package/dist/admin/oauth/user.d.ts +12 -0
- package/dist/admin/oauth/user.d.ts.map +1 -0
- package/dist/admin/oauth/user.js +28 -0
- package/dist/admin/oauth/user.js.map +1 -0
- package/dist/admin/query.d.ts +54 -0
- package/dist/admin/query.d.ts.map +1 -0
- package/dist/admin/query.js +168 -0
- package/dist/admin/query.js.map +1 -0
- package/dist/admin/transaction.d.ts +46 -0
- package/dist/admin/transaction.d.ts.map +1 -0
- package/dist/admin/transaction.js +52 -0
- package/dist/admin/transaction.js.map +1 -0
- package/dist/admin/views.d.ts +64 -0
- package/dist/admin/views.d.ts.map +1 -0
- package/dist/admin/views.js +197 -0
- package/dist/admin/views.js.map +1 -0
- package/dist/audit.d.ts +36 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +92 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth/jwt.d.ts +8 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +81 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/password.d.ts +4 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +15 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/auth/tables.d.ts +5 -0
- package/dist/auth/tables.d.ts.map +1 -0
- package/dist/auth/tables.js +65 -0
- package/dist/auth/tables.js.map +1 -0
- package/dist/auth/tokens.d.ts +16 -0
- package/dist/auth/tokens.d.ts.map +1 -0
- package/dist/auth/tokens.js +126 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/auth/types.d.ts +36 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/auth/users.d.ts +9 -0
- package/dist/auth/users.d.ts.map +1 -0
- package/dist/auth/users.js +83 -0
- package/dist/auth/users.js.map +1 -0
- package/dist/auth/validation.d.ts +5 -0
- package/dist/auth/validation.d.ts.map +1 -0
- package/dist/auth/validation.js +25 -0
- package/dist/auth/validation.js.map +1 -0
- package/dist/auth.d.ts +9 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +322 -0
- package/dist/cli.js.map +1 -0
- package/dist/collections/ddl.d.ts +25 -0
- package/dist/collections/ddl.d.ts.map +1 -0
- package/dist/collections/ddl.js +83 -0
- package/dist/collections/ddl.js.map +1 -0
- package/dist/collections/management.d.ts +57 -0
- package/dist/collections/management.d.ts.map +1 -0
- package/dist/collections/management.js +289 -0
- package/dist/collections/management.js.map +1 -0
- package/dist/collections.d.ts +3 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +3 -0
- package/dist/collections.js.map +1 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +274 -0
- package/dist/config.js.map +1 -0
- package/dist/db/cast.d.ts +15 -0
- package/dist/db/cast.d.ts.map +1 -0
- package/dist/db/cast.js +16 -0
- package/dist/db/cast.js.map +1 -0
- package/dist/db/manager.d.ts +93 -0
- package/dist/db/manager.d.ts.map +1 -0
- package/dist/db/manager.js +209 -0
- package/dist/db/manager.js.map +1 -0
- package/dist/db/pool.d.ts +99 -0
- package/dist/db/pool.d.ts.map +1 -0
- package/dist/db/pool.js +232 -0
- package/dist/db/pool.js.map +1 -0
- package/dist/entry.d.ts +11 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +80 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/indexes.d.ts +61 -0
- package/dist/indexes.d.ts.map +1 -0
- package/dist/indexes.js +174 -0
- package/dist/indexes.js.map +1 -0
- package/dist/logger.d.ts +40 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +147 -0
- package/dist/logger.js.map +1 -0
- package/dist/middleware/auth.d.ts +43 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +87 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors.d.ts +28 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +71 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/proxy.d.ts +10 -0
- package/dist/middleware/proxy.d.ts.map +1 -0
- package/dist/middleware/proxy.js +31 -0
- package/dist/middleware/proxy.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +64 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +130 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/migrations.d.ts +56 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +133 -0
- package/dist/migrations.js.map +1 -0
- package/dist/query/builder.d.ts +6 -0
- package/dist/query/builder.d.ts.map +1 -0
- package/dist/query/builder.js +97 -0
- package/dist/query/builder.js.map +1 -0
- package/dist/query/executor.d.ts +3 -0
- package/dist/query/executor.d.ts.map +1 -0
- package/dist/query/executor.js +64 -0
- package/dist/query/executor.js.map +1 -0
- package/dist/query/filter-builder.d.ts +8 -0
- package/dist/query/filter-builder.d.ts.map +1 -0
- package/dist/query/filter-builder.js +128 -0
- package/dist/query/filter-builder.js.map +1 -0
- package/dist/query/search.d.ts +4 -0
- package/dist/query/search.d.ts.map +1 -0
- package/dist/query/search.js +28 -0
- package/dist/query/search.js.map +1 -0
- package/dist/query/types.d.ts +45 -0
- package/dist/query/types.d.ts.map +1 -0
- package/dist/query/types.js +2 -0
- package/dist/query/types.js.map +1 -0
- package/dist/query.d.ts +6 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +6 -0
- package/dist/query.js.map +1 -0
- package/dist/records/batch.d.ts +13 -0
- package/dist/records/batch.d.ts.map +1 -0
- package/dist/records/batch.js +113 -0
- package/dist/records/batch.js.map +1 -0
- package/dist/records/count.d.ts +5 -0
- package/dist/records/count.d.ts.map +1 -0
- package/dist/records/count.js +34 -0
- package/dist/records/count.js.map +1 -0
- package/dist/records/crud.d.ts +8 -0
- package/dist/records/crud.d.ts.map +1 -0
- package/dist/records/crud.js +121 -0
- package/dist/records/crud.js.map +1 -0
- package/dist/records/distinct.d.ts +5 -0
- package/dist/records/distinct.d.ts.map +1 -0
- package/dist/records/distinct.js +22 -0
- package/dist/records/distinct.js.map +1 -0
- package/dist/records/helpers.d.ts +4 -0
- package/dist/records/helpers.d.ts.map +1 -0
- package/dist/records/helpers.js +9 -0
- package/dist/records/helpers.js.map +1 -0
- package/dist/records/list.d.ts +44 -0
- package/dist/records/list.d.ts.map +1 -0
- package/dist/records/list.js +133 -0
- package/dist/records/list.js.map +1 -0
- package/dist/records/schema-cache.d.ts +8 -0
- package/dist/records/schema-cache.d.ts.map +1 -0
- package/dist/records/schema-cache.js +64 -0
- package/dist/records/schema-cache.js.map +1 -0
- package/dist/records.d.ts +8 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +8 -0
- package/dist/records.js.map +1 -0
- package/dist/relations.d.ts +50 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/relations.js +179 -0
- package/dist/relations.js.map +1 -0
- package/dist/rls.d.ts +63 -0
- package/dist/rls.d.ts.map +1 -0
- package/dist/rls.js +146 -0
- package/dist/rls.js.map +1 -0
- package/dist/router.d.ts +53 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +104 -0
- package/dist/router.js.map +1 -0
- package/dist/routes/admin-query.d.ts +5 -0
- package/dist/routes/admin-query.d.ts.map +1 -0
- package/dist/routes/admin-query.js +57 -0
- package/dist/routes/admin-query.js.map +1 -0
- package/dist/routes/api-keys.d.ts +12 -0
- package/dist/routes/api-keys.d.ts.map +1 -0
- package/dist/routes/api-keys.js +114 -0
- package/dist/routes/api-keys.js.map +1 -0
- package/dist/routes/auth.d.ts +10 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +116 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/backup.d.ts +5 -0
- package/dist/routes/backup.d.ts.map +1 -0
- package/dist/routes/backup.js +88 -0
- package/dist/routes/backup.js.map +1 -0
- package/dist/routes/collections.d.ts +5 -0
- package/dist/routes/collections.d.ts.map +1 -0
- package/dist/routes/collections.js +110 -0
- package/dist/routes/collections.js.map +1 -0
- package/dist/routes/databases.d.ts +5 -0
- package/dist/routes/databases.d.ts.map +1 -0
- package/dist/routes/databases.js +90 -0
- package/dist/routes/databases.js.map +1 -0
- package/dist/routes/health.d.ts +9 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +34 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/import-export.d.ts +8 -0
- package/dist/routes/import-export.d.ts.map +1 -0
- package/dist/routes/import-export.js +173 -0
- package/dist/routes/import-export.js.map +1 -0
- package/dist/routes/indexes.d.ts +5 -0
- package/dist/routes/indexes.d.ts.map +1 -0
- package/dist/routes/indexes.js +94 -0
- package/dist/routes/indexes.js.map +1 -0
- package/dist/routes/migrations.d.ts +5 -0
- package/dist/routes/migrations.d.ts.map +1 -0
- package/dist/routes/migrations.js +87 -0
- package/dist/routes/migrations.js.map +1 -0
- package/dist/routes/oauth.d.ts +5 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +35 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/query.d.ts +5 -0
- package/dist/routes/query.d.ts.map +1 -0
- package/dist/routes/query.js +36 -0
- package/dist/routes/query.js.map +1 -0
- package/dist/routes/records.d.ts +5 -0
- package/dist/routes/records.d.ts.map +1 -0
- package/dist/routes/records.js +181 -0
- package/dist/routes/records.js.map +1 -0
- package/dist/routes/transactions.d.ts +5 -0
- package/dist/routes/transactions.d.ts.map +1 -0
- package/dist/routes/transactions.js +43 -0
- package/dist/routes/transactions.js.map +1 -0
- package/dist/routes/views.d.ts +5 -0
- package/dist/routes/views.d.ts.map +1 -0
- package/dist/routes/views.js +123 -0
- package/dist/routes/views.js.map +1 -0
- package/dist/server.d.ts +80 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +271 -0
- package/dist/server.js.map +1 -0
- package/package.json +20 -40
- package/bin/cli.ts +0 -185
- package/src/admin/assets.ts +0 -134
- package/src/admin/serve.ts +0 -447
- package/src/admin-ui/App.vue +0 -71
- package/src/admin-ui/api/client.ts +0 -179
- package/src/admin-ui/components/Icon.vue +0 -85
- package/src/admin-ui/components/Sidebar.vue +0 -275
- package/src/admin-ui/components/StatCard.vue +0 -40
- package/src/admin-ui/dist/assets/ApiKeys.css +0 -1
- package/src/admin-ui/dist/assets/ApiKeys.js +0 -1
- package/src/admin-ui/dist/assets/AppDashboard.css +0 -1
- package/src/admin-ui/dist/assets/AppDashboard.js +0 -1
- package/src/admin-ui/dist/assets/Backups.js +0 -1
- package/src/admin-ui/dist/assets/Dashboard.css +0 -1
- package/src/admin-ui/dist/assets/Dashboard.js +0 -3
- package/src/admin-ui/dist/assets/DataBrowser.css +0 -1
- package/src/admin-ui/dist/assets/DataBrowser.js +0 -1
- package/src/admin-ui/dist/assets/Docs.css +0 -1
- package/src/admin-ui/dist/assets/Docs.js +0 -1
- package/src/admin-ui/dist/assets/FileBrowser.css +0 -1
- package/src/admin-ui/dist/assets/FileBrowser.js +0 -1
- package/src/admin-ui/dist/assets/HookEditor.css +0 -1
- package/src/admin-ui/dist/assets/HookEditor.js +0 -2
- package/src/admin-ui/dist/assets/LogViewer.css +0 -1
- package/src/admin-ui/dist/assets/LogViewer.js +0 -1
- package/src/admin-ui/dist/assets/Login.css +0 -1
- package/src/admin-ui/dist/assets/Login.js +0 -1
- package/src/admin-ui/dist/assets/SchemaBuilder.css +0 -1
- package/src/admin-ui/dist/assets/SchemaBuilder.js +0 -1
- package/src/admin-ui/dist/assets/Settings.js +0 -1
- package/src/admin-ui/dist/assets/Setup.css +0 -1
- package/src/admin-ui/dist/assets/Setup.js +0 -1
- package/src/admin-ui/dist/assets/StatCard.css +0 -1
- package/src/admin-ui/dist/assets/StatCard.js +0 -1
- package/src/admin-ui/dist/assets/main.css +0 -1
- package/src/admin-ui/dist/assets/main.js +0 -30
- package/src/admin-ui/dist/index.html +0 -49
- package/src/admin-ui/index.html +0 -48
- package/src/admin-ui/main.ts +0 -25
- package/src/admin-ui/pages/ApiKeys.vue +0 -198
- package/src/admin-ui/pages/AppDashboard.vue +0 -274
- package/src/admin-ui/pages/Applications.vue +0 -123
- package/src/admin-ui/pages/Backups.vue +0 -140
- package/src/admin-ui/pages/Dashboard.vue +0 -293
- package/src/admin-ui/pages/DataBrowser.vue +0 -310
- package/src/admin-ui/pages/Docs.vue +0 -40
- package/src/admin-ui/pages/FileBrowser.vue +0 -587
- package/src/admin-ui/pages/HookEditor.vue +0 -258
- package/src/admin-ui/pages/LogViewer.vue +0 -109
- package/src/admin-ui/pages/Login.vue +0 -229
- package/src/admin-ui/pages/SchemaBuilder.vue +0 -501
- package/src/admin-ui/pages/Settings.vue +0 -251
- package/src/admin-ui/pages/Setup.vue +0 -275
- package/src/admin-ui/router.ts +0 -169
- package/src/admin-ui/stores/application.ts +0 -68
- package/src/admin-ui/stores/auth.ts +0 -109
- package/src/admin-ui/style.css +0 -530
- package/src/admin-ui/tsconfig.json +0 -21
- package/src/admin-ui/version.ts +0 -3
- package/src/admin-ui/vite.config.ts +0 -35
- package/src/api/admin-config.ts +0 -596
- package/src/api/admin.ts +0 -8
- package/src/api/aggregate.ts +0 -104
- package/src/api/applications.ts +0 -148
- package/src/api/auth.ts +0 -690
- package/src/api/backups.ts +0 -173
- package/src/api/batch.ts +0 -135
- package/src/api/collections.ts +0 -354
- package/src/api/files.ts +0 -801
- package/src/api/health.ts +0 -48
- package/src/api/helpers.ts +0 -86
- package/src/api/middleware/auth.ts +0 -202
- package/src/api/middleware/cors.ts +0 -37
- package/src/api/middleware/logging.ts +0 -27
- package/src/api/middleware/ratelimit.ts +0 -142
- package/src/api/middleware/rls.ts +0 -37
- package/src/api/records.ts +0 -563
- package/src/api/router.ts +0 -296
- package/src/app.ts +0 -617
- package/src/auth/apikey.ts +0 -73
- package/src/auth/jwt.ts +0 -210
- package/src/auth/oauth2.ts +0 -144
- package/src/auth/password.ts +0 -68
- package/src/backup/manager.ts +0 -227
- package/src/config/yaml.ts +0 -78
- package/src/config.ts +0 -240
- package/src/db/application-migrations.ts +0 -112
- package/src/db/application-schema.ts +0 -297
- package/src/db/migrations.ts +0 -54
- package/src/db/pool.ts +0 -143
- package/src/db/system-schema.ts +0 -153
- package/src/hooks/api.ts +0 -157
- package/src/hooks/loader.ts +0 -263
- package/src/hooks/runner.ts +0 -76
- package/src/index.ts +0 -17
- package/src/logging/logger.ts +0 -131
- package/src/realtime/broadcast.ts +0 -132
- package/src/realtime/subscriptions.ts +0 -124
- package/src/security/rls-engine.ts +0 -183
- package/src/security/sanitizer.ts +0 -72
- package/src/storage/interface.ts +0 -48
- package/src/storage/local.ts +0 -189
- package/src/storage/mime-types.ts +0 -32
- package/src/storage/s3.ts +0 -213
- package/src/sync/changelog.ts +0 -247
- package/src/sync/engine.ts +0 -159
- package/src/sync/lamport.ts +0 -48
- package/src/sync/protocol.ts +0 -234
- package/src/version.ts +0 -2
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured JSON logger with levels, request ID tracing, and asynchronous batched flushing.
|
|
3
|
+
*
|
|
4
|
+
* Logs are buffered in memory and flushed asynchronously on a short interval or when the
|
|
5
|
+
* buffer reaches a size threshold. This keeps the hot path non-blocking while still ensuring
|
|
6
|
+
* logs are written in order within each flush.
|
|
7
|
+
*
|
|
8
|
+
* @module boltstore/logger
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
11
|
+
export interface LogEntry {
|
|
12
|
+
level: LogLevel;
|
|
13
|
+
message: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
request_id?: string;
|
|
16
|
+
method?: string;
|
|
17
|
+
path?: string;
|
|
18
|
+
client_ip?: string;
|
|
19
|
+
user_agent?: string;
|
|
20
|
+
status?: number;
|
|
21
|
+
duration_ms?: number;
|
|
22
|
+
error?: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a unique request ID for tracing.
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateRequestId(): string;
|
|
29
|
+
/** Force an immediate flush of all buffered logs. */
|
|
30
|
+
export declare function flushLogger(): Promise<void>;
|
|
31
|
+
/** Stop the background flush timer. */
|
|
32
|
+
export declare function stopLogger(): void;
|
|
33
|
+
export declare const logger: {
|
|
34
|
+
debug(message: string, meta?: Partial<LogEntry>): void;
|
|
35
|
+
info(message: string, meta?: Partial<LogEntry>): void;
|
|
36
|
+
warn(message: string, meta?: Partial<LogEntry>): void;
|
|
37
|
+
error(message: string, meta?: Partial<LogEntry>): void;
|
|
38
|
+
};
|
|
39
|
+
export default logger;
|
|
40
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAuB3D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C;AAgFD,qDAAqD;AACrD,wBAAgB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3C;AAED,uCAAuC;AACvC,wBAAgB,UAAU,IAAI,IAAI,CAKjC;AAED,eAAO,MAAM,MAAM;mBACF,MAAM,SAAS,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;kBAIxC,MAAM,SAAS,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;kBAIvC,MAAM,SAAS,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;mBAItC,MAAM,SAAS,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;CAGvD,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured JSON logger with levels, request ID tracing, and asynchronous batched flushing.
|
|
3
|
+
*
|
|
4
|
+
* Logs are buffered in memory and flushed asynchronously on a short interval or when the
|
|
5
|
+
* buffer reaches a size threshold. This keeps the hot path non-blocking while still ensuring
|
|
6
|
+
* logs are written in order within each flush.
|
|
7
|
+
*
|
|
8
|
+
* @module boltstore/logger
|
|
9
|
+
*/
|
|
10
|
+
import { openSync, writeSync, closeSync } from "node:fs";
|
|
11
|
+
const LEVEL_PRIORITY = {
|
|
12
|
+
debug: 0,
|
|
13
|
+
info: 1,
|
|
14
|
+
warn: 2,
|
|
15
|
+
error: 3,
|
|
16
|
+
};
|
|
17
|
+
const LOG_LEVEL = (Bun.env.LOG_LEVEL || "info").toLowerCase();
|
|
18
|
+
/** Output destination: "stderr" | "stdout" | a file path. */
|
|
19
|
+
const LOG_OUTPUT = Bun.env.LOG_OUTPUT || "stderr";
|
|
20
|
+
/** Maximum number of entries to buffer before flushing. */
|
|
21
|
+
const LOG_BUFFER_LIMIT = Math.max(1, Math.min(1000, parseInt(Bun.env.LOG_BUFFER_LIMIT || "100", 10) || 100));
|
|
22
|
+
/** Flush interval in milliseconds. */
|
|
23
|
+
const LOG_FLUSH_MS = Math.max(10, parseInt(Bun.env.LOG_FLUSH_MS || "100", 10) || 100);
|
|
24
|
+
/** Optional sampling rate (0-1) applied to info-level logs. Error/warn are always logged. */
|
|
25
|
+
const LOG_SAMPLE_RATE = Math.max(0, Math.min(1, parseFloat(Bun.env.LOG_SAMPLE_RATE || "1")));
|
|
26
|
+
let requestCounter = 0;
|
|
27
|
+
/**
|
|
28
|
+
* Generate a unique request ID for tracing.
|
|
29
|
+
*/
|
|
30
|
+
export function generateRequestId() {
|
|
31
|
+
requestCounter++;
|
|
32
|
+
const random = new Uint8Array(6);
|
|
33
|
+
crypto.getRandomValues(random);
|
|
34
|
+
const rnd = Buffer.from(random).toString("base64url").replace(/=+$/, "");
|
|
35
|
+
return `req-${Date.now()}-${requestCounter}-${rnd}`;
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Async batched log writer
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
let logBuffer = [];
|
|
41
|
+
let flushTimer = null;
|
|
42
|
+
let flushPromise = null;
|
|
43
|
+
function shouldDrop(level) {
|
|
44
|
+
if (level === "error" || level === "warn")
|
|
45
|
+
return false;
|
|
46
|
+
if (level === "info" && LOG_SAMPLE_RATE >= 1)
|
|
47
|
+
return false;
|
|
48
|
+
if (level === "info" && Math.random() > LOG_SAMPLE_RATE)
|
|
49
|
+
return true;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
function writeEntries(entries) {
|
|
53
|
+
if (entries.length === 0)
|
|
54
|
+
return;
|
|
55
|
+
const chunk = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
56
|
+
try {
|
|
57
|
+
if (LOG_OUTPUT === "stdout") {
|
|
58
|
+
process.stdout.write(chunk);
|
|
59
|
+
}
|
|
60
|
+
else if (LOG_OUTPUT === "stderr") {
|
|
61
|
+
process.stderr.write(chunk);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const fd = openSync(LOG_OUTPUT, "a");
|
|
65
|
+
try {
|
|
66
|
+
writeSync(fd, chunk);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
closeSync(fd);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Logging failures must not break the request.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function flushLogs() {
|
|
78
|
+
if (flushPromise)
|
|
79
|
+
return flushPromise;
|
|
80
|
+
const batch = logBuffer;
|
|
81
|
+
logBuffer = [];
|
|
82
|
+
if (batch.length === 0)
|
|
83
|
+
return;
|
|
84
|
+
flushPromise = new Promise((resolve) => {
|
|
85
|
+
// Defer actual I/O to next tick to avoid blocking the event loop.
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
writeEntries(batch);
|
|
88
|
+
flushPromise = null;
|
|
89
|
+
resolve();
|
|
90
|
+
}, 0);
|
|
91
|
+
});
|
|
92
|
+
return flushPromise;
|
|
93
|
+
}
|
|
94
|
+
function scheduleFlush() {
|
|
95
|
+
if (!flushTimer) {
|
|
96
|
+
flushTimer = setInterval(() => {
|
|
97
|
+
flushLogs();
|
|
98
|
+
}, LOG_FLUSH_MS);
|
|
99
|
+
// Ensure the timer does not keep the process alive if it's the only remaining work.
|
|
100
|
+
if (typeof flushTimer.unref === "function")
|
|
101
|
+
flushTimer.unref();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Buffer a structured JSON log entry for asynchronous batched flushing.
|
|
106
|
+
*/
|
|
107
|
+
function writeLog(entry) {
|
|
108
|
+
if (LEVEL_PRIORITY[entry.level] < LEVEL_PRIORITY[LOG_LEVEL]) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (shouldDrop(entry.level))
|
|
112
|
+
return;
|
|
113
|
+
logBuffer.push(entry);
|
|
114
|
+
if (logBuffer.length >= LOG_BUFFER_LIMIT) {
|
|
115
|
+
flushLogs();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
scheduleFlush();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Force an immediate flush of all buffered logs. */
|
|
122
|
+
export function flushLogger() {
|
|
123
|
+
return flushLogs();
|
|
124
|
+
}
|
|
125
|
+
/** Stop the background flush timer. */
|
|
126
|
+
export function stopLogger() {
|
|
127
|
+
if (flushTimer) {
|
|
128
|
+
clearInterval(flushTimer);
|
|
129
|
+
flushTimer = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export const logger = {
|
|
133
|
+
debug(message, meta) {
|
|
134
|
+
writeLog({ level: "debug", message, timestamp: new Date().toISOString(), ...meta });
|
|
135
|
+
},
|
|
136
|
+
info(message, meta) {
|
|
137
|
+
writeLog({ level: "info", message, timestamp: new Date().toISOString(), ...meta });
|
|
138
|
+
},
|
|
139
|
+
warn(message, meta) {
|
|
140
|
+
writeLog({ level: "warn", message, timestamp: new Date().toISOString(), ...meta });
|
|
141
|
+
},
|
|
142
|
+
error(message, meta) {
|
|
143
|
+
writeLog({ level: "error", message, timestamp: new Date().toISOString(), ...meta });
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
export default logger;
|
|
147
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication/authorization middleware for Boltstore.
|
|
3
|
+
*
|
|
4
|
+
* Extracts a Bearer JWT token or an API key secret from the incoming request,
|
|
5
|
+
* verifies it against the database, and returns an auth context. Admin-only
|
|
6
|
+
* routes must additionally ensure the principal has role "admin" (or a valid
|
|
7
|
+
* API key with admin-scoped permissions).
|
|
8
|
+
*
|
|
9
|
+
* @module boltstore/middleware/auth
|
|
10
|
+
*/
|
|
11
|
+
import { DatabaseManager } from "../db/manager";
|
|
12
|
+
import { type AuthConfig } from "../auth";
|
|
13
|
+
export { type AuthConfig } from "../auth";
|
|
14
|
+
import { type ApiKeyContext } from "../admin/api-keys";
|
|
15
|
+
/** Authenticated principal returned by the middleware. */
|
|
16
|
+
export interface AuthContext {
|
|
17
|
+
/** User ID (JWT) or API key ID (API key). */
|
|
18
|
+
principalId: string;
|
|
19
|
+
/** Email when authenticated via JWT. */
|
|
20
|
+
email?: string;
|
|
21
|
+
/** Role when authenticated via JWT. */
|
|
22
|
+
role?: "user" | "admin";
|
|
23
|
+
/** API key context when authenticated via API key. */
|
|
24
|
+
apiKey?: ApiKeyContext;
|
|
25
|
+
/** True if the principal was resolved from an API key. */
|
|
26
|
+
isApiKey: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Result of authentication: context on success, Response on failure. */
|
|
29
|
+
export type AuthResult = AuthContext | Response;
|
|
30
|
+
/**
|
|
31
|
+
* Authenticate the request against the given database.
|
|
32
|
+
*
|
|
33
|
+
* Returns an `AuthContext` on success or a 401/403 Response on failure.
|
|
34
|
+
*/
|
|
35
|
+
export declare function authenticateRequest(request: Request, manager: DatabaseManager, database: string, authConfig: AuthConfig): Promise<AuthResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Require an authenticated admin principal.
|
|
38
|
+
*
|
|
39
|
+
* JWT users must have role "admin". API keys are not allowed for admin
|
|
40
|
+
* routes unless the key explicitly includes the "admin" operation.
|
|
41
|
+
*/
|
|
42
|
+
export declare function requireAdmin(auth: AuthContext): Response | null;
|
|
43
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAErE,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,sDAAsD;IACtD,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAoBhD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,UAAU,CAAC,CA4CrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAoB/D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication/authorization middleware for Boltstore.
|
|
3
|
+
*
|
|
4
|
+
* Extracts a Bearer JWT token or an API key secret from the incoming request,
|
|
5
|
+
* verifies it against the database, and returns an auth context. Admin-only
|
|
6
|
+
* routes must additionally ensure the principal has role "admin" (or a valid
|
|
7
|
+
* API key with admin-scoped permissions).
|
|
8
|
+
*
|
|
9
|
+
* @module boltstore/middleware/auth
|
|
10
|
+
*/
|
|
11
|
+
import { verifyAccessToken, } from "../auth";
|
|
12
|
+
import { verifyApiKey } from "../admin/api-keys";
|
|
13
|
+
/** Extract a Bearer token or API key secret from request headers. */
|
|
14
|
+
function extractCredentials(request) {
|
|
15
|
+
const auth = request.headers.get("Authorization");
|
|
16
|
+
if (auth?.startsWith("Bearer ")) {
|
|
17
|
+
const value = auth.slice(7).trim();
|
|
18
|
+
// API keys always start with "blt_"
|
|
19
|
+
if (value.startsWith("blt_")) {
|
|
20
|
+
return { apiKey: value };
|
|
21
|
+
}
|
|
22
|
+
return { token: value };
|
|
23
|
+
}
|
|
24
|
+
const apiKey = request.headers.get("X-API-Key") || request.headers.get("x-api-key");
|
|
25
|
+
if (apiKey)
|
|
26
|
+
return { apiKey: apiKey.trim() };
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Authenticate the request against the given database.
|
|
31
|
+
*
|
|
32
|
+
* Returns an `AuthContext` on success or a 401/403 Response on failure.
|
|
33
|
+
*/
|
|
34
|
+
export async function authenticateRequest(request, manager, database, authConfig) {
|
|
35
|
+
const { token, apiKey } = extractCredentials(request);
|
|
36
|
+
if (!token && !apiKey) {
|
|
37
|
+
return new Response(JSON.stringify({ error: { code: "UNAUTHORIZED", message: "Authentication required." } }), { status: 401, headers: { "Content-Type": "application/json" } });
|
|
38
|
+
}
|
|
39
|
+
const pool = database === "_system" ? manager.getMetaPool() : manager.get(database);
|
|
40
|
+
if (apiKey) {
|
|
41
|
+
try {
|
|
42
|
+
const ctx = await verifyApiKey(pool, apiKey);
|
|
43
|
+
return {
|
|
44
|
+
principalId: ctx.keyId,
|
|
45
|
+
apiKey: ctx,
|
|
46
|
+
isApiKey: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const message = err instanceof Error ? err.message : "Invalid API key";
|
|
51
|
+
return new Response(JSON.stringify({ error: { code: "UNAUTHORIZED", message } }), { status: 401, headers: { "Content-Type": "application/json" } });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const ctx = verifyAccessToken(pool, token, authConfig);
|
|
56
|
+
return {
|
|
57
|
+
principalId: ctx.userId,
|
|
58
|
+
email: ctx.email,
|
|
59
|
+
role: ctx.role,
|
|
60
|
+
isApiKey: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const message = err instanceof Error ? err.message : "Invalid token";
|
|
65
|
+
return new Response(JSON.stringify({ error: { code: "UNAUTHORIZED", message } }), { status: 401, headers: { "Content-Type": "application/json" } });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Require an authenticated admin principal.
|
|
70
|
+
*
|
|
71
|
+
* JWT users must have role "admin". API keys are not allowed for admin
|
|
72
|
+
* routes unless the key explicitly includes the "admin" operation.
|
|
73
|
+
*/
|
|
74
|
+
export function requireAdmin(auth) {
|
|
75
|
+
if (auth.isApiKey) {
|
|
76
|
+
const ops = auth.apiKey?.permissions.operations ?? [];
|
|
77
|
+
if (!ops.includes("admin")) {
|
|
78
|
+
return new Response(JSON.stringify({ error: { code: "FORBIDDEN", message: "Admin access required." } }), { status: 403, headers: { "Content-Type": "application/json" } });
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
if (auth.role !== "admin") {
|
|
83
|
+
return new Response(JSON.stringify({ error: { code: "FORBIDDEN", message: "Admin access required." } }), { status: 403, headers: { "Content-Type": "application/json" } });
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORS middleware — handles cross-origin requests.
|
|
3
|
+
*
|
|
4
|
+
* Configurable via environment variables:
|
|
5
|
+
* - CORS_ORIGINS: comma-separated list of allowed origins (default: "*")
|
|
6
|
+
* - CORS_METHODS: comma-separated list of allowed methods (default: "GET,POST,PATCH,DELETE,OPTIONS")
|
|
7
|
+
* - CORS_HEADERS: comma-separated list of allowed headers (default: "Content-Type,Authorization")
|
|
8
|
+
*
|
|
9
|
+
* @module boltstore/middleware/cors
|
|
10
|
+
*/
|
|
11
|
+
export interface CorsConfig {
|
|
12
|
+
origins: string[];
|
|
13
|
+
methods: string[];
|
|
14
|
+
headers: string[];
|
|
15
|
+
}
|
|
16
|
+
declare const defaultConfig: CorsConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Apply CORS headers to a Response object.
|
|
19
|
+
* Returns the response with CORS headers set, or a 204 for preflight requests.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyCors(response: Response, requestOrigin: string | null, config?: CorsConfig): Response;
|
|
22
|
+
/**
|
|
23
|
+
* Handle an OPTIONS preflight request.
|
|
24
|
+
* Returns a 204 No Content response with appropriate CORS headers.
|
|
25
|
+
*/
|
|
26
|
+
export declare function handlePreflight(requestOrigin: string | null, config?: CorsConfig): Response;
|
|
27
|
+
export { defaultConfig };
|
|
28
|
+
//# sourceMappingURL=cors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,QAAA,MAAM,aAAa,EAAE,UAMpB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,MAAM,GAAE,UAA0B,GACjC,QAAQ,CAwBV;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,GAAE,UAA0B,GAAG,QAAQ,CAsB1G;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORS middleware — handles cross-origin requests.
|
|
3
|
+
*
|
|
4
|
+
* Configurable via environment variables:
|
|
5
|
+
* - CORS_ORIGINS: comma-separated list of allowed origins (default: "*")
|
|
6
|
+
* - CORS_METHODS: comma-separated list of allowed methods (default: "GET,POST,PATCH,DELETE,OPTIONS")
|
|
7
|
+
* - CORS_HEADERS: comma-separated list of allowed headers (default: "Content-Type,Authorization")
|
|
8
|
+
*
|
|
9
|
+
* @module boltstore/middleware/cors
|
|
10
|
+
*/
|
|
11
|
+
const defaultConfig = {
|
|
12
|
+
origins: Bun.env.CORS_ORIGINS
|
|
13
|
+
? Bun.env.CORS_ORIGINS.split(",").map((s) => s.trim()).filter(Boolean)
|
|
14
|
+
: ["*"],
|
|
15
|
+
methods: (Bun.env.CORS_METHODS || "GET,POST,PATCH,DELETE,OPTIONS").split(",").map((s) => s.trim()),
|
|
16
|
+
headers: (Bun.env.CORS_HEADERS || "Content-Type,Authorization").split(",").map((s) => s.trim()),
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Apply CORS headers to a Response object.
|
|
20
|
+
* Returns the response with CORS headers set, or a 204 for preflight requests.
|
|
21
|
+
*/
|
|
22
|
+
export function applyCors(response, requestOrigin, config = defaultConfig) {
|
|
23
|
+
let origin = null;
|
|
24
|
+
if (config.origins.includes("*")) {
|
|
25
|
+
// When wildcard is explicitly configured, send wildcard (do not echo).
|
|
26
|
+
origin = "*";
|
|
27
|
+
}
|
|
28
|
+
else if (requestOrigin && config.origins.includes(requestOrigin)) {
|
|
29
|
+
origin = requestOrigin;
|
|
30
|
+
}
|
|
31
|
+
// No matching origin — return response unchanged.
|
|
32
|
+
if (!origin)
|
|
33
|
+
return response;
|
|
34
|
+
const headers = new Headers(response.headers);
|
|
35
|
+
headers.set("Access-Control-Allow-Origin", origin);
|
|
36
|
+
headers.set("Access-Control-Allow-Methods", config.methods.join(", "));
|
|
37
|
+
headers.set("Access-Control-Allow-Headers", config.headers.join(", "));
|
|
38
|
+
headers.set("Access-Control-Max-Age", "86400");
|
|
39
|
+
return new Response(response.body, {
|
|
40
|
+
status: response.status,
|
|
41
|
+
statusText: response.statusText,
|
|
42
|
+
headers,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Handle an OPTIONS preflight request.
|
|
47
|
+
* Returns a 204 No Content response with appropriate CORS headers.
|
|
48
|
+
*/
|
|
49
|
+
export function handlePreflight(requestOrigin, config = defaultConfig) {
|
|
50
|
+
let origin = null;
|
|
51
|
+
if (config.origins.includes("*")) {
|
|
52
|
+
origin = "*";
|
|
53
|
+
}
|
|
54
|
+
else if (requestOrigin && config.origins.includes(requestOrigin)) {
|
|
55
|
+
origin = requestOrigin;
|
|
56
|
+
}
|
|
57
|
+
if (!origin) {
|
|
58
|
+
return new Response(null, { status: 204 });
|
|
59
|
+
}
|
|
60
|
+
return new Response(null, {
|
|
61
|
+
status: 204,
|
|
62
|
+
headers: {
|
|
63
|
+
"Access-Control-Allow-Origin": origin,
|
|
64
|
+
"Access-Control-Allow-Methods": config.methods.join(", "),
|
|
65
|
+
"Access-Control-Allow-Headers": config.headers.join(", "),
|
|
66
|
+
"Access-Control-Max-Age": "86400",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export { defaultConfig };
|
|
71
|
+
//# sourceMappingURL=cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted proxy helper for Boltstore.
|
|
3
|
+
*
|
|
4
|
+
* @module boltstore/middleware/proxy
|
|
5
|
+
*/
|
|
6
|
+
/** Check whether the immediate connection IP is a trusted proxy. */
|
|
7
|
+
export declare function isTrustedProxy(remoteAddress: string, trusted: string[]): boolean;
|
|
8
|
+
/** Resolve the client IP from request headers, respecting trusted proxies. */
|
|
9
|
+
export declare function resolveClientIp(request: Request, trustedProxies: string[], remoteAddress?: string): string;
|
|
10
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/middleware/proxy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAIhF;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EAAE,EACxB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAgBR"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted proxy helper for Boltstore.
|
|
3
|
+
*
|
|
4
|
+
* @module boltstore/middleware/proxy
|
|
5
|
+
*/
|
|
6
|
+
/** Check whether the immediate connection IP is a trusted proxy. */
|
|
7
|
+
export function isTrustedProxy(remoteAddress, trusted) {
|
|
8
|
+
if (trusted.length === 0)
|
|
9
|
+
return false;
|
|
10
|
+
if (trusted.includes("*"))
|
|
11
|
+
return true;
|
|
12
|
+
return trusted.includes(remoteAddress) || trusted.includes("127.0.0.1") && remoteAddress === "127.0.0.1";
|
|
13
|
+
}
|
|
14
|
+
/** Resolve the client IP from request headers, respecting trusted proxies. */
|
|
15
|
+
export function resolveClientIp(request, trustedProxies, remoteAddress) {
|
|
16
|
+
const remote = remoteAddress || "127.0.0.1";
|
|
17
|
+
if (!isTrustedProxy(remote, trustedProxies)) {
|
|
18
|
+
return remote;
|
|
19
|
+
}
|
|
20
|
+
const forwarded = request.headers.get("X-Forwarded-For");
|
|
21
|
+
if (forwarded) {
|
|
22
|
+
const first = forwarded.split(",")[0]?.trim();
|
|
23
|
+
if (first)
|
|
24
|
+
return first;
|
|
25
|
+
}
|
|
26
|
+
const realIp = request.headers.get("X-Real-IP");
|
|
27
|
+
if (realIp)
|
|
28
|
+
return realIp.trim();
|
|
29
|
+
return remote;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/middleware/proxy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,aAAqB,EAAE,OAAiB;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,aAAa,KAAK,WAAW,CAAC;AAC3G,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAC7B,OAAgB,EAChB,cAAwB,EACxB,aAAsB;IAEtB,MAAM,MAAM,GAAG,aAAa,IAAI,WAAW,CAAC;IAC5C,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAC9C,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IAEjC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate limiting middleware for Boltstore.
|
|
3
|
+
*
|
|
4
|
+
* Uses a sliding-window counter approach with per-IP, per-endpoint,
|
|
5
|
+
* per-tier tracking. All state is in-memory (no SQLite dependency) for
|
|
6
|
+
* speed — resets on server restart.
|
|
7
|
+
*
|
|
8
|
+
* Three tiers:
|
|
9
|
+
* - **public**: Unauthenticated endpoints (health, login, register)
|
|
10
|
+
* - **auth**: Authenticated endpoints (CRUD, queries)
|
|
11
|
+
* - **admin**: Admin endpoints under `/api/admin/*`
|
|
12
|
+
*
|
|
13
|
+
* Configurable via `BoltstoreConfig.rateLimitPublic` and `rateLimitAuth`,
|
|
14
|
+
* or set explicitly in `ServerConfig.rateLimit`.
|
|
15
|
+
*
|
|
16
|
+
* @module boltstore/middleware/rate-limit
|
|
17
|
+
*/
|
|
18
|
+
export type RateLimitTier = "public" | "auth" | "admin";
|
|
19
|
+
export interface RateLimitConfig {
|
|
20
|
+
/** Requests per window for public endpoints. Default: 100. */
|
|
21
|
+
public: number;
|
|
22
|
+
/** Requests per window for authenticated endpoints. Default: 1000. */
|
|
23
|
+
auth: number;
|
|
24
|
+
/** Requests per window for admin endpoints. Default: 500. */
|
|
25
|
+
admin: number;
|
|
26
|
+
/** Window size in seconds. Default: 60 (1 minute). */
|
|
27
|
+
windowSeconds: number;
|
|
28
|
+
}
|
|
29
|
+
export interface RateLimitResult {
|
|
30
|
+
allowed: boolean;
|
|
31
|
+
/** How many requests remain in this window. */
|
|
32
|
+
remaining: number;
|
|
33
|
+
/** Total limit for this tier. */
|
|
34
|
+
limit: number;
|
|
35
|
+
/** Unix timestamp (seconds) when the window resets. */
|
|
36
|
+
reset: number;
|
|
37
|
+
/** Seconds until the window resets (only set when rate-limited). */
|
|
38
|
+
retryAfter: number;
|
|
39
|
+
}
|
|
40
|
+
export declare const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig;
|
|
41
|
+
/**
|
|
42
|
+
* Stop the cleanup timer. Call during server shutdown.
|
|
43
|
+
*/
|
|
44
|
+
export declare function stopRateLimitCleanup(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a request should be rate-limited.
|
|
47
|
+
*
|
|
48
|
+
* @param clientIp - The client's IP address (or "127.0.0.1" as fallback).
|
|
49
|
+
* @param pathname - The request path (used as part of the rate limit key).
|
|
50
|
+
* @param tier - The rate limit tier for this request.
|
|
51
|
+
* @param config - Rate limit configuration.
|
|
52
|
+
* @returns A result indicating whether the request is allowed.
|
|
53
|
+
*/
|
|
54
|
+
export declare function checkRateLimit(clientIp: string, pathname: string, tier: RateLimitTier, config: RateLimitConfig): RateLimitResult;
|
|
55
|
+
/**
|
|
56
|
+
* Get the current rate limit status for a client without incrementing.
|
|
57
|
+
* Useful for informational endpoints.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getRateLimitStatus(clientIp: string, pathname: string, tier: RateLimitTier, config: RateLimitConfig): RateLimitResult;
|
|
60
|
+
/**
|
|
61
|
+
* Reset all rate limit counters. Useful for testing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resetRateLimits(): void;
|
|
64
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,yBAAyB,EAAE,eAKvC,CAAC;AAsCF;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAMD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,eAAe,GACtB,eAAe,CAiCjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,eAAe,GACtB,eAAe,CA4BjB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|