@slopware/sloppy-linux-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 +34 -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,60 @@
|
|
|
1
|
+
import { Time } from "sloppy/time";
|
|
2
|
+
|
|
3
|
+
const ticks = [];
|
|
4
|
+
const runs = [];
|
|
5
|
+
const startedRuns = [];
|
|
6
|
+
|
|
7
|
+
let resolveStartedRuns;
|
|
8
|
+
const started = new Promise((resolve) => {
|
|
9
|
+
resolveStartedRuns = resolve;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function markStarted(name) {
|
|
13
|
+
startedRuns.push(name);
|
|
14
|
+
if (startedRuns.length === 2) {
|
|
15
|
+
resolveStartedRuns();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for await (const tick of Time.interval(1000, { immediate: true, maxTicks: 3 })) {
|
|
20
|
+
ticks.push(tick.index);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const job = Time.every(
|
|
24
|
+
"5m",
|
|
25
|
+
async (ctx) => {
|
|
26
|
+
runs.push(ctx.run);
|
|
27
|
+
markStarted("job");
|
|
28
|
+
await cleanup({ signal: ctx.signal });
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
immediate: true,
|
|
32
|
+
noOverlap: true,
|
|
33
|
+
missedRunPolicy: "skip",
|
|
34
|
+
maxRuns: 1,
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const scheduledJob = Time.every("5m", async (ctx) => {
|
|
39
|
+
markStarted("scheduledJob");
|
|
40
|
+
return cleanup({ signal: ctx.signal });
|
|
41
|
+
}, {
|
|
42
|
+
immediate: true,
|
|
43
|
+
noOverlap: true,
|
|
44
|
+
missedRunPolicy: "skip",
|
|
45
|
+
maxRuns: 1,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await started;
|
|
49
|
+
await job.stop();
|
|
50
|
+
await scheduledJob.stop();
|
|
51
|
+
|
|
52
|
+
async function cleanup({ signal }) {
|
|
53
|
+
if (signal.aborted) {
|
|
54
|
+
return "cancelled";
|
|
55
|
+
}
|
|
56
|
+
await Time.yield();
|
|
57
|
+
return "clean";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default { ticks, runs, startedRuns, skippedRuns: job.skippedRuns };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# SQLite Users API Example
|
|
2
|
+
|
|
3
|
+
## What This Demonstrates
|
|
4
|
+
|
|
5
|
+
This example shows a small SQLite-backed users API using the supported classic
|
|
6
|
+
artifact path:
|
|
7
|
+
|
|
8
|
+
- `GET /health`;
|
|
9
|
+
- `GET /users`;
|
|
10
|
+
- `GET /users/{id}`;
|
|
11
|
+
- `POST /users`;
|
|
12
|
+
- explicit `sqlite("main")` provider registration;
|
|
13
|
+
- a relative function module under `modules/users.js`;
|
|
14
|
+
- `sloppy.json` and `appsettings.json` project configuration.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- A V8-enabled `sloppy` runtime.
|
|
19
|
+
- SQLite bridge support in that runtime.
|
|
20
|
+
|
|
21
|
+
## Run
|
|
22
|
+
|
|
23
|
+
From this example directory:
|
|
24
|
+
|
|
25
|
+
```powershell
|
|
26
|
+
..\..\build\windows-relwithdebinfo\sloppy.exe run --once GET /users
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
From the repository root:
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
.\build\windows-relwithdebinfo\sloppy.exe run examples/users-api-sqlite/app.js --once GET /users
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Expected Result
|
|
36
|
+
|
|
37
|
+
The response body is JSON with the seeded users. The exact rows can include
|
|
38
|
+
users inserted by earlier requests when the configured database file is reused.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
[{"id":1,"name":"Ada Lovelace","email":"ada@example.test"},{"id":2,"name":"Grace Hopper","email":"grace@example.test"}]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## What To Inspect
|
|
45
|
+
|
|
46
|
+
- `app.js`: app creation, SQLite descriptor registration, and route wiring.
|
|
47
|
+
- `modules/users.js`: `app.provider("sqlite:main")` and users route handlers.
|
|
48
|
+
- `sloppy.json`: source-input project configuration.
|
|
49
|
+
- `appsettings.json`: SQLite provider database setting.
|
|
50
|
+
- Generated `.sloppy/app.plan.json`: route, module, provider, capability, and
|
|
51
|
+
source-location metadata.
|
|
52
|
+
|
|
53
|
+
After building artifacts, these commands inspect the Plan:
|
|
54
|
+
|
|
55
|
+
```powershell
|
|
56
|
+
..\..\build\windows-dev\sloppy.exe routes --plan .sloppy\app.plan.json
|
|
57
|
+
..\..\build\windows-dev\sloppy.exe capabilities --plan .sloppy\app.plan.json
|
|
58
|
+
..\..\build\windows-dev\sloppy.exe doctor --plan .sloppy\app.plan.json
|
|
59
|
+
..\..\build\windows-dev\sloppy.exe audit --plan .sloppy\app.plan.json --format json
|
|
60
|
+
..\..\build\windows-dev\sloppy.exe openapi --plan .sloppy\app.plan.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Current Limits
|
|
64
|
+
|
|
65
|
+
This example focuses on SQLite provider integration and localhost transport flow. PostgreSQL
|
|
66
|
+
and SQL Server are covered by separate examples, and streaming APIs are not included in
|
|
67
|
+
this slice.
|
|
68
|
+
|
|
69
|
+
## Related Docs
|
|
70
|
+
|
|
71
|
+
- `docs/guide/sqlite.md`
|
|
72
|
+
- `docs/api/data.md`
|
|
73
|
+
- `docs/reference/providers.md`
|
|
74
|
+
- `docs/reference/framework.md`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
import { sqlite } from "sloppy/providers/sqlite";
|
|
3
|
+
import { usersModule } from "./modules/users.js";
|
|
4
|
+
|
|
5
|
+
const app = Sloppy.create();
|
|
6
|
+
|
|
7
|
+
app.use(sqlite("main"));
|
|
8
|
+
app.get("/health", () => Results.text("ok"));
|
|
9
|
+
app.useModule(usersModule);
|
|
10
|
+
|
|
11
|
+
export default app;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Results } from "sloppy";
|
|
2
|
+
|
|
3
|
+
export function usersModule(app) {
|
|
4
|
+
const db = app.provider("sqlite:main");
|
|
5
|
+
const users = app.group("/users");
|
|
6
|
+
|
|
7
|
+
users.get("/", async () => {
|
|
8
|
+
await db.exec("create table if not exists users (id integer primary key, name text not null, email text not null unique)", []);
|
|
9
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [1, "Ada Lovelace", "ada@example.test", 1]);
|
|
10
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [2, "Grace Hopper", "grace@example.test", 2]);
|
|
11
|
+
return Results.json(await db.query("select id, name, email from users order by id", []));
|
|
12
|
+
}).withName("Users.List");
|
|
13
|
+
|
|
14
|
+
users.get("/{id:int}", async (ctx) => {
|
|
15
|
+
await db.exec("create table if not exists users (id integer primary key, name text not null, email text not null unique)", []);
|
|
16
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [1, "Ada Lovelace", "ada@example.test", 1]);
|
|
17
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [2, "Grace Hopper", "grace@example.test", 2]);
|
|
18
|
+
const user = await db.queryOne("select id, name, email from users where id = ?", [ctx.route.id]);
|
|
19
|
+
return user === null ? Results.notFound({ error: "user_not_found" }) : Results.json(user);
|
|
20
|
+
}).withName("Users.Get");
|
|
21
|
+
|
|
22
|
+
users.post("/", async (ctx) => {
|
|
23
|
+
const body = ctx.request.json();
|
|
24
|
+
if (body === null || Array.isArray(body) || typeof body !== "object" ||
|
|
25
|
+
typeof body.name !== "string" || body.name.length === 0 ||
|
|
26
|
+
typeof body.email !== "string" || body.email.length === 0) {
|
|
27
|
+
return Results.problem(
|
|
28
|
+
{ title: "Invalid user payload", detail: "name and email are required" },
|
|
29
|
+
{ status: 400 },
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await db.exec("create table if not exists users (id integer primary key, name text not null, email text not null unique)", []);
|
|
34
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [1, "Ada Lovelace", "ada@example.test", 1]);
|
|
35
|
+
await db.exec("insert into users (id, name, email) select ?, ?, ? where not exists (select 1 from users where id = ?)", [2, "Grace Hopper", "grace@example.test", 2]);
|
|
36
|
+
await db.exec("insert into users (name, email) values (?, ?)", [body.name, body.email]);
|
|
37
|
+
const user = await db.queryOne("select id, name, email from users where id = last_insert_rowid()", []);
|
|
38
|
+
return Results.created(`/users/${user.id}`, user);
|
|
39
|
+
}).withName("Users.Create");
|
|
40
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Validation Errors Example
|
|
2
|
+
|
|
3
|
+
This is a Plan/OpenAPI metadata example plus native Plan-backed validation fixture for
|
|
4
|
+
schema-backed body bindings.
|
|
5
|
+
|
|
6
|
+
Build artifacts from this directory:
|
|
7
|
+
|
|
8
|
+
```powershell
|
|
9
|
+
..\..\compiler\target\debug\sloppyc.exe build app.js --out .sloppy
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Then inspect the Plan-driven tooling:
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
..\..\build\windows-dev\sloppy.exe routes --plan .sloppy\app.plan.json
|
|
16
|
+
..\..\build\windows-dev\sloppy.exe doctor --plan .sloppy\app.plan.json
|
|
17
|
+
..\..\build\windows-dev\sloppy.exe openapi --plan .sloppy\app.plan.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Route:
|
|
21
|
+
|
|
22
|
+
- `POST /users`
|
|
23
|
+
|
|
24
|
+
The example demonstrates schema declaration extraction, `ctx.body.json(UserCreate)` request body
|
|
25
|
+
metadata, validation problem OpenAPI components, explicit partial/known metadata reporting,
|
|
26
|
+
and the request shape consumed by the native Plan-backed validation foundation.
|
|
27
|
+
`invalid-user.http` is a documentation fixture for the intended invalid request shape.
|
|
28
|
+
|
|
29
|
+
The native runtime now has a bounded Plan-backed validation path for route/query/header
|
|
30
|
+
scalars and schema-backed JSON request bodies.
|
|
31
|
+
|
|
32
|
+
## Limitations
|
|
33
|
+
|
|
34
|
+
This example focuses on validation metadata and Plan-backed request validation. Typed
|
|
35
|
+
handler execution, provider/DI integration, custom validators, native JSON fast paths, and
|
|
36
|
+
broader HTTP features are outside this slice.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Sloppy, Results, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const UserCreate = schema.object({
|
|
4
|
+
name: schema.string().min(1),
|
|
5
|
+
email: schema.string().email(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const app = Sloppy.create();
|
|
9
|
+
|
|
10
|
+
app.post("/users", (ctx) => Results.created("/users/1", {
|
|
11
|
+
user: ctx.body.json(UserCreate),
|
|
12
|
+
})).withName("Users.Create");
|
|
13
|
+
|
|
14
|
+
export default app;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Dynamic Web Routes
|
|
2
|
+
|
|
3
|
+
This example mixes one statically understood route with route registrations
|
|
4
|
+
that execute at startup.
|
|
5
|
+
|
|
6
|
+
```powershell
|
|
7
|
+
sloppyc build examples/web-dynamic-routes/app.ts --out .sloppy
|
|
8
|
+
sloppy routes .sloppy
|
|
9
|
+
sloppy openapi .sloppy --output openapi.json
|
|
10
|
+
sloppy run .sloppy --once GET /health
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`/health` has complete route metadata. The loop, computed path, conditional
|
|
14
|
+
registration, and dynamic status response stay runnable when V8 is enabled, but
|
|
15
|
+
the Plan marks their route metadata as dynamic and emits
|
|
16
|
+
`SLOPPYC_W_DYNAMIC_ROUTE` findings. OpenAPI includes only routes it can
|
|
17
|
+
represent safely.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Results, Sloppy } from "sloppy";
|
|
2
|
+
import { Environment } from "sloppy/os";
|
|
3
|
+
|
|
4
|
+
const app = Sloppy.create();
|
|
5
|
+
|
|
6
|
+
app.get("/health", () => Results.text("ok")).withName("Health.Get");
|
|
7
|
+
|
|
8
|
+
const routes = [
|
|
9
|
+
["/hello/Ada", () => Results.json({ hello: "Ada" })],
|
|
10
|
+
["/hello/Grace", () => Results.json({ hello: "Grace" })],
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
for (const [path, handler] of routes) {
|
|
14
|
+
app.get(path, handler);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getStatusPath() {
|
|
18
|
+
return "/status";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
app.get(getStatusPath(), () => Results.status(Date.now() % 2 === 0 ? 200 : 201));
|
|
22
|
+
|
|
23
|
+
if (Environment.get("ENABLE_ADMIN") === "true") {
|
|
24
|
+
app.get("/admin/status", () => Results.text("admin ok"));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default app;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Webhooks Basic
|
|
2
|
+
|
|
3
|
+
This example shows the public API shape for event descriptors, outbox
|
|
4
|
+
registration, transactional publish, and delivery worker wiring.
|
|
5
|
+
|
|
6
|
+
It is source-level documentation for the pre-alpha runtime. Run the bootstrap
|
|
7
|
+
webhook tests for executable coverage:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
node tests/bootstrap/test_webhooks.mjs
|
|
11
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Config, Http, Results, Sloppy, Webhooks, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const OrderCreated = Webhooks.event("order.created", {
|
|
4
|
+
version: 1,
|
|
5
|
+
schema: schema.object({
|
|
6
|
+
orderId: schema.string(),
|
|
7
|
+
customerId: schema.string(),
|
|
8
|
+
total: schema.number(),
|
|
9
|
+
}),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const builder = Sloppy.createBuilder();
|
|
13
|
+
|
|
14
|
+
builder.services.addHttpClient(Http.client("webhooks", {
|
|
15
|
+
baseUrl: Config.required("Webhooks:BaseUrl"),
|
|
16
|
+
retry: Http.retry.none(),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
builder.services.addWebhooks(Webhooks.outbox({
|
|
20
|
+
provider: "main",
|
|
21
|
+
signingSecret: Config.requiredSecret("Webhooks:SigningSecret"),
|
|
22
|
+
delivery: {
|
|
23
|
+
client: "webhooks",
|
|
24
|
+
retry: Webhooks.retry.exponential({
|
|
25
|
+
maxAttempts: 8,
|
|
26
|
+
initialDelayMs: 1000,
|
|
27
|
+
maxDelayMs: 300000,
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
const app = builder.build();
|
|
33
|
+
|
|
34
|
+
app.post("/orders", async (ctx) => {
|
|
35
|
+
const order = await ctx.services.get("data.main").transaction(async (tx) => {
|
|
36
|
+
const created = { id: "ord_1", customerId: "cus_1", total: 42 };
|
|
37
|
+
await ctx.webhooks.publish(tx, OrderCreated, {
|
|
38
|
+
orderId: created.id,
|
|
39
|
+
customerId: created.customerId,
|
|
40
|
+
total: created.total,
|
|
41
|
+
});
|
|
42
|
+
return created;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return Results.created(`/orders/${order.id}`, order);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export default app;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# WebSocket Auth
|
|
2
|
+
|
|
3
|
+
Protected WebSocket route using JWT bearer auth and a required `realtime`
|
|
4
|
+
scope. Test it with `host.websocket("/secure/ws").withJwt(...)`.
|
|
5
|
+
|
|
6
|
+
Native WebSocket routes fail closed when the route requires auth until the auth
|
|
7
|
+
principal bridge is attached to upgraded connections. Use TestHost for this
|
|
8
|
+
protected-route example.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Auth, Sloppy } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const app = Sloppy.create();
|
|
4
|
+
|
|
5
|
+
app.use(Auth.jwtBearer({
|
|
6
|
+
secret: "test-secret",
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
app.websocket("/secure/ws", async (socket) => {
|
|
10
|
+
const user = socket.ctx.requireUser();
|
|
11
|
+
await socket.accept();
|
|
12
|
+
await socket.sendJson({ type: "hello", sub: user.sub });
|
|
13
|
+
await socket.close();
|
|
14
|
+
}).requiresAuth().requiresScope("realtime");
|
|
15
|
+
|
|
16
|
+
export default app;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# WebSocket Echo
|
|
2
|
+
|
|
3
|
+
WebSocket echo endpoint with text, JSON, schema validation, origin policy,
|
|
4
|
+
subprotocol selection, and message limits.
|
|
5
|
+
|
|
6
|
+
Use `TestHost.create(app)` for the full app-host behavior, including JSON
|
|
7
|
+
validation, heartbeat, idle timeout, and queue limits. Native `sloppy run`
|
|
8
|
+
supports HTTP/1.1 Upgrade plus text and binary frame delivery for the same
|
|
9
|
+
route, but does not model the full TestHost helper surface.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Sloppy, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const app = Sloppy.create();
|
|
4
|
+
|
|
5
|
+
const ClientMessage = schema.object({
|
|
6
|
+
type: schema.enum(["ping", "echo"]),
|
|
7
|
+
text: schema.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
app.websocket("/ws", async (socket) => {
|
|
11
|
+
await socket.accept();
|
|
12
|
+
|
|
13
|
+
for await (const message of socket.messages()) {
|
|
14
|
+
if (message.kind === "text") {
|
|
15
|
+
await socket.sendText(`echo:${message.text}`);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (message.kind === "json") {
|
|
19
|
+
const input = message.validate(ClientMessage);
|
|
20
|
+
if (input.type === "ping") {
|
|
21
|
+
await socket.sendJson({ type: "pong" });
|
|
22
|
+
} else {
|
|
23
|
+
await socket.sendJson({ type: "echo", text: input.text ?? "" });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}, {
|
|
28
|
+
origins: ["https://app.example.com"],
|
|
29
|
+
protocols: ["sloppy.realtime"],
|
|
30
|
+
maxMessageBytes: 64 * 1024,
|
|
31
|
+
maxSendQueueBytes: 1024 * 1024,
|
|
32
|
+
heartbeatMs: 15_000,
|
|
33
|
+
idleTimeoutMs: 30_000,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default app;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Sloppy, schema } from "sloppy";
|
|
2
|
+
|
|
3
|
+
const app = Sloppy.create();
|
|
4
|
+
|
|
5
|
+
const ClientMessage = schema.object({
|
|
6
|
+
type: schema.enum(["ping", "echo"]),
|
|
7
|
+
text: schema.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
app.websocket("/json", async (socket) => {
|
|
11
|
+
await socket.accept();
|
|
12
|
+
|
|
13
|
+
for await (const message of socket.messages()) {
|
|
14
|
+
const input = message.validate(ClientMessage);
|
|
15
|
+
if (input.type === "ping") {
|
|
16
|
+
await socket.sendJson({ type: "pong" });
|
|
17
|
+
} else {
|
|
18
|
+
await socket.sendJson({ type: "echo", text: input.text ?? "" });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}, {
|
|
22
|
+
maxMessageBytes: 64 * 1024,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default app;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# WebSocket TestHost
|
|
2
|
+
|
|
3
|
+
Plain JavaScript TestHost example for the WebSocket echo app.
|
|
4
|
+
|
|
5
|
+
```powershell
|
|
6
|
+
node examples/websocket-testhost/test.mjs
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The test uses the app-host lane. Artifact, package, and loopback TestHost lanes
|
|
10
|
+
report `SLOPPY_E_TESTHOST_WEBSOCKET_UNSUPPORTED` unless a supplied runtime host
|
|
11
|
+
implements `websocketConnect`.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
|
|
3
|
+
import { Sloppy, TestHost, schema } from "sloppy";
|
|
4
|
+
|
|
5
|
+
const app = Sloppy.create();
|
|
6
|
+
|
|
7
|
+
const ClientMessage = schema.object({
|
|
8
|
+
type: schema.enum(["ping", "echo"]),
|
|
9
|
+
text: schema.string().optional(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
app.websocket("/ws", async (socket) => {
|
|
13
|
+
await socket.accept();
|
|
14
|
+
|
|
15
|
+
for await (const message of socket.messages()) {
|
|
16
|
+
if (message.kind === "text") {
|
|
17
|
+
await socket.sendText(`echo:${message.text}`);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (message.kind === "json") {
|
|
21
|
+
const input = message.validate(ClientMessage);
|
|
22
|
+
if (input.type === "ping") {
|
|
23
|
+
await socket.sendJson({ type: "pong" });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}, {
|
|
28
|
+
origins: ["https://app.example.com"],
|
|
29
|
+
protocols: ["sloppy.realtime"],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const host = await TestHost.create(app);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const ws = await host.websocket("/ws")
|
|
36
|
+
.origin("https://app.example.com")
|
|
37
|
+
.protocols(["sloppy.realtime"])
|
|
38
|
+
.connect();
|
|
39
|
+
|
|
40
|
+
assert.equal(ws.protocol, "sloppy.realtime");
|
|
41
|
+
|
|
42
|
+
await ws.sendText("hello");
|
|
43
|
+
await ws.expectText("echo:hello");
|
|
44
|
+
await ws.sendJson({ type: "ping" });
|
|
45
|
+
await ws.expectJson({ type: "pong" });
|
|
46
|
+
await ws.close();
|
|
47
|
+
} finally {
|
|
48
|
+
await host.close();
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
import { Time } from "sloppy/time";
|
|
3
|
+
import { BackgroundService } from "sloppy/workers";
|
|
4
|
+
|
|
5
|
+
const app = Sloppy.create();
|
|
6
|
+
|
|
7
|
+
const cleanup = BackgroundService.create("cleanup", async (ctx) => {
|
|
8
|
+
while (!ctx.signal.cancelled) {
|
|
9
|
+
await Time.delay(5 * 60 * 1000, { signal: ctx.signal });
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
app.use(cleanup);
|
|
14
|
+
app.mapGet("/", () => Results.text("worker service registered"));
|
|
15
|
+
|
|
16
|
+
export default app;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Workers JS Isolate
|
|
2
|
+
|
|
3
|
+
This is a V8-enabled worker API example.
|
|
4
|
+
|
|
5
|
+
Shows the explicit `Worker.start(...).invoke(...).stop()` API shape.
|
|
6
|
+
|
|
7
|
+
With V8 enabled, the worker module is loaded as Sloppy-owned source, invoked in
|
|
8
|
+
a worker-owned isolate, and settled back on the app isolate owner thread.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
import { Deadline } from "sloppy/time";
|
|
3
|
+
import { Worker } from "sloppy/workers";
|
|
4
|
+
|
|
5
|
+
const app = Sloppy.create();
|
|
6
|
+
|
|
7
|
+
app.mapPost("/parse", async () => {
|
|
8
|
+
const worker = await Worker.start("./workers/parser.ts", { memoryLimitMb: 128 });
|
|
9
|
+
try {
|
|
10
|
+
const parsed = await worker.invoke("parse", { text: "one two three" }, {
|
|
11
|
+
deadline: Deadline.after(1000),
|
|
12
|
+
});
|
|
13
|
+
return Results.json(parsed);
|
|
14
|
+
} finally {
|
|
15
|
+
await worker.stop();
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export default app;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function parse(payload) {
|
|
2
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
3
|
+
throw new TypeError("parse payload must be an object.");
|
|
4
|
+
}
|
|
5
|
+
if (typeof payload.text !== "string") {
|
|
6
|
+
throw new TypeError("parse payload text must be a string.");
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
tokens: payload.text.split(/\s+/u).filter(Boolean).length,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Sloppy, Results } from "sloppy";
|
|
2
|
+
import { WorkQueue } from "sloppy/workers";
|
|
3
|
+
|
|
4
|
+
const app = Sloppy.create();
|
|
5
|
+
|
|
6
|
+
const queue = WorkQueue.create("shutdown-demo", {
|
|
7
|
+
maxQueued: 8,
|
|
8
|
+
concurrency: 1,
|
|
9
|
+
overflow: "reject",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
queue.process(async (job, ctx) => {
|
|
13
|
+
if (ctx.signal.cancelled) {
|
|
14
|
+
return { skipped: true };
|
|
15
|
+
}
|
|
16
|
+
return { handled: job.data.id };
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
app.use(queue);
|
|
20
|
+
app.mapPost("/jobs", async () => {
|
|
21
|
+
await queue.enqueue({ id: 1 });
|
|
22
|
+
await queue.stop({ drain: true });
|
|
23
|
+
return Results.accepted({ drained: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export default app;
|