@gettersethya/mira 0.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/src/app/app.d.ts +100 -0
- package/dist/src/app/app.d.ts.map +1 -0
- package/dist/src/app/app.js +176 -0
- package/dist/src/app/app.js.map +1 -0
- package/dist/src/app/builder.d.ts +106 -0
- package/dist/src/app/builder.d.ts.map +1 -0
- package/dist/src/app/builder.js +122 -0
- package/dist/src/app/builder.js.map +1 -0
- package/dist/src/app/index.d.ts +33 -0
- package/dist/src/app/index.d.ts.map +1 -0
- package/dist/src/app/index.js +30 -0
- package/dist/src/app/index.js.map +1 -0
- package/dist/src/app/plugin.d.ts +60 -0
- package/dist/src/app/plugin.d.ts.map +1 -0
- package/dist/src/app/plugin.js +20 -0
- package/dist/src/app/plugin.js.map +1 -0
- package/dist/src/app/types.d.ts +55 -0
- package/dist/src/app/types.d.ts.map +1 -0
- package/dist/src/app/types.js +2 -0
- package/dist/src/app/types.js.map +1 -0
- package/dist/src/cache/cached-collection.d.ts +30 -0
- package/dist/src/cache/cached-collection.d.ts.map +1 -0
- package/dist/src/cache/cached-collection.js +107 -0
- package/dist/src/cache/cached-collection.js.map +1 -0
- package/dist/src/cache/collection-cache.d.ts +17 -0
- package/dist/src/cache/collection-cache.d.ts.map +1 -0
- package/dist/src/cache/collection-cache.js +37 -0
- package/dist/src/cache/collection-cache.js.map +1 -0
- package/dist/src/cache/index.d.ts +4 -0
- package/dist/src/cache/index.d.ts.map +1 -0
- package/dist/src/cache/index.js +3 -0
- package/dist/src/cache/index.js.map +1 -0
- package/dist/src/cache/types.d.ts +12 -0
- package/dist/src/cache/types.d.ts.map +1 -0
- package/dist/src/cache/types.js +2 -0
- package/dist/src/cache/types.js.map +1 -0
- package/dist/src/collection-service/collection-service.d.ts +62 -0
- package/dist/src/collection-service/collection-service.d.ts.map +1 -0
- package/dist/src/collection-service/collection-service.js +289 -0
- package/dist/src/collection-service/collection-service.js.map +1 -0
- package/dist/src/collection-service/context.d.ts +19 -0
- package/dist/src/collection-service/context.d.ts.map +1 -0
- package/dist/src/collection-service/context.js +2 -0
- package/dist/src/collection-service/context.js.map +1 -0
- package/dist/src/collection-service/decode.d.ts +6 -0
- package/dist/src/collection-service/decode.d.ts.map +1 -0
- package/dist/src/collection-service/decode.js +26 -0
- package/dist/src/collection-service/decode.js.map +1 -0
- package/dist/src/collection-service/errors.d.ts +67 -0
- package/dist/src/collection-service/errors.d.ts.map +1 -0
- package/dist/src/collection-service/errors.js +43 -0
- package/dist/src/collection-service/errors.js.map +1 -0
- package/dist/src/collection-service/index.d.ts +5 -0
- package/dist/src/collection-service/index.d.ts.map +1 -0
- package/dist/src/collection-service/index.js +3 -0
- package/dist/src/collection-service/index.js.map +1 -0
- package/dist/src/collection-service/input-schema.d.ts +10 -0
- package/dist/src/collection-service/input-schema.d.ts.map +1 -0
- package/dist/src/collection-service/input-schema.js +123 -0
- package/dist/src/collection-service/input-schema.js.map +1 -0
- package/dist/src/collection-service/where.d.ts +35 -0
- package/dist/src/collection-service/where.d.ts.map +1 -0
- package/dist/src/collection-service/where.js +91 -0
- package/dist/src/collection-service/where.js.map +1 -0
- package/dist/src/config/config.d.ts +44 -0
- package/dist/src/config/config.d.ts.map +1 -0
- package/dist/src/config/config.js +89 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/index.d.ts +3 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +2 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/config/types.d.ts +29 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config/types.js +2 -0
- package/dist/src/config/types.js.map +1 -0
- package/dist/src/crypto/crypto.d.ts +11 -0
- package/dist/src/crypto/crypto.d.ts.map +1 -0
- package/dist/src/crypto/crypto.js +4 -0
- package/dist/src/crypto/crypto.js.map +1 -0
- package/dist/src/crypto/index.d.ts +3 -0
- package/dist/src/crypto/index.d.ts.map +1 -0
- package/dist/src/crypto/index.js +3 -0
- package/dist/src/crypto/index.js.map +1 -0
- package/dist/src/crypto/node.d.ts +4 -0
- package/dist/src/crypto/node.d.ts.map +1 -0
- package/dist/src/crypto/node.js +9 -0
- package/dist/src/crypto/node.js.map +1 -0
- package/dist/src/databases/index.d.ts +2 -0
- package/dist/src/databases/index.d.ts.map +1 -0
- package/dist/src/databases/index.js +2 -0
- package/dist/src/databases/index.js.map +1 -0
- package/dist/src/databases/sqlite.d.ts +24 -0
- package/dist/src/databases/sqlite.d.ts.map +1 -0
- package/dist/src/databases/sqlite.js +27 -0
- package/dist/src/databases/sqlite.js.map +1 -0
- package/dist/src/hooks/hook-collection.d.ts +5 -0
- package/dist/src/hooks/hook-collection.d.ts.map +1 -0
- package/dist/src/hooks/hook-collection.js +77 -0
- package/dist/src/hooks/hook-collection.js.map +1 -0
- package/dist/src/hooks/hook-service.d.ts +33 -0
- package/dist/src/hooks/hook-service.d.ts.map +1 -0
- package/dist/src/hooks/hook-service.js +118 -0
- package/dist/src/hooks/hook-service.js.map +1 -0
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/types.d.ts +52 -0
- package/dist/src/hooks/types.d.ts.map +1 -0
- package/dist/src/hooks/types.js +2 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/http/auth-node.d.ts +4 -0
- package/dist/src/http/auth-node.d.ts.map +1 -0
- package/dist/src/http/auth-node.js +34 -0
- package/dist/src/http/auth-node.js.map +1 -0
- package/dist/src/http/auth.d.ts +40 -0
- package/dist/src/http/auth.d.ts.map +1 -0
- package/dist/src/http/auth.js +76 -0
- package/dist/src/http/auth.js.map +1 -0
- package/dist/src/http/errors.d.ts +31 -0
- package/dist/src/http/errors.d.ts.map +1 -0
- package/dist/src/http/errors.js +36 -0
- package/dist/src/http/errors.js.map +1 -0
- package/dist/src/http/file-serve.d.ts +10 -0
- package/dist/src/http/file-serve.d.ts.map +1 -0
- package/dist/src/http/file-serve.js +159 -0
- package/dist/src/http/file-serve.js.map +1 -0
- package/dist/src/http/file-token.d.ts +7 -0
- package/dist/src/http/file-token.d.ts.map +1 -0
- package/dist/src/http/file-token.js +57 -0
- package/dist/src/http/file-token.js.map +1 -0
- package/dist/src/http/files.d.ts +11 -0
- package/dist/src/http/files.d.ts.map +1 -0
- package/dist/src/http/files.js +85 -0
- package/dist/src/http/files.js.map +1 -0
- package/dist/src/http/index.d.ts +11 -0
- package/dist/src/http/index.d.ts.map +1 -0
- package/dist/src/http/index.js +9 -0
- package/dist/src/http/index.js.map +1 -0
- package/dist/src/http/ip-middleware.d.ts +4 -0
- package/dist/src/http/ip-middleware.d.ts.map +1 -0
- package/dist/src/http/ip-middleware.js +24 -0
- package/dist/src/http/ip-middleware.js.map +1 -0
- package/dist/src/http/params.d.ts +15 -0
- package/dist/src/http/params.d.ts.map +1 -0
- package/dist/src/http/params.js +48 -0
- package/dist/src/http/params.js.map +1 -0
- package/dist/src/http/router.d.ts +11 -0
- package/dist/src/http/router.d.ts.map +1 -0
- package/dist/src/http/router.js +300 -0
- package/dist/src/http/router.js.map +1 -0
- package/dist/src/http/schema.d.ts +5 -0
- package/dist/src/http/schema.d.ts.map +1 -0
- package/dist/src/http/schema.js +17 -0
- package/dist/src/http/schema.js.map +1 -0
- package/dist/src/http/server-factory-node.d.ts +4 -0
- package/dist/src/http/server-factory-node.d.ts.map +1 -0
- package/dist/src/http/server-factory-node.js +8 -0
- package/dist/src/http/server-factory-node.js.map +1 -0
- package/dist/src/http/server-factory.d.ts +11 -0
- package/dist/src/http/server-factory.d.ts.map +1 -0
- package/dist/src/http/server-factory.js +4 -0
- package/dist/src/http/server-factory.js.map +1 -0
- package/dist/src/http/telemetry-routes.d.ts +5 -0
- package/dist/src/http/telemetry-routes.d.ts.map +1 -0
- package/dist/src/http/telemetry-routes.js +156 -0
- package/dist/src/http/telemetry-routes.js.map +1 -0
- package/dist/src/index.d.ts +19 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +22 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/migrator/dialect-sqlite.d.ts +9 -0
- package/dist/src/migrator/dialect-sqlite.d.ts.map +1 -0
- package/dist/src/migrator/dialect-sqlite.js +102 -0
- package/dist/src/migrator/dialect-sqlite.js.map +1 -0
- package/dist/src/migrator/dialect.d.ts +24 -0
- package/dist/src/migrator/dialect.d.ts.map +1 -0
- package/dist/src/migrator/dialect.js +5 -0
- package/dist/src/migrator/dialect.js.map +1 -0
- package/dist/src/migrator/index.d.ts +8 -0
- package/dist/src/migrator/index.d.ts.map +1 -0
- package/dist/src/migrator/index.js +6 -0
- package/dist/src/migrator/index.js.map +1 -0
- package/dist/src/migrator/migrator.d.ts +36 -0
- package/dist/src/migrator/migrator.d.ts.map +1 -0
- package/dist/src/migrator/migrator.js +200 -0
- package/dist/src/migrator/migrator.js.map +1 -0
- package/dist/src/migrator/schema-diff.d.ts +25 -0
- package/dist/src/migrator/schema-diff.d.ts.map +1 -0
- package/dist/src/migrator/schema-diff.js +157 -0
- package/dist/src/migrator/schema-diff.js.map +1 -0
- package/dist/src/migrator/types.d.ts +91 -0
- package/dist/src/migrator/types.d.ts.map +1 -0
- package/dist/src/migrator/types.js +13 -0
- package/dist/src/migrator/types.js.map +1 -0
- package/dist/src/platforms/node.d.ts +40 -0
- package/dist/src/platforms/node.d.ts.map +1 -0
- package/dist/src/platforms/node.js +45 -0
- package/dist/src/platforms/node.js.map +1 -0
- package/dist/src/repository/id.d.ts +5 -0
- package/dist/src/repository/id.d.ts.map +1 -0
- package/dist/src/repository/id.js +9 -0
- package/dist/src/repository/id.js.map +1 -0
- package/dist/src/repository/index.d.ts +3 -0
- package/dist/src/repository/index.d.ts.map +1 -0
- package/dist/src/repository/index.js +2 -0
- package/dist/src/repository/index.js.map +1 -0
- package/dist/src/repository/repository.d.ts +53 -0
- package/dist/src/repository/repository.d.ts.map +1 -0
- package/dist/src/repository/repository.js +150 -0
- package/dist/src/repository/repository.js.map +1 -0
- package/dist/src/repository/types.d.ts +42 -0
- package/dist/src/repository/types.d.ts.map +1 -0
- package/dist/src/repository/types.js +2 -0
- package/dist/src/repository/types.js.map +1 -0
- package/dist/src/rule/compiler.d.ts +52 -0
- package/dist/src/rule/compiler.d.ts.map +1 -0
- package/dist/src/rule/compiler.js +115 -0
- package/dist/src/rule/compiler.js.map +1 -0
- package/dist/src/rule/enforcer.d.ts +47 -0
- package/dist/src/rule/enforcer.d.ts.map +1 -0
- package/dist/src/rule/enforcer.js +60 -0
- package/dist/src/rule/enforcer.js.map +1 -0
- package/dist/src/rule/index.d.ts +3 -0
- package/dist/src/rule/index.d.ts.map +1 -0
- package/dist/src/rule/index.js +3 -0
- package/dist/src/rule/index.js.map +1 -0
- package/dist/src/storage/index.d.ts +3 -0
- package/dist/src/storage/index.d.ts.map +1 -0
- package/dist/src/storage/index.js +3 -0
- package/dist/src/storage/index.js.map +1 -0
- package/dist/src/storage/local-preset.d.ts +21 -0
- package/dist/src/storage/local-preset.d.ts.map +1 -0
- package/dist/src/storage/local-preset.js +21 -0
- package/dist/src/storage/local-preset.js.map +1 -0
- package/dist/src/storage/storage.d.ts +83 -0
- package/dist/src/storage/storage.d.ts.map +1 -0
- package/dist/src/storage/storage.js +120 -0
- package/dist/src/storage/storage.js.map +1 -0
- package/dist/src/telemetry/collections.d.ts +4 -0
- package/dist/src/telemetry/collections.d.ts.map +1 -0
- package/dist/src/telemetry/collections.js +19 -0
- package/dist/src/telemetry/collections.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +9 -0
- package/dist/src/telemetry/index.d.ts.map +1 -0
- package/dist/src/telemetry/index.js +9 -0
- package/dist/src/telemetry/index.js.map +1 -0
- package/dist/src/telemetry/logger.d.ts +4 -0
- package/dist/src/telemetry/logger.d.ts.map +1 -0
- package/dist/src/telemetry/logger.js +27 -0
- package/dist/src/telemetry/logger.js.map +1 -0
- package/dist/src/telemetry/sqlite-logger.d.ts +24 -0
- package/dist/src/telemetry/sqlite-logger.d.ts.map +1 -0
- package/dist/src/telemetry/sqlite-logger.js +152 -0
- package/dist/src/telemetry/sqlite-logger.js.map +1 -0
- package/dist/src/telemetry/telemetry-sql-client.d.ts +11 -0
- package/dist/src/telemetry/telemetry-sql-client.d.ts.map +1 -0
- package/dist/src/telemetry/telemetry-sql-client.js +8 -0
- package/dist/src/telemetry/telemetry-sql-client.js.map +1 -0
- package/dist/src/telemetry/tracer.d.ts +16 -0
- package/dist/src/telemetry/tracer.d.ts.map +1 -0
- package/dist/src/telemetry/tracer.js +106 -0
- package/dist/src/telemetry/tracer.js.map +1 -0
- package/dist/src/thumbnail/index.d.ts +4 -0
- package/dist/src/thumbnail/index.d.ts.map +1 -0
- package/dist/src/thumbnail/index.js +3 -0
- package/dist/src/thumbnail/index.js.map +1 -0
- package/dist/src/thumbnail/photon.d.ts +9 -0
- package/dist/src/thumbnail/photon.d.ts.map +1 -0
- package/dist/src/thumbnail/photon.js +73 -0
- package/dist/src/thumbnail/photon.js.map +1 -0
- package/dist/src/thumbnail/types.d.ts +23 -0
- package/dist/src/thumbnail/types.d.ts.map +1 -0
- package/dist/src/thumbnail/types.js +22 -0
- package/dist/src/thumbnail/types.js.map +1 -0
- package/dist/tests/app/app.test.d.ts +2 -0
- package/dist/tests/app/app.test.d.ts.map +1 -0
- package/dist/tests/app/app.test.js +125 -0
- package/dist/tests/app/app.test.js.map +1 -0
- package/dist/tests/app/builder.test.d.ts +2 -0
- package/dist/tests/app/builder.test.d.ts.map +1 -0
- package/dist/tests/app/builder.test.js +70 -0
- package/dist/tests/app/builder.test.js.map +1 -0
- package/dist/tests/cache/cached-collection.test.d.ts +2 -0
- package/dist/tests/cache/cached-collection.test.d.ts.map +1 -0
- package/dist/tests/cache/cached-collection.test.js +244 -0
- package/dist/tests/cache/cached-collection.test.js.map +1 -0
- package/dist/tests/cache/collection-cache.test.d.ts +2 -0
- package/dist/tests/cache/collection-cache.test.d.ts.map +1 -0
- package/dist/tests/cache/collection-cache.test.js +73 -0
- package/dist/tests/cache/collection-cache.test.js.map +1 -0
- package/dist/tests/collection-service/collection-service.test.d.ts +2 -0
- package/dist/tests/collection-service/collection-service.test.d.ts.map +1 -0
- package/dist/tests/collection-service/collection-service.test.js +938 -0
- package/dist/tests/collection-service/collection-service.test.js.map +1 -0
- package/dist/tests/collection-service/input-schema.test.d.ts +2 -0
- package/dist/tests/collection-service/input-schema.test.d.ts.map +1 -0
- package/dist/tests/collection-service/input-schema.test.js +327 -0
- package/dist/tests/collection-service/input-schema.test.js.map +1 -0
- package/dist/tests/config/config.test.d.ts +2 -0
- package/dist/tests/config/config.test.d.ts.map +1 -0
- package/dist/tests/config/config.test.js +84 -0
- package/dist/tests/config/config.test.js.map +1 -0
- package/dist/tests/crypto/crypto.test.d.ts +2 -0
- package/dist/tests/crypto/crypto.test.d.ts.map +1 -0
- package/dist/tests/crypto/crypto.test.js +56 -0
- package/dist/tests/crypto/crypto.test.js.map +1 -0
- package/dist/tests/hooks/hook-collection.test.d.ts +2 -0
- package/dist/tests/hooks/hook-collection.test.d.ts.map +1 -0
- package/dist/tests/hooks/hook-collection.test.js +103 -0
- package/dist/tests/hooks/hook-collection.test.js.map +1 -0
- package/dist/tests/hooks/hook-service.test.d.ts +2 -0
- package/dist/tests/hooks/hook-service.test.d.ts.map +1 -0
- package/dist/tests/hooks/hook-service.test.js +216 -0
- package/dist/tests/hooks/hook-service.test.js.map +1 -0
- package/dist/tests/http/file-serve.test.d.ts +2 -0
- package/dist/tests/http/file-serve.test.d.ts.map +1 -0
- package/dist/tests/http/file-serve.test.js +210 -0
- package/dist/tests/http/file-serve.test.js.map +1 -0
- package/dist/tests/http/file-token.test.d.ts +2 -0
- package/dist/tests/http/file-token.test.d.ts.map +1 -0
- package/dist/tests/http/file-token.test.js +165 -0
- package/dist/tests/http/file-token.test.js.map +1 -0
- package/dist/tests/http/ip-middleware.test.d.ts +2 -0
- package/dist/tests/http/ip-middleware.test.d.ts.map +1 -0
- package/dist/tests/http/ip-middleware.test.js +58 -0
- package/dist/tests/http/ip-middleware.test.js.map +1 -0
- package/dist/tests/http/router.test.d.ts +2 -0
- package/dist/tests/http/router.test.d.ts.map +1 -0
- package/dist/tests/http/router.test.js +312 -0
- package/dist/tests/http/router.test.js.map +1 -0
- package/dist/tests/migrator/dialect-sqlite.test.d.ts +2 -0
- package/dist/tests/migrator/dialect-sqlite.test.d.ts.map +1 -0
- package/dist/tests/migrator/dialect-sqlite.test.js +90 -0
- package/dist/tests/migrator/dialect-sqlite.test.js.map +1 -0
- package/dist/tests/migrator/integration.test.d.ts +2 -0
- package/dist/tests/migrator/integration.test.d.ts.map +1 -0
- package/dist/tests/migrator/integration.test.js +180 -0
- package/dist/tests/migrator/integration.test.js.map +1 -0
- package/dist/tests/migrator/migrator.test.d.ts +2 -0
- package/dist/tests/migrator/migrator.test.d.ts.map +1 -0
- package/dist/tests/migrator/migrator.test.js +225 -0
- package/dist/tests/migrator/migrator.test.js.map +1 -0
- package/dist/tests/migrator/schema-diff.test.d.ts +2 -0
- package/dist/tests/migrator/schema-diff.test.d.ts.map +1 -0
- package/dist/tests/migrator/schema-diff.test.js +323 -0
- package/dist/tests/migrator/schema-diff.test.js.map +1 -0
- package/dist/tests/repository/repository.test.d.ts +2 -0
- package/dist/tests/repository/repository.test.d.ts.map +1 -0
- package/dist/tests/repository/repository.test.js +255 -0
- package/dist/tests/repository/repository.test.js.map +1 -0
- package/dist/tests/rule/compiler.test.d.ts +2 -0
- package/dist/tests/rule/compiler.test.d.ts.map +1 -0
- package/dist/tests/rule/compiler.test.js +226 -0
- package/dist/tests/rule/compiler.test.js.map +1 -0
- package/dist/tests/rule/enforcer.test.d.ts +2 -0
- package/dist/tests/rule/enforcer.test.d.ts.map +1 -0
- package/dist/tests/rule/enforcer.test.js +190 -0
- package/dist/tests/rule/enforcer.test.js.map +1 -0
- package/dist/tests/storage/storage.test.d.ts +2 -0
- package/dist/tests/storage/storage.test.d.ts.map +1 -0
- package/dist/tests/storage/storage.test.js +76 -0
- package/dist/tests/storage/storage.test.js.map +1 -0
- package/dist/tests/telemetry/collections.test.d.ts +2 -0
- package/dist/tests/telemetry/collections.test.d.ts.map +1 -0
- package/dist/tests/telemetry/collections.test.js +67 -0
- package/dist/tests/telemetry/collections.test.js.map +1 -0
- package/dist/tests/telemetry/instrumentation.test.d.ts +2 -0
- package/dist/tests/telemetry/instrumentation.test.d.ts.map +1 -0
- package/dist/tests/telemetry/instrumentation.test.js +226 -0
- package/dist/tests/telemetry/instrumentation.test.js.map +1 -0
- package/dist/tests/telemetry/logger.test.d.ts +2 -0
- package/dist/tests/telemetry/logger.test.d.ts.map +1 -0
- package/dist/tests/telemetry/logger.test.js +56 -0
- package/dist/tests/telemetry/logger.test.js.map +1 -0
- package/dist/tests/telemetry/sqlite-logger.test.d.ts +2 -0
- package/dist/tests/telemetry/sqlite-logger.test.d.ts.map +1 -0
- package/dist/tests/telemetry/sqlite-logger.test.js +218 -0
- package/dist/tests/telemetry/sqlite-logger.test.js.map +1 -0
- package/dist/tests/telemetry/telemetry-routes.test.d.ts +2 -0
- package/dist/tests/telemetry/telemetry-routes.test.d.ts.map +1 -0
- package/dist/tests/telemetry/telemetry-routes.test.js +133 -0
- package/dist/tests/telemetry/telemetry-routes.test.js.map +1 -0
- package/dist/tests/telemetry/tracer.test.d.ts +2 -0
- package/dist/tests/telemetry/tracer.test.d.ts.map +1 -0
- package/dist/tests/telemetry/tracer.test.js +63 -0
- package/dist/tests/telemetry/tracer.test.js.map +1 -0
- package/dist/tests/thumbnail/photon.test.d.ts +2 -0
- package/dist/tests/thumbnail/photon.test.d.ts.map +1 -0
- package/dist/tests/thumbnail/photon.test.js +478 -0
- package/dist/tests/thumbnail/photon.test.js.map +1 -0
- package/dist/tests/thumbnail/thumbnail.test.d.ts +2 -0
- package/dist/tests/thumbnail/thumbnail.test.d.ts.map +1 -0
- package/dist/tests/thumbnail/thumbnail.test.js +35 -0
- package/dist/tests/thumbnail/thumbnail.test.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** A raw database row — no domain types at this layer. */
|
|
2
|
+
export type RepoRecord = Record<string, unknown>;
|
|
3
|
+
/** A cursor-based result from a paginated list query. No COUNT(*) overhead. */
|
|
4
|
+
export type CursorResult<A> = {
|
|
5
|
+
items: ReadonlyArray<A>;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* A pre-compiled WHERE fragment from `enforcerForAction()`.
|
|
9
|
+
* The repository wraps it in `unsafeFragment` and splices it into template literals.
|
|
10
|
+
*/
|
|
11
|
+
export type WhereClause = {
|
|
12
|
+
sql: string;
|
|
13
|
+
params: ReadonlyArray<unknown>;
|
|
14
|
+
};
|
|
15
|
+
export type SortOrder = {
|
|
16
|
+
field: string;
|
|
17
|
+
direction: "asc" | "desc";
|
|
18
|
+
};
|
|
19
|
+
/** One LEFT JOIN to inline a related record alongside the main row. */
|
|
20
|
+
export type ExpandDef = {
|
|
21
|
+
localField: string;
|
|
22
|
+
targetTable: string;
|
|
23
|
+
targetColumns: ReadonlyArray<string>;
|
|
24
|
+
};
|
|
25
|
+
/** Options for list() — where is optional (omit for public collections). */
|
|
26
|
+
export type ListOptions = {
|
|
27
|
+
where?: WhereClause;
|
|
28
|
+
sort?: SortOrder;
|
|
29
|
+
fields?: ReadonlyArray<string>;
|
|
30
|
+
expand?: ReadonlyArray<ExpandDef>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Options for viewFilter() — where is required because the caller always
|
|
34
|
+
* specifies what they are filtering by.
|
|
35
|
+
*/
|
|
36
|
+
export type FilterOptions = {
|
|
37
|
+
where: WhereClause;
|
|
38
|
+
sort?: SortOrder;
|
|
39
|
+
fields?: ReadonlyArray<string>;
|
|
40
|
+
expand?: ReadonlyArray<ExpandDef>;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/repository/types.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD,+EAA+E;AAC/E,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B,CAAA;AAED,uEAAuE;AACvE,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACrC,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;CAClC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;CAClC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/repository/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { CollectionSchema, ExprNode, OperandNode } from "@gettersethya/mira-client";
|
|
2
|
+
/**
|
|
3
|
+
* Context passed through the compilation pipeline.
|
|
4
|
+
* Manages parameter generation, table aliasing, and field mapping.
|
|
5
|
+
*/
|
|
6
|
+
export type CompileCtx = {
|
|
7
|
+
/** Maps field names to their database column names. */
|
|
8
|
+
columnOfField: (field: string) => string;
|
|
9
|
+
/** Table alias prefix (e.g., `"t"`). `undefined` omits the prefix. */
|
|
10
|
+
tableAlias?: string;
|
|
11
|
+
/** Generates the next placeholder name (e.g., `@p0`, `@p1`). */
|
|
12
|
+
nextParam: () => string;
|
|
13
|
+
/** Accumulator for parameter bindings (placeholder → value). */
|
|
14
|
+
params: Record<string, unknown>;
|
|
15
|
+
/** Map of all collection schemas for subquery resolution. */
|
|
16
|
+
collectionSchemas: Record<string, CollectionSchema>;
|
|
17
|
+
/** Name of the auth collection for `@auth_*` placeholders. */
|
|
18
|
+
authCollection?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Compiles a rule expression tree into a SQL WHERE clause string.
|
|
22
|
+
* Parameter values are written into `ctx.params` as side effects.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const ctx = {
|
|
26
|
+
* tableAlias: "t",
|
|
27
|
+
* nextParam: () => `@p${i++}`,
|
|
28
|
+
* params: {},
|
|
29
|
+
* columnOfField: (f) => f,
|
|
30
|
+
* collectionSchemas: {},
|
|
31
|
+
* authCollection: "users"
|
|
32
|
+
* }
|
|
33
|
+
* compile(Rule.field("age").gt(Rule.literal(18)), ctx)
|
|
34
|
+
* // => "t.age > @p0"
|
|
35
|
+
*/
|
|
36
|
+
export declare function compile(node: ExprNode, ctx: CompileCtx): string;
|
|
37
|
+
/**
|
|
38
|
+
* Compiles an operand node (value expression) into its SQL representation.
|
|
39
|
+
* Handles field references, literals, auth tokens, subqueries, date functions, and request values.
|
|
40
|
+
*
|
|
41
|
+
* - `field` → `t.columnName` (with optional table alias and `columnOfField` mapping)
|
|
42
|
+
* - `literal` → `@pN` (stored in `ctx.params`)
|
|
43
|
+
* - `auth` → `@auth_fieldName`
|
|
44
|
+
* - `authId` → `@auth_id`
|
|
45
|
+
* - `request` → `@request_source_key`
|
|
46
|
+
* - `now` → `datetime('now')`
|
|
47
|
+
* - `dateAdd` → `datetime(expr, '+N days')`
|
|
48
|
+
* - `dateDiff` → `(julianday(a) - julianday(b))`
|
|
49
|
+
* - `subquery` → `SELECT field FROM collection WHERE ...`
|
|
50
|
+
*/
|
|
51
|
+
export declare function compileOperand(node: OperandNode, ctx: CompileCtx): string;
|
|
52
|
+
//# sourceMappingURL=compiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/rule/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAExF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,uDAAuD;IACvD,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,SAAS,EAAE,MAAM,MAAM,CAAA;IACvB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,6DAA6D;IAC7D,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACnD,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAyC/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAwCzE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles a rule expression tree into a SQL WHERE clause string.
|
|
3
|
+
* Parameter values are written into `ctx.params` as side effects.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const ctx = {
|
|
7
|
+
* tableAlias: "t",
|
|
8
|
+
* nextParam: () => `@p${i++}`,
|
|
9
|
+
* params: {},
|
|
10
|
+
* columnOfField: (f) => f,
|
|
11
|
+
* collectionSchemas: {},
|
|
12
|
+
* authCollection: "users"
|
|
13
|
+
* }
|
|
14
|
+
* compile(Rule.field("age").gt(Rule.literal(18)), ctx)
|
|
15
|
+
* // => "t.age > @p0"
|
|
16
|
+
*/
|
|
17
|
+
export function compile(node, ctx) {
|
|
18
|
+
switch (node.op) {
|
|
19
|
+
case "public":
|
|
20
|
+
return "1 = 1";
|
|
21
|
+
case "eq":
|
|
22
|
+
return `${compileOperand(node.left, ctx)} = ${compileOperand(node.right, ctx)}`;
|
|
23
|
+
case "neq":
|
|
24
|
+
return `${compileOperand(node.left, ctx)} != ${compileOperand(node.right, ctx)}`;
|
|
25
|
+
case "gt":
|
|
26
|
+
return `${compileOperand(node.left, ctx)} > ${compileOperand(node.right, ctx)}`;
|
|
27
|
+
case "gte":
|
|
28
|
+
return `${compileOperand(node.left, ctx)} >= ${compileOperand(node.right, ctx)}`;
|
|
29
|
+
case "lt":
|
|
30
|
+
return `${compileOperand(node.left, ctx)} < ${compileOperand(node.right, ctx)}`;
|
|
31
|
+
case "lte":
|
|
32
|
+
return `${compileOperand(node.left, ctx)} <= ${compileOperand(node.right, ctx)}`;
|
|
33
|
+
case "in": {
|
|
34
|
+
const leftSql = compileOperand(node.left, ctx);
|
|
35
|
+
if (node.right.kind === "literal" && Array.isArray(node.right.value)) {
|
|
36
|
+
const items = node.right.value;
|
|
37
|
+
if (items.length === 0)
|
|
38
|
+
return "1 = 0";
|
|
39
|
+
const placeholders = items.map((item) => {
|
|
40
|
+
const param = ctx.nextParam();
|
|
41
|
+
ctx.params[param] = item;
|
|
42
|
+
return param;
|
|
43
|
+
});
|
|
44
|
+
return `${leftSql} IN (${placeholders.join(", ")})`;
|
|
45
|
+
}
|
|
46
|
+
return `${leftSql} IN (${compileOperand(node.right, ctx)})`;
|
|
47
|
+
}
|
|
48
|
+
case "and":
|
|
49
|
+
return `(${compile(node.left, ctx)}) AND (${compile(node.right, ctx)})`;
|
|
50
|
+
case "or":
|
|
51
|
+
return `(${compile(node.left, ctx)}) OR (${compile(node.right, ctx)})`;
|
|
52
|
+
case "not":
|
|
53
|
+
return `NOT (${compile(node.expr, ctx)})`;
|
|
54
|
+
case "startsWith":
|
|
55
|
+
return `${compileOperand(node.left, ctx)} LIKE (${compileOperand(node.right, ctx)} || '%')`;
|
|
56
|
+
case "contains":
|
|
57
|
+
return `${compileOperand(node.left, ctx)} LIKE ('%' || ${compileOperand(node.right, ctx)} || '%')`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Compiles an operand node (value expression) into its SQL representation.
|
|
62
|
+
* Handles field references, literals, auth tokens, subqueries, date functions, and request values.
|
|
63
|
+
*
|
|
64
|
+
* - `field` → `t.columnName` (with optional table alias and `columnOfField` mapping)
|
|
65
|
+
* - `literal` → `@pN` (stored in `ctx.params`)
|
|
66
|
+
* - `auth` → `@auth_fieldName`
|
|
67
|
+
* - `authId` → `@auth_id`
|
|
68
|
+
* - `request` → `@request_source_key`
|
|
69
|
+
* - `now` → `datetime('now')`
|
|
70
|
+
* - `dateAdd` → `datetime(expr, '+N days')`
|
|
71
|
+
* - `dateDiff` → `(julianday(a) - julianday(b))`
|
|
72
|
+
* - `subquery` → `SELECT field FROM collection WHERE ...`
|
|
73
|
+
*/
|
|
74
|
+
export function compileOperand(node, ctx) {
|
|
75
|
+
switch (node.kind) {
|
|
76
|
+
case "field": {
|
|
77
|
+
const col = ctx.columnOfField(node.field);
|
|
78
|
+
if (ctx.tableAlias !== undefined && node.collection === undefined) {
|
|
79
|
+
return `${ctx.tableAlias}.${col}`;
|
|
80
|
+
}
|
|
81
|
+
return col;
|
|
82
|
+
}
|
|
83
|
+
case "literal": {
|
|
84
|
+
const param = ctx.nextParam();
|
|
85
|
+
ctx.params[param] = node.value;
|
|
86
|
+
return param;
|
|
87
|
+
}
|
|
88
|
+
case "auth":
|
|
89
|
+
return `@auth_${node.field}`;
|
|
90
|
+
case "authId":
|
|
91
|
+
return `@auth_id`;
|
|
92
|
+
case "authCollection":
|
|
93
|
+
return `@auth_collection`;
|
|
94
|
+
case "request":
|
|
95
|
+
return `@request_${node.source}_${node.key}`;
|
|
96
|
+
case "now":
|
|
97
|
+
return `datetime('now')`;
|
|
98
|
+
case "subquery": {
|
|
99
|
+
const { tableAlias: _alias, ...subCtx } = ctx;
|
|
100
|
+
const whereSql = compile(node.where, subCtx);
|
|
101
|
+
return `SELECT ${node.field} FROM ${node.collection} WHERE ${whereSql}`;
|
|
102
|
+
}
|
|
103
|
+
case "dateAdd": {
|
|
104
|
+
const operandSql = compileOperand(node.operand, ctx);
|
|
105
|
+
const sign = node.amount >= 0 ? "+" : "";
|
|
106
|
+
return `datetime(${operandSql}, '${sign}${node.amount} ${node.unit}s')`;
|
|
107
|
+
}
|
|
108
|
+
case "dateDiff": {
|
|
109
|
+
const leftSql = compileOperand(node.left, ctx);
|
|
110
|
+
const rightSql = compileOperand(node.right, ctx);
|
|
111
|
+
return `(julianday(${leftSql}) - julianday(${rightSql}))`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../src/rule/compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CollectionSchema, ExprNode } from "@gettersethya/mira-client";
|
|
2
|
+
import type { CompileCtx } from "./compiler.js";
|
|
3
|
+
/** Result of compiling a rule for runtime enforcement: SQL string + ordered params. */
|
|
4
|
+
export type EnforceResult = {
|
|
5
|
+
sql: string;
|
|
6
|
+
params: ReadonlyArray<unknown>;
|
|
7
|
+
};
|
|
8
|
+
/** Context values available to rule evaluation at enforcement time. */
|
|
9
|
+
export type EnforcementCtx = {
|
|
10
|
+
auth?: {
|
|
11
|
+
collection: string;
|
|
12
|
+
record: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
query: Record<string, string | Array<string>>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Compiles a rule expression into a SQL snippet with `?` placeholders
|
|
19
|
+
* and an ordered array of parameter values, ready for use with `@effect/sql`.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const { sql, params } = enforceRule(
|
|
23
|
+
* Rule.field("ownerId").eq(Rule.authId(Users))
|
|
24
|
+
* )
|
|
25
|
+
* // sql: "t.ownerId = ?"
|
|
26
|
+
* // params: []
|
|
27
|
+
*
|
|
28
|
+
* const { sql, params } = enforceRule(
|
|
29
|
+
* Rule.field("status").eq(Rule.literal("active"))
|
|
30
|
+
* )
|
|
31
|
+
* // sql: "t.status = ?"
|
|
32
|
+
* // params: ["active"]
|
|
33
|
+
*/
|
|
34
|
+
export declare function enforceRule(rule: ExprNode, overrides?: Partial<CompileCtx>): EnforceResult;
|
|
35
|
+
/**
|
|
36
|
+
* Resolves and compiles the rule for a specific action on a collection schema.
|
|
37
|
+
* Returns `null` if the collection has no `x-rules` or the action has no rule defined.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const schema = Posts.schema // CollectionSchema with x-rules
|
|
41
|
+
* const result = enforcerForAction(schema, "list")
|
|
42
|
+
* if (result) {
|
|
43
|
+
* sql.unsafe(`SELECT * FROM posts WHERE ${result.sql}`, result.params)
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
export declare function enforcerForAction(collection: CollectionSchema, action: keyof NonNullable<CollectionSchema["x-rules"]>): EnforceResult | null;
|
|
47
|
+
//# sourceMappingURL=enforcer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcer.d.ts","sourceRoot":"","sources":["../../../src/rule/enforcer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAG/C,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;IAC9D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAC9C,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,aAAa,CAkB1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,WAAW,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,GACrD,aAAa,GAAG,IAAI,CAUtB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { compile } from "./compiler.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compiles a rule expression into a SQL snippet with `?` placeholders
|
|
4
|
+
* and an ordered array of parameter values, ready for use with `@effect/sql`.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const { sql, params } = enforceRule(
|
|
8
|
+
* Rule.field("ownerId").eq(Rule.authId(Users))
|
|
9
|
+
* )
|
|
10
|
+
* // sql: "t.ownerId = ?"
|
|
11
|
+
* // params: []
|
|
12
|
+
*
|
|
13
|
+
* const { sql, params } = enforceRule(
|
|
14
|
+
* Rule.field("status").eq(Rule.literal("active"))
|
|
15
|
+
* )
|
|
16
|
+
* // sql: "t.status = ?"
|
|
17
|
+
* // params: ["active"]
|
|
18
|
+
*/
|
|
19
|
+
export function enforceRule(rule, overrides) {
|
|
20
|
+
let i = 0;
|
|
21
|
+
const paramRecord = {};
|
|
22
|
+
const ctx = {
|
|
23
|
+
tableAlias: "t",
|
|
24
|
+
nextParam: () => `@p${i++}`,
|
|
25
|
+
params: paramRecord,
|
|
26
|
+
columnOfField: (f) => f,
|
|
27
|
+
collectionSchemas: {},
|
|
28
|
+
...overrides
|
|
29
|
+
};
|
|
30
|
+
const rawSql = compile(rule, ctx);
|
|
31
|
+
const sql = rawSql.replace(/@p(\d+)/g, "?");
|
|
32
|
+
const params = [];
|
|
33
|
+
for (let j = 0; j < i; j++) {
|
|
34
|
+
params.push(paramRecord[`@p${j}`]);
|
|
35
|
+
}
|
|
36
|
+
return { sql, params };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolves and compiles the rule for a specific action on a collection schema.
|
|
40
|
+
* Returns `null` if the collection has no `x-rules` or the action has no rule defined.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const schema = Posts.schema // CollectionSchema with x-rules
|
|
44
|
+
* const result = enforcerForAction(schema, "list")
|
|
45
|
+
* if (result) {
|
|
46
|
+
* sql.unsafe(`SELECT * FROM posts WHERE ${result.sql}`, result.params)
|
|
47
|
+
* }
|
|
48
|
+
*/
|
|
49
|
+
export function enforcerForAction(collection, action) {
|
|
50
|
+
const rules = collection["x-rules"];
|
|
51
|
+
if (rules === undefined) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const rule = rules[action];
|
|
55
|
+
if (rule === undefined) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return enforceRule(rule);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=enforcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcer.js","sourceRoot":"","sources":["../../../src/rule/enforcer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAevC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,SAA+B;IACzE,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,MAAM,WAAW,GAA4B,EAAE,CAAA;IAC/C,MAAM,GAAG,GAAe;QACtB,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE;QAC3B,MAAM,EAAE,WAAW;QACnB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvB,iBAAiB,EAAE,EAAE;QACrB,GAAG,SAAS;KACb,CAAA;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACjC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;IACpC,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;AACxB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAA4B,EAC5B,MAAsD;IAEtD,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rule/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rule/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { MiraStorage } from "../app/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Local file storage preset using the filesystem.
|
|
4
|
+
*
|
|
5
|
+
* Creates a `MiraStorage` using the local disk-based `FileStorage` implementation.
|
|
6
|
+
* Files are stored in the specified directory, with automatic subdirectory creation.
|
|
7
|
+
*
|
|
8
|
+
* @param config.directory - The root directory for file storage
|
|
9
|
+
* @returns A MiraStorage preset
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* Mira.builder()
|
|
13
|
+
* .storage(LocalFileStorage({ directory: "./uploads" }))
|
|
14
|
+
*
|
|
15
|
+
* @see makeFileStorageLayer — underlying implementation
|
|
16
|
+
* @see MiraStorage — the interface LocalFileStorage implements
|
|
17
|
+
*/
|
|
18
|
+
export declare const LocalFileStorage: (config: {
|
|
19
|
+
directory: string;
|
|
20
|
+
}) => MiraStorage;
|
|
21
|
+
//# sourceMappingURL=local-preset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-preset.d.ts","sourceRoot":"","sources":["../../../src/storage/local-preset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,KAAG,WAE/D,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { makeFileStorageLayer } from "./storage.js";
|
|
2
|
+
/**
|
|
3
|
+
* Local file storage preset using the filesystem.
|
|
4
|
+
*
|
|
5
|
+
* Creates a `MiraStorage` using the local disk-based `FileStorage` implementation.
|
|
6
|
+
* Files are stored in the specified directory, with automatic subdirectory creation.
|
|
7
|
+
*
|
|
8
|
+
* @param config.directory - The root directory for file storage
|
|
9
|
+
* @returns A MiraStorage preset
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* Mira.builder()
|
|
13
|
+
* .storage(LocalFileStorage({ directory: "./uploads" }))
|
|
14
|
+
*
|
|
15
|
+
* @see makeFileStorageLayer — underlying implementation
|
|
16
|
+
* @see MiraStorage — the interface LocalFileStorage implements
|
|
17
|
+
*/
|
|
18
|
+
export const LocalFileStorage = (config) => ({
|
|
19
|
+
layer: makeFileStorageLayer("local", { directory: config.directory }),
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=local-preset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-preset.js","sourceRoot":"","sources":["../../../src/storage/local-preset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGnD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAA6B,EAAe,EAAE,CAAC,CAAC;IAC/E,KAAK,EAAE,oBAAoB,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;CACtE,CAAC,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { FileSystem, Path } from "@effect/platform";
|
|
2
|
+
import { Context, Effect, Layer, Stream } from "effect";
|
|
3
|
+
declare const FileStorageError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
4
|
+
readonly _tag: "FileStorageError";
|
|
5
|
+
} & Readonly<A>;
|
|
6
|
+
/**
|
|
7
|
+
* Error raised when a file storage operation fails (disk I/O, permission issues, etc.).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* new FileStorageError({ reason: "ENOSPC: no space left on device" })
|
|
11
|
+
*/
|
|
12
|
+
export declare class FileStorageError extends FileStorageError_base<{
|
|
13
|
+
reason: string;
|
|
14
|
+
}> {
|
|
15
|
+
}
|
|
16
|
+
declare const FileStorageNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
17
|
+
readonly _tag: "FileStorageNotFound";
|
|
18
|
+
} & Readonly<A>;
|
|
19
|
+
/**
|
|
20
|
+
* Error raised when a requested file does not exist in storage.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* new FileStorageNotFound({ key: "uploads/abc123/image.jpg" })
|
|
24
|
+
*/
|
|
25
|
+
export declare class FileStorageNotFound extends FileStorageNotFound_base<{
|
|
26
|
+
key: string;
|
|
27
|
+
}> {
|
|
28
|
+
}
|
|
29
|
+
declare const FileStorage_base: Context.TagClass<FileStorage, "FileStorage", {
|
|
30
|
+
upload<E>(key: string, stream: Stream.Stream<Uint8Array, E>, mimeType: string): Effect.Effect<string, E | FileStorageError>;
|
|
31
|
+
delete(key: string): Effect.Effect<void, FileStorageError>;
|
|
32
|
+
url(key: string): string;
|
|
33
|
+
read(key: string): Effect.Effect<Uint8Array, FileStorageError | FileStorageNotFound>;
|
|
34
|
+
exists(key: string): Effect.Effect<boolean, FileStorageError>;
|
|
35
|
+
list(prefix: string): Effect.Effect<ReadonlyArray<string>, FileStorageError>;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* File storage abstraction tag.
|
|
39
|
+
*
|
|
40
|
+
* Provides `upload`, `delete`, `url`, `read`, `exists`, and `list` operations
|
|
41
|
+
* for file management. The concrete implementation can be local disk or S3.
|
|
42
|
+
*
|
|
43
|
+
* All operations return `Effect` with typed error channels.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* import { FileStorage } from "@gettersethya/mira"
|
|
47
|
+
*
|
|
48
|
+
* Effect.gen(function* () {
|
|
49
|
+
* const storage = yield* FileStorage
|
|
50
|
+
* const key = yield* storage.upload("path/to/file", stream, "image/jpeg")
|
|
51
|
+
* const url = storage.url(key) // synchronous — returns the URL string
|
|
52
|
+
* const data = yield* storage.read(key)
|
|
53
|
+
* const exists = yield* storage.exists(key)
|
|
54
|
+
* const files = yield* storage.list("uploads/")
|
|
55
|
+
* yield* storage.delete(key)
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* @see makeFileStorageLayer — factory function
|
|
59
|
+
* @see LocalFileStorage — local disk preset
|
|
60
|
+
*/
|
|
61
|
+
export declare class FileStorage extends FileStorage_base {
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a FileStorage layer backed by the local filesystem.
|
|
65
|
+
*
|
|
66
|
+
* Files are stored under a root directory (default: `./uploads`).
|
|
67
|
+
* Nested subdirectories are created automatically based on the key path.
|
|
68
|
+
*
|
|
69
|
+
* Note: the `_provider` parameter is currently unused and reserved for future
|
|
70
|
+
* provider detection. Pass `"local"` for now.
|
|
71
|
+
*
|
|
72
|
+
* @param _provider - Provider type (currently unused, pass "local")
|
|
73
|
+
* @param config.directory - Storage root directory (default: "./uploads")
|
|
74
|
+
* @returns A Layer providing FileStorage
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* makeFileStorageLayer("local", { directory: "/var/data/uploads" })
|
|
78
|
+
*
|
|
79
|
+
* @see LocalFileStorage — preset wrapping this function
|
|
80
|
+
*/
|
|
81
|
+
export declare function makeFileStorageLayer(_provider: string, config: Record<string, string>): Layer.Layer<FileStorage, never, FileSystem.FileSystem | Path.Path>;
|
|
82
|
+
export {};
|
|
83
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/storage/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;;;;AAEnE;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,sBAAqC;IACzE,MAAM,EAAE,MAAM,CAAA;CACf,CAAC;CAAG;;;;AAEL;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,yBAAwC;IAC/E,GAAG,EAAE,MAAM,CAAA;CACZ,CAAC;CAAG;;WA6BM,CAAC,OACD,MAAM,UACH,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,YAC1B,MAAM,GACf,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,gBAAgB,CAAC;gBAClC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,CAAC;aACjD,MAAM,GAAG,MAAM;cACd,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;gBACxE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC;iBAChD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;;AApChF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,WAAY,SAAQ,gBAc9B;CAAG;AAEN;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,sEA8FrF"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { FileSystem, Path } from "@effect/platform";
|
|
2
|
+
import { Context, Data, Effect, Layer, Sink, Stream } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* Error raised when a file storage operation fails (disk I/O, permission issues, etc.).
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* new FileStorageError({ reason: "ENOSPC: no space left on device" })
|
|
8
|
+
*/
|
|
9
|
+
export class FileStorageError extends Data.TaggedError("FileStorageError") {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Error raised when a requested file does not exist in storage.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* new FileStorageNotFound({ key: "uploads/abc123/image.jpg" })
|
|
16
|
+
*/
|
|
17
|
+
export class FileStorageNotFound extends Data.TaggedError("FileStorageNotFound") {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* File storage abstraction tag.
|
|
21
|
+
*
|
|
22
|
+
* Provides `upload`, `delete`, `url`, `read`, `exists`, and `list` operations
|
|
23
|
+
* for file management. The concrete implementation can be local disk or S3.
|
|
24
|
+
*
|
|
25
|
+
* All operations return `Effect` with typed error channels.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* import { FileStorage } from "@gettersethya/mira"
|
|
29
|
+
*
|
|
30
|
+
* Effect.gen(function* () {
|
|
31
|
+
* const storage = yield* FileStorage
|
|
32
|
+
* const key = yield* storage.upload("path/to/file", stream, "image/jpeg")
|
|
33
|
+
* const url = storage.url(key) // synchronous — returns the URL string
|
|
34
|
+
* const data = yield* storage.read(key)
|
|
35
|
+
* const exists = yield* storage.exists(key)
|
|
36
|
+
* const files = yield* storage.list("uploads/")
|
|
37
|
+
* yield* storage.delete(key)
|
|
38
|
+
* })
|
|
39
|
+
*
|
|
40
|
+
* @see makeFileStorageLayer — factory function
|
|
41
|
+
* @see LocalFileStorage — local disk preset
|
|
42
|
+
*/
|
|
43
|
+
export class FileStorage extends Context.Tag("FileStorage")() {
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a FileStorage layer backed by the local filesystem.
|
|
47
|
+
*
|
|
48
|
+
* Files are stored under a root directory (default: `./uploads`).
|
|
49
|
+
* Nested subdirectories are created automatically based on the key path.
|
|
50
|
+
*
|
|
51
|
+
* Note: the `_provider` parameter is currently unused and reserved for future
|
|
52
|
+
* provider detection. Pass `"local"` for now.
|
|
53
|
+
*
|
|
54
|
+
* @param _provider - Provider type (currently unused, pass "local")
|
|
55
|
+
* @param config.directory - Storage root directory (default: "./uploads")
|
|
56
|
+
* @returns A Layer providing FileStorage
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* makeFileStorageLayer("local", { directory: "/var/data/uploads" })
|
|
60
|
+
*
|
|
61
|
+
* @see LocalFileStorage — preset wrapping this function
|
|
62
|
+
*/
|
|
63
|
+
export function makeFileStorageLayer(_provider, config) {
|
|
64
|
+
return Layer.effect(FileStorage, Effect.gen(function* () {
|
|
65
|
+
const fs = yield* FileSystem.FileSystem;
|
|
66
|
+
const pathSvc = yield* Path.Path;
|
|
67
|
+
const root = config["directory"] ?? "./uploads";
|
|
68
|
+
return FileStorage.of({
|
|
69
|
+
upload: (key, stream, _mimeType) => Effect.gen(function* () {
|
|
70
|
+
const fullPath = pathSvc.join(root, key);
|
|
71
|
+
yield* fs.makeDirectory(pathSvc.dirname(fullPath), { recursive: true }).pipe(Effect.catchTags({
|
|
72
|
+
BadArgument: (e) => Effect.fail(new FileStorageError({ reason: e.message })),
|
|
73
|
+
SystemError: (e) => Effect.fail(new FileStorageError({ reason: e.message }))
|
|
74
|
+
}));
|
|
75
|
+
// Map PlatformError at the sink level so generic E is not involved
|
|
76
|
+
const mappedSink = Sink.mapError(fs.sink(fullPath), (e) => new FileStorageError({ reason: e.message ?? String(e) }));
|
|
77
|
+
yield* Stream.run(stream, mappedSink);
|
|
78
|
+
return key;
|
|
79
|
+
}),
|
|
80
|
+
delete: (key) => Effect.gen(function* () {
|
|
81
|
+
const fullPath = pathSvc.join(root, key);
|
|
82
|
+
yield* fs.remove(fullPath, { force: true }).pipe(Effect.catchTags({
|
|
83
|
+
BadArgument: (e) => Effect.fail(new FileStorageError({ reason: e.message })),
|
|
84
|
+
SystemError: (e) => Effect.fail(new FileStorageError({ reason: e.message }))
|
|
85
|
+
}));
|
|
86
|
+
}),
|
|
87
|
+
url: (key) => `/files/${key}`,
|
|
88
|
+
read: (key) => Effect.gen(function* () {
|
|
89
|
+
const fullPath = pathSvc.join(root, key);
|
|
90
|
+
const present = yield* fs.exists(fullPath).pipe(Effect.catchTags({
|
|
91
|
+
BadArgument: () => Effect.succeed(false),
|
|
92
|
+
SystemError: () => Effect.succeed(false)
|
|
93
|
+
}));
|
|
94
|
+
if (!present)
|
|
95
|
+
return yield* new FileStorageNotFound({ key });
|
|
96
|
+
return yield* fs.readFile(fullPath).pipe(Effect.catchTags({
|
|
97
|
+
BadArgument: (e) => Effect.fail(new FileStorageError({ reason: e.message })),
|
|
98
|
+
SystemError: (e) => Effect.fail(new FileStorageError({ reason: e.message }))
|
|
99
|
+
}));
|
|
100
|
+
}),
|
|
101
|
+
exists: (key) => Effect.gen(function* () {
|
|
102
|
+
const fullPath = pathSvc.join(root, key);
|
|
103
|
+
return yield* fs.exists(fullPath).pipe(Effect.catchTags({
|
|
104
|
+
BadArgument: () => Effect.succeed(false),
|
|
105
|
+
SystemError: () => Effect.succeed(false)
|
|
106
|
+
}));
|
|
107
|
+
}),
|
|
108
|
+
list: (prefix) => Effect.gen(function* () {
|
|
109
|
+
const prefixPath = pathSvc.join(root, prefix);
|
|
110
|
+
const entries = yield* fs.readDirectory(prefixPath, { recursive: true }).pipe(Effect.catchTags({
|
|
111
|
+
BadArgument: () => Effect.succeed([]),
|
|
112
|
+
SystemError: () => Effect.succeed([])
|
|
113
|
+
}));
|
|
114
|
+
const fileEntries = yield* Effect.filter(entries, (entry) => fs.stat(pathSvc.join(prefixPath, entry)).pipe(Effect.map((info) => info.type === "File"), Effect.orElseSucceed(() => false)), { concurrency: "unbounded" });
|
|
115
|
+
return fileEntries.map((entry) => pathSvc.join(prefix, entry).split(pathSvc.sep).join("/"));
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=storage.js.map
|