@slopware/sloppy-darwin-x64 0.1.0-alpha.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/LICENSE +201 -0
- package/README.md +5 -0
- package/bin/sloppy +0 -0
- package/bin/sloppyc +0 -0
- package/docs/KNOWN_LIMITATIONS.md +16 -0
- package/docs/LICENSES.md +6 -0
- package/docs/NOTICE.md +8 -0
- package/examples/README.md +140 -0
- package/examples/auth-api/README.md +20 -0
- package/examples/auth-api/app.js +61 -0
- package/examples/auth-api/appsettings.json +7 -0
- package/examples/auth-api/sloppy.json +5 -0
- package/examples/cache-basic/README.md +9 -0
- package/examples/cache-basic/app.js +32 -0
- package/examples/cache-hybrid-postgres/README.md +10 -0
- package/examples/cache-hybrid-postgres/app.js +27 -0
- package/examples/cache-output-api/README.md +10 -0
- package/examples/cache-output-api/app.js +35 -0
- package/examples/codec-base64-hex/README.md +14 -0
- package/examples/codec-base64-hex/app.js +15 -0
- package/examples/codec-checksums/README.md +15 -0
- package/examples/codec-checksums/app.js +8 -0
- package/examples/codec-compression/README.md +13 -0
- package/examples/codec-compression/app.js +9 -0
- package/examples/codec-streaming-compression/README.md +19 -0
- package/examples/codec-streaming-compression/app.js +16 -0
- package/examples/codec-text-binary/README.md +16 -0
- package/examples/codec-text-binary/app.js +17 -0
- package/examples/compiler-hello/README.md +71 -0
- package/examples/compiler-hello/app.js +7 -0
- package/examples/compiler-hello/expected/app.js +8 -0
- package/examples/compiler-hello/expected/app.js.map +53 -0
- package/examples/compiler-hello/expected/app.plan.json +229 -0
- package/examples/compiler-hello/expected/routes.slrt +0 -0
- package/examples/config-basic/README.md +13 -0
- package/examples/config-basic/app.js +13 -0
- package/examples/config-basic/appsettings.json +7 -0
- package/examples/config-secrets-redaction/README.md +9 -0
- package/examples/config-secrets-redaction/app.js +9 -0
- package/examples/config-secrets-redaction/appsettings.json +5 -0
- package/examples/config-strict-mode/README.md +7 -0
- package/examples/config-strict-mode/app.js +10 -0
- package/examples/config-strict-mode/appsettings.json +7 -0
- package/examples/configured-api/README.md +38 -0
- package/examples/configured-api/app.js +12 -0
- package/examples/configured-api/appsettings.Development.json +5 -0
- package/examples/configured-api/appsettings.json +6 -0
- package/examples/configured-api/sloppy.json +5 -0
- package/examples/core-config-secrets/README.md +10 -0
- package/examples/core-config-secrets/app.js +15 -0
- package/examples/core-fs-time-codec/README.md +9 -0
- package/examples/core-fs-time-codec/app.js +8 -0
- package/examples/core-network-time-codec/README.md +11 -0
- package/examples/core-network-time-codec/app.js +20 -0
- package/examples/core-policy-audit/README.md +7 -0
- package/examples/core-policy-audit/app.js +22 -0
- package/examples/core-process-time-codec/README.md +8 -0
- package/examples/core-process-time-codec/app.js +28 -0
- package/examples/core-worker-time/README.md +8 -0
- package/examples/core-worker-time/app.js +17 -0
- package/examples/crypto-hash-hmac/README.md +17 -0
- package/examples/crypto-hash-hmac/app.js +29 -0
- package/examples/crypto-password/README.md +21 -0
- package/examples/crypto-password/app.js +12 -0
- package/examples/crypto-random-token/README.md +16 -0
- package/examples/crypto-random-token/app.js +12 -0
- package/examples/crypto-secret-constant-time/README.md +21 -0
- package/examples/crypto-secret-constant-time/app.js +15 -0
- package/examples/data-foundation/README.md +39 -0
- package/examples/data-foundation/app.js +63 -0
- package/examples/dependency-graph/README.md +19 -0
- package/examples/dependency-graph/fixtures/graph-helper/index.js +3 -0
- package/examples/dependency-graph/fixtures/graph-helper/package.json +6 -0
- package/examples/dependency-graph/package.json +7 -0
- package/examples/dependency-graph/public/message.txt +1 -0
- package/examples/dependency-graph/sloppy.json +9 -0
- package/examples/dependency-graph/src/main.ts +8 -0
- package/examples/dogfood/README.md +23 -0
- package/examples/dogfood/dogfood.json +136 -0
- package/examples/dynamic-module-include/README.md +20 -0
- package/examples/dynamic-module-include/public/readme.txt +1 -0
- package/examples/dynamic-module-include/sloppy.json +12 -0
- package/examples/dynamic-module-include/src/main.ts +6 -0
- package/examples/dynamic-module-include/src/plugins/alpha.js +3 -0
- package/examples/dynamic-module-include/src/plugins/beta.js +3 -0
- package/examples/ergonomics/README.md +42 -0
- package/examples/ergonomics/app.js +38 -0
- package/examples/framework-controller/README.md +12 -0
- package/examples/framework-controller/app.js +31 -0
- package/examples/framework-di-services/README.md +17 -0
- package/examples/framework-di-services/app.ts +40 -0
- package/examples/framework-explicit-binding/README.md +12 -0
- package/examples/framework-explicit-binding/app.ts +34 -0
- package/examples/framework-hello/README.md +16 -0
- package/examples/framework-hello/app.ts +16 -0
- package/examples/framework-postgres-crud/README.md +73 -0
- package/examples/framework-postgres-crud/app.ts +64 -0
- package/examples/framework-sqlite-crud/README.md +52 -0
- package/examples/framework-sqlite-crud/app.ts +90 -0
- package/examples/framework-sqlite-crud/appsettings.json +11 -0
- package/examples/framework-sqlserver-crud/README.md +73 -0
- package/examples/framework-sqlserver-crud/app.ts +64 -0
- package/examples/framework-validation-errors/README.md +12 -0
- package/examples/framework-validation-errors/app.ts +16 -0
- package/examples/fs-basic/README.md +24 -0
- package/examples/fs-basic/app.js +12 -0
- package/examples/fs-roots-policy/README.md +14 -0
- package/examples/fs-roots-policy/app.js +4 -0
- package/examples/fs-streams/README.md +18 -0
- package/examples/fs-streams/app.js +11 -0
- package/examples/fs-watch/README.md +19 -0
- package/examples/fs-watch/app.js +11 -0
- package/examples/hello/README.md +63 -0
- package/examples/hello/app.js +19 -0
- package/examples/hello-minimal/README.md +51 -0
- package/examples/hello-minimal/sloppy.json +5 -0
- package/examples/hello-minimal/src/main.ts +9 -0
- package/examples/http-client-basic/README.md +11 -0
- package/examples/http-client-basic/app.js +46 -0
- package/examples/http-client-generated/README.md +22 -0
- package/examples/http-client-generated/openapi.json +45 -0
- package/examples/http-client-resilience/README.md +4 -0
- package/examples/http-client-resilience/app.js +38 -0
- package/examples/http-client-runtime-loopback/README.md +24 -0
- package/examples/http-client-testhost/README.md +4 -0
- package/examples/http-client-testhost/app.js +27 -0
- package/examples/http-client-testhost-package-mock/README.md +26 -0
- package/examples/http-client-typed/README.md +5 -0
- package/examples/http-client-typed/app.js +33 -0
- package/examples/modules-api/README.md +30 -0
- package/examples/modules-api/app.js +9 -0
- package/examples/modules-api/modules/routes.js +16 -0
- package/examples/modules-api/sloppy.json +5 -0
- package/examples/modules-basic/README.md +32 -0
- package/examples/modules-basic/app.js +41 -0
- package/examples/net-deadline-cancel/README.md +13 -0
- package/examples/net-deadline-cancel/app.js +34 -0
- package/examples/net-local-ipc/README.md +12 -0
- package/examples/net-local-ipc/app.js +46 -0
- package/examples/net-policy-strict/README.md +12 -0
- package/examples/net-policy-strict/app.js +34 -0
- package/examples/net-tcp-client/README.md +10 -0
- package/examples/net-tcp-client/app.js +23 -0
- package/examples/net-tcp-echo/README.md +11 -0
- package/examples/net-tcp-echo/app.js +45 -0
- package/examples/net-tcp-server/README.md +10 -0
- package/examples/net-tcp-server/app.js +28 -0
- package/examples/node-compat-path-events/README.md +15 -0
- package/examples/node-compat-path-events/sloppy.json +6 -0
- package/examples/node-compat-path-events/src/main.ts +15 -0
- package/examples/ops-compiler/README.md +9 -0
- package/examples/ops-compiler/app.js +26 -0
- package/examples/ops-health-metrics-management/README.md +14 -0
- package/examples/ops-health-metrics-management/app.js +24 -0
- package/examples/orm-basic/README.md +17 -0
- package/examples/orm-basic/app.js +82 -0
- package/examples/orm-cursor-export/README.md +16 -0
- package/examples/orm-cursor-export/app.js +28 -0
- package/examples/orm-migrations/README.md +14 -0
- package/examples/orm-migrations/migrations/.gitkeep +1 -0
- package/examples/orm-migrations/sloppy.json +9 -0
- package/examples/orm-migrations/src/app.ts +34 -0
- package/examples/orm-relations-includes/README.md +10 -0
- package/examples/orm-relations-includes/app.js +47 -0
- package/examples/orm-testservices/README.md +37 -0
- package/examples/orm-testservices/test.mjs +32 -0
- package/examples/os-runtime-api/README.md +11 -0
- package/examples/os-runtime-api/app.js +44 -0
- package/examples/package-zod-like/README.md +28 -0
- package/examples/package-zod-like/fixtures/zod-like/index.js +48 -0
- package/examples/package-zod-like/fixtures/zod-like/package.json +12 -0
- package/examples/package-zod-like/package.json +7 -0
- package/examples/package-zod-like/sloppy.json +6 -0
- package/examples/package-zod-like/src/main.ts +16 -0
- package/examples/postgres-basic/README.md +31 -0
- package/examples/postgres-basic/app.js +50 -0
- package/examples/prealpha-control-plane/README.md +50 -0
- package/examples/prealpha-control-plane/appsettings.Development.json +11 -0
- package/examples/prealpha-control-plane/appsettings.json +15 -0
- package/examples/prealpha-control-plane/sloppy.json +5 -0
- package/examples/prealpha-control-plane/src/db/schema.js +7 -0
- package/examples/prealpha-control-plane/src/db/seed.js +6 -0
- package/examples/prealpha-control-plane/src/main.js +21 -0
- package/examples/prealpha-control-plane/src/routes/apps.js +34 -0
- package/examples/prealpha-control-plane/src/routes/builds.js +25 -0
- package/examples/prealpha-control-plane/src/routes/deployments.js +19 -0
- package/examples/prealpha-control-plane/src/routes/diagnostics.js +11 -0
- package/examples/prealpha-control-plane/src/routes/health.js +27 -0
- package/examples/prealpha-control-plane/src/routes/projects.js +38 -0
- package/examples/prealpha-control-plane/src/services/diagnosticsSink.js +11 -0
- package/examples/prealpha-control-plane/src/services/repositories.js +9 -0
- package/examples/prealpha-control-plane/src/validation/schemas.js +6 -0
- package/examples/program-fs-process/README.md +31 -0
- package/examples/program-fs-process/sloppy.json +9 -0
- package/examples/program-fs-process/src/main.ts +27 -0
- package/examples/program-hello/README.md +32 -0
- package/examples/program-hello/main.ts +8 -0
- package/examples/program-hello/message.ts +1 -0
- package/examples/program-hello/sloppy.json +5 -0
- package/examples/rate-limit-auth/README.md +3 -0
- package/examples/rate-limit-auth/app.js +14 -0
- package/examples/rate-limit-basic/README.md +3 -0
- package/examples/rate-limit-basic/app.js +13 -0
- package/examples/rate-limit-redis/README.md +5 -0
- package/examples/rate-limit-redis/app.js +20 -0
- package/examples/rate-limit-testhost/README.md +4 -0
- package/examples/rate-limit-testhost/app.js +13 -0
- package/examples/rate-limit-websocket/README.md +3 -0
- package/examples/rate-limit-websocket/app.js +16 -0
- package/examples/realtime-auth/README.md +8 -0
- package/examples/realtime-auth/app.js +25 -0
- package/examples/realtime-auth/test.mjs +43 -0
- package/examples/realtime-chat/README.md +8 -0
- package/examples/realtime-chat/app.js +32 -0
- package/examples/realtime-chat/test.mjs +52 -0
- package/examples/realtime-dashboard/README.md +20 -0
- package/examples/realtime-dashboard/app.js +37 -0
- package/examples/realtime-presence/README.md +8 -0
- package/examples/realtime-presence/app.js +32 -0
- package/examples/realtime-presence/test.mjs +50 -0
- package/examples/realtime-testhost/README.md +8 -0
- package/examples/realtime-testhost/test.mjs +31 -0
- package/examples/redis-basic/README.md +17 -0
- package/examples/redis-basic/app.js +39 -0
- package/examples/redis-cache/README.md +14 -0
- package/examples/redis-cache/app.js +36 -0
- package/examples/redis-locks/README.md +13 -0
- package/examples/redis-locks/app.js +49 -0
- package/examples/request-context/README.md +32 -0
- package/examples/request-context/app.js +15 -0
- package/examples/sqlite-basic/README.md +52 -0
- package/examples/sqlite-basic/app.js +56 -0
- package/examples/sqlserver-basic/README.md +36 -0
- package/examples/sqlserver-basic/app.js +59 -0
- package/examples/static-files-basic/README.md +11 -0
- package/examples/static-files-basic/app.js +12 -0
- package/examples/static-files-basic/public/app.js +1 -0
- package/examples/static-files-basic/public/site.css +3 -0
- package/examples/static-files-package/README.md +12 -0
- package/examples/static-files-package/app.js +10 -0
- package/examples/static-files-package/public/index.html +2 -0
- package/examples/static-files-precompressed/README.md +12 -0
- package/examples/static-files-precompressed/app.js +11 -0
- package/examples/static-files-precompressed/public/app.js +1 -0
- package/examples/static-files-precompressed/public/app.js.br +0 -0
- package/examples/static-files-precompressed/public/app.js.gz +0 -0
- package/examples/static-files-spa/README.md +12 -0
- package/examples/static-files-spa/app.js +16 -0
- package/examples/static-files-spa/dist/assets/app.js +1 -0
- package/examples/static-files-spa/dist/index.html +4 -0
- package/examples/static-files-testhost/README.md +8 -0
- package/examples/static-files-testhost/app.js +13 -0
- package/examples/static-files-testhost/public/app.js +1 -0
- package/examples/static-files-testhost/public/app.js.gz +0 -0
- package/examples/static-files-testhost/test.mjs +38 -0
- package/examples/testhost-basic/README.md +26 -0
- package/examples/testhost-db/README.md +31 -0
- package/examples/testservices-postgres/README.md +68 -0
- package/examples/testservices-redis/README.md +71 -0
- package/examples/testservices-sqlserver/README.md +75 -0
- package/examples/time-basic/README.md +18 -0
- package/examples/time-basic/app.js +12 -0
- package/examples/time-deadline-cancellation/README.md +11 -0
- package/examples/time-deadline-cancellation/app.js +27 -0
- package/examples/time-fake-clock/README.md +14 -0
- package/examples/time-fake-clock/app.js +25 -0
- package/examples/time-interval-schedule/README.md +13 -0
- package/examples/time-interval-schedule/app.js +60 -0
- package/examples/users-api-sqlite/README.md +74 -0
- package/examples/users-api-sqlite/app.js +11 -0
- package/examples/users-api-sqlite/appsettings.Development.json +11 -0
- package/examples/users-api-sqlite/appsettings.json +11 -0
- package/examples/users-api-sqlite/modules/users.js +40 -0
- package/examples/users-api-sqlite/sloppy.json +5 -0
- package/examples/validation-errors/README.md +36 -0
- package/examples/validation-errors/app.js +14 -0
- package/examples/validation-errors/invalid-user.http +6 -0
- package/examples/validation-errors/sloppy.json +5 -0
- package/examples/web-dynamic-routes/README.md +17 -0
- package/examples/web-dynamic-routes/app.ts +27 -0
- package/examples/webhooks-basic/README.md +11 -0
- package/examples/webhooks-basic/app.js +48 -0
- package/examples/websocket-auth/README.md +8 -0
- package/examples/websocket-auth/app.js +16 -0
- package/examples/websocket-echo/README.md +9 -0
- package/examples/websocket-echo/app.js +36 -0
- package/examples/websocket-json-schema/README.md +5 -0
- package/examples/websocket-json-schema/app.js +25 -0
- package/examples/websocket-testhost/README.md +11 -0
- package/examples/websocket-testhost/test.mjs +49 -0
- package/examples/workers-background-service/README.md +7 -0
- package/examples/workers-background-service/app.js +16 -0
- package/examples/workers-js-isolate/README.md +8 -0
- package/examples/workers-js-isolate/app.js +19 -0
- package/examples/workers-js-isolate/workers/parser.ts +11 -0
- package/examples/workers-shutdown/README.md +6 -0
- package/examples/workers-shutdown/app.js +26 -0
- package/examples/workers-workerpool/README.md +6 -0
- package/examples/workers-workerpool/app.js +23 -0
- package/examples/workers-workqueue/README.md +8 -0
- package/examples/workers-workqueue/app.js +24 -0
- package/manifest.json +59 -0
- package/package.json +31 -0
- package/stdlib/sloppy/README.md +177 -0
- package/stdlib/sloppy/app.js +2142 -0
- package/stdlib/sloppy/auth.js +1813 -0
- package/stdlib/sloppy/bootstrap.manifest.json +83 -0
- package/stdlib/sloppy/cache.js +1542 -0
- package/stdlib/sloppy/codec.js +1153 -0
- package/stdlib/sloppy/config.js +61 -0
- package/stdlib/sloppy/crypto.js +312 -0
- package/stdlib/sloppy/data.js +2945 -0
- package/stdlib/sloppy/ffi.js +185 -0
- package/stdlib/sloppy/fs.js +795 -0
- package/stdlib/sloppy/health.js +603 -0
- package/stdlib/sloppy/http.js +1595 -0
- package/stdlib/sloppy/index.js +59 -0
- package/stdlib/sloppy/internal/bytes.js +31 -0
- package/stdlib/sloppy/internal/capabilities.js +155 -0
- package/stdlib/sloppy/internal/config.js +640 -0
- package/stdlib/sloppy/internal/disposable.js +31 -0
- package/stdlib/sloppy/internal/headers.js +63 -0
- package/stdlib/sloppy/internal/intrinsics.js +2 -0
- package/stdlib/sloppy/internal/json.js +20 -0
- package/stdlib/sloppy/internal/logging.js +278 -0
- package/stdlib/sloppy/internal/modules.js +405 -0
- package/stdlib/sloppy/internal/redaction.js +87 -0
- package/stdlib/sloppy/internal/routes.js +2279 -0
- package/stdlib/sloppy/internal/runtime-classic.js +19837 -0
- package/stdlib/sloppy/internal/services.js +690 -0
- package/stdlib/sloppy/internal/shared.js +32 -0
- package/stdlib/sloppy/internal/testhost-diagnostics.js +88 -0
- package/stdlib/sloppy/internal/testhost-http-server.js +238 -0
- package/stdlib/sloppy/internal/testhost-http.js +118 -0
- package/stdlib/sloppy/internal/testhost-loopback.js +50 -0
- package/stdlib/sloppy/internal/testservices-docker.js +154 -0
- package/stdlib/sloppy/internal/validation.js +117 -0
- package/stdlib/sloppy/metrics.js +427 -0
- package/stdlib/sloppy/net.js +5208 -0
- package/stdlib/sloppy/node/assert/strict.js +39 -0
- package/stdlib/sloppy/node/assert.js +228 -0
- package/stdlib/sloppy/node/buffer.js +247 -0
- package/stdlib/sloppy/node/console.js +33 -0
- package/stdlib/sloppy/node/constants.js +9 -0
- package/stdlib/sloppy/node/crypto.js +89 -0
- package/stdlib/sloppy/node/diagnostics_channel.js +41 -0
- package/stdlib/sloppy/node/events.js +113 -0
- package/stdlib/sloppy/node/fs/promises.js +27 -0
- package/stdlib/sloppy/node/fs.js +280 -0
- package/stdlib/sloppy/node/http.js +11 -0
- package/stdlib/sloppy/node/https.js +11 -0
- package/stdlib/sloppy/node/module.js +40 -0
- package/stdlib/sloppy/node/os.js +22 -0
- package/stdlib/sloppy/node/path.js +78 -0
- package/stdlib/sloppy/node/perf_hooks.js +12 -0
- package/stdlib/sloppy/node/process.js +129 -0
- package/stdlib/sloppy/node/querystring.js +21 -0
- package/stdlib/sloppy/node/stream/promises.js +3 -0
- package/stdlib/sloppy/node/stream.js +132 -0
- package/stdlib/sloppy/node/string_decoder.js +23 -0
- package/stdlib/sloppy/node/timers.js +26 -0
- package/stdlib/sloppy/node/tty.js +18 -0
- package/stdlib/sloppy/node/url.js +17 -0
- package/stdlib/sloppy/node/util.js +95 -0
- package/stdlib/sloppy/node/zlib.js +72 -0
- package/stdlib/sloppy/orm.js +2188 -0
- package/stdlib/sloppy/os.js +580 -0
- package/stdlib/sloppy/problem-details.js +29 -0
- package/stdlib/sloppy/providers/sqlite.js +26 -0
- package/stdlib/sloppy/rate-limit.js +856 -0
- package/stdlib/sloppy/realtime.js +1508 -0
- package/stdlib/sloppy/redis.js +1272 -0
- package/stdlib/sloppy/request-id.js +184 -0
- package/stdlib/sloppy/request-logging.js +101 -0
- package/stdlib/sloppy/results.js +933 -0
- package/stdlib/sloppy/schema.js +546 -0
- package/stdlib/sloppy/testing.js +4081 -0
- package/stdlib/sloppy/testservices.js +1041 -0
- package/stdlib/sloppy/time.js +894 -0
- package/stdlib/sloppy/webhooks.js +1330 -0
- package/stdlib/sloppy/workers.js +986 -0
- package/templates/api/README.md +82 -0
- package/templates/api/appsettings.Development.json +14 -0
- package/templates/api/appsettings.json +13 -0
- package/templates/api/data/.gitkeep +1 -0
- package/templates/api/gitignore +4 -0
- package/templates/api/migrations/0001_create_users.sql +1 -0
- package/templates/api/package.json +16 -0
- package/templates/api/public/hello.txt +1 -0
- package/templates/api/sloppy.json +14 -0
- package/templates/api/src/config.ts +1 -0
- package/templates/api/src/db/migrate.ts +14 -0
- package/templates/api/src/db/schema.ts +4 -0
- package/templates/api/src/db/usersRepository.ts +23 -0
- package/templates/api/src/main.ts +18 -0
- package/templates/api/src/models/user.ts +7 -0
- package/templates/api/src/routes/health.ts +20 -0
- package/templates/api/src/routes/users.ts +40 -0
- package/templates/api/src/services/usersService.ts +21 -0
- package/templates/api/tsconfig.json +15 -0
- package/templates/cli/README.md +16 -0
- package/templates/cli/gitignore +2 -0
- package/templates/cli/package.json +13 -0
- package/templates/cli/sloppy.json +6 -0
- package/templates/cli/src/commands/echo.ts +9 -0
- package/templates/cli/src/commands/inspect.ts +20 -0
- package/templates/cli/src/main.ts +50 -0
- package/templates/cli/tsconfig.json +15 -0
- package/templates/minimal-api/README.md +14 -0
- package/templates/minimal-api/gitignore +3 -0
- package/templates/minimal-api/package.json +14 -0
- package/templates/minimal-api/sloppy.json +5 -0
- package/templates/minimal-api/src/main.ts +9 -0
- package/templates/minimal-api/tsconfig.json +15 -0
- package/templates/node-compat/README.md +40 -0
- package/templates/node-compat/gitignore +2 -0
- package/templates/node-compat/package.json +11 -0
- package/templates/node-compat/sloppy.json +6 -0
- package/templates/node-compat/src/main.ts +40 -0
- package/templates/package-api/README.md +44 -0
- package/templates/package-api/fixtures/validator-lite/index.js +7 -0
- package/templates/package-api/fixtures/validator-lite/package.json +6 -0
- package/templates/package-api/gitignore +3 -0
- package/templates/package-api/package.json +17 -0
- package/templates/package-api/sloppy.json +5 -0
- package/templates/package-api/src/main.ts +10 -0
- package/templates/package-api/src/routes/health.ts +5 -0
- package/templates/package-api/src/routes/users.ts +12 -0
- package/templates/package-api/tsconfig.json +15 -0
- package/templates/program/README.md +12 -0
- package/templates/program/gitignore +1 -0
- package/templates/program/package.json +10 -0
- package/templates/program/sloppy.json +6 -0
- package/templates/program/src/main.ts +9 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Realtime, Sloppy, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
export const Chat = Realtime.channel("chat", {
|
|
4
|
+
client: {
|
|
5
|
+
sendMessage: schema.object({
|
|
6
|
+
roomId: schema.string(),
|
|
7
|
+
text: schema.string().maxLength(1000),
|
|
8
|
+
}),
|
|
9
|
+
},
|
|
10
|
+
server: {
|
|
11
|
+
messageCreated: schema.object({
|
|
12
|
+
roomId: schema.string(),
|
|
13
|
+
text: schema.string(),
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const app = Sloppy.create();
|
|
19
|
+
|
|
20
|
+
app.realtime("/rooms/{roomId}", Chat, async (ctx) => {
|
|
21
|
+
await ctx.accept();
|
|
22
|
+
await ctx.groups.join(`room:${ctx.params.roomId}`);
|
|
23
|
+
|
|
24
|
+
ctx.on("sendMessage", async (input) => {
|
|
25
|
+
await ctx.group(`room:${ctx.params.roomId}`).broadcast("messageCreated", {
|
|
26
|
+
roomId: ctx.params.roomId,
|
|
27
|
+
text: input.text,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}).requiresAuth().requiresScope("chat");
|
|
31
|
+
|
|
32
|
+
export default app;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
|
|
3
|
+
import { Realtime, Sloppy, TestHost, schema } from "sloppy";
|
|
4
|
+
|
|
5
|
+
const Chat = Realtime.channel("chat", {
|
|
6
|
+
client: {
|
|
7
|
+
sendMessage: schema.object({
|
|
8
|
+
roomId: schema.string(),
|
|
9
|
+
text: schema.string().maxLength(1000),
|
|
10
|
+
}),
|
|
11
|
+
},
|
|
12
|
+
server: {
|
|
13
|
+
messageCreated: schema.object({
|
|
14
|
+
roomId: schema.string(),
|
|
15
|
+
text: schema.string(),
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const app = Sloppy.create();
|
|
21
|
+
|
|
22
|
+
app.realtime("/rooms/{roomId}", Chat, async (ctx) => {
|
|
23
|
+
await ctx.accept();
|
|
24
|
+
await ctx.groups.join(`room:${ctx.params.roomId}`);
|
|
25
|
+
ctx.on("sendMessage", async (input) => {
|
|
26
|
+
await ctx.group(`room:${ctx.params.roomId}`).broadcast("messageCreated", {
|
|
27
|
+
roomId: ctx.params.roomId,
|
|
28
|
+
text: input.text,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}).requiresAuth().requiresScope("chat");
|
|
32
|
+
|
|
33
|
+
const host = await TestHost.create(app);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const alice = await host.realtime("/rooms/r1", Chat)
|
|
37
|
+
.asUser({ sub: "alice", scopes: ["chat"] })
|
|
38
|
+
.connect();
|
|
39
|
+
const bob = await host.realtime("/rooms/r1", Chat)
|
|
40
|
+
.asUser({ sub: "bob", scopes: ["chat"] })
|
|
41
|
+
.connect();
|
|
42
|
+
|
|
43
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
44
|
+
await alice.send("sendMessage", { roomId: "r1", text: "hello" });
|
|
45
|
+
await bob.expect("messageCreated", { roomId: "r1", text: "hello" });
|
|
46
|
+
|
|
47
|
+
assert.equal(bob.closed, false);
|
|
48
|
+
await alice.close();
|
|
49
|
+
await bob.close();
|
|
50
|
+
} finally {
|
|
51
|
+
await host.close();
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Realtime Dashboard
|
|
2
|
+
|
|
3
|
+
This example shows the current alpha realtime API shape:
|
|
4
|
+
|
|
5
|
+
- `app.sse("/events", ...)` records and emits an SSE route.
|
|
6
|
+
- `app.ws("/socket", ...)` records WebSocket route intent and executes through
|
|
7
|
+
native HTTP/1.1 Upgrade in V8-backed `sloppy run`.
|
|
8
|
+
- `Realtime.hub("dashboard")` is an in-process helper, not an external broker.
|
|
9
|
+
|
|
10
|
+
Build and inspect the route metadata:
|
|
11
|
+
|
|
12
|
+
```powershell
|
|
13
|
+
sloppy build examples/realtime-dashboard/app.js --out .sloppy
|
|
14
|
+
sloppy routes .sloppy
|
|
15
|
+
sloppy openapi .sloppy
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Handler execution through `sloppy run --once` requires a V8-enabled build.
|
|
19
|
+
The SSE route uses the bounded `Results.stream` descriptor path; it does not
|
|
20
|
+
claim production socket backpressure or incremental live push yet.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const app = Sloppy.create();
|
|
4
|
+
|
|
5
|
+
app.get("/", () => Results.html(`<!doctype html>
|
|
6
|
+
<html lang="en">
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="utf-8">
|
|
9
|
+
<title>Sloppy Realtime Dashboard</title>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<h1>Sloppy Realtime Dashboard</h1>
|
|
13
|
+
<pre id="events"></pre>
|
|
14
|
+
<script>
|
|
15
|
+
const output = document.getElementById("events");
|
|
16
|
+
const events = new EventSource("/events");
|
|
17
|
+
events.addEventListener("status", (event) => {
|
|
18
|
+
output.textContent += event.data + "\\n";
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
</body>
|
|
22
|
+
</html>`));
|
|
23
|
+
|
|
24
|
+
app.sse("/events", async (ctx, stream) => {
|
|
25
|
+
stream.comment("dashboard connected");
|
|
26
|
+
stream.event("status", {
|
|
27
|
+
path: ctx.request.path,
|
|
28
|
+
state: "ready",
|
|
29
|
+
});
|
|
30
|
+
stream.heartbeat();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
app.ws("/socket", async (ctx, socket) => {
|
|
34
|
+
await socket.sendJson({ state: "ready" });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default app;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Realtime, Sloppy, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
export const PresenceChannel = Realtime.channel("presence", {
|
|
4
|
+
client: {
|
|
5
|
+
setStatus: schema.object({
|
|
6
|
+
status: schema.string(),
|
|
7
|
+
}),
|
|
8
|
+
list: schema.object({}),
|
|
9
|
+
},
|
|
10
|
+
server: {
|
|
11
|
+
presenceCount: schema.object({
|
|
12
|
+
count: schema.int(),
|
|
13
|
+
}),
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const app = Sloppy.create();
|
|
18
|
+
|
|
19
|
+
app.realtime("/presence/{roomId}", PresenceChannel, async (ctx) => {
|
|
20
|
+
await ctx.accept();
|
|
21
|
+
await ctx.groups.join(`room:${ctx.params.roomId}`);
|
|
22
|
+
|
|
23
|
+
ctx.on("setStatus", async (input) => {
|
|
24
|
+
await ctx.presence.set({ metadata: { status: input.status } });
|
|
25
|
+
});
|
|
26
|
+
ctx.on("list", async () => {
|
|
27
|
+
const users = await ctx.presence.inGroup(`room:${ctx.params.roomId}`);
|
|
28
|
+
await ctx.send("presenceCount", { count: users.length });
|
|
29
|
+
});
|
|
30
|
+
}, { presence: true }).requiresAuth();
|
|
31
|
+
|
|
32
|
+
export default app;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Realtime, Sloppy, TestHost, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const PresenceChannel = Realtime.channel("presence", {
|
|
4
|
+
client: {
|
|
5
|
+
setStatus: schema.object({
|
|
6
|
+
status: schema.string(),
|
|
7
|
+
}),
|
|
8
|
+
list: schema.object({}),
|
|
9
|
+
},
|
|
10
|
+
server: {
|
|
11
|
+
presenceCount: schema.object({
|
|
12
|
+
count: schema.int(),
|
|
13
|
+
}),
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const app = Sloppy.create();
|
|
18
|
+
|
|
19
|
+
app.realtime("/presence/{roomId}", PresenceChannel, async (ctx) => {
|
|
20
|
+
await ctx.accept();
|
|
21
|
+
await ctx.groups.join(`room:${ctx.params.roomId}`);
|
|
22
|
+
ctx.on("setStatus", async (input) => {
|
|
23
|
+
await ctx.presence.set({ metadata: { status: input.status } });
|
|
24
|
+
});
|
|
25
|
+
ctx.on("list", async () => {
|
|
26
|
+
const users = await ctx.presence.inGroup(`room:${ctx.params.roomId}`);
|
|
27
|
+
await ctx.send("presenceCount", { count: users.length });
|
|
28
|
+
});
|
|
29
|
+
}, { presence: true }).requiresAuth();
|
|
30
|
+
|
|
31
|
+
const host = await TestHost.create(app);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const alice = await host.realtime("/presence/r1", PresenceChannel)
|
|
35
|
+
.asUser({ sub: "alice" })
|
|
36
|
+
.connect();
|
|
37
|
+
const bob = await host.realtime("/presence/r1", PresenceChannel)
|
|
38
|
+
.asUser({ sub: "bob" })
|
|
39
|
+
.connect();
|
|
40
|
+
|
|
41
|
+
await alice.send("setStatus", { status: "online" });
|
|
42
|
+
await bob.send("setStatus", { status: "online" });
|
|
43
|
+
await bob.send("list", {});
|
|
44
|
+
await bob.expect("presenceCount", { count: 2 });
|
|
45
|
+
|
|
46
|
+
await alice.close();
|
|
47
|
+
await bob.close();
|
|
48
|
+
} finally {
|
|
49
|
+
await host.close();
|
|
50
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Realtime, Sloppy, TestHost, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const Echo = Realtime.channel("echo", {
|
|
4
|
+
client: {
|
|
5
|
+
echo: schema.object({ text: schema.string() }),
|
|
6
|
+
},
|
|
7
|
+
server: {
|
|
8
|
+
echoed: schema.object({ text: schema.string() }),
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const app = Sloppy.create();
|
|
13
|
+
|
|
14
|
+
app.realtime("/echo", Echo, async (ctx) => {
|
|
15
|
+
await ctx.accept();
|
|
16
|
+
ctx.on("echo", async (input) => {
|
|
17
|
+
await ctx.send("echoed", input);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const host = await TestHost.create(app);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const client = await host.realtime("/echo", Echo).connect();
|
|
25
|
+
|
|
26
|
+
await client.send("echo", { text: "hello" });
|
|
27
|
+
await client.expect("echoed", { text: "hello" });
|
|
28
|
+
await client.close();
|
|
29
|
+
} finally {
|
|
30
|
+
await host.close();
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Redis Basic
|
|
2
|
+
|
|
3
|
+
This is an API-shape example for the first-party Redis client.
|
|
4
|
+
|
|
5
|
+
It shows Redis client creation, JSON/text/bytes values, scripts, diagnostics,
|
|
6
|
+
health, and bounded pooling. It does not contact Redis unless the exported
|
|
7
|
+
functions are called in a runtime with the Sloppy network bridge and a Redis
|
|
8
|
+
server.
|
|
9
|
+
|
|
10
|
+
Current limitations:
|
|
11
|
+
|
|
12
|
+
- requires a Redis server such as `TestServices.redis()` or a configured
|
|
13
|
+
`REDIS_URL`;
|
|
14
|
+
- requires the Sloppy outbound network bridge;
|
|
15
|
+
- `rediss://` also requires the outbound TLS bridge;
|
|
16
|
+
- no npm Redis client;
|
|
17
|
+
- no cluster, sentinel, pub/sub, streams, or modules contract.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Redis, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const userSchema = schema.object({
|
|
4
|
+
id: schema.number(),
|
|
5
|
+
email: schema.string().email(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
function createRedis(url = "redis://127.0.0.1:6379/0") {
|
|
9
|
+
return Redis.client("main", {
|
|
10
|
+
url,
|
|
11
|
+
commandTimeoutMs: 1000,
|
|
12
|
+
pool: {
|
|
13
|
+
maxConnections: 4,
|
|
14
|
+
pendingQueueLimit: 16,
|
|
15
|
+
acquireTimeoutMs: 1000,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function writeUser(redis, user) {
|
|
21
|
+
await redis.set(`users:${user.id}`, user, { ttlMs: 60_000 });
|
|
22
|
+
return await redis.get(`users:${user.id}`, userSchema);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function writeStatus(redis) {
|
|
26
|
+
await redis.setText("status", "ready", { ttlMs: 5000 });
|
|
27
|
+
return await redis.getText("status");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function writeBytes(redis, bytes) {
|
|
31
|
+
await redis.setBytes("payload", bytes, { ttlMs: 5000 });
|
|
32
|
+
return await redis.getBytes("payload");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function deleteWithScript(redis, key) {
|
|
36
|
+
return await redis.script("return redis.call('del', KEYS[1])", [key]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { createRedis, deleteWithScript, writeBytes, writeStatus, writeUser };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Redis Cache
|
|
2
|
+
|
|
3
|
+
This is an API-shape example for `Cache.redis(...)`.
|
|
4
|
+
|
|
5
|
+
It shows a Redis-backed cache, tags, `getOrCreate`, health, stats, and app-host
|
|
6
|
+
service registration. It does not provide an in-memory fallback when Redis is
|
|
7
|
+
unavailable.
|
|
8
|
+
|
|
9
|
+
Current limitations:
|
|
10
|
+
|
|
11
|
+
- requires Redis and the Sloppy outbound network bridge when executed;
|
|
12
|
+
- tag invalidation is Redis-set based, not pub/sub based;
|
|
13
|
+
- `getOrCreate` coalesces same-process misses only;
|
|
14
|
+
- cluster, sentinel, and Redis streams are outside this cache contract.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Cache, Redis, Results, Sloppy } from "sloppy";
|
|
2
|
+
|
|
3
|
+
function createCache(url = "redis://127.0.0.1:6379/0") {
|
|
4
|
+
const redis = Redis.client("main", { url });
|
|
5
|
+
return Cache.redis(redis, {
|
|
6
|
+
name: "default",
|
|
7
|
+
prefix: "example:",
|
|
8
|
+
ttlMs: 60_000,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function loadSettings(cache) {
|
|
13
|
+
return await cache.getOrCreate("settings", async () => ({
|
|
14
|
+
theme: "dark",
|
|
15
|
+
updatedAt: "2026-05-13T00:00:00.000Z",
|
|
16
|
+
}), {
|
|
17
|
+
ttlMs: 30_000,
|
|
18
|
+
tags: ["settings"],
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function createApp(cache) {
|
|
23
|
+
const app = Sloppy.create();
|
|
24
|
+
app.services.addCache(cache);
|
|
25
|
+
app.get("/settings", async (ctx) => {
|
|
26
|
+
const provider = ctx.services.get("cache.default");
|
|
27
|
+
return Results.json(await loadSettings(provider));
|
|
28
|
+
});
|
|
29
|
+
app.get("/health/redis-cache", async (ctx) => {
|
|
30
|
+
const provider = ctx.services.get("cache.default");
|
|
31
|
+
return Results.json(await provider.health());
|
|
32
|
+
});
|
|
33
|
+
return app;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { createApp, createCache, loadSettings };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Redis Locks
|
|
2
|
+
|
|
3
|
+
This is an API-shape example for `Redis.locks(...)`.
|
|
4
|
+
|
|
5
|
+
It shows a single-key Redis lease with bounded acquisition, explicit TTL, lease
|
|
6
|
+
extension, and release through async disposal.
|
|
7
|
+
|
|
8
|
+
Current limitations:
|
|
9
|
+
|
|
10
|
+
- requires Redis and the Sloppy outbound network bridge when executed;
|
|
11
|
+
- locks are single Redis-key leases, not Redlock or multi-node consensus;
|
|
12
|
+
- owner tokens are internal and redacted;
|
|
13
|
+
- cluster and sentinel behavior are not claimed.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Redis } from "sloppy";
|
|
2
|
+
|
|
3
|
+
function createLocks(url = "redis://127.0.0.1:6379/0") {
|
|
4
|
+
const redis = Redis.client("locks", { url });
|
|
5
|
+
return Redis.locks(redis, {
|
|
6
|
+
prefix: "example:locks:",
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function runExclusive(locks, name, operation) {
|
|
11
|
+
const lease = await locks.acquire(name, {
|
|
12
|
+
ttlMs: 30_000,
|
|
13
|
+
waitTimeoutMs: 5000,
|
|
14
|
+
retryDelayMs: 50,
|
|
15
|
+
});
|
|
16
|
+
let finished = false;
|
|
17
|
+
let timer;
|
|
18
|
+
let resolveExtender;
|
|
19
|
+
const extender = new Promise((resolve) => {
|
|
20
|
+
resolveExtender = resolve;
|
|
21
|
+
const tick = async () => {
|
|
22
|
+
if (finished) {
|
|
23
|
+
resolve();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await lease.extend(30_000);
|
|
28
|
+
} finally {
|
|
29
|
+
if (finished) {
|
|
30
|
+
resolve();
|
|
31
|
+
} else {
|
|
32
|
+
timer = setTimeout(tick, 15_000);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
timer = setTimeout(tick, 15_000);
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
return await operation();
|
|
40
|
+
} finally {
|
|
41
|
+
finished = true;
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
resolveExtender();
|
|
44
|
+
await extender.catch(() => {});
|
|
45
|
+
await lease.dispose();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { createLocks, runExclusive };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Request Context Example
|
|
2
|
+
|
|
3
|
+
This is a compiler-input example for the dev-only V8 `sloppy run --artifacts` path.
|
|
4
|
+
This example demonstrates the current request context shape:
|
|
5
|
+
|
|
6
|
+
- `route.id` comes from `/users/{id:int}`;
|
|
7
|
+
- `query.q` comes from the query string;
|
|
8
|
+
- `request.method` is the parsed HTTP method;
|
|
9
|
+
- `request.path` comes from the parsed request target.
|
|
10
|
+
- `request.rawTarget` preserves the original target string.
|
|
11
|
+
|
|
12
|
+
Build artifacts:
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
cargo run --manifest-path compiler/Cargo.toml -- build examples/request-context/app.js --out .sloppy-test
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run one deterministic request with a V8-enabled build:
|
|
19
|
+
|
|
20
|
+
```powershell
|
|
21
|
+
.\build\windows-relwithdebinfo\sloppy.exe run --artifacts .sloppy-test --once GET /users/123?q=abc
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This is still dev-only. Route `{id:int}` validates the matched path segment, but the handler
|
|
25
|
+
receives `route.id` as the string `"123"`. Query values are strings, repeated query keys use
|
|
26
|
+
last-wins behavior, and `%XX`/`+` query decoding is supported.
|
|
27
|
+
|
|
28
|
+
Headers and JSON/text/byte body helpers exist in the broader request-context runtime and
|
|
29
|
+
app test host lanes. This small example intentionally stays on fields that `sloppy run
|
|
30
|
+
--once` can exercise from only a method and target. Middleware, streaming request APIs,
|
|
31
|
+
cookies, and content negotiation are not covered by this request-context
|
|
32
|
+
example.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const app = Sloppy.create();
|
|
4
|
+
|
|
5
|
+
app.mapGet("/users/{id:int}", (ctx) => {
|
|
6
|
+
return Results.json({
|
|
7
|
+
id: ctx.route.id,
|
|
8
|
+
q: ctx.query.q,
|
|
9
|
+
method: ctx.request.method,
|
|
10
|
+
path: ctx.request.path,
|
|
11
|
+
rawTarget: ctx.request.rawTarget,
|
|
12
|
+
});
|
|
13
|
+
}).withName("Users.Get");
|
|
14
|
+
|
|
15
|
+
export default app;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# SQLite Basic Example
|
|
2
|
+
|
|
3
|
+
This is a SQLite provider API-shape example with native provider coverage in C tests and a
|
|
4
|
+
separate V8-gated SQLite runtime fixture.
|
|
5
|
+
|
|
6
|
+
This example shows the intended bootstrap shape for registering SQLite as `data.main`,
|
|
7
|
+
using in-memory configuration, and writing query-template-based route code.
|
|
8
|
+
|
|
9
|
+
What works today:
|
|
10
|
+
|
|
11
|
+
- the native C SQLite provider opens `:memory:` databases in tests;
|
|
12
|
+
- native C tests cover `exec`, `query`, `queryOne`, parameter binding, transactions, and
|
|
13
|
+
diagnostics;
|
|
14
|
+
- V8-enabled runtime tests cover the real SQLite JS-to-native bridge through
|
|
15
|
+
`data.sqlite("main")`, provider metadata, the native capability hook, and safe resource
|
|
16
|
+
IDs;
|
|
17
|
+
- `Sloppy.module("data.sqlite").capabilities(...)` declares SQLite database metadata;
|
|
18
|
+
- `data.sqlite.open({ database: ":memory:", capability: "data.main" })` opens a native
|
|
19
|
+
SQLite connection only when the V8 runtime installs the SQLite bridge intrinsics and has
|
|
20
|
+
Plan-backed capability metadata;
|
|
21
|
+
- `data.sqlite.open({ database: ":memory:", capability: "data.main", access: "readwrite" })`
|
|
22
|
+
is the canonical explicit shape. `path` remains only a transitional alias for
|
|
23
|
+
`database`, and unsupported option fields fail before provider work;
|
|
24
|
+
- access is enforced twice: against Plan capability metadata before open/use, and against
|
|
25
|
+
the opened resource mode before every operation. `read` permits `query`/`queryOne`,
|
|
26
|
+
`write` permits `exec`/transaction writes, and `readwrite` permits both;
|
|
27
|
+
- result mapping is small and stable: `NULL` becomes `null`, integers/floats become
|
|
28
|
+
JavaScript numbers, text becomes strings, blobs become `Uint8Array`, `queryOne` returns a
|
|
29
|
+
row or `null`, and duplicate column names should be avoided with SQL aliases;
|
|
30
|
+
- `db.transaction(callback)` commits when the callback succeeds, rolls back when it throws
|
|
31
|
+
or rejects, rejects nested transactions, and rejects transaction-object use after
|
|
32
|
+
commit/rollback on the current synchronous SQLite bridge;
|
|
33
|
+
- query templates lower to `?` placeholders without interpolating values.
|
|
34
|
+
- public prepared statement handles are intentionally absent; SQLite prepare/bind/step/
|
|
35
|
+
finalize remains internal to `exec`, `query`, `queryOne`, and transaction operations.
|
|
36
|
+
|
|
37
|
+
Current product state:
|
|
38
|
+
|
|
39
|
+
- This source-stdlib example is a checked-in API-shape fixture.
|
|
40
|
+
- `sloppy run --artifacts` currently runs emitted artifacts such as
|
|
41
|
+
`examples/compiler-hello`.
|
|
42
|
+
- `sloppyc` compilation and `app.plan.json` emission for this SQLite source
|
|
43
|
+
shape are planned separately.
|
|
44
|
+
- The bounded `sloppy run` path currently loads generated artifacts, not this
|
|
45
|
+
source-stdlib SQLite example directly.
|
|
46
|
+
- Executable SQLite runtime coverage currently lives in the internal V8-gated artifact
|
|
47
|
+
fixture.
|
|
48
|
+
- PostgreSQL and SQL Server providers are covered by their own examples and tests.
|
|
49
|
+
- PostgreSQL has its own V8-gated true-async bridge and live PostgreSQL checks.
|
|
50
|
+
- ORM, migrations, expanded pooling, public prepared statement handles, and mid-operation
|
|
51
|
+
interruption are separate SQLite/provider features.
|
|
52
|
+
- Bare `"sloppy"` imports are the current source shape for this example.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Sloppy, data, Results, sql } from "sloppy";
|
|
2
|
+
|
|
3
|
+
export const SqliteModule = Sloppy.module("data.sqlite")
|
|
4
|
+
.capabilities((caps) => {
|
|
5
|
+
caps.addDatabase("data.main", {
|
|
6
|
+
provider: "sqlite",
|
|
7
|
+
database: ":memory:",
|
|
8
|
+
access: "readwrite",
|
|
9
|
+
});
|
|
10
|
+
})
|
|
11
|
+
.services((services) => {
|
|
12
|
+
services.addSingleton("data.main", () => data.sqlite.open({
|
|
13
|
+
database: ":memory:",
|
|
14
|
+
capability: "data.main",
|
|
15
|
+
access: "readwrite",
|
|
16
|
+
}));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const UsersModule = Sloppy.module("users")
|
|
20
|
+
.dependsOn("data.sqlite")
|
|
21
|
+
.routes((app) => {
|
|
22
|
+
app.mapGet("/users/{id:int}", async ({ route, services }) => {
|
|
23
|
+
const db = services.get("data.main");
|
|
24
|
+
|
|
25
|
+
await db.exec`
|
|
26
|
+
create table if not exists users (id integer primary key, name text not null)
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
await db.transaction(async (tx) => {
|
|
30
|
+
await tx.exec`
|
|
31
|
+
insert or ignore into users (id, name) values (${1}, ${"Ada"})
|
|
32
|
+
`;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const user = await db.queryOne`
|
|
36
|
+
select id, name
|
|
37
|
+
from users
|
|
38
|
+
where id = ${route.id ?? 1}
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
return user ? Results.ok(user) : Results.notFound();
|
|
42
|
+
})
|
|
43
|
+
.withName("Users.Get");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export const lowered = sql`select name from users where id = ${1}`;
|
|
47
|
+
|
|
48
|
+
const builder = Sloppy.createBuilder();
|
|
49
|
+
|
|
50
|
+
builder
|
|
51
|
+
.addModule(SqliteModule)
|
|
52
|
+
.addModule(UsersModule);
|
|
53
|
+
|
|
54
|
+
const app = builder.build();
|
|
55
|
+
|
|
56
|
+
export default app;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# SQL Server Basic Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates SQL Server provider wiring: module/capability setup,
|
|
4
|
+
ODBC `?` query-template lowering, a bounded pool option, transaction usage, and the
|
|
5
|
+
SQL Server doctor helper shape.
|
|
6
|
+
|
|
7
|
+
Current limitations:
|
|
8
|
+
|
|
9
|
+
- requires SQL Server and Microsoft ODBC Driver 18 for SQL Server, or
|
|
10
|
+
Microsoft ODBC Driver 17 for SQL Server;
|
|
11
|
+
- this example requires SQL Server, Microsoft ODBC Driver 17 or 18, and a live
|
|
12
|
+
connection string;
|
|
13
|
+
- normal Sloppy apps, the Quickstart, SQLite, templates, and package support do
|
|
14
|
+
not require SQL Server or ODBC;
|
|
15
|
+
- uses true-async ODBC connection/statement mode through the V8 provider bridge when the
|
|
16
|
+
configured driver supports async completion;
|
|
17
|
+
- set `SLOPPY_SQLSERVER_TEST_CONNECTION_STRING` or equivalent config for live use;
|
|
18
|
+
- not part of default CI live database execution;
|
|
19
|
+
- no migrations;
|
|
20
|
+
- no ORM;
|
|
21
|
+
- pooling is bounded and provider-owned, not an ORM/session abstraction;
|
|
22
|
+
- unsupported drivers report SQL Server async-driver unavailability instead of falling
|
|
23
|
+
back to a blocking pool and calling it true async;
|
|
24
|
+
- TLS/auth hardening, table-valued parameters, bulk copy, richer date/time mapping, and
|
|
25
|
+
advanced pooling policies remain separate provider-hardening work.
|
|
26
|
+
|
|
27
|
+
Native live provider tests are opt-in:
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
$env:SLOPPY_SQLSERVER_TEST_CONNECTION_STRING="<redacted SQL Server connection string>"
|
|
31
|
+
.\tools\windows\test-live-sqlserver.ps1
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Do not paste credentials into PR bodies or diagnostics. Connection strings must be redacted
|
|
35
|
+
before reporting. Use `TrustServerCertificate=yes` only for local development when that is
|
|
36
|
+
appropriate for the server you are connecting to.
|