@stacksjs/ts-cloud 0.7.91 → 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 +403 -344
- package/dist/bin/dashboard-server.js +280 -221
- package/dist/{chunk-3scf213a.js → chunk-fbwcv2vf.js} +53 -9
- package/dist/{chunk-j1kkmmrz.js → chunk-y5wrqyyz.js} +92 -21
- package/dist/control-plane/store.d.ts +1 -0
- package/dist/deploy/index.js +2 -2
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/rpx-gateway.d.ts +4 -0
- package/dist/index.js +2 -2
- package/dist/telemetry/store.d.ts +1 -0
- package/dist/ui/access-denied.html +2 -2
- package/dist/ui/account/automation.html +4 -4
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +4 -4
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +4 -4
- 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 +4 -4
- package/dist/ui/operations/maintenance.html +4 -4
- package/dist/ui/operations/observability.html +4 -4
- package/dist/ui/operations/previews.html +4 -4
- 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 +3 -3
- 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/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 +3 -3
- package/package.json +3 -3
|
@@ -1347,6 +1347,35 @@ function writeFileHeredoc(path, content, delimiter, mode = "0644") {
|
|
|
1347
1347
|
`chmod ${mode} ${path}`
|
|
1348
1348
|
];
|
|
1349
1349
|
}
|
|
1350
|
+
function shellSingleQuote(value) {
|
|
1351
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
1352
|
+
}
|
|
1353
|
+
function writeRpxFragment(path, content, delimiter, options) {
|
|
1354
|
+
if (!options.preserveManagementDashboardRoutes)
|
|
1355
|
+
return writeFileHeredoc(path, content, delimiter, "0600");
|
|
1356
|
+
const mergeScript = `
|
|
1357
|
+
const { readFileSync, writeFileSync } = require('node:fs')
|
|
1358
|
+
const currentPath = process.env.TS_CLOUD_RPX_CURRENT_FRAGMENT
|
|
1359
|
+
const candidatePath = process.env.TS_CLOUD_RPX_CANDIDATE_FRAGMENT
|
|
1360
|
+
const isDashboard = route => /^(?:dashboard|cloud)\\./i.test(String(route?.to || ''))
|
|
1361
|
+
const current = JSON.parse(readFileSync(currentPath, 'utf8'))
|
|
1362
|
+
const candidate = JSON.parse(readFileSync(candidatePath, 'utf8'))
|
|
1363
|
+
const retained = Array.isArray(current.proxies) ? current.proxies.filter(isDashboard) : []
|
|
1364
|
+
const next = Array.isArray(candidate.proxies) ? candidate.proxies.filter(route => !isDashboard(route)) : []
|
|
1365
|
+
candidate.proxies = [...next, ...retained]
|
|
1366
|
+
writeFileSync(candidatePath, JSON.stringify(candidate, null, 2) + '\\n', { mode: 0o600 })
|
|
1367
|
+
`.trim();
|
|
1368
|
+
return [
|
|
1369
|
+
`__tsc_fragment_candidate="$(mktemp "${path}.candidate.XXXXXX")"`,
|
|
1370
|
+
`cat > "$__tsc_fragment_candidate" <<'${delimiter}'`,
|
|
1371
|
+
content,
|
|
1372
|
+
delimiter,
|
|
1373
|
+
'chmod 0600 "$__tsc_fragment_candidate"',
|
|
1374
|
+
`if [ -f ${path} ]; then TS_CLOUD_RPX_CURRENT_FRAGMENT=${path} TS_CLOUD_RPX_CANDIDATE_FRAGMENT="$__tsc_fragment_candidate" ${options.bunBin} -e ${shellSingleQuote(mergeScript)}; fi`,
|
|
1375
|
+
`mv -f "$__tsc_fragment_candidate" ${path}`,
|
|
1376
|
+
`chmod 0600 ${path}`
|
|
1377
|
+
];
|
|
1378
|
+
}
|
|
1350
1379
|
function rpxCertRenewServiceName(slug) {
|
|
1351
1380
|
const safeSlug = (slug || "app").replace(/[^a-z0-9._-]+/gi, "-");
|
|
1352
1381
|
return `rpx-cert-renew-${safeSlug}.service`;
|
|
@@ -1459,7 +1488,10 @@ function buildRpxProvisionScript(options) {
|
|
|
1459
1488
|
`mv ${RPX_INSTALL_DIR}.next ${RPX_INSTALL_DIR}`,
|
|
1460
1489
|
`rm -rf ${RPX_INSTALL_DIR}.prev`,
|
|
1461
1490
|
`ln -sfn ${RPX_INSTALL_DIR}/node_modules ${RPX_DIR}/node_modules`,
|
|
1462
|
-
...
|
|
1491
|
+
...writeRpxFragment(`${RPX_SITES_DIR}/${slug}.json`, fragment, "TS_CLOUD_RPX_FRAGMENT_EOF", {
|
|
1492
|
+
bunBin,
|
|
1493
|
+
preserveManagementDashboardRoutes: options.preserveManagementDashboardRoutes
|
|
1494
|
+
}),
|
|
1463
1495
|
...writeFileHeredoc(RPX_LAUNCHER_PATH, assembler, "TS_CLOUD_RPX_EOF"),
|
|
1464
1496
|
`${bunBin} build --production --compile --outfile ${RPX_BINARY_PATH}.next ${RPX_LAUNCHER_PATH}`,
|
|
1465
1497
|
`chmod 0755 ${RPX_BINARY_PATH}.next`,
|
|
@@ -1508,7 +1540,10 @@ function buildRpxFragmentRefreshScript(options) {
|
|
|
1508
1540
|
return [
|
|
1509
1541
|
"set -euo pipefail",
|
|
1510
1542
|
`mkdir -p ${RPX_SITES_DIR}`,
|
|
1511
|
-
...
|
|
1543
|
+
...writeRpxFragment(`${RPX_SITES_DIR}/${slug}.json`, fragment, "TS_CLOUD_RPX_FRAGMENT_EOF", {
|
|
1544
|
+
bunBin: "/usr/local/bin/bun",
|
|
1545
|
+
preserveManagementDashboardRoutes: options.preserveManagementDashboardRoutes
|
|
1546
|
+
}),
|
|
1512
1547
|
`systemctl restart ${RPX_SERVICE_NAME}`
|
|
1513
1548
|
];
|
|
1514
1549
|
}
|
|
@@ -5909,16 +5944,16 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
5909
5944
|
perInstance: result.perInstance
|
|
5910
5945
|
};
|
|
5911
5946
|
}
|
|
5912
|
-
function
|
|
5947
|
+
function shellSingleQuote2(value) {
|
|
5913
5948
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
5914
5949
|
}
|
|
5915
5950
|
function buildManagementDashboardServiceReconciliationScript(slug, desiredSiteNames, serverOwner = false, desiredDomains = []) {
|
|
5916
5951
|
const prefix = `${slug}-dashboard-`;
|
|
5917
5952
|
const desiredUnits = desiredSiteNames.map((siteName) => `${slug}-${siteName}.service`);
|
|
5918
5953
|
const routeReconciliation = serverOwner ? [
|
|
5919
|
-
`export TS_CLOUD_DASHBOARD_KEEP_DOMAINS=${
|
|
5954
|
+
`export TS_CLOUD_DASHBOARD_KEEP_DOMAINS=${shellSingleQuote2(JSON.stringify(desiredDomains))}`,
|
|
5920
5955
|
"rm -f /run/ts-cloud-dashboard-routes-changed",
|
|
5921
|
-
`/usr/local/bin/bun --bun -e ${
|
|
5956
|
+
`/usr/local/bin/bun --bun -e ${shellSingleQuote2(`
|
|
5922
5957
|
const { chmodSync, existsSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } = require('node:fs')
|
|
5923
5958
|
const { basename, join } = require('node:path')
|
|
5924
5959
|
const root = '/etc/rpx/sites.d'
|
|
@@ -5954,9 +5989,9 @@ function buildManagementDashboardServiceReconciliationScript(slug, desiredSiteNa
|
|
|
5954
5989
|
] : [];
|
|
5955
5990
|
return [
|
|
5956
5991
|
"set -euo pipefail",
|
|
5957
|
-
`TS_CLOUD_DASHBOARD_PREFIX=${
|
|
5992
|
+
`TS_CLOUD_DASHBOARD_PREFIX=${shellSingleQuote2(prefix)}`,
|
|
5958
5993
|
`TS_CLOUD_DASHBOARD_SERVER_OWNER=${serverOwner ? "1" : "0"}`,
|
|
5959
|
-
`TS_CLOUD_DASHBOARD_DESIRED=${
|
|
5994
|
+
`TS_CLOUD_DASHBOARD_DESIRED=${shellSingleQuote2(` ${desiredUnits.join(" ")} `)}`,
|
|
5960
5995
|
"for TS_CLOUD_UNIT_FILE in /etc/systemd/system/*.service; do",
|
|
5961
5996
|
' [ -e "$TS_CLOUD_UNIT_FILE" ] || continue',
|
|
5962
5997
|
' TS_CLOUD_UNIT=$(basename "$TS_CLOUD_UNIT_FILE")',
|
|
@@ -6169,7 +6204,11 @@ async function reloadRpxGateway(options) {
|
|
|
6169
6204
|
logger.step(`Reloading the load balancer's rpx gateway with ${lbConfig.proxies.length} route(s)...`);
|
|
6170
6205
|
const result2 = await driver.runRemoteDeploy({
|
|
6171
6206
|
targets: lbTargets,
|
|
6172
|
-
commands: buildRpxFragmentRefreshScript({
|
|
6207
|
+
commands: buildRpxFragmentRefreshScript({
|
|
6208
|
+
config: lbConfig,
|
|
6209
|
+
slug,
|
|
6210
|
+
preserveManagementDashboardRoutes: options.managementDashboard === false
|
|
6211
|
+
}),
|
|
6173
6212
|
comment: `ts-cloud rpx gateway reload ${slug}`,
|
|
6174
6213
|
tags: {
|
|
6175
6214
|
Project: slug,
|
|
@@ -6200,7 +6239,12 @@ async function reloadRpxGateway(options) {
|
|
|
6200
6239
|
return true;
|
|
6201
6240
|
}
|
|
6202
6241
|
logger.step(`Reloading rpx gateway with ${rpxConfig.proxies.length} route(s)...`);
|
|
6203
|
-
const script = buildRpxProvisionScript({
|
|
6242
|
+
const script = buildRpxProvisionScript({
|
|
6243
|
+
proxy,
|
|
6244
|
+
config: rpxConfig,
|
|
6245
|
+
slug,
|
|
6246
|
+
preserveManagementDashboardRoutes: options.managementDashboard === false
|
|
6247
|
+
});
|
|
6204
6248
|
const result = await driver.runRemoteDeploy({
|
|
6205
6249
|
targets,
|
|
6206
6250
|
commands: script,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveSiteKind,
|
|
46
46
|
resolveUiSource,
|
|
47
47
|
siteInstallBase
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-fbwcv2vf.js";
|
|
49
49
|
import {
|
|
50
50
|
artifactKey,
|
|
51
51
|
buildCloudFormationTemplate,
|
|
@@ -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
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
synchronizeDashboardUsers,
|
|
31
31
|
trackDashboardOperation,
|
|
32
32
|
verifyStaticApiOrigin
|
|
33
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-y5wrqyyz.js";
|
|
34
34
|
import {
|
|
35
35
|
deleteStaticSite,
|
|
36
36
|
deployStaticSite,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
siteInstallBase,
|
|
71
71
|
validateDeploymentConfig,
|
|
72
72
|
verifyAddressRecord
|
|
73
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-fbwcv2vf.js";
|
|
74
74
|
import"../chunk-hmehkeqx.js";
|
|
75
75
|
import"../chunk-7m60qnc8.js";
|
|
76
76
|
import"../chunk-4cjrg98a.js";
|
package/dist/drivers/index.js
CHANGED
|
@@ -272,6 +272,8 @@ export interface BuildRpxProvisionOptions {
|
|
|
272
272
|
slug?: string;
|
|
273
273
|
/** Absolute path to the `bun` binary on the box. @default '/usr/local/bin/bun' */
|
|
274
274
|
bunBin?: string;
|
|
275
|
+
/** Keep the dashboard route currently running on the box during an app-only deploy. */
|
|
276
|
+
preserveManagementDashboardRoutes?: boolean;
|
|
275
277
|
}
|
|
276
278
|
export declare const RPX_CERT_RENEW_SCRIPT = "/etc/rpx/renew-certs.sh";
|
|
277
279
|
export declare const RPX_CERT_RENEW_SERVICE = "rpx-cert-renew.service";
|
|
@@ -310,6 +312,8 @@ export interface BuildRpxFragmentRefreshOptions {
|
|
|
310
312
|
* Defaults to `'app'`.
|
|
311
313
|
*/
|
|
312
314
|
slug?: string;
|
|
315
|
+
/** Keep the dashboard route currently running on the box during an app-only deploy. */
|
|
316
|
+
preserveManagementDashboardRoutes?: boolean;
|
|
313
317
|
}
|
|
314
318
|
/**
|
|
315
319
|
* Build the shell commands that rewrite ONLY this app's rpx route fragment
|
package/dist/index.js
CHANGED
|
@@ -283,7 +283,7 @@ import {
|
|
|
283
283
|
volumeCapabilities,
|
|
284
284
|
webhookEndpoint,
|
|
285
285
|
zeroCapacity
|
|
286
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-y5wrqyyz.js";
|
|
287
287
|
import {
|
|
288
288
|
deleteStaticSite,
|
|
289
289
|
deployStaticSite,
|
|
@@ -403,7 +403,7 @@ import {
|
|
|
403
403
|
waitForCloudInit,
|
|
404
404
|
waitForSsh,
|
|
405
405
|
wrapCloudInitUserData
|
|
406
|
-
} from "./chunk-
|
|
406
|
+
} from "./chunk-fbwcv2vf.js";
|
|
407
407
|
import {
|
|
408
408
|
ABTestManager,
|
|
409
409
|
AI,
|