@digimuza/saas-core 0.0.2
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/CLAUDE.md +1165 -0
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/dist/api-keys/index.d.ts +9 -0
- package/dist/api-keys/index.d.ts.map +1 -0
- package/dist/api-keys/index.js +37 -0
- package/dist/api-keys/index.js.map +1 -0
- package/dist/api-keys/keys.d.ts +55 -0
- package/dist/api-keys/keys.d.ts.map +1 -0
- package/dist/api-keys/keys.js +92 -0
- package/dist/api-keys/keys.js.map +1 -0
- package/dist/api-keys/service.d.ts +111 -0
- package/dist/api-keys/service.d.ts.map +1 -0
- package/dist/api-keys/service.js +210 -0
- package/dist/api-keys/service.js.map +1 -0
- package/dist/audit/index.d.ts +5 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +44 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/service.d.ts +88 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +128 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/auth/client.d.ts +5 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +26 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/cookies.d.ts +51 -0
- package/dist/auth/cookies.d.ts.map +1 -0
- package/dist/auth/cookies.js +58 -0
- package/dist/auth/cookies.js.map +1 -0
- package/dist/auth/index.d.ts +14 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +46 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/service.d.ts +67 -0
- package/dist/auth/service.d.ts.map +1 -0
- package/dist/auth/service.js +275 -0
- package/dist/auth/service.js.map +1 -0
- package/dist/auth/types.d.ts +56 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/authorization/index.d.ts +4 -0
- package/dist/authorization/index.d.ts.map +1 -0
- package/dist/authorization/index.js +24 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/authorization/service.d.ts +92 -0
- package/dist/authorization/service.d.ts.map +1 -0
- package/dist/authorization/service.js +254 -0
- package/dist/authorization/service.js.map +1 -0
- package/dist/billing/index.d.ts +16 -0
- package/dist/billing/index.d.ts.map +1 -0
- package/dist/billing/index.js +47 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/provider.d.ts +114 -0
- package/dist/billing/provider.d.ts.map +1 -0
- package/dist/billing/provider.js +2 -0
- package/dist/billing/provider.js.map +1 -0
- package/dist/billing/revolut.d.ts +68 -0
- package/dist/billing/revolut.d.ts.map +1 -0
- package/dist/billing/revolut.js +181 -0
- package/dist/billing/revolut.js.map +1 -0
- package/dist/billing/service.d.ts +124 -0
- package/dist/billing/service.d.ts.map +1 -0
- package/dist/billing/service.js +470 -0
- package/dist/billing/service.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +43 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +212 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/project.d.ts +12 -0
- package/dist/cli/commands/project.d.ts.map +1 -0
- package/dist/cli/commands/project.js +49 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/docker.d.ts +50 -0
- package/dist/cli/docker.d.ts.map +1 -0
- package/dist/cli/docker.js +84 -0
- package/dist/cli/docker.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +198 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output.d.ts +30 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +66 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/templates.d.ts +52 -0
- package/dist/cli/templates.d.ts.map +1 -0
- package/dist/cli/templates.js +225 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/config/client.d.ts +60 -0
- package/dist/config/client.d.ts.map +1 -0
- package/dist/config/client.js +94 -0
- package/dist/config/client.js.map +1 -0
- package/dist/config/config-loader.d.ts +2 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +2 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/env.d.ts +24 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +40 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/errors.d.ts +17 -0
- package/dist/config/errors.d.ts.map +1 -0
- package/dist/config/errors.js +26 -0
- package/dist/config/errors.js.map +1 -0
- package/dist/config/index.d.ts +72 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +106 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/runtime.d.ts +15 -0
- package/dist/config/runtime.d.ts.map +1 -0
- package/dist/config/runtime.js +22 -0
- package/dist/config/runtime.js.map +1 -0
- package/dist/config/sections.d.ts +226 -0
- package/dist/config/sections.d.ts.map +1 -0
- package/dist/config/sections.js +141 -0
- package/dist/config/sections.js.map +1 -0
- package/dist/db/client.d.ts +43 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +77 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/errors.d.ts +39 -0
- package/dist/db/errors.d.ts.map +1 -0
- package/dist/db/errors.js +67 -0
- package/dist/db/errors.js.map +1 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +10 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrate.d.ts +21 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +28 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema/_shared.d.ts +30 -0
- package/dist/db/schema/_shared.d.ts.map +1 -0
- package/dist/db/schema/_shared.js +36 -0
- package/dist/db/schema/_shared.js.map +1 -0
- package/dist/db/schema/apikeys.d.ts +263 -0
- package/dist/db/schema/apikeys.d.ts.map +1 -0
- package/dist/db/schema/apikeys.js +70 -0
- package/dist/db/schema/apikeys.js.map +1 -0
- package/dist/db/schema/authorization.d.ts +465 -0
- package/dist/db/schema/authorization.d.ts.map +1 -0
- package/dist/db/schema/authorization.js +134 -0
- package/dist/db/schema/authorization.js.map +1 -0
- package/dist/db/schema/billing.d.ts +1100 -0
- package/dist/db/schema/billing.d.ts.map +1 -0
- package/dist/db/schema/billing.js +223 -0
- package/dist/db/schema/billing.js.map +1 -0
- package/dist/db/schema/events.d.ts +161 -0
- package/dist/db/schema/events.d.ts.map +1 -0
- package/dist/db/schema/events.js +66 -0
- package/dist/db/schema/events.js.map +1 -0
- package/dist/db/schema/features.d.ts +243 -0
- package/dist/db/schema/features.d.ts.map +1 -0
- package/dist/db/schema/features.js +87 -0
- package/dist/db/schema/features.js.map +1 -0
- package/dist/db/schema/files.d.ts +253 -0
- package/dist/db/schema/files.d.ts.map +1 -0
- package/dist/db/schema/files.js +74 -0
- package/dist/db/schema/files.js.map +1 -0
- package/dist/db/schema/index.d.ts +38 -0
- package/dist/db/schema/index.d.ts.map +1 -0
- package/dist/db/schema/index.js +38 -0
- package/dist/db/schema/index.js.map +1 -0
- package/dist/db/schema/invitations.d.ts +214 -0
- package/dist/db/schema/invitations.d.ts.map +1 -0
- package/dist/db/schema/invitations.js +80 -0
- package/dist/db/schema/invitations.js.map +1 -0
- package/dist/db/schema/messaging.d.ts +442 -0
- package/dist/db/schema/messaging.d.ts.map +1 -0
- package/dist/db/schema/messaging.js +120 -0
- package/dist/db/schema/messaging.js.map +1 -0
- package/dist/db/schema/users.d.ts +246 -0
- package/dist/db/schema/users.d.ts.map +1 -0
- package/dist/db/schema/users.js +60 -0
- package/dist/db/schema/users.js.map +1 -0
- package/dist/db/schema/webhooks.d.ts +693 -0
- package/dist/db/schema/webhooks.d.ts.map +1 -0
- package/dist/db/schema/webhooks.js +147 -0
- package/dist/db/schema/webhooks.js.map +1 -0
- package/dist/db/schema/workspaces.d.ts +196 -0
- package/dist/db/schema/workspaces.d.ts.map +1 -0
- package/dist/db/schema/workspaces.js +57 -0
- package/dist/db/schema/workspaces.js.map +1 -0
- package/dist/db/types.d.ts +18 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +2 -0
- package/dist/db/types.js.map +1 -0
- package/dist/email/adapters.d.ts +29 -0
- package/dist/email/adapters.d.ts.map +1 -0
- package/dist/email/adapters.js +60 -0
- package/dist/email/adapters.js.map +1 -0
- package/dist/email/index.d.ts +20 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +79 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/provider.d.ts +47 -0
- package/dist/email/provider.d.ts.map +1 -0
- package/dist/email/provider.js +7 -0
- package/dist/email/provider.js.map +1 -0
- package/dist/email/resend.d.ts +22 -0
- package/dist/email/resend.d.ts.map +1 -0
- package/dist/email/resend.js +51 -0
- package/dist/email/resend.js.map +1 -0
- package/dist/email/service.d.ts +55 -0
- package/dist/email/service.d.ts.map +1 -0
- package/dist/email/service.js +87 -0
- package/dist/email/service.js.map +1 -0
- package/dist/email/templates.d.ts +81 -0
- package/dist/email/templates.d.ts.map +1 -0
- package/dist/email/templates.js +84 -0
- package/dist/email/templates.js.map +1 -0
- package/dist/entitlements/index.d.ts +10 -0
- package/dist/entitlements/index.d.ts.map +1 -0
- package/dist/entitlements/index.js +28 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/entitlements/service.d.ts +83 -0
- package/dist/entitlements/service.d.ts.map +1 -0
- package/dist/entitlements/service.js +158 -0
- package/dist/entitlements/service.js.map +1 -0
- package/dist/errors.d.ts +85 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +95 -0
- package/dist/errors.js.map +1 -0
- package/dist/events/core-events.d.ts +120 -0
- package/dist/events/core-events.d.ts.map +1 -0
- package/dist/events/core-events.js +109 -0
- package/dist/events/core-events.js.map +1 -0
- package/dist/events/index.d.ts +15 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +58 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/publisher.d.ts +46 -0
- package/dist/events/publisher.d.ts.map +1 -0
- package/dist/events/publisher.js +54 -0
- package/dist/events/publisher.js.map +1 -0
- package/dist/events/registry.d.ts +87 -0
- package/dist/events/registry.d.ts.map +1 -0
- package/dist/events/registry.js +34 -0
- package/dist/events/registry.js.map +1 -0
- package/dist/events/service.d.ts +78 -0
- package/dist/events/service.d.ts.map +1 -0
- package/dist/events/service.js +182 -0
- package/dist/events/service.js.map +1 -0
- package/dist/features/bucket.d.ts +22 -0
- package/dist/features/bucket.d.ts.map +1 -0
- package/dist/features/bucket.js +42 -0
- package/dist/features/bucket.js.map +1 -0
- package/dist/features/index.d.ts +15 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +78 -0
- package/dist/features/index.js.map +1 -0
- package/dist/features/registry.d.ts +51 -0
- package/dist/features/registry.d.ts.map +1 -0
- package/dist/features/registry.js +52 -0
- package/dist/features/registry.js.map +1 -0
- package/dist/features/service.d.ts +78 -0
- package/dist/features/service.d.ts.map +1 -0
- package/dist/features/service.js +207 -0
- package/dist/features/service.js.map +1 -0
- package/dist/files/index.d.ts +6 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +64 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/service.d.ts +92 -0
- package/dist/files/service.d.ts.map +1 -0
- package/dist/files/service.js +303 -0
- package/dist/files/service.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/backend.d.ts +23 -0
- package/dist/jobs/backend.d.ts.map +1 -0
- package/dist/jobs/backend.js +23 -0
- package/dist/jobs/backend.js.map +1 -0
- package/dist/jobs/index.d.ts +29 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +114 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/service.d.ts +67 -0
- package/dist/jobs/service.d.ts.map +1 -0
- package/dist/jobs/service.js +139 -0
- package/dist/jobs/service.js.map +1 -0
- package/dist/jobs/types.d.ts +78 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +4 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/logger/default.d.ts +7 -0
- package/dist/logger/default.d.ts.map +1 -0
- package/dist/logger/default.js +28 -0
- package/dist/logger/default.js.map +1 -0
- package/dist/logger/index.d.ts +24 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +90 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/redact.d.ts +40 -0
- package/dist/logger/redact.d.ts.map +1 -0
- package/dist/logger/redact.js +178 -0
- package/dist/logger/redact.js.map +1 -0
- package/dist/logger/service.d.ts +14 -0
- package/dist/logger/service.d.ts.map +1 -0
- package/dist/logger/service.js +56 -0
- package/dist/logger/service.js.map +1 -0
- package/dist/logger/sinks.d.ts +37 -0
- package/dist/logger/sinks.d.ts.map +1 -0
- package/dist/logger/sinks.js +135 -0
- package/dist/logger/sinks.js.map +1 -0
- package/dist/logger/types.d.ts +47 -0
- package/dist/logger/types.d.ts.map +1 -0
- package/dist/logger/types.js +8 -0
- package/dist/logger/types.js.map +1 -0
- package/dist/notifications/index.d.ts +8 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +72 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/service.d.ts +79 -0
- package/dist/notifications/service.d.ts.map +1 -0
- package/dist/notifications/service.js +164 -0
- package/dist/notifications/service.js.map +1 -0
- package/dist/realtime/channels.d.ts +37 -0
- package/dist/realtime/channels.d.ts.map +1 -0
- package/dist/realtime/channels.js +58 -0
- package/dist/realtime/channels.js.map +1 -0
- package/dist/realtime/index.d.ts +19 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +118 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/postgres.d.ts +48 -0
- package/dist/realtime/postgres.d.ts.map +1 -0
- package/dist/realtime/postgres.js +151 -0
- package/dist/realtime/postgres.js.map +1 -0
- package/dist/realtime/service.d.ts +75 -0
- package/dist/realtime/service.d.ts.map +1 -0
- package/dist/realtime/service.js +103 -0
- package/dist/realtime/service.js.map +1 -0
- package/dist/realtime/sse.d.ts +55 -0
- package/dist/realtime/sse.d.ts.map +1 -0
- package/dist/realtime/sse.js +123 -0
- package/dist/realtime/sse.js.map +1 -0
- package/dist/realtime/transport.d.ts +52 -0
- package/dist/realtime/transport.d.ts.map +1 -0
- package/dist/realtime/transport.js +2 -0
- package/dist/realtime/transport.js.map +1 -0
- package/dist/storage/index.d.ts +18 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +89 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/keys.d.ts +50 -0
- package/dist/storage/keys.d.ts.map +1 -0
- package/dist/storage/keys.js +120 -0
- package/dist/storage/keys.js.map +1 -0
- package/dist/storage/memory.d.ts +32 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +84 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/provider.d.ts +93 -0
- package/dist/storage/provider.d.ts.map +1 -0
- package/dist/storage/provider.js +2 -0
- package/dist/storage/provider.js.map +1 -0
- package/dist/storage/s3.d.ts +34 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +175 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/storage/service.d.ts +86 -0
- package/dist/storage/service.d.ts.map +1 -0
- package/dist/storage/service.js +107 -0
- package/dist/storage/service.js.map +1 -0
- package/dist/storage/sigv4.d.ts +58 -0
- package/dist/storage/sigv4.d.ts.map +1 -0
- package/dist/storage/sigv4.js +114 -0
- package/dist/storage/sigv4.js.map +1 -0
- package/dist/streams/client.d.ts +91 -0
- package/dist/streams/client.d.ts.map +1 -0
- package/dist/streams/client.js +128 -0
- package/dist/streams/client.js.map +1 -0
- package/dist/streams/events.d.ts +68 -0
- package/dist/streams/events.d.ts.map +1 -0
- package/dist/streams/events.js +81 -0
- package/dist/streams/events.js.map +1 -0
- package/dist/streams/index.d.ts +47 -0
- package/dist/streams/index.d.ts.map +1 -0
- package/dist/streams/index.js +47 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/streams/realtime.d.ts +27 -0
- package/dist/streams/realtime.d.ts.map +1 -0
- package/dist/streams/realtime.js +50 -0
- package/dist/streams/realtime.js.map +1 -0
- package/dist/streams/state.d.ts +26 -0
- package/dist/streams/state.d.ts.map +1 -0
- package/dist/streams/state.js +34 -0
- package/dist/streams/state.js.map +1 -0
- package/dist/users/index.d.ts +9 -0
- package/dist/users/index.d.ts.map +1 -0
- package/dist/users/index.js +23 -0
- package/dist/users/index.js.map +1 -0
- package/dist/users/service.d.ts +43 -0
- package/dist/users/service.d.ts.map +1 -0
- package/dist/users/service.js +113 -0
- package/dist/users/service.js.map +1 -0
- package/dist/webhooks/inbound.d.ts +70 -0
- package/dist/webhooks/inbound.d.ts.map +1 -0
- package/dist/webhooks/inbound.js +146 -0
- package/dist/webhooks/inbound.js.map +1 -0
- package/dist/webhooks/index.d.ts +12 -0
- package/dist/webhooks/index.d.ts.map +1 -0
- package/dist/webhooks/index.js +65 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/outgoing.d.ts +89 -0
- package/dist/webhooks/outgoing.d.ts.map +1 -0
- package/dist/webhooks/outgoing.js +375 -0
- package/dist/webhooks/outgoing.js.map +1 -0
- package/dist/webhooks/signature.d.ts +40 -0
- package/dist/webhooks/signature.d.ts.map +1 -0
- package/dist/webhooks/signature.js +77 -0
- package/dist/webhooks/signature.js.map +1 -0
- package/dist/workspaces/context.d.ts +30 -0
- package/dist/workspaces/context.d.ts.map +1 -0
- package/dist/workspaces/context.js +12 -0
- package/dist/workspaces/context.js.map +1 -0
- package/dist/workspaces/index.d.ts +5 -0
- package/dist/workspaces/index.d.ts.map +1 -0
- package/dist/workspaces/index.js +21 -0
- package/dist/workspaces/index.js.map +1 -0
- package/dist/workspaces/service.d.ts +126 -0
- package/dist/workspaces/service.d.ts.map +1 -0
- package/dist/workspaces/service.js +495 -0
- package/dist/workspaces/service.js.map +1 -0
- package/docs/README.md +71 -0
- package/docs/api-keys.md +184 -0
- package/docs/audit.md +198 -0
- package/docs/auth.md +196 -0
- package/docs/authorization.md +225 -0
- package/docs/billing.md +293 -0
- package/docs/cli.md +238 -0
- package/docs/config.md +163 -0
- package/docs/db.md +219 -0
- package/docs/email.md +222 -0
- package/docs/entitlements.md +194 -0
- package/docs/errors.md +158 -0
- package/docs/events.md +279 -0
- package/docs/feature-flags.md +237 -0
- package/docs/files.md +229 -0
- package/docs/jobs.md +288 -0
- package/docs/logger.md +269 -0
- package/docs/notifications.md +179 -0
- package/docs/publishing.md +128 -0
- package/docs/realtime.md +360 -0
- package/docs/storage.md +279 -0
- package/docs/streams.md +296 -0
- package/docs/users.md +117 -0
- package/docs/webhooks.md +272 -0
- package/docs/workspaces.md +269 -0
- package/drizzle/0000_init_users.sql +21 -0
- package/drizzle/0001_workspaces_roles_permissions.sql +86 -0
- package/drizzle/0002_billing_entitlements.sql +97 -0
- package/drizzle/0003_events.sql +17 -0
- package/drizzle/0004_notifications_audit.sql +64 -0
- package/drizzle/0005_api_keys_webhooks.sql +77 -0
- package/drizzle/0006_feature_flags.sql +22 -0
- package/drizzle/0007_files.sql +23 -0
- package/drizzle/meta/0000_snapshot.json +160 -0
- package/drizzle/meta/0001_snapshot.json +837 -0
- package/drizzle/meta/0002_snapshot.json +1580 -0
- package/drizzle/meta/0003_snapshot.json +1751 -0
- package/drizzle/meta/0004_snapshot.json +2109 -0
- package/drizzle/meta/0005_snapshot.json +2719 -0
- package/drizzle/meta/0006_snapshot.json +2909 -0
- package/drizzle/meta/0007_snapshot.json +3113 -0
- package/drizzle/meta/_journal.json +62 -0
- package/package.json +180 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createInterface } from "node:readline/promises";
|
|
3
|
+
import { basename, resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { parseArgs } from "node:util";
|
|
6
|
+
import { devDown, devInit, devLogs, devStatus, devUp } from "./commands/dev.js";
|
|
7
|
+
import { projectInit, projectStart } from "./commands/project.js";
|
|
8
|
+
import { CliError, failure, info, style } from "./output.js";
|
|
9
|
+
import { normaliseProjectName } from "./templates.js";
|
|
10
|
+
const USAGE = `${style.bold("sc")} — bootstrap and run a @digimuza/saas-core project
|
|
11
|
+
|
|
12
|
+
${style.bold("Usage")}
|
|
13
|
+
sc init Ask for a project name and create docker-compose.yml
|
|
14
|
+
sc start Start PostgreSQL and wait until it is ready
|
|
15
|
+
|
|
16
|
+
${style.bold("Advanced development stack")}
|
|
17
|
+
saas-core dev up Start postgres, minio and caddy, then wait for health
|
|
18
|
+
saas-core dev down Stop the stack, keeping data
|
|
19
|
+
saas-core dev down --volumes
|
|
20
|
+
Stop and delete the volumes
|
|
21
|
+
saas-core dev status Show container state
|
|
22
|
+
saas-core dev logs Recent logs
|
|
23
|
+
saas-core dev init Write the stack files without starting anything
|
|
24
|
+
|
|
25
|
+
${style.bold("Options")}
|
|
26
|
+
--project <name> Compose project name (default: the directory name)
|
|
27
|
+
--domain <host> Host Caddy serves (default: app.localhost)
|
|
28
|
+
--app-port <n> Dev server port Caddy forwards to (default: 3000)
|
|
29
|
+
--postgres-port <n> Host port for postgres (default: 5432)
|
|
30
|
+
--minio-port <n> Host port for minio; console takes the next one
|
|
31
|
+
(default: 9000)
|
|
32
|
+
--force Overwrite generated files that already exist
|
|
33
|
+
--follow, -f Follow logs
|
|
34
|
+
--volumes With \`down\`: delete volumes too
|
|
35
|
+
--help, -h This text
|
|
36
|
+
--version Package version
|
|
37
|
+
|
|
38
|
+
${style.bold("Notes")}
|
|
39
|
+
The stack is generated into .saas-core/ and meant to be committed — it is
|
|
40
|
+
infrastructure, and a change to it should show up in a diff.
|
|
41
|
+
|
|
42
|
+
Every port binds to 127.0.0.1. Credentials are fixed and weak on purpose: this
|
|
43
|
+
holds throwaway data, and a generated password is one more thing to look up.
|
|
44
|
+
`;
|
|
45
|
+
async function promptProjectName() {
|
|
46
|
+
const defaultName = normaliseProjectName(basename(resolve(process.cwd())));
|
|
47
|
+
const prompt = createInterface({ input: process.stdin, output: process.stdout });
|
|
48
|
+
try {
|
|
49
|
+
const answer = await prompt.question(`Project name (${defaultName}): `);
|
|
50
|
+
return answer.trim() === "" ? defaultName : normaliseProjectName(answer);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
prompt.close();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Parse a port, rejecting anything that would fail later inside Docker. */
|
|
57
|
+
function port(raw, flag) {
|
|
58
|
+
if (raw === undefined) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const value = Number(raw);
|
|
62
|
+
if (!Number.isInteger(value) || value < 1 || value > 65_535) {
|
|
63
|
+
throw new CliError(`${flag} must be a port between 1 and 65535, not "${raw}".`);
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
export async function main(argv, dependencies = { promptProjectName }) {
|
|
68
|
+
let parsed;
|
|
69
|
+
try {
|
|
70
|
+
parsed = parseArgs({
|
|
71
|
+
args: [...argv],
|
|
72
|
+
allowPositionals: true,
|
|
73
|
+
options: {
|
|
74
|
+
project: { type: "string" },
|
|
75
|
+
domain: { type: "string" },
|
|
76
|
+
"app-port": { type: "string" },
|
|
77
|
+
"postgres-port": { type: "string" },
|
|
78
|
+
"minio-port": { type: "string" },
|
|
79
|
+
force: { type: "boolean" },
|
|
80
|
+
volumes: { type: "boolean" },
|
|
81
|
+
follow: { type: "boolean", short: "f" },
|
|
82
|
+
help: { type: "boolean", short: "h" },
|
|
83
|
+
version: { type: "boolean" },
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// parseArgs rejects unknown flags; say which and show usage.
|
|
89
|
+
failure(error instanceof Error ? error.message : "Could not parse arguments.");
|
|
90
|
+
info("");
|
|
91
|
+
info(USAGE);
|
|
92
|
+
return 2;
|
|
93
|
+
}
|
|
94
|
+
const { values, positionals } = parsed;
|
|
95
|
+
if (values.version === true) {
|
|
96
|
+
const { VERSION } = await import("../index.js");
|
|
97
|
+
info(VERSION);
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
if (values.help === true || positionals.length === 0) {
|
|
101
|
+
info(USAGE);
|
|
102
|
+
return values.help === true ? 0 : 2;
|
|
103
|
+
}
|
|
104
|
+
const appPort = port(values["app-port"], "--app-port");
|
|
105
|
+
const postgresPort = port(values["postgres-port"], "--postgres-port");
|
|
106
|
+
const minioPort = port(values["minio-port"], "--minio-port");
|
|
107
|
+
const options = {
|
|
108
|
+
...(typeof values.project === "string" ? { projectName: values.project } : {}),
|
|
109
|
+
...(typeof values.domain === "string" ? { domain: values.domain } : {}),
|
|
110
|
+
...(appPort !== undefined ? { appPort } : {}),
|
|
111
|
+
...(postgresPort !== undefined ? { postgresPort } : {}),
|
|
112
|
+
...(minioPort !== undefined ? { minioPort } : {}),
|
|
113
|
+
...(values.force === true ? { force: true } : {}),
|
|
114
|
+
};
|
|
115
|
+
const [group, action, ...rest] = positionals;
|
|
116
|
+
if (group === "init") {
|
|
117
|
+
if (action !== undefined) {
|
|
118
|
+
throw new CliError(`Unexpected argument "${action}" after \`sc init\`.`);
|
|
119
|
+
}
|
|
120
|
+
await projectInit({
|
|
121
|
+
...options,
|
|
122
|
+
projectName: typeof values.project === "string"
|
|
123
|
+
? values.project
|
|
124
|
+
: await dependencies.promptProjectName(),
|
|
125
|
+
});
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
if (group === "start") {
|
|
129
|
+
if (action !== undefined) {
|
|
130
|
+
throw new CliError(`Unexpected argument "${action}" after \`sc start\`.`);
|
|
131
|
+
}
|
|
132
|
+
await projectStart(options);
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
if (group !== "dev") {
|
|
136
|
+
throw new CliError(`Unknown command "${String(group)}".`, {
|
|
137
|
+
hint: "`sc --help` lists what there is.",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
switch (action) {
|
|
141
|
+
case "up":
|
|
142
|
+
await devUp(options);
|
|
143
|
+
return 0;
|
|
144
|
+
case "down":
|
|
145
|
+
await devDown({ ...options, ...(values.volumes === true ? { volumes: true } : {}) });
|
|
146
|
+
return 0;
|
|
147
|
+
case "status":
|
|
148
|
+
case "ps":
|
|
149
|
+
await devStatus(options);
|
|
150
|
+
return 0;
|
|
151
|
+
case "logs":
|
|
152
|
+
await devLogs({
|
|
153
|
+
...options,
|
|
154
|
+
...(values.follow === true ? { follow: true } : {}),
|
|
155
|
+
...(rest[0] !== undefined ? { service: rest[0] } : {}),
|
|
156
|
+
});
|
|
157
|
+
return 0;
|
|
158
|
+
case "init":
|
|
159
|
+
await devInit(options);
|
|
160
|
+
return 0;
|
|
161
|
+
default:
|
|
162
|
+
throw new CliError(action === undefined
|
|
163
|
+
? "`dev` needs a subcommand."
|
|
164
|
+
: `Unknown subcommand "dev ${action}".`, { hint: "One of: up, down, status, logs, init." });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Only run when executed as a binary, not when imported.
|
|
169
|
+
*
|
|
170
|
+
* Comparing resolved URLs rather than matching on the path: a substring check
|
|
171
|
+
* misfires on symlinks and on any path that merely ends with the same characters.
|
|
172
|
+
* The guard is what lets the tests call `main` directly instead of spawning a
|
|
173
|
+
* process, which is what makes the argument handling testable at all.
|
|
174
|
+
*/
|
|
175
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
176
|
+
if (invokedDirectly) {
|
|
177
|
+
try {
|
|
178
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof CliError) {
|
|
182
|
+
// A stack trace tells a CLI user nothing actionable and buries the message.
|
|
183
|
+
failure(error.message);
|
|
184
|
+
if (error.hint !== undefined) {
|
|
185
|
+
info(style.dim(` ${error.hint}`));
|
|
186
|
+
}
|
|
187
|
+
process.exitCode = 1;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
failure(error instanceof Error ? error.message : "Unexpected failure.");
|
|
191
|
+
if (error instanceof Error && error.stack !== undefined) {
|
|
192
|
+
info(style.dim(error.stack.split("\n").slice(1, 6).join("\n")));
|
|
193
|
+
}
|
|
194
|
+
process.exitCode = 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const style: {
|
|
2
|
+
bold: (text: string) => string;
|
|
3
|
+
dim: (text: string) => string;
|
|
4
|
+
red: (text: string) => string;
|
|
5
|
+
green: (text: string) => string;
|
|
6
|
+
yellow: (text: string) => string;
|
|
7
|
+
cyan: (text: string) => string;
|
|
8
|
+
};
|
|
9
|
+
export declare function info(message: string): void;
|
|
10
|
+
export declare function step(message: string): void;
|
|
11
|
+
export declare function success(message: string): void;
|
|
12
|
+
export declare function warn(message: string): void;
|
|
13
|
+
export declare function failure(message: string): void;
|
|
14
|
+
/** An aligned key/value block. For printing the environment a stack exposes. */
|
|
15
|
+
export declare function table(rows: readonly (readonly [string, string])[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* A problem the user can fix.
|
|
18
|
+
*
|
|
19
|
+
* Printed as a message and a hint, without a stack trace — a stack tells someone
|
|
20
|
+
* running a CLI nothing they can act on, and buries the one line that matters.
|
|
21
|
+
*/
|
|
22
|
+
export declare class CliError extends Error {
|
|
23
|
+
readonly name = "CliError";
|
|
24
|
+
/** Shown after the message, as a suggested next step. */
|
|
25
|
+
readonly hint?: string;
|
|
26
|
+
constructor(message: string, options?: {
|
|
27
|
+
hint?: string;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,KAAK;IAChB,IAAI,SAAS,MAAM;IACnB,GAAG,SAAS,MAAM;IAClB,GAAG,SAAS,MAAM;IAClB,KAAK,SAAS,MAAM;IACpB,MAAM,SAAS,MAAM;IACrB,IAAI,SAAS,MAAM;CACpB,CAAC;AAEF,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAG1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,gFAAgF;AAChF,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,IAAI,CAQxE;AAED;;;;;GAKG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAkB,IAAI,cAAc;IAEpC,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,EAK3D;CACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal output.
|
|
3
|
+
*
|
|
4
|
+
* No dependency: colour is a handful of escape codes and a TTY check. Anything
|
|
5
|
+
* writing to a pipe or a CI log gets plain text, because escape codes in a build
|
|
6
|
+
* log are noise a human then has to read around.
|
|
7
|
+
*/
|
|
8
|
+
const useColour = process.stdout.isTTY === true &&
|
|
9
|
+
process.env.NO_COLOR === undefined &&
|
|
10
|
+
process.env.TERM !== "dumb";
|
|
11
|
+
const ESC = "\u001b";
|
|
12
|
+
function paint(code, text) {
|
|
13
|
+
return useColour ? `${ESC}[${code}m${text}${ESC}[0m` : text;
|
|
14
|
+
}
|
|
15
|
+
export const style = {
|
|
16
|
+
bold: (text) => paint("1", text),
|
|
17
|
+
dim: (text) => paint("2", text),
|
|
18
|
+
red: (text) => paint("31", text),
|
|
19
|
+
green: (text) => paint("32", text),
|
|
20
|
+
yellow: (text) => paint("33", text),
|
|
21
|
+
cyan: (text) => paint("36", text),
|
|
22
|
+
};
|
|
23
|
+
export function info(message) {
|
|
24
|
+
process.stdout.write(`${message}\n`);
|
|
25
|
+
}
|
|
26
|
+
export function step(message) {
|
|
27
|
+
process.stdout.write(`${style.cyan(">")} ${message}\n`);
|
|
28
|
+
}
|
|
29
|
+
export function success(message) {
|
|
30
|
+
process.stdout.write(`${style.green("ok")} ${message}\n`);
|
|
31
|
+
}
|
|
32
|
+
export function warn(message) {
|
|
33
|
+
// Diagnostics go to stderr, so piping stdout stays clean.
|
|
34
|
+
process.stderr.write(`${style.yellow("!")} ${message}\n`);
|
|
35
|
+
}
|
|
36
|
+
export function failure(message) {
|
|
37
|
+
process.stderr.write(`${style.red("x")} ${message}\n`);
|
|
38
|
+
}
|
|
39
|
+
/** An aligned key/value block. For printing the environment a stack exposes. */
|
|
40
|
+
export function table(rows) {
|
|
41
|
+
if (rows.length === 0) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const width = Math.max(...rows.map(([key]) => key.length));
|
|
45
|
+
for (const [key, value] of rows) {
|
|
46
|
+
process.stdout.write(` ${style.dim(key.padEnd(width))} ${value}\n`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A problem the user can fix.
|
|
51
|
+
*
|
|
52
|
+
* Printed as a message and a hint, without a stack trace — a stack tells someone
|
|
53
|
+
* running a CLI nothing they can act on, and buries the one line that matters.
|
|
54
|
+
*/
|
|
55
|
+
export class CliError extends Error {
|
|
56
|
+
name = "CliError";
|
|
57
|
+
/** Shown after the message, as a suggested next step. */
|
|
58
|
+
hint;
|
|
59
|
+
constructor(message, options = {}) {
|
|
60
|
+
super(message);
|
|
61
|
+
if (options.hint !== undefined) {
|
|
62
|
+
this.hint = options.hint;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The local development stack, generated rather than shipped as a static file.
|
|
3
|
+
*
|
|
4
|
+
* Generated because ports collide: a developer with an existing PostgreSQL on
|
|
5
|
+
* 5432 needs a different one, and editing a vendored file means losing the edit
|
|
6
|
+
* on every upgrade. The output is written into the project and meant to be
|
|
7
|
+
* committed — it is infrastructure, and it should be reviewable in a diff.
|
|
8
|
+
*/
|
|
9
|
+
export interface StackConfig {
|
|
10
|
+
/** Compose project name. Namespaces containers, networks and volumes. */
|
|
11
|
+
readonly projectName: string;
|
|
12
|
+
/** Hostname Caddy terminates TLS for. */
|
|
13
|
+
readonly domain: string;
|
|
14
|
+
/** Where Caddy forwards to — the framework dev server on the host. */
|
|
15
|
+
readonly appPort: number;
|
|
16
|
+
readonly postgresPort: number;
|
|
17
|
+
readonly postgresUser: string;
|
|
18
|
+
readonly postgresPassword: string;
|
|
19
|
+
readonly postgresDatabase: string;
|
|
20
|
+
readonly minioPort: number;
|
|
21
|
+
readonly minioConsolePort: number;
|
|
22
|
+
readonly minioAccessKey: string;
|
|
23
|
+
readonly minioSecretKey: string;
|
|
24
|
+
readonly storageBucket: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const DEFAULT_STACK: Omit<StackConfig, "projectName">;
|
|
27
|
+
export interface ProjectComposeConfig {
|
|
28
|
+
readonly projectName: string;
|
|
29
|
+
readonly postgresPort: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The small stack created by `sc init`.
|
|
33
|
+
*
|
|
34
|
+
* Product projects start with PostgreSQL only. Additional infrastructure belongs
|
|
35
|
+
* in the product's compose file when it has a concrete need for it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderProjectComposeFile(config: ProjectComposeConfig): string;
|
|
38
|
+
export declare function renderComposeFile(config: StackConfig): string;
|
|
39
|
+
export declare function renderCaddyfile(config: StackConfig): string;
|
|
40
|
+
/** The `.gitignore` for the generated directory: state is local, config is not. */
|
|
41
|
+
export declare function renderStackGitignore(): string;
|
|
42
|
+
/**
|
|
43
|
+
* The environment this stack exposes.
|
|
44
|
+
*
|
|
45
|
+
* Printed rather than written to a file: configuration comes from Infisical, and
|
|
46
|
+
* a `.env` sitting in the project is exactly the habit that leads to one in
|
|
47
|
+
* production.
|
|
48
|
+
*/
|
|
49
|
+
export declare function stackEnvironment(config: StackConfig): (readonly [string, string])[];
|
|
50
|
+
/** A compose project name Docker will accept. */
|
|
51
|
+
export declare function normaliseProjectName(raw: string): string;
|
|
52
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,CAiB1D,CAAC;AAcF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CA2B7E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAsF7D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAsB3D;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,IAAI,MAAM,CAS7C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAcnF;AAED,iDAAiD;AACjD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUxD"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The local development stack, generated rather than shipped as a static file.
|
|
3
|
+
*
|
|
4
|
+
* Generated because ports collide: a developer with an existing PostgreSQL on
|
|
5
|
+
* 5432 needs a different one, and editing a vendored file means losing the edit
|
|
6
|
+
* on every upgrade. The output is written into the project and meant to be
|
|
7
|
+
* committed — it is infrastructure, and it should be reviewable in a diff.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_STACK = {
|
|
10
|
+
domain: "app.localhost",
|
|
11
|
+
appPort: 3000,
|
|
12
|
+
postgresPort: 5432,
|
|
13
|
+
/**
|
|
14
|
+
* Fixed, weak credentials. This stack binds to localhost and holds throwaway
|
|
15
|
+
* data; a generated password would only need storing somewhere, and a developer
|
|
16
|
+
* would then have to look it up to run `psql`.
|
|
17
|
+
*/
|
|
18
|
+
postgresUser: "saas",
|
|
19
|
+
postgresPassword: "saas",
|
|
20
|
+
postgresDatabase: "saas_core",
|
|
21
|
+
minioPort: 9000,
|
|
22
|
+
minioConsolePort: 9001,
|
|
23
|
+
minioAccessKey: "saascoredev",
|
|
24
|
+
minioSecretKey: "saascoredev",
|
|
25
|
+
storageBucket: "saas-core-dev",
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* PostgreSQL 17.
|
|
29
|
+
*
|
|
30
|
+
* 15 is the real floor: the schema uses `UNIQUE NULLS NOT DISTINCT` for feature
|
|
31
|
+
* flag overrides, which does not exist before it. Pinning the major version keeps
|
|
32
|
+
* a developer's local database from silently diverging from production.
|
|
33
|
+
*/
|
|
34
|
+
const POSTGRES_IMAGE = "postgres:17-alpine";
|
|
35
|
+
const MINIO_IMAGE = "minio/minio:latest";
|
|
36
|
+
const MINIO_CLIENT_IMAGE = "minio/mc:latest";
|
|
37
|
+
const CADDY_IMAGE = "caddy:2-alpine";
|
|
38
|
+
/**
|
|
39
|
+
* The small stack created by `sc init`.
|
|
40
|
+
*
|
|
41
|
+
* Product projects start with PostgreSQL only. Additional infrastructure belongs
|
|
42
|
+
* in the product's compose file when it has a concrete need for it.
|
|
43
|
+
*/
|
|
44
|
+
export function renderProjectComposeFile(config) {
|
|
45
|
+
const database = config.projectName.replaceAll("-", "_");
|
|
46
|
+
return `# Generated by \`sc init\`. Safe to edit and commit.
|
|
47
|
+
name: ${config.projectName}
|
|
48
|
+
|
|
49
|
+
services:
|
|
50
|
+
postgres:
|
|
51
|
+
image: ${POSTGRES_IMAGE}
|
|
52
|
+
restart: unless-stopped
|
|
53
|
+
environment:
|
|
54
|
+
POSTGRES_USER: sc
|
|
55
|
+
POSTGRES_PASSWORD: sc
|
|
56
|
+
POSTGRES_DB: ${database}
|
|
57
|
+
ports:
|
|
58
|
+
- "127.0.0.1:${config.postgresPort}:5432"
|
|
59
|
+
volumes:
|
|
60
|
+
- postgres-data:/var/lib/postgresql/data
|
|
61
|
+
healthcheck:
|
|
62
|
+
test: ["CMD-SHELL", "pg_isready -U sc -d ${database}"]
|
|
63
|
+
interval: 2s
|
|
64
|
+
timeout: 3s
|
|
65
|
+
retries: 30
|
|
66
|
+
|
|
67
|
+
volumes:
|
|
68
|
+
postgres-data:
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
export function renderComposeFile(config) {
|
|
72
|
+
return `# Generated by \`saas-core dev\`. Safe to edit and commit.
|
|
73
|
+
#
|
|
74
|
+
# Local development only. Nothing here is hardened: credentials are fixed, TLS
|
|
75
|
+
# uses Caddy's local CA, and every port binds to 127.0.0.1.
|
|
76
|
+
|
|
77
|
+
name: ${config.projectName}
|
|
78
|
+
|
|
79
|
+
services:
|
|
80
|
+
postgres:
|
|
81
|
+
image: ${POSTGRES_IMAGE}
|
|
82
|
+
restart: unless-stopped
|
|
83
|
+
environment:
|
|
84
|
+
POSTGRES_USER: ${config.postgresUser}
|
|
85
|
+
POSTGRES_PASSWORD: ${config.postgresPassword}
|
|
86
|
+
POSTGRES_DB: ${config.postgresDatabase}
|
|
87
|
+
ports:
|
|
88
|
+
# Bound to the loopback interface, not 0.0.0.0 — otherwise a laptop on a
|
|
89
|
+
# cafe network is serving an unauthenticated database to the room.
|
|
90
|
+
- "127.0.0.1:${config.postgresPort}:5432"
|
|
91
|
+
volumes:
|
|
92
|
+
- postgres-data:/var/lib/postgresql/data
|
|
93
|
+
healthcheck:
|
|
94
|
+
# \`--wait\` blocks on this, so "up" means "ready to accept a connection"
|
|
95
|
+
# rather than "the container started".
|
|
96
|
+
test: ["CMD-SHELL", "pg_isready -U ${config.postgresUser} -d ${config.postgresDatabase}"]
|
|
97
|
+
interval: 2s
|
|
98
|
+
timeout: 3s
|
|
99
|
+
retries: 30
|
|
100
|
+
|
|
101
|
+
minio:
|
|
102
|
+
image: ${MINIO_IMAGE}
|
|
103
|
+
restart: unless-stopped
|
|
104
|
+
command: server /data --console-address ":9001"
|
|
105
|
+
environment:
|
|
106
|
+
MINIO_ROOT_USER: ${config.minioAccessKey}
|
|
107
|
+
MINIO_ROOT_PASSWORD: ${config.minioSecretKey}
|
|
108
|
+
ports:
|
|
109
|
+
- "127.0.0.1:${config.minioPort}:9000"
|
|
110
|
+
- "127.0.0.1:${config.minioConsolePort}:9001"
|
|
111
|
+
volumes:
|
|
112
|
+
- minio-data:/data
|
|
113
|
+
healthcheck:
|
|
114
|
+
test: ["CMD", "mc", "ready", "local"]
|
|
115
|
+
interval: 2s
|
|
116
|
+
timeout: 3s
|
|
117
|
+
retries: 30
|
|
118
|
+
|
|
119
|
+
minio-init:
|
|
120
|
+
# One-shot: MinIO starts with no buckets, and the storage module expects the
|
|
121
|
+
# configured one to exist. Without this every upload fails on a fresh volume.
|
|
122
|
+
image: ${MINIO_CLIENT_IMAGE}
|
|
123
|
+
depends_on:
|
|
124
|
+
minio:
|
|
125
|
+
condition: service_healthy
|
|
126
|
+
entrypoint:
|
|
127
|
+
- sh
|
|
128
|
+
- -c
|
|
129
|
+
- |
|
|
130
|
+
mc alias set local http://minio:9000 ${config.minioAccessKey} ${config.minioSecretKey}
|
|
131
|
+
mc mb --ignore-existing local/${config.storageBucket}
|
|
132
|
+
echo "bucket ${config.storageBucket} ready"
|
|
133
|
+
|
|
134
|
+
caddy:
|
|
135
|
+
image: ${CADDY_IMAGE}
|
|
136
|
+
restart: unless-stopped
|
|
137
|
+
ports:
|
|
138
|
+
- "127.0.0.1:80:80"
|
|
139
|
+
- "127.0.0.1:443:443"
|
|
140
|
+
volumes:
|
|
141
|
+
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
142
|
+
# Persisted so the local CA survives a restart. Without it every restart
|
|
143
|
+
# issues a new root and the browser trust has to be redone.
|
|
144
|
+
- caddy-data:/data
|
|
145
|
+
- caddy-config:/config
|
|
146
|
+
extra_hosts:
|
|
147
|
+
# Caddy proxies to the dev server running on the *host*. Docker Desktop
|
|
148
|
+
# provides this name; on Linux it has to be mapped explicitly.
|
|
149
|
+
- "host.docker.internal:host-gateway"
|
|
150
|
+
|
|
151
|
+
volumes:
|
|
152
|
+
postgres-data:
|
|
153
|
+
minio-data:
|
|
154
|
+
caddy-data:
|
|
155
|
+
caddy-config:
|
|
156
|
+
`;
|
|
157
|
+
}
|
|
158
|
+
export function renderCaddyfile(config) {
|
|
159
|
+
return `# Generated by \`saas-core dev\`. Safe to edit and commit.
|
|
160
|
+
|
|
161
|
+
{
|
|
162
|
+
# Local development only. Never point this at a public address.
|
|
163
|
+
admin off
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
${config.domain} {
|
|
167
|
+
# Caddy's own CA, so local development runs over HTTPS.
|
|
168
|
+
#
|
|
169
|
+
# This matters beyond neatness: the auth module marks session cookies Secure
|
|
170
|
+
# outside development, WorkOS redirect URIs are easier to keep consistent when
|
|
171
|
+
# local and production are both https, and SameSite behaviour differs between
|
|
172
|
+
# schemes. Testing over plain http hides all three.
|
|
173
|
+
tls internal
|
|
174
|
+
|
|
175
|
+
# The framework dev server, on the host rather than in a container — so
|
|
176
|
+
# hot reload and the real node_modules keep working.
|
|
177
|
+
reverse_proxy host.docker.internal:${config.appPort}
|
|
178
|
+
}
|
|
179
|
+
`;
|
|
180
|
+
}
|
|
181
|
+
/** The `.gitignore` for the generated directory: state is local, config is not. */
|
|
182
|
+
export function renderStackGitignore() {
|
|
183
|
+
return `# Generated by \`saas-core dev\`.
|
|
184
|
+
#
|
|
185
|
+
# docker-compose.yml and Caddyfile are checked in — they are infrastructure, and
|
|
186
|
+
# a change to either should show up in a diff. Everything else here is local
|
|
187
|
+
# state.
|
|
188
|
+
*.log
|
|
189
|
+
.stack-state.json
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The environment this stack exposes.
|
|
194
|
+
*
|
|
195
|
+
* Printed rather than written to a file: configuration comes from Infisical, and
|
|
196
|
+
* a `.env` sitting in the project is exactly the habit that leads to one in
|
|
197
|
+
* production.
|
|
198
|
+
*/
|
|
199
|
+
export function stackEnvironment(config) {
|
|
200
|
+
return [
|
|
201
|
+
["APP_URL", `https://${config.domain}`],
|
|
202
|
+
[
|
|
203
|
+
"DATABASE_URL",
|
|
204
|
+
`postgres://${config.postgresUser}:${config.postgresPassword}` +
|
|
205
|
+
`@localhost:${config.postgresPort}/${config.postgresDatabase}`,
|
|
206
|
+
],
|
|
207
|
+
["STORAGE_BUCKET", config.storageBucket],
|
|
208
|
+
["STORAGE_REGION", "us-east-1"],
|
|
209
|
+
["STORAGE_ENDPOINT", `http://localhost:${config.minioPort}`],
|
|
210
|
+
["STORAGE_ACCESS_KEY_ID", config.minioAccessKey],
|
|
211
|
+
["STORAGE_SECRET_ACCESS_KEY", config.minioSecretKey],
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
/** A compose project name Docker will accept. */
|
|
215
|
+
export function normaliseProjectName(raw) {
|
|
216
|
+
const cleaned = raw
|
|
217
|
+
.toLowerCase()
|
|
218
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
219
|
+
.replace(/^[^a-z0-9]+/, "")
|
|
220
|
+
.replace(/[^a-z0-9]+$/, "")
|
|
221
|
+
.slice(0, 40);
|
|
222
|
+
// Compose rejects an empty or non-alphanumeric-leading name.
|
|
223
|
+
return cleaned.length === 0 ? "saas-core" : cleaned;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/cli/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Public configuration safe to ship in a browser bundle.
|
|
4
|
+
*
|
|
5
|
+
* This module is deliberately standalone: it does not import `./sections.js` or
|
|
6
|
+
* any other server configuration code, so nothing that describes or reads a
|
|
7
|
+
* secret can be pulled into a client bundle through it.
|
|
8
|
+
*
|
|
9
|
+
* Every variable is read as a **literal** `process.env.NEXT_PUBLIC_*` access.
|
|
10
|
+
* Next.js performs a textual substitution of those expressions at build time; a
|
|
11
|
+
* dynamic lookup such as `process.env[key]` is not substituted and would be
|
|
12
|
+
* `undefined` in the browser. Do not refactor these into a loop.
|
|
13
|
+
*/
|
|
14
|
+
declare const clientEnvSchema: z.ZodPipe<z.ZodObject<{
|
|
15
|
+
NEXT_PUBLIC_APP_NAME: z.ZodString;
|
|
16
|
+
NEXT_PUBLIC_APP_URL: z.ZodURL;
|
|
17
|
+
NEXT_PUBLIC_APP_ENV: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
development: "development";
|
|
19
|
+
production: "production";
|
|
20
|
+
staging: "staging";
|
|
21
|
+
test: "test";
|
|
22
|
+
}>>;
|
|
23
|
+
NEXT_PUBLIC_WORKOS_CLIENT_ID: z.ZodString;
|
|
24
|
+
NEXT_PUBLIC_REALTIME_URL: z.ZodOptional<z.ZodURL>;
|
|
25
|
+
}, z.core.$strip>, z.ZodTransform<{
|
|
26
|
+
appName: string;
|
|
27
|
+
appUrl: string;
|
|
28
|
+
environment: "development" | "production" | "staging" | "test";
|
|
29
|
+
isProduction: boolean;
|
|
30
|
+
workosClientId: string;
|
|
31
|
+
realtimeUrl: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
NEXT_PUBLIC_APP_NAME: string;
|
|
34
|
+
NEXT_PUBLIC_APP_URL: string;
|
|
35
|
+
NEXT_PUBLIC_APP_ENV: "development" | "production" | "staging" | "test";
|
|
36
|
+
NEXT_PUBLIC_WORKOS_CLIENT_ID: string;
|
|
37
|
+
NEXT_PUBLIC_REALTIME_URL?: string | undefined;
|
|
38
|
+
}>>;
|
|
39
|
+
export type ClientConfig = z.output<typeof clientEnvSchema>;
|
|
40
|
+
/** Typed, validated public configuration. Safe for client components. */
|
|
41
|
+
export declare const clientConfig: {
|
|
42
|
+
readonly app: {
|
|
43
|
+
name: string;
|
|
44
|
+
url: string;
|
|
45
|
+
environment: "development" | "production" | "staging" | "test";
|
|
46
|
+
isProduction: boolean;
|
|
47
|
+
};
|
|
48
|
+
readonly auth: {
|
|
49
|
+
workosClientId: string;
|
|
50
|
+
};
|
|
51
|
+
readonly realtime: {
|
|
52
|
+
url: string | undefined;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/** Eagerly validate public configuration. Call from a client entry point. */
|
|
56
|
+
export declare function assertClientConfig(): void;
|
|
57
|
+
/** Clear memoised public configuration. Test-only. */
|
|
58
|
+
export declare function resetClientConfigCache(): void;
|
|
59
|
+
export { ConfigError } from "./errors.ts";
|
|
60
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/config/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;GAWG;AAEH,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;GAmBhB,CAAC;AAEN,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAyC5D,yEAAyE;AACzE,eAAO,MAAM,YAAY;aACnB,GAAG;QAGH,IAAI;QACJ,GAAG;QACH,WAAW;QACX,YAAY;;aAGZ,IAAI;QACG,cAAc;;aAErB,QAAQ;QACD,GAAG;;CAEf,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|