@stacksjs/ts-cloud 0.7.92 → 0.7.93
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/dist/bin/cli.js +432 -384
- package/dist/bin/dashboard-server.js +271 -223
- package/dist/{chunk-29fwqkb7.js → chunk-y5wrqyyz.js} +91 -20
- package/dist/control-plane/store.d.ts +1 -0
- package/dist/deploy/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/telemetry/store.d.ts +1 -0
- package/dist/ui/access-denied.html +2 -2
- package/dist/ui/account/automation.html +3 -3
- package/dist/ui/applications/compose.html +4 -4
- package/dist/ui/data/backups.html +3 -3
- package/dist/ui/data/services.html +4 -4
- package/dist/ui/data/volumes.html +4 -4
- package/dist/ui/index.html +4 -4
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +4 -4
- package/dist/ui/operations/configuration.html +4 -4
- package/dist/ui/operations/jobs.html +3 -3
- package/dist/ui/operations/maintenance.html +4 -4
- package/dist/ui/operations/observability.html +3 -3
- package/dist/ui/operations/previews.html +3 -3
- package/dist/ui/operations/queue.html +4 -4
- package/dist/ui/operations/regions.html +4 -4
- package/dist/ui/operations/releases.html +4 -4
- package/dist/ui/operations/workloads.html +4 -4
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +4 -4
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +4 -4
- package/dist/ui/server/database.html +4 -4
- package/dist/ui/server/deployments.html +4 -4
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +4 -4
- package/dist/ui/server/fleet.html +4 -4
- package/dist/ui/server/logs.html +4 -4
- package/dist/ui/server/metrics.html +4 -4
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +4 -4
- package/dist/ui/server/ssh-keys.html +4 -4
- package/dist/ui/server/team.html +4 -4
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +4 -4
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +4 -4
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +4 -4
- package/dist/ui/serverless/logs.html +4 -4
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +4 -4
- package/dist/ui/serverless/secrets.html +4 -4
- package/dist/ui/serverless/traces.html +4 -4
- package/dist/ui/serverless.html +4 -4
- package/package.json +3 -3
|
@@ -92,7 +92,7 @@ import {
|
|
|
92
92
|
import { createHash as createHash5 } from "node:crypto";
|
|
93
93
|
|
|
94
94
|
// src/control-plane/migrations.ts
|
|
95
|
-
var CONTROL_PLANE_SCHEMA_VERSION =
|
|
95
|
+
var CONTROL_PLANE_SCHEMA_VERSION = 36;
|
|
96
96
|
var controlPlaneMigrations = [
|
|
97
97
|
{
|
|
98
98
|
version: 1,
|
|
@@ -1506,11 +1506,56 @@ var controlPlaneMigrations = [
|
|
|
1506
1506
|
CREATE INDEX cleanup_plan_status ON cleanup_plans(project_id,status,expires_at);
|
|
1507
1507
|
CREATE INDEX dr_drill_status ON disaster_recovery_drills(project_id,status,created_at DESC);
|
|
1508
1508
|
`
|
|
1509
|
+
},
|
|
1510
|
+
{
|
|
1511
|
+
version: 36,
|
|
1512
|
+
name: "telemetry_source_rollups",
|
|
1513
|
+
sql: `
|
|
1514
|
+
CREATE TABLE telemetry_source_rollups (
|
|
1515
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
1516
|
+
environment_id TEXT NOT NULL DEFAULT '',
|
|
1517
|
+
resource_id TEXT NOT NULL DEFAULT '',
|
|
1518
|
+
source TEXT NOT NULL,
|
|
1519
|
+
first_observed_at TEXT NOT NULL,
|
|
1520
|
+
latest_observed_at TEXT NOT NULL,
|
|
1521
|
+
ingested_bytes INTEGER NOT NULL DEFAULT 0 CHECK (ingested_bytes >= 0),
|
|
1522
|
+
record_count INTEGER NOT NULL DEFAULT 0 CHECK (record_count >= 0),
|
|
1523
|
+
PRIMARY KEY(project_id, environment_id, resource_id, source)
|
|
1524
|
+
) STRICT;
|
|
1525
|
+
|
|
1526
|
+
INSERT INTO telemetry_source_rollups (
|
|
1527
|
+
project_id, environment_id, resource_id, source,
|
|
1528
|
+
first_observed_at, latest_observed_at, ingested_bytes, record_count
|
|
1529
|
+
)
|
|
1530
|
+
SELECT
|
|
1531
|
+
project_id, COALESCE(environment_id, ''), COALESCE(resource_id, ''), source,
|
|
1532
|
+
MIN(observed_at), MAX(observed_at), SUM(ingested_bytes), COUNT(*)
|
|
1533
|
+
FROM telemetry_records
|
|
1534
|
+
GROUP BY project_id, COALESCE(environment_id, ''), COALESCE(resource_id, ''), source;
|
|
1535
|
+
|
|
1536
|
+
CREATE TRIGGER telemetry_source_rollups_insert
|
|
1537
|
+
AFTER INSERT ON telemetry_records
|
|
1538
|
+
BEGIN
|
|
1539
|
+
INSERT INTO telemetry_source_rollups (
|
|
1540
|
+
project_id, environment_id, resource_id, source,
|
|
1541
|
+
first_observed_at, latest_observed_at, ingested_bytes, record_count
|
|
1542
|
+
)
|
|
1543
|
+
VALUES (
|
|
1544
|
+
NEW.project_id, COALESCE(NEW.environment_id, ''), COALESCE(NEW.resource_id, ''), NEW.source,
|
|
1545
|
+
NEW.observed_at, NEW.observed_at, NEW.ingested_bytes, 1
|
|
1546
|
+
)
|
|
1547
|
+
ON CONFLICT(project_id, environment_id, resource_id, source) DO UPDATE SET
|
|
1548
|
+
first_observed_at = MIN(first_observed_at, excluded.first_observed_at),
|
|
1549
|
+
latest_observed_at = MAX(latest_observed_at, excluded.latest_observed_at),
|
|
1550
|
+
ingested_bytes = ingested_bytes + excluded.ingested_bytes,
|
|
1551
|
+
record_count = record_count + 1;
|
|
1552
|
+
END;
|
|
1553
|
+
`
|
|
1509
1554
|
}
|
|
1510
1555
|
];
|
|
1511
1556
|
// src/control-plane/store.ts
|
|
1512
1557
|
import { createHash, randomBytes } from "node:crypto";
|
|
1513
|
-
import { chmodSync, existsSync, mkdirSync, statSync
|
|
1558
|
+
import { chmodSync, existsSync, mkdirSync, statSync } from "node:fs";
|
|
1514
1559
|
import { dirname } from "node:path";
|
|
1515
1560
|
import { Database } from "bun:sqlite";
|
|
1516
1561
|
|
|
@@ -1978,6 +2023,12 @@ class ControlPlaneStore {
|
|
|
1978
2023
|
} catch {}
|
|
1979
2024
|
}
|
|
1980
2025
|
}
|
|
2026
|
+
backupTo(path) {
|
|
2027
|
+
this.database.run("VACUUM INTO ?", [path]);
|
|
2028
|
+
try {
|
|
2029
|
+
chmodSync(path, 384);
|
|
2030
|
+
} catch {}
|
|
2031
|
+
}
|
|
1981
2032
|
migrate() {
|
|
1982
2033
|
const row = this.database.query("PRAGMA user_version").get();
|
|
1983
2034
|
const current = Number(row?.user_version ?? 0);
|
|
@@ -1988,7 +2039,7 @@ class ControlPlaneStore {
|
|
|
1988
2039
|
let backupPath;
|
|
1989
2040
|
if (current > 0 && this.path !== ":memory:") {
|
|
1990
2041
|
backupPath = `${this.path}.v${current}.${Date.now()}.bak`;
|
|
1991
|
-
|
|
2042
|
+
this.backupTo(backupPath);
|
|
1992
2043
|
}
|
|
1993
2044
|
try {
|
|
1994
2045
|
const apply = this.database.transaction(() => {
|
|
@@ -2263,7 +2314,7 @@ class ControlPlaneStore {
|
|
|
2263
2314
|
return row ? mapMembership(row) : undefined;
|
|
2264
2315
|
}
|
|
2265
2316
|
listMemberships(organizationId, options = {}) {
|
|
2266
|
-
const revoked = options.includeRevoked ? "" :
|
|
2317
|
+
const revoked = options.includeRevoked ? "" : `AND status = 'active'`;
|
|
2267
2318
|
return this.database.query(`SELECT * FROM organization_memberships WHERE organization_id = ? ${revoked} ORDER BY created_at, id`).all(organizationId).map(mapMembership);
|
|
2268
2319
|
}
|
|
2269
2320
|
updateMembership(input) {
|
|
@@ -2314,7 +2365,7 @@ class ControlPlaneStore {
|
|
|
2314
2365
|
return membership;
|
|
2315
2366
|
}
|
|
2316
2367
|
assertAnotherOwner(current) {
|
|
2317
|
-
const owners = Number(this.database.query(
|
|
2368
|
+
const owners = Number(this.database.query(`SELECT COUNT(*) AS count FROM organization_memberships WHERE organization_id = ? AND status = ? AND role_template = 'owner'`).get(current.organizationId, "active")?.count ?? 0);
|
|
2318
2369
|
if (owners <= 1)
|
|
2319
2370
|
throw new Error("Cannot remove or demote the last organization owner");
|
|
2320
2371
|
}
|
|
@@ -2873,7 +2924,7 @@ class ControlPlaneStore {
|
|
|
2873
2924
|
if (this.path === ":memory:")
|
|
2874
2925
|
throw new Error("Cannot create a filesystem backup for an in-memory control plane");
|
|
2875
2926
|
const backupPath = `${this.path}.${Date.now()}.bak`;
|
|
2876
|
-
|
|
2927
|
+
this.backupTo(backupPath);
|
|
2877
2928
|
this.setSetting("storage.last_backup", { path: backupPath, createdAt: this.now(), reason });
|
|
2878
2929
|
return backupPath;
|
|
2879
2930
|
}
|
|
@@ -7990,7 +8041,7 @@ function estimateExistingStaticFullStackMonthlyCost(options = {}) {
|
|
|
7990
8041
|
// src/deploy/container-image.ts
|
|
7991
8042
|
import { execFileSync } from "node:child_process";
|
|
7992
8043
|
import { createHash as createHash8 } from "node:crypto";
|
|
7993
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, readdirSync, readFileSync, rmSync, statSync as statSync2, writeFileSync
|
|
8044
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, readdirSync, readFileSync, rmSync, statSync as statSync2, writeFileSync } from "node:fs";
|
|
7994
8045
|
import { tmpdir } from "node:os";
|
|
7995
8046
|
import { basename as basename2, join as join3, relative, resolve as resolve2 } from "node:path";
|
|
7996
8047
|
var IGNORED_DIRECTORIES = new Set([".git", "node_modules", "dist", "coverage"]);
|
|
@@ -8093,7 +8144,7 @@ async function buildAndPushContainerImage(options, injected) {
|
|
|
8093
8144
|
const registry = auth.proxyEndpoint.replace(/^https?:\/\//, "");
|
|
8094
8145
|
const dockerConfig = join3(temporaryDirectory, "docker");
|
|
8095
8146
|
mkdirSync2(dockerConfig, { recursive: true });
|
|
8096
|
-
|
|
8147
|
+
writeFileSync(join3(dockerConfig, "config.json"), JSON.stringify({ auths: { [registry]: { auth: auth.authorizationToken } } }), { mode: 384 });
|
|
8097
8148
|
dependencies2.run("docker", ["push", imageUri], { env: { ...process.env, DOCKER_CONFIG: dockerConfig } });
|
|
8098
8149
|
} finally {
|
|
8099
8150
|
rmSync(temporaryDirectory, { recursive: true, force: true });
|
|
@@ -10895,9 +10946,11 @@ class TelemetryStore {
|
|
|
10895
10946
|
if (environmentId)
|
|
10896
10947
|
bindings.push(environmentId);
|
|
10897
10948
|
const boundedResources = [...new Set(resourceIds ?? [])].slice(0, 100);
|
|
10949
|
+
if (resourceIds && boundedResources.length === 0)
|
|
10950
|
+
return [];
|
|
10898
10951
|
const resources = resourceIds ? ` AND resource_id IN (${boundedResources.map(() => "?").join(",") || "''"})` : "";
|
|
10899
10952
|
bindings.push(...boundedResources);
|
|
10900
|
-
const rows = this.controlPlane.database.query(`SELECT source, MAX(
|
|
10953
|
+
const rows = this.controlPlane.database.query(`SELECT source, MAX(latest_observed_at) latest, SUM(ingested_bytes) bytes, SUM(record_count) count, MIN(first_observed_at) first FROM telemetry_source_rollups WHERE project_id=?${environment2}${resources} GROUP BY source`).all(...bindings);
|
|
10901
10954
|
const now = this.now().getTime();
|
|
10902
10955
|
return rows.map((row) => {
|
|
10903
10956
|
const latest = String(row.latest);
|
|
@@ -11016,8 +11069,26 @@ class TelemetryStore {
|
|
|
11016
11069
|
const excess = Number(this.controlPlane.database.query(`SELECT MAX(0, COUNT(*)-?) excess FROM telemetry_records${projectId ? " WHERE project_id=?" : ""}`).get(policy.maxRecords, ...projectId ? [projectId] : [])?.excess ?? 0);
|
|
11017
11070
|
if (excess > 0)
|
|
11018
11071
|
this.controlPlane.database.run(`DELETE FROM telemetry_records WHERE id IN (SELECT id FROM telemetry_records${projectId ? " WHERE project_id=?" : ""} ORDER BY timestamp ASC LIMIT ?)`, projectId ? [projectId, excess] : [excess]);
|
|
11072
|
+
this.rebuildStatusRollups(projectId);
|
|
11019
11073
|
return { deleted: removed + excess, ...downsampled };
|
|
11020
11074
|
}
|
|
11075
|
+
rebuildStatusRollups(projectId) {
|
|
11076
|
+
const scope = projectId ? " WHERE project_id=?" : "";
|
|
11077
|
+
const bindings = projectId ? [projectId] : [];
|
|
11078
|
+
const rebuild = this.controlPlane.database.transaction(() => {
|
|
11079
|
+
this.controlPlane.database.run(`DELETE FROM telemetry_source_rollups${scope}`, bindings);
|
|
11080
|
+
this.controlPlane.database.run(`INSERT INTO telemetry_source_rollups (
|
|
11081
|
+
project_id, environment_id, resource_id, source,
|
|
11082
|
+
first_observed_at, latest_observed_at, ingested_bytes, record_count
|
|
11083
|
+
)
|
|
11084
|
+
SELECT
|
|
11085
|
+
project_id, COALESCE(environment_id, ''), COALESCE(resource_id, ''), source,
|
|
11086
|
+
MIN(observed_at), MAX(observed_at), SUM(ingested_bytes), COUNT(*)
|
|
11087
|
+
FROM telemetry_records${scope}
|
|
11088
|
+
GROUP BY project_id, COALESCE(environment_id, ''), COALESCE(resource_id, ''), source`, bindings);
|
|
11089
|
+
});
|
|
11090
|
+
rebuild();
|
|
11091
|
+
}
|
|
11021
11092
|
}
|
|
11022
11093
|
// src/alerts/telemetry.ts
|
|
11023
11094
|
function evaluateTelemetryAlertRules(store4, projectId, environmentId, now = new Date) {
|
|
@@ -12075,7 +12146,7 @@ async function manifestRequest(fetchFn, root, image, token, signal, authorizatio
|
|
|
12075
12146
|
}
|
|
12076
12147
|
// src/onboarding/artifact-store.ts
|
|
12077
12148
|
import { createHash as createHash12 } from "node:crypto";
|
|
12078
|
-
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, renameSync, unlinkSync, writeFileSync as
|
|
12149
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
12079
12150
|
import { basename as basename3, join as join5 } from "node:path";
|
|
12080
12151
|
function map2(row) {
|
|
12081
12152
|
return {
|
|
@@ -12122,7 +12193,7 @@ class ApplicationArtifactStore {
|
|
|
12122
12193
|
const path = join5(this.root, `${id}.archive`);
|
|
12123
12194
|
const temporary = `${path}.partial`;
|
|
12124
12195
|
try {
|
|
12125
|
-
|
|
12196
|
+
writeFileSync2(temporary, input.bytes, { mode: 384, flag: "wx" });
|
|
12126
12197
|
renameSync(temporary, path);
|
|
12127
12198
|
chmodSync2(path, 384);
|
|
12128
12199
|
this.controlPlane.database.run("INSERT INTO application_artifacts (id, organization_id, project_id, filename, storage_path, sha256, size, format, entry_count, expanded_bytes, created_by_actor_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
|
|
@@ -14755,7 +14826,7 @@ function webhookEndpoint(baseUrl, webhook) {
|
|
|
14755
14826
|
return new URL(`/api/source/webhooks/${encodeURIComponent(webhook.endpointToken)}`, base).href;
|
|
14756
14827
|
}
|
|
14757
14828
|
// src/source/git-workspace.ts
|
|
14758
|
-
import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as
|
|
14829
|
+
import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
14759
14830
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
14760
14831
|
import { join as join6, resolve as resolve5 } from "node:path";
|
|
14761
14832
|
function validateRemote(value, deployKey) {
|
|
@@ -14802,8 +14873,8 @@ function transportEnvironment(options) {
|
|
|
14802
14873
|
directory = mkdtempSync2(join6(tmpdir2(), "ts-cloud-git-transport-"));
|
|
14803
14874
|
const keyPath = join6(directory, "key");
|
|
14804
14875
|
const knownHostsPath = join6(directory, "known_hosts");
|
|
14805
|
-
|
|
14806
|
-
|
|
14876
|
+
writeFileSync3(keyPath, options.deployKey.privateKey, { mode: 384 });
|
|
14877
|
+
writeFileSync3(knownHostsPath, `${options.deployKey.host} ${options.deployKey.hostKey}
|
|
14807
14878
|
`, { mode: 384 });
|
|
14808
14879
|
chmodSync3(keyPath, 384);
|
|
14809
14880
|
chmodSync3(knownHostsPath, 384);
|
|
@@ -18280,7 +18351,7 @@ async function sendAuthenticationEmail(config, message) {
|
|
|
18280
18351
|
}
|
|
18281
18352
|
// src/auth/encryption.ts
|
|
18282
18353
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
18283
|
-
import { chmodSync as chmodSync4, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as
|
|
18354
|
+
import { chmodSync as chmodSync4, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
18284
18355
|
import { dirname as dirname2 } from "node:path";
|
|
18285
18356
|
function authEncryptionKeyFile() {
|
|
18286
18357
|
return statePath("auth-encryption-key");
|
|
@@ -18300,7 +18371,7 @@ function resolveAuthEncryptionKey(cwd) {
|
|
|
18300
18371
|
const key = randomBytes6(32).toString("base64url");
|
|
18301
18372
|
try {
|
|
18302
18373
|
mkdirSync4(dirname2(file), { recursive: true, mode: 448 });
|
|
18303
|
-
|
|
18374
|
+
writeFileSync4(file, `${key}
|
|
18304
18375
|
`, { mode: 384 });
|
|
18305
18376
|
chmodSync4(file, 384);
|
|
18306
18377
|
} catch {}
|
|
@@ -23027,7 +23098,7 @@ import { homedir as homedir3 } from "os";
|
|
|
23027
23098
|
import { dirname as dirname4, resolve as resolve12 } from "path";
|
|
23028
23099
|
import process20 from "process";
|
|
23029
23100
|
import { existsSync as existsSync22, statSync as statSync22 } from "fs";
|
|
23030
|
-
import { existsSync as existsSync82, mkdirSync as mkdirSync32, readdirSync as readdirSync32, writeFileSync as
|
|
23101
|
+
import { existsSync as existsSync82, mkdirSync as mkdirSync32, readdirSync as readdirSync32, writeFileSync as writeFileSync5 } from "fs";
|
|
23031
23102
|
import { homedir as homedir2 } from "os";
|
|
23032
23103
|
import { dirname as dirname3, resolve as resolve72 } from "path";
|
|
23033
23104
|
import process12 from "process";
|
|
@@ -28162,7 +28233,7 @@ function generateConfigTypes(options) {
|
|
|
28162
28233
|
const content = `// Generated by bunfig v${version}
|
|
28163
28234
|
export type ConfigNames = ${files.length ? `'${files.join("' | '")}'` : "string"}
|
|
28164
28235
|
`;
|
|
28165
|
-
|
|
28236
|
+
writeFileSync5(outputFile, content, { mode: 438 });
|
|
28166
28237
|
}
|
|
28167
28238
|
function createLibraryConfig(options) {
|
|
28168
28239
|
let configCache = null;
|
|
@@ -40133,7 +40204,7 @@ function clearSessionCookie(options = { secure: true }) {
|
|
|
40133
40204
|
}
|
|
40134
40205
|
|
|
40135
40206
|
// src/deploy/dashboard-users.ts
|
|
40136
|
-
import { chmodSync as chmodSync6, existsSync as existsSync19, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as
|
|
40207
|
+
import { chmodSync as chmodSync6, existsSync as existsSync19, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
40137
40208
|
import { dirname as dirname8 } from "node:path";
|
|
40138
40209
|
function usersFile() {
|
|
40139
40210
|
return statePath("dashboard-users.json");
|
|
@@ -40188,7 +40259,7 @@ function loadUsers(cwd) {
|
|
|
40188
40259
|
function saveUsers(cwd, users) {
|
|
40189
40260
|
const file = usersFilePath(cwd);
|
|
40190
40261
|
mkdirSync7(dirname8(file), { recursive: true });
|
|
40191
|
-
|
|
40262
|
+
writeFileSync9(file, `${JSON.stringify({ users }, null, 2)}
|
|
40192
40263
|
`);
|
|
40193
40264
|
chmodSync6(file, 384);
|
|
40194
40265
|
}
|
package/dist/deploy/index.js
CHANGED
package/dist/index.js
CHANGED