@slopware/sloppy-darwin-arm64 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,580 @@
|
|
|
1
|
+
import { Text } from "./codec.js";
|
|
2
|
+
|
|
3
|
+
class OsError extends Error {
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(`${code}: ${message}`);
|
|
6
|
+
this.name = "OsError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function osError(code, message) {
|
|
12
|
+
return new OsError(code, message);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function bridge() {
|
|
16
|
+
const os = globalThis.__sloppy?.os ?? null;
|
|
17
|
+
if (os === null) {
|
|
18
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "sloppy/os requires the stdlib.os runtime bridge.");
|
|
19
|
+
}
|
|
20
|
+
return os;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function requireKey(key, operation) {
|
|
24
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
25
|
+
throw new TypeError(`${operation} requires a non-empty environment key string.`);
|
|
26
|
+
}
|
|
27
|
+
if (key.includes("=") || key.includes("\0")) {
|
|
28
|
+
throw new TypeError(`${operation} environment key must not contain '=' or NUL.`);
|
|
29
|
+
}
|
|
30
|
+
return key;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function validateListOptions(options) {
|
|
34
|
+
if (options === undefined) {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
38
|
+
throw new TypeError("Environment.list options must be an object when provided.");
|
|
39
|
+
}
|
|
40
|
+
for (const key of Object.keys(options)) {
|
|
41
|
+
if (key !== "prefix") {
|
|
42
|
+
throw new TypeError(`Environment.list does not support option ${key}.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (options.prefix === undefined) {
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
if (typeof options.prefix !== "string") {
|
|
49
|
+
throw new TypeError("Environment.list prefix must be a string.");
|
|
50
|
+
}
|
|
51
|
+
return options.prefix;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function requireArgv(command, args) {
|
|
55
|
+
if (typeof command !== "string" || command.length === 0 || command.includes("\0")) {
|
|
56
|
+
throw new TypeError("OS run command must be a non-empty string without NUL.");
|
|
57
|
+
}
|
|
58
|
+
if (args === undefined) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
if (!Array.isArray(args)) {
|
|
62
|
+
throw new TypeError("OS run args must be an array when provided.");
|
|
63
|
+
}
|
|
64
|
+
return args.map((arg, index) => {
|
|
65
|
+
if (typeof arg !== "string" || arg.includes("\0")) {
|
|
66
|
+
throw new TypeError(`OS run args[${index}] must be a string without NUL.`);
|
|
67
|
+
}
|
|
68
|
+
return arg;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isCancellationSignal(value) {
|
|
73
|
+
return (
|
|
74
|
+
value !== null &&
|
|
75
|
+
typeof value === "object" &&
|
|
76
|
+
typeof value.aborted === "boolean" &&
|
|
77
|
+
("reason" in value || typeof value.addEventListener === "function")
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function validateRunOptions(options) {
|
|
82
|
+
const normalized = {
|
|
83
|
+
capture: "text",
|
|
84
|
+
maxStdoutBytes: 65536,
|
|
85
|
+
maxStderrBytes: 65536,
|
|
86
|
+
timeoutMs: 0,
|
|
87
|
+
};
|
|
88
|
+
if (options === undefined) {
|
|
89
|
+
return normalized;
|
|
90
|
+
}
|
|
91
|
+
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
92
|
+
throw new TypeError("OS run options must be an object when provided.");
|
|
93
|
+
}
|
|
94
|
+
for (const key of Object.keys(options)) {
|
|
95
|
+
if (!["cwd", "env", "capture", "maxStdoutBytes", "maxStderrBytes", "timeoutMs", "deadline", "signal"].includes(key)) {
|
|
96
|
+
throw new TypeError(`OS run does not support option ${key}.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (options.cwd !== undefined) {
|
|
100
|
+
if (typeof options.cwd !== "string" || options.cwd.includes("\0")) {
|
|
101
|
+
throw new TypeError("OS run cwd must be a string without NUL.");
|
|
102
|
+
}
|
|
103
|
+
normalized.cwd = options.cwd;
|
|
104
|
+
}
|
|
105
|
+
if (options.env !== undefined) {
|
|
106
|
+
if (options.env === null || typeof options.env !== "object" || Array.isArray(options.env)) {
|
|
107
|
+
throw new TypeError("OS run env must be an object when provided.");
|
|
108
|
+
}
|
|
109
|
+
normalized.env = Object.freeze(Object.fromEntries(Object.entries(options.env).map(([key, value]) => {
|
|
110
|
+
requireKey(key, "OS run env");
|
|
111
|
+
if (typeof value !== "string" || value.includes("\0")) {
|
|
112
|
+
throw new TypeError(`OS run env.${key} must be a string without NUL.`);
|
|
113
|
+
}
|
|
114
|
+
return [key, value];
|
|
115
|
+
})));
|
|
116
|
+
}
|
|
117
|
+
if (options.capture !== undefined) {
|
|
118
|
+
if (!["none", "text", "bytes"].includes(options.capture)) {
|
|
119
|
+
throw new TypeError('OS run capture must be "none", "text", or "bytes".');
|
|
120
|
+
}
|
|
121
|
+
normalized.capture = options.capture;
|
|
122
|
+
}
|
|
123
|
+
for (const key of ["maxStdoutBytes", "maxStderrBytes", "timeoutMs"]) {
|
|
124
|
+
if (options[key] !== undefined) {
|
|
125
|
+
if (!Number.isFinite(options[key]) || options[key] < 0) {
|
|
126
|
+
throw new TypeError(`OS run ${key} must be a non-negative number.`);
|
|
127
|
+
}
|
|
128
|
+
normalized[key] = Math.ceil(options[key]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (options.deadline !== undefined && options.deadline !== null) {
|
|
132
|
+
if (typeof options.deadline.remainingMs !== "function") {
|
|
133
|
+
throw new TypeError("OS run deadline must come from sloppy/time Deadline.");
|
|
134
|
+
}
|
|
135
|
+
const remaining = options.deadline.remainingMs();
|
|
136
|
+
if (remaining <= 0) {
|
|
137
|
+
throw osError("SLOPPY_E_OS_PROCESS_TIMEOUT", "deadline already expired");
|
|
138
|
+
}
|
|
139
|
+
if (remaining !== Infinity) {
|
|
140
|
+
if (!Number.isFinite(remaining)) {
|
|
141
|
+
throw new TypeError("OS run deadline remaining time must be finite or Infinity.");
|
|
142
|
+
}
|
|
143
|
+
normalized.timeoutMs = Math.min(normalized.timeoutMs || Infinity, Math.ceil(remaining));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (options.signal !== undefined) {
|
|
147
|
+
if (!isCancellationSignal(options.signal)) {
|
|
148
|
+
throw new TypeError("OS run signal must be a cancellation signal.");
|
|
149
|
+
}
|
|
150
|
+
if (options.signal.aborted === true) {
|
|
151
|
+
throw osError("SLOPPY_E_OS_PROCESS_CANCELLED", "operation was cancelled");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return normalized;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function validateStartOptions(options) {
|
|
158
|
+
const normalized = {
|
|
159
|
+
stdin: "ignore",
|
|
160
|
+
stdout: "ignore",
|
|
161
|
+
stderr: "ignore",
|
|
162
|
+
};
|
|
163
|
+
if (options === undefined) {
|
|
164
|
+
return normalized;
|
|
165
|
+
}
|
|
166
|
+
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
167
|
+
throw new TypeError("OS start options must be an object when provided.");
|
|
168
|
+
}
|
|
169
|
+
for (const key of Object.keys(options)) {
|
|
170
|
+
if (!["cwd", "env", "stdin", "stdout", "stderr", "deadline", "signal"].includes(key)) {
|
|
171
|
+
throw new TypeError(`OS start does not support option ${key}.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (options.cwd !== undefined) {
|
|
175
|
+
if (typeof options.cwd !== "string" || options.cwd.includes("\0")) {
|
|
176
|
+
throw new TypeError("OS start cwd must be a string without NUL.");
|
|
177
|
+
}
|
|
178
|
+
normalized.cwd = options.cwd;
|
|
179
|
+
}
|
|
180
|
+
if (options.env !== undefined) {
|
|
181
|
+
if (options.env === null || typeof options.env !== "object" || Array.isArray(options.env)) {
|
|
182
|
+
throw new TypeError("OS start env must be an object when provided.");
|
|
183
|
+
}
|
|
184
|
+
normalized.env = Object.freeze(Object.fromEntries(Object.entries(options.env).map(([key, value]) => {
|
|
185
|
+
requireKey(key, "OS start env");
|
|
186
|
+
if (typeof value !== "string" || value.includes("\0")) {
|
|
187
|
+
throw new TypeError(`OS start env.${key} must be a string without NUL.`);
|
|
188
|
+
}
|
|
189
|
+
return [key, value];
|
|
190
|
+
})));
|
|
191
|
+
}
|
|
192
|
+
for (const key of ["stdin", "stdout", "stderr"]) {
|
|
193
|
+
if (options[key] !== undefined) {
|
|
194
|
+
if (!["ignore", "pipe"].includes(options[key])) {
|
|
195
|
+
throw new TypeError(`OS start ${key} must be "ignore" or "pipe".`);
|
|
196
|
+
}
|
|
197
|
+
normalized[key] = options[key];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (options.deadline !== undefined && options.deadline !== null) {
|
|
201
|
+
if (typeof options.deadline.remainingMs !== "function") {
|
|
202
|
+
throw new TypeError("OS start deadline must come from sloppy/time Deadline.");
|
|
203
|
+
}
|
|
204
|
+
if (options.deadline.remainingMs() <= 0) {
|
|
205
|
+
throw osError("SLOPPY_E_OS_PROCESS_TIMEOUT", "deadline already expired");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (options.signal !== undefined) {
|
|
209
|
+
if (!isCancellationSignal(options.signal)) {
|
|
210
|
+
throw new TypeError("OS start signal must be a cancellation signal.");
|
|
211
|
+
}
|
|
212
|
+
if (options.signal.aborted === true) {
|
|
213
|
+
throw osError("SLOPPY_E_OS_PROCESS_CANCELLED", "process was cancelled");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return normalized;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function validateWaitOptions(options) {
|
|
220
|
+
const normalized = { timeoutMs: 0 };
|
|
221
|
+
if (options === undefined) {
|
|
222
|
+
return normalized;
|
|
223
|
+
}
|
|
224
|
+
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
225
|
+
throw new TypeError("ProcessHandle.wait options must be an object when provided.");
|
|
226
|
+
}
|
|
227
|
+
for (const key of Object.keys(options)) {
|
|
228
|
+
if (!["timeoutMs", "deadline", "signal"].includes(key)) {
|
|
229
|
+
throw new TypeError(`ProcessHandle.wait does not support option ${key}.`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (options.timeoutMs !== undefined) {
|
|
233
|
+
if (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0) {
|
|
234
|
+
throw new TypeError("ProcessHandle.wait timeoutMs must be a non-negative number.");
|
|
235
|
+
}
|
|
236
|
+
normalized.timeoutMs = Math.ceil(options.timeoutMs);
|
|
237
|
+
}
|
|
238
|
+
if (options.deadline !== undefined && options.deadline !== null) {
|
|
239
|
+
if (typeof options.deadline.remainingMs !== "function") {
|
|
240
|
+
throw new TypeError("ProcessHandle.wait deadline must come from sloppy/time Deadline.");
|
|
241
|
+
}
|
|
242
|
+
const remaining = options.deadline.remainingMs();
|
|
243
|
+
if (remaining <= 0) {
|
|
244
|
+
throw osError("SLOPPY_E_OS_PROCESS_TIMEOUT", "deadline already expired");
|
|
245
|
+
}
|
|
246
|
+
if (remaining !== Infinity) {
|
|
247
|
+
if (!Number.isFinite(remaining)) {
|
|
248
|
+
throw new TypeError("ProcessHandle.wait deadline remaining time must be finite or Infinity.");
|
|
249
|
+
}
|
|
250
|
+
normalized.timeoutMs = Math.min(normalized.timeoutMs || Infinity, Math.ceil(remaining));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (options.signal !== undefined) {
|
|
254
|
+
if (!isCancellationSignal(options.signal)) {
|
|
255
|
+
throw new TypeError("ProcessHandle.wait signal must be a cancellation signal.");
|
|
256
|
+
}
|
|
257
|
+
if (options.signal.aborted === true) {
|
|
258
|
+
throw osError("SLOPPY_E_OS_PROCESS_CANCELLED", "process was cancelled");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return normalized;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function normalizeProcessInfo(value) {
|
|
265
|
+
if (value === null || typeof value !== "object") {
|
|
266
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS process info bridge returned invalid data.");
|
|
267
|
+
}
|
|
268
|
+
const invalid = () => {
|
|
269
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS process info bridge returned invalid data.");
|
|
270
|
+
};
|
|
271
|
+
const isProcessId = (pid) => Number.isInteger(pid) && pid >= 0;
|
|
272
|
+
if (
|
|
273
|
+
!isProcessId(value.pid) ||
|
|
274
|
+
!isProcessId(value.parentPid) ||
|
|
275
|
+
typeof value.executablePath !== "string" ||
|
|
276
|
+
typeof value.cwd !== "string" ||
|
|
277
|
+
typeof value.argsAvailable !== "boolean" ||
|
|
278
|
+
!Array.isArray(value.args)
|
|
279
|
+
) {
|
|
280
|
+
invalid();
|
|
281
|
+
}
|
|
282
|
+
if (!value.argsAvailable && value.args.length !== 0) {
|
|
283
|
+
invalid();
|
|
284
|
+
}
|
|
285
|
+
const args = value.argsAvailable ? value.args.map((arg) => {
|
|
286
|
+
if (typeof arg !== "string") {
|
|
287
|
+
invalid();
|
|
288
|
+
}
|
|
289
|
+
return arg;
|
|
290
|
+
}) : [];
|
|
291
|
+
return Object.freeze({
|
|
292
|
+
pid: value.pid,
|
|
293
|
+
parentPid: value.parentPid,
|
|
294
|
+
executablePath: value.executablePath,
|
|
295
|
+
cwd: value.cwd,
|
|
296
|
+
args: Object.freeze(args),
|
|
297
|
+
argsAvailable: value.argsAvailable,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function callProcessBridge(handle, directName, bridgeName, args, unavailableMessage) {
|
|
302
|
+
if (handle !== null && typeof handle === "object" && typeof handle[directName] === "function") {
|
|
303
|
+
return handle[directName](...args);
|
|
304
|
+
}
|
|
305
|
+
const os = bridge();
|
|
306
|
+
if (typeof os[bridgeName] === "function") {
|
|
307
|
+
return os[bridgeName](handle, ...args);
|
|
308
|
+
}
|
|
309
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", unavailableMessage);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
class ProcessPipe {
|
|
313
|
+
constructor(handle, name) {
|
|
314
|
+
this._handle = handle;
|
|
315
|
+
this._name = name;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async read(maxBytes = 65536) {
|
|
319
|
+
if (!Number.isFinite(maxBytes) || maxBytes <= 0) {
|
|
320
|
+
throw new TypeError("Process pipe read maxBytes must be a positive number.");
|
|
321
|
+
}
|
|
322
|
+
const method = this._name === "stderr" ? "readStderr" : "readStdout";
|
|
323
|
+
const bridgeMethod = this._name === "stderr" ? "processReadStderr" : "processReadStdout";
|
|
324
|
+
return callProcessBridge(
|
|
325
|
+
this._handle,
|
|
326
|
+
method,
|
|
327
|
+
bridgeMethod,
|
|
328
|
+
[Math.ceil(maxBytes)],
|
|
329
|
+
"OS process pipe bridge is unavailable.",
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async readText(maxBytes = 65536) {
|
|
334
|
+
const value = await this.read(maxBytes);
|
|
335
|
+
if (typeof value === "string") {
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
return Text.utf8.decode(value);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async *readLines(options = undefined) {
|
|
342
|
+
if (options !== undefined && (options === null || typeof options !== "object" || Array.isArray(options))) {
|
|
343
|
+
throw new TypeError("Process pipe readLines options must be an object when provided.");
|
|
344
|
+
}
|
|
345
|
+
const chunkSize = options?.chunkSize ?? 4096;
|
|
346
|
+
const decoder = Text.utf8.decoder();
|
|
347
|
+
let buffered = "";
|
|
348
|
+
for (;;) {
|
|
349
|
+
const value = await this.read(chunkSize);
|
|
350
|
+
const chunk = typeof value === "string" ? value : decoder.decode(value, { stream: true });
|
|
351
|
+
if (chunk.length === 0) {
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
buffered += chunk;
|
|
355
|
+
for (;;) {
|
|
356
|
+
const newline = buffered.indexOf("\n");
|
|
357
|
+
if (newline < 0) {
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
const line = buffered.slice(0, newline).replace(/\r$/, "");
|
|
361
|
+
buffered = buffered.slice(newline + 1);
|
|
362
|
+
yield line;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
buffered += decoder.finish();
|
|
366
|
+
if (buffered.length !== 0) {
|
|
367
|
+
yield buffered.replace(/\r$/, "");
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
class ProcessInput {
|
|
373
|
+
constructor(handle) {
|
|
374
|
+
this._handle = handle;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async write(value) {
|
|
378
|
+
if (typeof value !== "string" && !(value instanceof Uint8Array)) {
|
|
379
|
+
throw new TypeError("Process stdin write requires a string or Uint8Array.");
|
|
380
|
+
}
|
|
381
|
+
return callProcessBridge(
|
|
382
|
+
this._handle,
|
|
383
|
+
"writeStdin",
|
|
384
|
+
"processWriteStdin",
|
|
385
|
+
[value],
|
|
386
|
+
"OS process stdin bridge is unavailable.",
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async writeText(text) {
|
|
391
|
+
if (typeof text !== "string") {
|
|
392
|
+
throw new TypeError("Process stdin writeText requires a string.");
|
|
393
|
+
}
|
|
394
|
+
return this.write(text);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async close() {
|
|
398
|
+
return callProcessBridge(
|
|
399
|
+
this._handle,
|
|
400
|
+
"closeStdin",
|
|
401
|
+
"processCloseStdin",
|
|
402
|
+
[],
|
|
403
|
+
"OS process stdin bridge is unavailable.",
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
class ProcessHandle {
|
|
409
|
+
constructor(handle, options) {
|
|
410
|
+
this._handle = handle;
|
|
411
|
+
this.stdin = options.stdin === "pipe" ? new ProcessInput(handle) : undefined;
|
|
412
|
+
this.stdout = options.stdout === "pipe" ? new ProcessPipe(handle, "stdout") : undefined;
|
|
413
|
+
this.stderr = options.stderr === "pipe" ? new ProcessPipe(handle, "stderr") : undefined;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
async wait(options = undefined) {
|
|
417
|
+
return callProcessBridge(
|
|
418
|
+
this._handle,
|
|
419
|
+
"wait",
|
|
420
|
+
"processWait",
|
|
421
|
+
[validateWaitOptions(options)],
|
|
422
|
+
"OS process wait bridge is unavailable.",
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
async terminate() {
|
|
427
|
+
return callProcessBridge(
|
|
428
|
+
this._handle,
|
|
429
|
+
"terminate",
|
|
430
|
+
"processTerminate",
|
|
431
|
+
[],
|
|
432
|
+
"OS process terminate bridge is unavailable.",
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async kill() {
|
|
437
|
+
return callProcessBridge(
|
|
438
|
+
this._handle,
|
|
439
|
+
"kill",
|
|
440
|
+
"processKill",
|
|
441
|
+
[],
|
|
442
|
+
"OS process kill bridge is unavailable.",
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async cancel() {
|
|
447
|
+
return callProcessBridge(
|
|
448
|
+
this._handle,
|
|
449
|
+
"cancel",
|
|
450
|
+
"processCancel",
|
|
451
|
+
[],
|
|
452
|
+
"OS process cancel bridge is unavailable.",
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async dispose() {
|
|
457
|
+
if (typeof this._handle.dispose === "function") {
|
|
458
|
+
return this._handle.dispose();
|
|
459
|
+
}
|
|
460
|
+
const os = bridge();
|
|
461
|
+
if (typeof os.processDispose === "function") {
|
|
462
|
+
return os.processDispose(this._handle);
|
|
463
|
+
}
|
|
464
|
+
return undefined;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function validateShutdownHandler(handler) {
|
|
469
|
+
if (typeof handler !== "function") {
|
|
470
|
+
throw new TypeError("Signals.onShutdown requires a function.");
|
|
471
|
+
}
|
|
472
|
+
return handler;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function normalizeShutdownContext(ctx = undefined) {
|
|
476
|
+
const source = ctx === null || typeof ctx !== "object" ? {} : ctx;
|
|
477
|
+
return Object.freeze({
|
|
478
|
+
signal: typeof source.signal === "string" ? source.signal : "shutdown",
|
|
479
|
+
forced: source.forced === true,
|
|
480
|
+
reason: source.reason,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function signalHandlerFailure(error) {
|
|
485
|
+
const failure = osError("SLOPPY_E_OS_SIGNAL_HANDLER_FAILURE", "shutdown signal handler failed");
|
|
486
|
+
failure.cause = error;
|
|
487
|
+
return failure;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function systemInfo() {
|
|
491
|
+
const info = bridge().systemInfo();
|
|
492
|
+
if (info === null || typeof info !== "object") {
|
|
493
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "System metadata bridge returned invalid data.");
|
|
494
|
+
}
|
|
495
|
+
return info;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const System = Object.freeze({
|
|
499
|
+
get platform() {
|
|
500
|
+
return systemInfo().platform;
|
|
501
|
+
},
|
|
502
|
+
get arch() {
|
|
503
|
+
return systemInfo().arch;
|
|
504
|
+
},
|
|
505
|
+
get cpuCount() {
|
|
506
|
+
return systemInfo().cpuCount;
|
|
507
|
+
},
|
|
508
|
+
get tempDirectory() {
|
|
509
|
+
return systemInfo().tempDirectory;
|
|
510
|
+
},
|
|
511
|
+
get hostname() {
|
|
512
|
+
return systemInfo().hostname;
|
|
513
|
+
},
|
|
514
|
+
get endOfLine() {
|
|
515
|
+
return systemInfo().endOfLine;
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
const Environment = Object.freeze({
|
|
520
|
+
get(key) {
|
|
521
|
+
key = requireKey(key, "Environment.get");
|
|
522
|
+
const value = bridge().environmentGet(key);
|
|
523
|
+
return value === undefined ? undefined : String(value);
|
|
524
|
+
},
|
|
525
|
+
has(key) {
|
|
526
|
+
key = requireKey(key, "Environment.has");
|
|
527
|
+
return bridge().environmentHas(key) === true;
|
|
528
|
+
},
|
|
529
|
+
list(options = undefined) {
|
|
530
|
+
const prefix = validateListOptions(options);
|
|
531
|
+
return Object.freeze([...bridge().environmentList(prefix)].map(String));
|
|
532
|
+
},
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
const Process = Object.freeze({
|
|
536
|
+
info() {
|
|
537
|
+
const os = bridge();
|
|
538
|
+
if (typeof os.processInfo !== "function") {
|
|
539
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS process info bridge is unavailable.");
|
|
540
|
+
}
|
|
541
|
+
return normalizeProcessInfo(os.processInfo());
|
|
542
|
+
},
|
|
543
|
+
async run(command, args = [], options = undefined) {
|
|
544
|
+
const argv = requireArgv(command, args);
|
|
545
|
+
const runOptions = validateRunOptions(options);
|
|
546
|
+
const os = bridge();
|
|
547
|
+
if (typeof os.processRun !== "function") {
|
|
548
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS run bridge is unavailable.");
|
|
549
|
+
}
|
|
550
|
+
return os.processRun(command, argv, runOptions);
|
|
551
|
+
},
|
|
552
|
+
async start(command, args = [], options = undefined) {
|
|
553
|
+
const argv = requireArgv(command, args);
|
|
554
|
+
const startOptions = validateStartOptions(options);
|
|
555
|
+
const os = bridge();
|
|
556
|
+
if (typeof os.processStart !== "function") {
|
|
557
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS start bridge is unavailable.");
|
|
558
|
+
}
|
|
559
|
+
return new ProcessHandle(await os.processStart(command, argv, startOptions), startOptions);
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
const Signals = Object.freeze({
|
|
564
|
+
onShutdown(handler) {
|
|
565
|
+
handler = validateShutdownHandler(handler);
|
|
566
|
+
const os = bridge();
|
|
567
|
+
if (typeof os.signalsOnShutdown !== "function") {
|
|
568
|
+
throw osError("SLOPPY_E_OS_FEATURE_UNAVAILABLE", "OS shutdown signal bridge is unavailable.");
|
|
569
|
+
}
|
|
570
|
+
return os.signalsOnShutdown(async (ctx = undefined) => {
|
|
571
|
+
try {
|
|
572
|
+
await handler(normalizeShutdownContext(ctx));
|
|
573
|
+
} catch (error) {
|
|
574
|
+
throw signalHandlerFailure(error);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
export { Environment, OsError, Process, ProcessHandle, Signals, System };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isPlainObject } from "./internal/shared.js";
|
|
2
|
+
|
|
3
|
+
const DETAIL_POLICIES = new Set(["never", "development", "always"]);
|
|
4
|
+
|
|
5
|
+
function validateDetailPolicy(value) {
|
|
6
|
+
if (value === undefined) {
|
|
7
|
+
return "never";
|
|
8
|
+
}
|
|
9
|
+
if (!DETAIL_POLICIES.has(value)) {
|
|
10
|
+
throw new TypeError("Sloppy ProblemDetails detail policy must be never, development, or always.");
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function defaults(options) {
|
|
16
|
+
if (options !== undefined && !isPlainObject(options)) {
|
|
17
|
+
throw new TypeError("Sloppy ProblemDetails.defaults options must be a plain object.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
__sloppyErrorPolicy: true,
|
|
22
|
+
__sloppyProblemDetails: true,
|
|
23
|
+
detail: validateDetailPolicy(options?.detail),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const ProblemDetails = Object.freeze({
|
|
28
|
+
defaults,
|
|
29
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { validateSqliteProviderOptions } from "../internal/validation.js";
|
|
2
|
+
|
|
3
|
+
const SQLITE_PROVIDER_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/u;
|
|
4
|
+
|
|
5
|
+
function validateSqliteProviderName(name) {
|
|
6
|
+
if (typeof name !== "string" || name.length === 0 || name.includes("\0")) {
|
|
7
|
+
throw new TypeError("Sloppy sqlite provider name must be a non-empty string without NUL.");
|
|
8
|
+
}
|
|
9
|
+
if (name.trim() !== name || !SQLITE_PROVIDER_NAME_PATTERN.test(name)) {
|
|
10
|
+
throw new TypeError(
|
|
11
|
+
"Sloppy sqlite provider name must contain only letters, digits, dots, underscores, or hyphens.",
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function sqlite(name, options) {
|
|
17
|
+
validateSqliteProviderName(name);
|
|
18
|
+
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
__sloppyProvider: true,
|
|
21
|
+
kind: "sqlite",
|
|
22
|
+
name,
|
|
23
|
+
token: name.includes(".") ? name : `data.${name}`,
|
|
24
|
+
options: options === undefined ? Object.freeze({}) : validateSqliteProviderOptions(options),
|
|
25
|
+
});
|
|
26
|
+
}
|