sporades 0.1.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.
Files changed (112) hide show
  1. package/Dockerfile.base +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +289 -0
  4. package/bin/sporades-host-helper.js +4001 -0
  5. package/bin/sporades.js +14198 -0
  6. package/dist/base-image.d.ts +43 -0
  7. package/dist/base-image.d.ts.map +1 -0
  8. package/dist/base-image.js +53 -0
  9. package/dist/base-image.js.map +1 -0
  10. package/dist/bundle-pipeline.d.ts +110 -0
  11. package/dist/bundle-pipeline.d.ts.map +1 -0
  12. package/dist/bundle-pipeline.js +369 -0
  13. package/dist/bundle-pipeline.js.map +1 -0
  14. package/dist/capsule-services.d.ts +94 -0
  15. package/dist/capsule-services.d.ts.map +1 -0
  16. package/dist/capsule-services.js +310 -0
  17. package/dist/capsule-services.js.map +1 -0
  18. package/dist/cli/cli-help.d.ts +16 -0
  19. package/dist/cli/cli-help.d.ts.map +1 -0
  20. package/dist/cli/cli-help.js +202 -0
  21. package/dist/cli/cli-help.js.map +1 -0
  22. package/dist/cli/cli-support.d.ts +17 -0
  23. package/dist/cli/cli-support.d.ts.map +1 -0
  24. package/dist/cli/cli-support.js +46 -0
  25. package/dist/cli/cli-support.js.map +1 -0
  26. package/dist/cli/github-autodeploy-workflow.d.ts +7 -0
  27. package/dist/cli/github-autodeploy-workflow.d.ts.map +1 -0
  28. package/dist/cli/github-autodeploy-workflow.js +185 -0
  29. package/dist/cli/github-autodeploy-workflow.js.map +1 -0
  30. package/dist/cli/host-helper-archive.d.ts +9 -0
  31. package/dist/cli/host-helper-archive.d.ts.map +1 -0
  32. package/dist/cli/host-helper-archive.js +74 -0
  33. package/dist/cli/host-helper-archive.js.map +1 -0
  34. package/dist/cli/host-helper-config.d.ts +15 -0
  35. package/dist/cli/host-helper-config.d.ts.map +1 -0
  36. package/dist/cli/host-helper-config.js +111 -0
  37. package/dist/cli/host-helper-config.js.map +1 -0
  38. package/dist/cli/host-helper-contract.d.ts +5 -0
  39. package/dist/cli/host-helper-contract.d.ts.map +1 -0
  40. package/dist/cli/host-helper-contract.js +5 -0
  41. package/dist/cli/host-helper-contract.js.map +1 -0
  42. package/dist/cli/host-helper-docker-types.d.ts +27 -0
  43. package/dist/cli/host-helper-docker-types.d.ts.map +1 -0
  44. package/dist/cli/host-helper-docker-types.js +2 -0
  45. package/dist/cli/host-helper-docker-types.js.map +1 -0
  46. package/dist/cli/host-helper-json.d.ts +6 -0
  47. package/dist/cli/host-helper-json.d.ts.map +1 -0
  48. package/dist/cli/host-helper-json.js +2 -0
  49. package/dist/cli/host-helper-json.js.map +1 -0
  50. package/dist/cli/host-helper-release-files.d.ts +4 -0
  51. package/dist/cli/host-helper-release-files.d.ts.map +1 -0
  52. package/dist/cli/host-helper-release-files.js +21 -0
  53. package/dist/cli/host-helper-release-files.js.map +1 -0
  54. package/dist/cli/host-helper-requests.d.ts +163 -0
  55. package/dist/cli/host-helper-requests.d.ts.map +1 -0
  56. package/dist/cli/host-helper-requests.js +2 -0
  57. package/dist/cli/host-helper-requests.js.map +1 -0
  58. package/dist/cli/host-helper-validation.d.ts +27 -0
  59. package/dist/cli/host-helper-validation.d.ts.map +1 -0
  60. package/dist/cli/host-helper-validation.js +256 -0
  61. package/dist/cli/host-helper-validation.js.map +1 -0
  62. package/dist/cli/host-request-builders.d.ts +143 -0
  63. package/dist/cli/host-request-builders.d.ts.map +1 -0
  64. package/dist/cli/host-request-builders.js +266 -0
  65. package/dist/cli/host-request-builders.js.map +1 -0
  66. package/dist/cli/hosted-capsule-contract.d.ts +128 -0
  67. package/dist/cli/hosted-capsule-contract.d.ts.map +1 -0
  68. package/dist/cli/hosted-capsule-contract.js +2 -0
  69. package/dist/cli/hosted-capsule-contract.js.map +1 -0
  70. package/dist/cli/sporades-host-helper.d.ts +3 -0
  71. package/dist/cli/sporades-host-helper.d.ts.map +1 -0
  72. package/dist/cli/sporades-host-helper.js +3120 -0
  73. package/dist/cli/sporades-host-helper.js.map +1 -0
  74. package/dist/cli/sporades.d.ts +3 -0
  75. package/dist/cli/sporades.d.ts.map +1 -0
  76. package/dist/cli/sporades.js +4066 -0
  77. package/dist/cli/sporades.js.map +1 -0
  78. package/dist/client.d.ts +7 -0
  79. package/dist/client.d.ts.map +1 -0
  80. package/dist/client.js +9 -0
  81. package/dist/client.js.map +1 -0
  82. package/dist/runtime-restart-policy.d.ts +29 -0
  83. package/dist/runtime-restart-policy.d.ts.map +1 -0
  84. package/dist/runtime-restart-policy.js +53 -0
  85. package/dist/runtime-restart-policy.js.map +1 -0
  86. package/dist/sealed-server-env.d.ts +56 -0
  87. package/dist/sealed-server-env.d.ts.map +1 -0
  88. package/dist/sealed-server-env.js +170 -0
  89. package/dist/sealed-server-env.js.map +1 -0
  90. package/dist/server-runtime-source.d.ts +1262 -0
  91. package/dist/server-runtime-source.d.ts.map +1 -0
  92. package/dist/server-runtime-source.js +6397 -0
  93. package/dist/server-runtime-source.js.map +1 -0
  94. package/dist/server.d.ts +58 -0
  95. package/dist/server.d.ts.map +1 -0
  96. package/dist/server.js +183 -0
  97. package/dist/server.js.map +1 -0
  98. package/dist/templates/client-runtime-template.d.ts +2 -0
  99. package/dist/templates/client-runtime-template.d.ts.map +1 -0
  100. package/dist/templates/client-runtime-template.js +438 -0
  101. package/dist/templates/client-runtime-template.js.map +1 -0
  102. package/dist/templates/scaffold-template.d.ts +19 -0
  103. package/dist/templates/scaffold-template.d.ts.map +1 -0
  104. package/dist/templates/scaffold-template.js +1201 -0
  105. package/dist/templates/scaffold-template.js.map +1 -0
  106. package/dist/templates/server-bundle-template.d.ts +8 -0
  107. package/dist/templates/server-bundle-template.d.ts.map +1 -0
  108. package/dist/templates/server-bundle-template.js +162 -0
  109. package/dist/templates/server-bundle-template.js.map +1 -0
  110. package/package.json +44 -0
  111. package/src/types/client.d.ts +161 -0
  112. package/src/types/server.d.ts +300 -0
@@ -0,0 +1,94 @@
1
+ export type JsonRecord = Record<string, unknown>;
2
+ export type DatabaseEngine = "libsql" | "postgres";
3
+ export type StorageEngine = "minio";
4
+ export type CapsuleServiceKind = "database" | "storage";
5
+ export type CapsuleServiceCredentials = {
6
+ databaseUser: string;
7
+ databasePassword: string;
8
+ storageAccessKey: string;
9
+ storageSecretKey: string;
10
+ };
11
+ export type CapsuleServiceOptions = {
12
+ credentials?: Partial<CapsuleServiceCredentials>;
13
+ publishPorts?: boolean;
14
+ };
15
+ export type DatabaseServiceDeclaration = {
16
+ kind: "database";
17
+ engine: DatabaseEngine;
18
+ };
19
+ export type StorageServiceDeclaration = {
20
+ kind: "storage";
21
+ engine: StorageEngine;
22
+ };
23
+ export type CapsuleServicesDeclaration = JsonRecord & {
24
+ database?: DatabaseServiceDeclaration;
25
+ storage?: StorageServiceDeclaration;
26
+ };
27
+ export type CapsuleProjectConfig = JsonRecord & {
28
+ name?: unknown;
29
+ services?: CapsuleServicesDeclaration;
30
+ };
31
+ export type CapsuleServiceBase = {
32
+ kind: CapsuleServiceKind;
33
+ name: string;
34
+ engine: string;
35
+ image: string;
36
+ stateDir: string;
37
+ targetPort: number;
38
+ volumeTarget: string;
39
+ environment: Record<string, string>;
40
+ healthcheck: string[];
41
+ command: string | null;
42
+ labels: Record<string, string>;
43
+ };
44
+ export type CapsuleDatabaseService = CapsuleServiceBase & {
45
+ kind: "database";
46
+ engine: DatabaseEngine;
47
+ user: string;
48
+ password: string;
49
+ databaseName: string;
50
+ };
51
+ export type CapsuleStorageService = CapsuleServiceBase & {
52
+ kind: "storage";
53
+ engine: StorageEngine;
54
+ accessKey: string;
55
+ secretKey: string;
56
+ bucket: string;
57
+ region: string;
58
+ namespace: string;
59
+ };
60
+ export type CapsuleService = CapsuleDatabaseService | CapsuleStorageService;
61
+ export type CapsuleServices = {
62
+ database?: CapsuleDatabaseService;
63
+ storage?: CapsuleStorageService;
64
+ };
65
+ export type CapsuleServicesComposeModel = {
66
+ projectSlug: string;
67
+ composeProjectName: string;
68
+ publishPorts: boolean;
69
+ credentials: CapsuleServiceCredentials;
70
+ services: CapsuleServices;
71
+ networks: {
72
+ services: string;
73
+ };
74
+ labels: Record<string, string>;
75
+ };
76
+ export type DatabaseEngineModel = {
77
+ engine: DatabaseEngine;
78
+ image: string;
79
+ targetPort: number;
80
+ volumeTarget: string;
81
+ environment: Record<string, string>;
82
+ healthcheck: string[];
83
+ };
84
+ export type WrittenCapsuleServicesCompose = CapsuleServicesComposeModel & {
85
+ path: string;
86
+ relativePath: string;
87
+ };
88
+ export declare const CAPSULE_SERVICES_COMPOSE_FILE: string;
89
+ export declare const CAPSULE_SERVICES_STATE_DIR: string;
90
+ export declare const CAPSULE_SERVICES_CREDENTIALS_FILE: string;
91
+ export declare function validateCapsuleServicesConfig(services: unknown): CapsuleServicesDeclaration | null;
92
+ export declare function writeCapsuleServicesCompose(projectDir: string, config: CapsuleProjectConfig, options?: CapsuleServiceOptions): Promise<WrittenCapsuleServicesCompose | null>;
93
+ export declare function capsuleServicesComposeModel(config: CapsuleProjectConfig, projectDir?: string, options?: CapsuleServiceOptions): CapsuleServicesComposeModel;
94
+ //# sourceMappingURL=capsule-services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capsule-services.d.ts","sourceRoot":"","sources":["../src/capsule-services.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,310 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ const SUPPORTED_SERVICE_KEYS = new Set(["database", "storage"]);
5
+ const SUPPORTED_DATABASE_ENGINES = new Set(["libsql", "postgres"]);
6
+ const SUPPORTED_STORAGE_ENGINES = new Set(["minio"]);
7
+ const LIBSQL_IMAGE = "ghcr.io/tursodatabase/libsql-server:v0.24.32";
8
+ const POSTGRES_IMAGE = "postgres:16-alpine";
9
+ const POSTGRES_USER = "sporades";
10
+ const POSTGRES_DATABASE = "sporades";
11
+ const MINIO_IMAGE = "quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Z";
12
+ const MINIO_ROOT_USER = "sporades";
13
+ const MINIO_BUCKET = "sporades-files";
14
+ const MINIO_REGION = "us-east-1";
15
+ export const CAPSULE_SERVICES_COMPOSE_FILE = path.join(".sporades", "compose", "capsule-services.compose.yml");
16
+ export const CAPSULE_SERVICES_STATE_DIR = path.join(".sporades", "services");
17
+ export const CAPSULE_SERVICES_CREDENTIALS_FILE = path.join(".sporades", "services", "credentials.json");
18
+ export function validateCapsuleServicesConfig(services) {
19
+ if (services === undefined) {
20
+ return null;
21
+ }
22
+ if (!isRecord(services)) {
23
+ throw commandError("Invalid Capsule services declaration.", "Set `services` in sporades.json to an object.");
24
+ }
25
+ for (const key of Object.keys(services)) {
26
+ if (!SUPPORTED_SERVICE_KEYS.has(key)) {
27
+ throw commandError(`Unsupported Capsule service: ${key}`, "Use supported Capsule service declarations: `services.database` or `services.storage`.");
28
+ }
29
+ }
30
+ if (services.database !== undefined) {
31
+ validateDatabaseServiceConfig(services.database);
32
+ }
33
+ if (services.storage !== undefined) {
34
+ validateStorageServiceConfig(services.storage);
35
+ }
36
+ return services;
37
+ }
38
+ export async function writeCapsuleServicesCompose(projectDir, config, options = {}) {
39
+ const composePath = path.join(projectDir, CAPSULE_SERVICES_COMPOSE_FILE);
40
+ if (!hasDeclaredCapsuleServices(config)) {
41
+ await rm(composePath, { force: true });
42
+ return null;
43
+ }
44
+ validateCapsuleServicesConfig(config.services);
45
+ await mkdir(path.dirname(composePath), { recursive: true });
46
+ const credentials = await loadOrCreateCapsuleServiceCredentials(projectDir);
47
+ const model = capsuleServicesComposeModel(config, projectDir, {
48
+ credentials,
49
+ publishPorts: options.publishPorts === true,
50
+ });
51
+ await Promise.all(Object.values(model.services).map((service) => mkdir(service.stateDir, { recursive: true })));
52
+ const source = renderCapsuleServicesCompose(model);
53
+ await writeFile(composePath, source);
54
+ return {
55
+ path: composePath,
56
+ relativePath: CAPSULE_SERVICES_COMPOSE_FILE,
57
+ ...model,
58
+ };
59
+ }
60
+ async function loadOrCreateCapsuleServiceCredentials(projectDir) {
61
+ const credentialsPath = path.join(projectDir, CAPSULE_SERVICES_CREDENTIALS_FILE);
62
+ let existing = {};
63
+ try {
64
+ const parsed = JSON.parse(await readFile(credentialsPath, "utf8"));
65
+ if (isRecord(parsed)) {
66
+ existing = parsed;
67
+ }
68
+ }
69
+ catch {
70
+ // Missing or unreadable credentials are regenerated below.
71
+ }
72
+ const credentials = {
73
+ databaseUser: typeof existing.databaseUser === "string" && existing.databaseUser ? existing.databaseUser : POSTGRES_USER,
74
+ databasePassword: typeof existing.databasePassword === "string" && existing.databasePassword
75
+ ? existing.databasePassword
76
+ : randomBytes(24).toString("base64url"),
77
+ storageAccessKey: typeof existing.storageAccessKey === "string" && existing.storageAccessKey ? existing.storageAccessKey : MINIO_ROOT_USER,
78
+ storageSecretKey: typeof existing.storageSecretKey === "string" && existing.storageSecretKey
79
+ ? existing.storageSecretKey
80
+ : randomBytes(24).toString("base64url"),
81
+ };
82
+ if (credentials.databaseUser !== existing.databaseUser ||
83
+ credentials.databasePassword !== existing.databasePassword ||
84
+ credentials.storageAccessKey !== existing.storageAccessKey ||
85
+ credentials.storageSecretKey !== existing.storageSecretKey) {
86
+ await mkdir(path.dirname(credentialsPath), { recursive: true });
87
+ await writeFile(credentialsPath, `${JSON.stringify(credentials, null, 2)}\n`, { mode: 0o600 });
88
+ }
89
+ return credentials;
90
+ }
91
+ export function capsuleServicesComposeModel(config, projectDir = process.cwd(), options = {}) {
92
+ const credentials = options.credentials ?? {};
93
+ const databaseUser = credentials.databaseUser ?? POSTGRES_USER;
94
+ const databasePassword = credentials.databasePassword ?? "";
95
+ const storageAccessKey = credentials.storageAccessKey ?? MINIO_ROOT_USER;
96
+ const storageSecretKey = credentials.storageSecretKey ?? "";
97
+ const projectSlug = slugify(config.name ?? "capsule");
98
+ const networkName = `sporades-${projectSlug}-services`;
99
+ const services = {};
100
+ const database = config.services?.database;
101
+ const storage = config.services?.storage;
102
+ const labels = {
103
+ "com.sporades.managed": "true",
104
+ "com.sporades.runtime-state": "true",
105
+ "com.sporades.project": projectSlug,
106
+ };
107
+ if (database) {
108
+ const engine = database.engine ?? "libsql";
109
+ const engineModel = engine === "postgres"
110
+ ? {
111
+ engine,
112
+ image: POSTGRES_IMAGE,
113
+ targetPort: 5432,
114
+ volumeTarget: "/var/lib/postgresql/data",
115
+ environment: {
116
+ POSTGRES_USER: databaseUser,
117
+ POSTGRES_PASSWORD: databasePassword,
118
+ POSTGRES_DB: POSTGRES_DATABASE,
119
+ },
120
+ healthcheck: ["CMD", "pg_isready", "-U", databaseUser, "-d", POSTGRES_DATABASE],
121
+ }
122
+ : {
123
+ engine: "libsql",
124
+ image: LIBSQL_IMAGE,
125
+ targetPort: 8080,
126
+ volumeTarget: "/var/lib/sqld",
127
+ environment: {},
128
+ healthcheck: ["CMD", "/bin/bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/8080"],
129
+ };
130
+ services.database = {
131
+ kind: "database",
132
+ name: `sporades-${projectSlug}-database`,
133
+ engine: engineModel.engine,
134
+ image: engineModel.image,
135
+ stateDir: path.join(projectDir, CAPSULE_SERVICES_STATE_DIR, "database"),
136
+ targetPort: engineModel.targetPort,
137
+ volumeTarget: engineModel.volumeTarget,
138
+ environment: engineModel.environment,
139
+ healthcheck: engineModel.healthcheck,
140
+ command: null,
141
+ labels: serviceLabels(labels, "database", engineModel.engine),
142
+ user: databaseUser,
143
+ password: databasePassword,
144
+ databaseName: POSTGRES_DATABASE,
145
+ };
146
+ }
147
+ if (storage) {
148
+ services.storage = {
149
+ kind: "storage",
150
+ name: `sporades-${projectSlug}-storage`,
151
+ engine: "minio",
152
+ image: MINIO_IMAGE,
153
+ stateDir: path.join(projectDir, CAPSULE_SERVICES_STATE_DIR, "storage"),
154
+ targetPort: 9000,
155
+ volumeTarget: "/data",
156
+ environment: {
157
+ MINIO_ROOT_USER: storageAccessKey,
158
+ MINIO_ROOT_PASSWORD: storageSecretKey,
159
+ },
160
+ healthcheck: ["CMD", "curl", "-fsS", "http://127.0.0.1:9000/minio/health/ready"],
161
+ command: 'server /data --console-address ":9001"',
162
+ labels: serviceLabels(labels, "storage", "minio"),
163
+ accessKey: storageAccessKey,
164
+ secretKey: storageSecretKey,
165
+ bucket: MINIO_BUCKET,
166
+ region: MINIO_REGION,
167
+ namespace: projectSlug,
168
+ };
169
+ }
170
+ const model = {
171
+ projectSlug,
172
+ composeProjectName: `sporades-${projectSlug}-services`,
173
+ publishPorts: options.publishPorts === true,
174
+ credentials: {
175
+ databaseUser,
176
+ databasePassword,
177
+ storageAccessKey,
178
+ storageSecretKey,
179
+ },
180
+ services,
181
+ networks: {
182
+ services: networkName,
183
+ },
184
+ labels,
185
+ };
186
+ return model;
187
+ }
188
+ function validateDatabaseServiceConfig(database) {
189
+ if (!isRecord(database)) {
190
+ throw commandError("Invalid database Capsule service declaration.", "Set `services.database` to `{ \"kind\": \"database\", \"engine\": \"libsql\" }` or `{ \"kind\": \"database\", \"engine\": \"postgres\" }`.");
191
+ }
192
+ if (database.kind !== "database") {
193
+ throw commandError("Unsupported database Capsule service kind.", "Use `services.database.kind` of `database`.");
194
+ }
195
+ if (typeof database.engine !== "string" || !SUPPORTED_DATABASE_ENGINES.has(database.engine)) {
196
+ throw commandError(`Unsupported database Capsule service engine: ${database.engine ?? "missing"}`, "Use `services.database.engine` of `libsql` or `postgres`.");
197
+ }
198
+ }
199
+ function validateStorageServiceConfig(storage) {
200
+ if (!isRecord(storage)) {
201
+ throw commandError("Invalid storage Capsule service declaration.", "Set `services.storage` to `{ \"kind\": \"storage\", \"engine\": \"minio\" }`.");
202
+ }
203
+ if (storage.kind !== "storage") {
204
+ throw commandError("Unsupported storage Capsule service kind.", "Use `services.storage.kind` of `storage`.");
205
+ }
206
+ if (typeof storage.engine !== "string" || !SUPPORTED_STORAGE_ENGINES.has(storage.engine)) {
207
+ throw commandError(`Unsupported storage Capsule service engine: ${storage.engine ?? "missing"}`, "Use `services.storage.engine` of `minio`.");
208
+ }
209
+ }
210
+ function renderCapsuleServicesCompose(model) {
211
+ const services = Object.values(model.services)
212
+ .map((service) => renderServiceCompose(service, model))
213
+ .join("\n");
214
+ return `# Sporades-owned runtime state. Do not edit by hand.
215
+ # Generated from sporades.json Capsule service declarations.
216
+ name: ${model.composeProjectName}
217
+
218
+ services:
219
+ ${services}
220
+
221
+ networks:
222
+ ${model.networks.services}:
223
+ name: ${model.networks.services}
224
+ labels:
225
+ ${renderLabels(model.labels, 6)}
226
+ `;
227
+ }
228
+ function renderServiceCompose(service, model) {
229
+ // Ports are published (loopback-only) solely for local dev sessions, where the
230
+ // Capsule runs as a host process. Container sessions reach services by name on
231
+ // the project network; publishing a port would also open it to containers on
232
+ // other Docker networks.
233
+ const ports = model.publishPorts
234
+ ? ` ports:
235
+ - "127.0.0.1::${service.targetPort}"
236
+ `
237
+ : "";
238
+ return ` ${service.name}:
239
+ image: ${service.image}
240
+ container_name: ${service.name}
241
+ labels:
242
+ ${renderLabels(service.labels, 6)}
243
+ ${renderEnvironment(service.environment, 4)}${renderCommand(service.command, 4)}${renderHealthcheck(service.healthcheck, 4)}
244
+ networks:
245
+ - ${model.networks.services}
246
+ ${ports} volumes:
247
+ - ${JSON.stringify(`${service.stateDir}:${service.volumeTarget}:rw`)}
248
+ `;
249
+ }
250
+ function renderHealthcheck(healthcheck, indent) {
251
+ if (!healthcheck) {
252
+ return "";
253
+ }
254
+ const padding = " ".repeat(indent);
255
+ return `${padding}healthcheck:
256
+ ${padding} test: ${JSON.stringify(healthcheck)}
257
+ ${padding} interval: 5s
258
+ ${padding} timeout: 3s
259
+ ${padding} retries: 3
260
+ ${padding} start_period: 60s
261
+ ${padding} start_interval: 1s
262
+ `;
263
+ }
264
+ function renderCommand(command, indent) {
265
+ if (!command) {
266
+ return "";
267
+ }
268
+ const padding = " ".repeat(indent);
269
+ return `${padding}command: ${JSON.stringify(command)}\n`;
270
+ }
271
+ function renderEnvironment(environment, indent) {
272
+ const entries = Object.entries(environment ?? {});
273
+ if (entries.length === 0) {
274
+ return "";
275
+ }
276
+ const padding = " ".repeat(indent);
277
+ return `${padding}environment:\n${entries.map(([key, value]) => `${padding} ${key}: ${JSON.stringify(value)}`).join("\n")}\n`;
278
+ }
279
+ function renderLabels(labels, indent) {
280
+ const padding = " ".repeat(indent);
281
+ return Object.entries(labels)
282
+ .map(([key, value]) => `${padding}${key}: ${JSON.stringify(value)}`)
283
+ .join("\n");
284
+ }
285
+ function slugify(value) {
286
+ const slug = String(value)
287
+ .toLowerCase()
288
+ .replace(/[^a-z0-9]+/g, "-")
289
+ .replace(/^-+|-+$/g, "");
290
+ return slug || "capsule";
291
+ }
292
+ function hasDeclaredCapsuleServices(config) {
293
+ return Boolean(config.services?.database || config.services?.storage);
294
+ }
295
+ function serviceLabels(labels, kind, engine) {
296
+ return {
297
+ ...labels,
298
+ "com.sporades.capsule-service.kind": kind,
299
+ "com.sporades.capsule-service.engine": engine,
300
+ };
301
+ }
302
+ function isRecord(value) {
303
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
304
+ }
305
+ function commandError(message, hint) {
306
+ const error = new Error(message);
307
+ error.hint = hint;
308
+ return error;
309
+ }
310
+ //# sourceMappingURL=capsule-services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capsule-services.js","sourceRoot":"","sources":["../src/capsule-services.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ declare const HELP_TEXT: {
2
+ readonly create: "Usage: sporades create <name> [options]\n\nScaffold a new Capsule.\n\nOptions:\n --framework <name> Client framework: react or preact\n --template <name> Template: blank, todo, guestbook, or photo-library\n --no-install Skip npm install\n --no-git Skip git initialization\n --json Write JSON output\n --help, -h Show this help\n";
3
+ readonly dev: "Usage: sporades dev [status|stop|reset] [options]\n\nStart and manage a local Dev session.\n\nCommands:\n dev Start a Dev session\n dev status Print Dev session status\n dev stop Stop the running Dev session\n dev reset Stop the Dev session and remove local Dev state\n\nOptions:\n --port <number> Dev session port when starting\n --public Allow non-localhost access when starting\n --json Write JSON output\n --help, -h Show this help\n";
4
+ readonly auth: "Usage: sporades auth <command> [options]\n\nManage local auth configuration and identity simulation.\n\nCommands:\n status Print auth provider status\n clients List connected Dev session clients\n set google Configure Google OAuth credentials\n as email Simulate a local email identity\n\nOptions:\n --client-id <id> Google OAuth client ID\n --client-secret <secret> Google OAuth client secret\n --client-json <path> Read Google OAuth credentials JSON\n --email <address> Simulated email identity\n --display-name <name> Simulated display name\n --picture <url> Simulated profile picture URL\n --port <number> Target Dev session port\n --client <target> Delivery target: current, all, or a client ID\n --json Write JSON output\n --help, -h Show this help\n";
5
+ readonly security: "Usage: sporades security [options]\n\nInspect effective Capsule security policy.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --json Write JSON output\n --help, -h Show this help\n";
6
+ readonly env: "Usage: sporades env <command> [options]\n\nManage Sealed Server env.\n\nCommands:\n init Create local Sealed Server env key material\n import Import Server env values from a file\n status Print Sealed Server env status\n export Export Sealed Server env for a Host profile\n reencrypt Re-encrypt local Sealed Server env material\n\nOptions:\n --file <path> Input file for import or export\n --host <alias> Host profile alias\n --subname <name> Hosted Capsule subname\n --output <path> Export output path\n --sealed Treat input as an already sealed export\n --json Write JSON output\n --help, -h Show this help\n";
7
+ readonly deploy: "Usage: sporades deploy [status|stop|restart|remove|reset] [options]\n\nStart and manage a local Container session.\n\nCommands:\n deploy Start a local Container session\n deploy status Print Container session status\n deploy stop Stop the running Container session\n deploy restart Restart the running Container session\n deploy remove Remove the Container session\n deploy reset Remove the Container session and local container state\n\nOptions:\n --port <number> Published local port when starting\n --force Replace stale or conflicting container state when starting\n --json Write JSON output\n --help, -h Show this help\n";
8
+ readonly host: "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n health [subname] Check Host server or Hosted Capsule health\n\nCapsule commands:\n bind <subname> Bind this project to a Hosted Capsule\n register <subname> Register a Hosted Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n";
9
+ readonly logs: "Usage: sporades logs [tail] [options]\n\nPrint Dev session logs.\n\nCommands:\n logs Print recent Dev session logs\n logs tail Follow Dev session logs\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
10
+ readonly db: "Usage: sporades db <command> [options]\n\nInspect the Dev session database.\n\nCommands:\n list List database tables\n dump Dump database contents\n query <sql> Run a read-only SQL query\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
11
+ readonly default: "Usage: sporades <command> [options]\n \n Commands:\n create <name> Scaffold a new Capsule\n dev Start a local Dev session\n auth Manage local auth configuration and simulation\n security Inspect effective Capsule security policy\n env Manage Sealed Server env\n deploy Start a local Container session\n host Manage Host profiles and Hosted Capsules\n logs Print Dev session logs\n db Inspect the Dev session database\n \n Options:\n --help, -h Show help for command\n --json Write JSON output when supported by the command\n ";
12
+ };
13
+ export type CliHelpCommand = keyof Omit<typeof HELP_TEXT, "default">;
14
+ export declare function renderCliHelp(command?: string): "Usage: sporades create <name> [options]\n\nScaffold a new Capsule.\n\nOptions:\n --framework <name> Client framework: react or preact\n --template <name> Template: blank, todo, guestbook, or photo-library\n --no-install Skip npm install\n --no-git Skip git initialization\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades dev [status|stop|reset] [options]\n\nStart and manage a local Dev session.\n\nCommands:\n dev Start a Dev session\n dev status Print Dev session status\n dev stop Stop the running Dev session\n dev reset Stop the Dev session and remove local Dev state\n\nOptions:\n --port <number> Dev session port when starting\n --public Allow non-localhost access when starting\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades auth <command> [options]\n\nManage local auth configuration and identity simulation.\n\nCommands:\n status Print auth provider status\n clients List connected Dev session clients\n set google Configure Google OAuth credentials\n as email Simulate a local email identity\n\nOptions:\n --client-id <id> Google OAuth client ID\n --client-secret <secret> Google OAuth client secret\n --client-json <path> Read Google OAuth credentials JSON\n --email <address> Simulated email identity\n --display-name <name> Simulated display name\n --picture <url> Simulated profile picture URL\n --port <number> Target Dev session port\n --client <target> Delivery target: current, all, or a client ID\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades security [options]\n\nInspect effective Capsule security policy.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades env <command> [options]\n\nManage Sealed Server env.\n\nCommands:\n init Create local Sealed Server env key material\n import Import Server env values from a file\n status Print Sealed Server env status\n export Export Sealed Server env for a Host profile\n reencrypt Re-encrypt local Sealed Server env material\n\nOptions:\n --file <path> Input file for import or export\n --host <alias> Host profile alias\n --subname <name> Hosted Capsule subname\n --output <path> Export output path\n --sealed Treat input as an already sealed export\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades deploy [status|stop|restart|remove|reset] [options]\n\nStart and manage a local Container session.\n\nCommands:\n deploy Start a local Container session\n deploy status Print Container session status\n deploy stop Stop the running Container session\n deploy restart Restart the running Container session\n deploy remove Remove the Container session\n deploy reset Remove the Container session and local container state\n\nOptions:\n --port <number> Published local port when starting\n --force Replace stale or conflicting container state when starting\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n health [subname] Check Host server or Hosted Capsule health\n\nCapsule commands:\n bind <subname> Bind this project to a Hosted Capsule\n register <subname> Register a Hosted Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades logs [tail] [options]\n\nPrint Dev session logs.\n\nCommands:\n logs Print recent Dev session logs\n logs tail Follow Dev session logs\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades db <command> [options]\n\nInspect the Dev session database.\n\nCommands:\n list List database tables\n dump Dump database contents\n query <sql> Run a read-only SQL query\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
15
+ export {};
16
+ //# sourceMappingURL=cli-help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../../src/cli/cli-help.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,SAAS;;;;;;;;;;;CAqML,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC;AAErE,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,04MAE7C"}