@specific.dev/cli 0.1.222 → 0.1.224
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/admin/404/index.html +1 -1
- package/dist/admin/404.html +1 -1
- package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +1 -1
- package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/__next._full.txt +2 -2
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +2 -2
- package/dist/admin/__next._tree.txt +2 -2
- package/dist/admin/_next/static/chunks/{1fac7a1b12b837ea.css → 24ff82c52f4b2700.css} +3 -3
- package/dist/admin/_not-found/__next._full.txt +2 -2
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +2 -2
- package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/admin/_not-found/__next._not-found.txt +1 -1
- package/dist/admin/_not-found/__next._tree.txt +2 -2
- package/dist/admin/_not-found/index.html +1 -1
- package/dist/admin/_not-found/index.txt +2 -2
- package/dist/admin/crons/__next.!KGRlZmF1bHQp.crons.__PAGE__.txt +1 -1
- package/dist/admin/crons/__next.!KGRlZmF1bHQp.crons.txt +1 -1
- package/dist/admin/crons/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/crons/__next._full.txt +2 -2
- package/dist/admin/crons/__next._head.txt +1 -1
- package/dist/admin/crons/__next._index.txt +2 -2
- package/dist/admin/crons/__next._tree.txt +2 -2
- package/dist/admin/crons/index.html +1 -1
- package/dist/admin/crons/index.txt +2 -2
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/databases/__next._full.txt +2 -2
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +2 -2
- package/dist/admin/databases/__next._tree.txt +2 -2
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +2 -2
- package/dist/admin/fullscreen/__next._full.txt +2 -2
- package/dist/admin/fullscreen/__next._head.txt +1 -1
- package/dist/admin/fullscreen/__next._index.txt +2 -2
- package/dist/admin/fullscreen/__next._tree.txt +2 -2
- package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._full.txt +2 -2
- package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._index.txt +2 -2
- package/dist/admin/fullscreen/databases/__next._tree.txt +2 -2
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/index.html +1 -1
- package/dist/admin/fullscreen/databases/index.txt +2 -2
- package/dist/admin/fullscreen/index.html +1 -1
- package/dist/admin/fullscreen/index.txt +2 -2
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +2 -2
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.__PAGE__.txt +1 -1
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.txt +1 -1
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/mail/__next._full.txt +2 -2
- package/dist/admin/mail/__next._head.txt +1 -1
- package/dist/admin/mail/__next._index.txt +2 -2
- package/dist/admin/mail/__next._tree.txt +2 -2
- package/dist/admin/mail/index.html +1 -1
- package/dist/admin/mail/index.txt +2 -2
- package/dist/admin/services/__next.!KGRlZmF1bHQp.services.__PAGE__.txt +1 -1
- package/dist/admin/services/__next.!KGRlZmF1bHQp.services.txt +1 -1
- package/dist/admin/services/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/services/__next._full.txt +2 -2
- package/dist/admin/services/__next._head.txt +1 -1
- package/dist/admin/services/__next._index.txt +2 -2
- package/dist/admin/services/__next._tree.txt +2 -2
- package/dist/admin/services/index.html +1 -1
- package/dist/admin/services/index.txt +2 -2
- package/dist/admin/storage/__next.!KGRlZmF1bHQp.storage.__PAGE__.txt +1 -1
- package/dist/admin/storage/__next.!KGRlZmF1bHQp.storage.txt +1 -1
- package/dist/admin/storage/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/storage/__next._full.txt +2 -2
- package/dist/admin/storage/__next._head.txt +1 -1
- package/dist/admin/storage/__next._index.txt +2 -2
- package/dist/admin/storage/__next._tree.txt +2 -2
- package/dist/admin/storage/index.html +1 -1
- package/dist/admin/storage/index.txt +2 -2
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
- package/dist/admin/workflows/__next._full.txt +2 -2
- package/dist/admin/workflows/__next._head.txt +1 -1
- package/dist/admin/workflows/__next._index.txt +2 -2
- package/dist/admin/workflows/__next._tree.txt +2 -2
- package/dist/admin/workflows/index.html +1 -1
- package/dist/admin/workflows/index.txt +2 -2
- package/dist/cli.js +349 -187
- package/package.json +1 -2
- /package/dist/admin/_next/static/{M3IqeXp32gvmPrMB03Tis → iE-b86kGlgLliZY5m6XDj}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{M3IqeXp32gvmPrMB03Tis → iE-b86kGlgLliZY5m6XDj}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{M3IqeXp32gvmPrMB03Tis → iE-b86kGlgLliZY5m6XDj}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -367566,6 +367566,7 @@ function progressStreamFromBuffer(buffer, onProgress) {
|
|
|
367566
367566
|
var FEEDBACK_NOT_ENABLED_CODE = "FEEDBACK_NOT_ENABLED";
|
|
367567
367567
|
var CLI_DEPLOYMENTS_DISABLED_CODE = "CLI_DEPLOYMENTS_DISABLED";
|
|
367568
367568
|
var PROJECT_PAUSED_CODE = "PROJECT_PAUSED";
|
|
367569
|
+
var QUOTA_EXCEEDED_CODE = "QUOTA_EXCEEDED";
|
|
367569
367570
|
var ApiError = class extends Error {
|
|
367570
367571
|
code;
|
|
367571
367572
|
httpStatus;
|
|
@@ -371172,7 +371173,7 @@ function getClient(info) {
|
|
|
371172
371173
|
const cacheKey = `${info.host}:${info.port}:${info.accessKey}`;
|
|
371173
371174
|
const cached2 = clientCache.get(cacheKey);
|
|
371174
371175
|
if (cached2) return cached2;
|
|
371175
|
-
const
|
|
371176
|
+
const client = new S3Client({
|
|
371176
371177
|
endpoint: `http://${info.host}:${info.port}`,
|
|
371177
371178
|
region: "us-east-1",
|
|
371178
371179
|
credentials: {
|
|
@@ -371181,8 +371182,8 @@ function getClient(info) {
|
|
|
371181
371182
|
},
|
|
371182
371183
|
forcePathStyle: true
|
|
371183
371184
|
});
|
|
371184
|
-
clientCache.set(cacheKey,
|
|
371185
|
-
return
|
|
371185
|
+
clientCache.set(cacheKey, client);
|
|
371186
|
+
return client;
|
|
371186
371187
|
}
|
|
371187
371188
|
function sendJson(res, status, body) {
|
|
371188
371189
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -371200,14 +371201,14 @@ async function readJsonBody(req) {
|
|
|
371200
371201
|
const text = Buffer.concat(chunks).toString("utf8");
|
|
371201
371202
|
return text.length > 0 ? JSON.parse(text) : {};
|
|
371202
371203
|
}
|
|
371203
|
-
async function handleListObjects(
|
|
371204
|
+
async function handleListObjects(client, bucket, url, res) {
|
|
371204
371205
|
const prefix = url.searchParams.get("prefix") ?? "";
|
|
371205
371206
|
const cursor = url.searchParams.get("cursor") ?? void 0;
|
|
371206
371207
|
const maxKeys = Math.min(
|
|
371207
371208
|
Math.max(parseInt(url.searchParams.get("maxKeys") ?? "100", 10) || 100, 1),
|
|
371208
371209
|
1e3
|
|
371209
371210
|
);
|
|
371210
|
-
const response = await
|
|
371211
|
+
const response = await client.send(
|
|
371211
371212
|
new ListObjectsV2Command({
|
|
371212
371213
|
Bucket: bucket,
|
|
371213
371214
|
Prefix: prefix,
|
|
@@ -371228,14 +371229,14 @@ async function handleListObjects(client2, bucket, url, res) {
|
|
|
371228
371229
|
prefix
|
|
371229
371230
|
});
|
|
371230
371231
|
}
|
|
371231
|
-
async function handleMetrics(
|
|
371232
|
+
async function handleMetrics(client, bucket, res) {
|
|
371232
371233
|
let totalObjects = 0;
|
|
371233
371234
|
let totalSize = 0;
|
|
371234
371235
|
let continuationToken;
|
|
371235
371236
|
let pages = 0;
|
|
371236
371237
|
const MAX_PAGES = 100;
|
|
371237
371238
|
do {
|
|
371238
|
-
const response = await
|
|
371239
|
+
const response = await client.send(
|
|
371239
371240
|
new ListObjectsV2Command({
|
|
371240
371241
|
Bucket: bucket,
|
|
371241
371242
|
ContinuationToken: continuationToken
|
|
@@ -371255,9 +371256,9 @@ async function handleMetrics(client2, bucket, res) {
|
|
|
371255
371256
|
...pages >= MAX_PAGES ? { truncated: true } : {}
|
|
371256
371257
|
});
|
|
371257
371258
|
}
|
|
371258
|
-
async function handleGetObject(
|
|
371259
|
+
async function handleGetObject(client, bucket, key, res) {
|
|
371259
371260
|
try {
|
|
371260
|
-
const response = await
|
|
371261
|
+
const response = await client.send(
|
|
371261
371262
|
new HeadObjectCommand({ Bucket: bucket, Key: key })
|
|
371262
371263
|
);
|
|
371263
371264
|
sendJson(res, 200, {
|
|
@@ -371277,12 +371278,12 @@ async function handleGetObject(client2, bucket, key, res) {
|
|
|
371277
371278
|
throw error;
|
|
371278
371279
|
}
|
|
371279
371280
|
}
|
|
371280
|
-
async function handleDeleteObject(
|
|
371281
|
+
async function handleDeleteObject(client, bucket, key, res) {
|
|
371281
371282
|
if (key.endsWith("/")) {
|
|
371282
371283
|
const allKeys = [];
|
|
371283
371284
|
let continuationToken;
|
|
371284
371285
|
do {
|
|
371285
|
-
const listResponse = await
|
|
371286
|
+
const listResponse = await client.send(
|
|
371286
371287
|
new ListObjectsV2Command({
|
|
371287
371288
|
Bucket: bucket,
|
|
371288
371289
|
Prefix: key,
|
|
@@ -371297,7 +371298,7 @@ async function handleDeleteObject(client2, bucket, key, res) {
|
|
|
371297
371298
|
const batches = [];
|
|
371298
371299
|
for (let i = 0; i < allKeys.length; i += 1e3) {
|
|
371299
371300
|
batches.push(
|
|
371300
|
-
|
|
371301
|
+
client.send(
|
|
371301
371302
|
new DeleteObjectsCommand({
|
|
371302
371303
|
Bucket: bucket,
|
|
371303
371304
|
Delete: {
|
|
@@ -371310,11 +371311,11 @@ async function handleDeleteObject(client2, bucket, key, res) {
|
|
|
371310
371311
|
}
|
|
371311
371312
|
await Promise.all(batches);
|
|
371312
371313
|
} else {
|
|
371313
|
-
await
|
|
371314
|
+
await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
371314
371315
|
}
|
|
371315
371316
|
sendJson(res, 200, { success: true });
|
|
371316
371317
|
}
|
|
371317
|
-
async function handleCreateFolder(
|
|
371318
|
+
async function handleCreateFolder(client, bucket, body, res) {
|
|
371318
371319
|
const path172 = body.path;
|
|
371319
371320
|
if (typeof path172 !== "string") {
|
|
371320
371321
|
sendError(res, 400, "Missing path");
|
|
@@ -371326,12 +371327,12 @@ async function handleCreateFolder(client2, bucket, body, res) {
|
|
|
371326
371327
|
sendError(res, 400, keyError);
|
|
371327
371328
|
return;
|
|
371328
371329
|
}
|
|
371329
|
-
await
|
|
371330
|
+
await client.send(
|
|
371330
371331
|
new PutObjectCommand({ Bucket: bucket, Key: folderKey, Body: "" })
|
|
371331
371332
|
);
|
|
371332
371333
|
sendJson(res, 200, { key: folderKey });
|
|
371333
371334
|
}
|
|
371334
|
-
async function handleRename(
|
|
371335
|
+
async function handleRename(client, bucket, body, res) {
|
|
371335
371336
|
const { sourceKey, destinationKey } = body;
|
|
371336
371337
|
if (typeof sourceKey !== "string" || typeof destinationKey !== "string") {
|
|
371337
371338
|
sendError(res, 400, "Missing sourceKey or destinationKey");
|
|
@@ -371348,7 +371349,7 @@ async function handleRename(client2, bucket, body, res) {
|
|
|
371348
371349
|
const allKeys = [];
|
|
371349
371350
|
let continuationToken;
|
|
371350
371351
|
do {
|
|
371351
|
-
const listResponse = await
|
|
371352
|
+
const listResponse = await client.send(
|
|
371352
371353
|
new ListObjectsV2Command({
|
|
371353
371354
|
Bucket: bucket,
|
|
371354
371355
|
Prefix: sourceKey,
|
|
@@ -371366,7 +371367,7 @@ async function handleRename(client2, bucket, body, res) {
|
|
|
371366
371367
|
}
|
|
371367
371368
|
await Promise.all(
|
|
371368
371369
|
allKeys.map(
|
|
371369
|
-
(k) =>
|
|
371370
|
+
(k) => client.send(
|
|
371370
371371
|
new CopyObjectCommand({
|
|
371371
371372
|
Bucket: bucket,
|
|
371372
371373
|
CopySource: `${bucket}/${encodeURI(k)}`,
|
|
@@ -371378,7 +371379,7 @@ async function handleRename(client2, bucket, body, res) {
|
|
|
371378
371379
|
const deleteBatches = [];
|
|
371379
371380
|
for (let i = 0; i < allKeys.length; i += 1e3) {
|
|
371380
371381
|
deleteBatches.push(
|
|
371381
|
-
|
|
371382
|
+
client.send(
|
|
371382
371383
|
new DeleteObjectsCommand({
|
|
371383
371384
|
Bucket: bucket,
|
|
371384
371385
|
Delete: {
|
|
@@ -371391,27 +371392,27 @@ async function handleRename(client2, bucket, body, res) {
|
|
|
371391
371392
|
}
|
|
371392
371393
|
await Promise.all(deleteBatches);
|
|
371393
371394
|
} else {
|
|
371394
|
-
await
|
|
371395
|
+
await client.send(
|
|
371395
371396
|
new CopyObjectCommand({
|
|
371396
371397
|
Bucket: bucket,
|
|
371397
371398
|
CopySource: `${bucket}/${encodeURI(sourceKey)}`,
|
|
371398
371399
|
Key: destinationKey
|
|
371399
371400
|
})
|
|
371400
371401
|
);
|
|
371401
|
-
await
|
|
371402
|
+
await client.send(
|
|
371402
371403
|
new DeleteObjectCommand({ Bucket: bucket, Key: sourceKey })
|
|
371403
371404
|
);
|
|
371404
371405
|
}
|
|
371405
371406
|
sendJson(res, 200, { key: destinationKey });
|
|
371406
371407
|
}
|
|
371407
|
-
async function handleUploadData(
|
|
371408
|
+
async function handleUploadData(client, bucket, key, req, res) {
|
|
371408
371409
|
const chunks = [];
|
|
371409
371410
|
for await (const chunk of req) {
|
|
371410
371411
|
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
371411
371412
|
}
|
|
371412
371413
|
const body = Buffer.concat(chunks);
|
|
371413
371414
|
const contentType = req.headers["content-type"];
|
|
371414
|
-
await
|
|
371415
|
+
await client.send(
|
|
371415
371416
|
new PutObjectCommand({
|
|
371416
371417
|
Bucket: bucket,
|
|
371417
371418
|
Key: key,
|
|
@@ -371422,9 +371423,9 @@ async function handleUploadData(client2, bucket, key, req, res) {
|
|
|
371422
371423
|
res.writeHead(200);
|
|
371423
371424
|
res.end();
|
|
371424
371425
|
}
|
|
371425
|
-
async function handleDownloadData(
|
|
371426
|
+
async function handleDownloadData(client, bucket, key, res) {
|
|
371426
371427
|
try {
|
|
371427
|
-
const response = await
|
|
371428
|
+
const response = await client.send(
|
|
371428
371429
|
new GetObjectCommand({ Bucket: bucket, Key: key })
|
|
371429
371430
|
);
|
|
371430
371431
|
if (response.ContentType) {
|
|
@@ -371491,15 +371492,15 @@ async function handleStorageRequest(req, res, pathname, url, getStorageInstance)
|
|
|
371491
371492
|
sendError(res, 404, `Storage '${storageName}' not found`);
|
|
371492
371493
|
return true;
|
|
371493
371494
|
}
|
|
371494
|
-
const
|
|
371495
|
+
const client = getClient(info);
|
|
371495
371496
|
const bucket = info.bucket;
|
|
371496
371497
|
try {
|
|
371497
371498
|
if (sub === "/objects" && req.method === "GET") {
|
|
371498
|
-
await handleListObjects(
|
|
371499
|
+
await handleListObjects(client, bucket, url, res);
|
|
371499
371500
|
return true;
|
|
371500
371501
|
}
|
|
371501
371502
|
if (sub === "/metrics" && req.method === "GET") {
|
|
371502
|
-
await handleMetrics(
|
|
371503
|
+
await handleMetrics(client, bucket, res);
|
|
371503
371504
|
return true;
|
|
371504
371505
|
}
|
|
371505
371506
|
if (sub === "/object") {
|
|
@@ -371514,11 +371515,11 @@ async function handleStorageRequest(req, res, pathname, url, getStorageInstance)
|
|
|
371514
371515
|
return true;
|
|
371515
371516
|
}
|
|
371516
371517
|
if (req.method === "GET") {
|
|
371517
|
-
await handleGetObject(
|
|
371518
|
+
await handleGetObject(client, bucket, key, res);
|
|
371518
371519
|
return true;
|
|
371519
371520
|
}
|
|
371520
371521
|
if (req.method === "DELETE") {
|
|
371521
|
-
await handleDeleteObject(
|
|
371522
|
+
await handleDeleteObject(client, bucket, key, res);
|
|
371522
371523
|
return true;
|
|
371523
371524
|
}
|
|
371524
371525
|
}
|
|
@@ -371534,22 +371535,22 @@ async function handleStorageRequest(req, res, pathname, url, getStorageInstance)
|
|
|
371534
371535
|
return true;
|
|
371535
371536
|
}
|
|
371536
371537
|
if (req.method === "PUT") {
|
|
371537
|
-
await handleUploadData(
|
|
371538
|
+
await handleUploadData(client, bucket, key, req, res);
|
|
371538
371539
|
return true;
|
|
371539
371540
|
}
|
|
371540
371541
|
if (req.method === "GET") {
|
|
371541
|
-
await handleDownloadData(
|
|
371542
|
+
await handleDownloadData(client, bucket, key, res);
|
|
371542
371543
|
return true;
|
|
371543
371544
|
}
|
|
371544
371545
|
}
|
|
371545
371546
|
if (sub === "/folder" && req.method === "POST") {
|
|
371546
371547
|
const body = await readJsonBody(req);
|
|
371547
|
-
await handleCreateFolder(
|
|
371548
|
+
await handleCreateFolder(client, bucket, body, res);
|
|
371548
371549
|
return true;
|
|
371549
371550
|
}
|
|
371550
371551
|
if (sub === "/rename" && req.method === "POST") {
|
|
371551
371552
|
const body = await readJsonBody(req);
|
|
371552
|
-
await handleRename(
|
|
371553
|
+
await handleRename(client, bucket, body, res);
|
|
371553
371554
|
return true;
|
|
371554
371555
|
}
|
|
371555
371556
|
if (sub === "/presigned" && req.method === "POST") {
|
|
@@ -374611,7 +374612,6 @@ function getDefaultKey() {
|
|
|
374611
374612
|
}
|
|
374612
374613
|
|
|
374613
374614
|
// src/lib/analytics/index.ts
|
|
374614
|
-
import { PostHog } from "posthog-node";
|
|
374615
374615
|
import * as os6 from "os";
|
|
374616
374616
|
import * as crypto4 from "crypto";
|
|
374617
374617
|
|
|
@@ -374716,6 +374716,52 @@ function findEnvironmentByNameOrId(environments, flag) {
|
|
|
374716
374716
|
return environments.find((e) => e.id === flag) ?? environments.find((e) => e.name === flag);
|
|
374717
374717
|
}
|
|
374718
374718
|
|
|
374719
|
+
// src/lib/deployments/format.ts
|
|
374720
|
+
var DASHBOARD_URL = "https://dashboard.specific.dev";
|
|
374721
|
+
function dashboardBillingUrl(projectId) {
|
|
374722
|
+
return `${DASHBOARD_URL}/projects/${encodeURIComponent(projectId)}/organization-settings/billing`;
|
|
374723
|
+
}
|
|
374724
|
+
function dashboardDeploymentUrl(projectId, environmentId, deploymentId) {
|
|
374725
|
+
return `${DASHBOARD_URL}/projects/${encodeURIComponent(projectId)}/env/${encodeURIComponent(environmentId)}/deployments/${encodeURIComponent(deploymentId)}`;
|
|
374726
|
+
}
|
|
374727
|
+
var PLAN_LIMIT_LABELS = {
|
|
374728
|
+
service: ["service", "services"],
|
|
374729
|
+
cron: ["cron", "crons"],
|
|
374730
|
+
postgres: ["postgres database", "postgres databases"],
|
|
374731
|
+
storage: ["storage bucket", "storage buckets"],
|
|
374732
|
+
redis: ["redis instance", "redis instances"],
|
|
374733
|
+
temporal: ["temporal namespace", "temporal namespaces"],
|
|
374734
|
+
mail: ["mail block", "mail blocks"]
|
|
374735
|
+
};
|
|
374736
|
+
function formatPlanLimitViolations(violations) {
|
|
374737
|
+
return violations.map((v) => {
|
|
374738
|
+
const [singular, plural] = PLAN_LIMIT_LABELS[v.resource] ?? [v.resource, v.resource];
|
|
374739
|
+
return `${v.declared} ${v.declared === 1 ? singular : plural} (limit ${v.limit})`;
|
|
374740
|
+
}).join(", ");
|
|
374741
|
+
}
|
|
374742
|
+
function formatErrorCode(code) {
|
|
374743
|
+
const labels = {
|
|
374744
|
+
build_failed: "Build failed",
|
|
374745
|
+
pre_deploy_failed: "Pre-deploy hook failed",
|
|
374746
|
+
deploy_failed: "Service failed to deploy",
|
|
374747
|
+
provisioning_failed: "Resource provisioning failed",
|
|
374748
|
+
health_check_failed: "Health check failed",
|
|
374749
|
+
post_deploy_failed: "Post-deploy hook failed",
|
|
374750
|
+
volume_reset_failed: "Volume reset failed",
|
|
374751
|
+
internal_error: "Internal error"
|
|
374752
|
+
};
|
|
374753
|
+
return labels[code] || code;
|
|
374754
|
+
}
|
|
374755
|
+
|
|
374756
|
+
// src/lib/project/quota.ts
|
|
374757
|
+
function formatProjectQuotaError(err) {
|
|
374758
|
+
if (!(err instanceof ApiError) || err.code !== QUOTA_EXCEEDED_CODE) return null;
|
|
374759
|
+
if (!err.apiError.includes("maxProjects")) return null;
|
|
374760
|
+
const limit = /limit:\s*(\d+)/.exec(err.apiError)?.[1];
|
|
374761
|
+
if (limit === void 0) return err.apiError;
|
|
374762
|
+
return `Your plan allows ${limit} project${limit === "1" ? "" : "s"}. Upgrade at ${DASHBOARD_URL} or delete a project.`;
|
|
374763
|
+
}
|
|
374764
|
+
|
|
374719
374765
|
// src/lib/auth/freebuff.ts
|
|
374720
374766
|
import { createHash as createHash2 } from "node:crypto";
|
|
374721
374767
|
import { mkdirSync as mkdirSync12, readFileSync as readFileSync9, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
@@ -375283,11 +375329,11 @@ async function getAgentAccessToken(credentials) {
|
|
|
375283
375329
|
}
|
|
375284
375330
|
async function saveCredentialsFromToken(token, deviceCode) {
|
|
375285
375331
|
const freebuffConversionToken = (deviceCode ? readDeviceAttribution(deviceCode) : void 0) ?? process.env.SPECIFIC_FREEBUFF_BFCID;
|
|
375286
|
-
const
|
|
375332
|
+
const client = new ApiClient({
|
|
375287
375333
|
token: token.access_token,
|
|
375288
375334
|
...freebuffConversionToken ? { freebuffConversionToken } : {}
|
|
375289
375335
|
});
|
|
375290
|
-
const user = await
|
|
375336
|
+
const user = await client.getMe();
|
|
375291
375337
|
const expiresAt = getTokenExpiresAt(token.access_token) ?? Date.now() + 3600 * 1e3;
|
|
375292
375338
|
writeUserCredentials({
|
|
375293
375339
|
accessToken: token.access_token,
|
|
@@ -375360,7 +375406,8 @@ async function getValidAccessToken() {
|
|
|
375360
375406
|
|
|
375361
375407
|
// src/lib/analytics/index.ts
|
|
375362
375408
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
375363
|
-
var
|
|
375409
|
+
var pendingRequests = /* @__PURE__ */ new Set();
|
|
375410
|
+
var shuttingDown = false;
|
|
375364
375411
|
var anonymousId = null;
|
|
375365
375412
|
var identified = false;
|
|
375366
375413
|
function isEnabled() {
|
|
@@ -375381,52 +375428,88 @@ function getProjectId() {
|
|
|
375381
375428
|
}
|
|
375382
375429
|
return void 0;
|
|
375383
375430
|
}
|
|
375384
|
-
function
|
|
375385
|
-
|
|
375386
|
-
|
|
375387
|
-
|
|
375388
|
-
|
|
375389
|
-
|
|
375390
|
-
|
|
375391
|
-
|
|
375431
|
+
async function sendEvents(events) {
|
|
375432
|
+
let timer;
|
|
375433
|
+
const controller = new AbortController();
|
|
375434
|
+
try {
|
|
375435
|
+
const body = JSON.stringify({
|
|
375436
|
+
api_key: "phc_qNQCEUXh6ErdciQRRmeG2xlVvwFjkcW6A5bnOFJ8vXZ",
|
|
375437
|
+
batch: events.map((event) => ({
|
|
375438
|
+
...event,
|
|
375439
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
375440
|
+
uuid: crypto4.randomUUID(),
|
|
375441
|
+
properties: {
|
|
375442
|
+
...event.properties,
|
|
375443
|
+
$geoip_disable: true,
|
|
375444
|
+
$lib: "specific-cli",
|
|
375445
|
+
$lib_version: "0.1.224"
|
|
375446
|
+
}
|
|
375447
|
+
}))
|
|
375392
375448
|
});
|
|
375449
|
+
await Promise.race([
|
|
375450
|
+
fetch(`${POSTHOG_HOST}/batch/`, {
|
|
375451
|
+
method: "POST",
|
|
375452
|
+
headers: { "Content-Type": "application/json" },
|
|
375453
|
+
body,
|
|
375454
|
+
signal: controller.signal
|
|
375455
|
+
}).then(async (response) => {
|
|
375456
|
+
await response.body?.cancel();
|
|
375457
|
+
}),
|
|
375458
|
+
new Promise((resolve10) => {
|
|
375459
|
+
timer = setTimeout(() => {
|
|
375460
|
+
controller.abort();
|
|
375461
|
+
resolve10();
|
|
375462
|
+
}, 1e3);
|
|
375463
|
+
timer.unref();
|
|
375464
|
+
})
|
|
375465
|
+
]);
|
|
375466
|
+
} catch {
|
|
375467
|
+
} finally {
|
|
375468
|
+
clearTimeout(timer);
|
|
375469
|
+
controller.abort();
|
|
375393
375470
|
}
|
|
375394
|
-
return client;
|
|
375395
375471
|
}
|
|
375396
375472
|
function trackEvent(event, properties) {
|
|
375397
|
-
|
|
375398
|
-
|
|
375399
|
-
|
|
375400
|
-
|
|
375401
|
-
|
|
375402
|
-
|
|
375403
|
-
|
|
375473
|
+
try {
|
|
375474
|
+
if (!isEnabled() || shuttingDown) return;
|
|
375475
|
+
const userId = getUserId();
|
|
375476
|
+
const distinctId = userId ?? getAnonymousId();
|
|
375477
|
+
const events = [];
|
|
375478
|
+
if (userId && !identified) {
|
|
375479
|
+
events.push({
|
|
375480
|
+
event: "$identify",
|
|
375481
|
+
distinct_id: userId,
|
|
375482
|
+
properties: { $set: { anonymous_id: getAnonymousId() } }
|
|
375483
|
+
}, {
|
|
375484
|
+
event: "$create_alias",
|
|
375485
|
+
distinct_id: userId,
|
|
375486
|
+
properties: { distinct_id: userId, alias: getAnonymousId() }
|
|
375487
|
+
});
|
|
375488
|
+
identified = true;
|
|
375489
|
+
}
|
|
375490
|
+
events.push({
|
|
375491
|
+
event,
|
|
375492
|
+
distinct_id: distinctId,
|
|
375404
375493
|
properties: {
|
|
375405
|
-
|
|
375494
|
+
...properties,
|
|
375495
|
+
cli_version: "0.1.224",
|
|
375496
|
+
platform: process.platform,
|
|
375497
|
+
node_version: process.version,
|
|
375498
|
+
project_id: getProjectId()
|
|
375406
375499
|
}
|
|
375407
375500
|
});
|
|
375408
|
-
|
|
375409
|
-
|
|
375410
|
-
|
|
375411
|
-
|
|
375501
|
+
const request2 = sendEvents(events);
|
|
375502
|
+
pendingRequests.add(request2);
|
|
375503
|
+
void request2.then(
|
|
375504
|
+
() => pendingRequests.delete(request2),
|
|
375505
|
+
() => pendingRequests.delete(request2)
|
|
375506
|
+
);
|
|
375507
|
+
} catch {
|
|
375412
375508
|
}
|
|
375413
|
-
ph.capture({
|
|
375414
|
-
distinctId: userId ?? getAnonymousId(),
|
|
375415
|
-
event,
|
|
375416
|
-
properties: {
|
|
375417
|
-
...properties,
|
|
375418
|
-
cli_version: "0.1.222",
|
|
375419
|
-
platform: process.platform,
|
|
375420
|
-
node_version: process.version,
|
|
375421
|
-
project_id: getProjectId()
|
|
375422
|
-
}
|
|
375423
|
-
});
|
|
375424
375509
|
}
|
|
375425
375510
|
async function shutdown() {
|
|
375426
|
-
|
|
375427
|
-
|
|
375428
|
-
client = null;
|
|
375429
|
-
}
|
|
375511
|
+
shuttingDown = true;
|
|
375512
|
+
await Promise.allSettled([...pendingRequests]);
|
|
375430
375513
|
}
|
|
375431
375514
|
|
|
375432
375515
|
// src/commands/init.tsx
|
|
@@ -377623,9 +377706,9 @@ async function performAgentLogin() {
|
|
|
377623
377706
|
userId: ""
|
|
377624
377707
|
};
|
|
377625
377708
|
const accessToken = await getAgentAccessToken(base);
|
|
377626
|
-
const
|
|
377627
|
-
const me = await
|
|
377628
|
-
const info = await
|
|
377709
|
+
const client = new SpecificClient({ accessToken, ...freebuffAttributionOptions() });
|
|
377710
|
+
const me = await client.getMe();
|
|
377711
|
+
const info = await client.getAgentRegistration();
|
|
377629
377712
|
writeUserCredentials({ ...readAgentCredentials() ?? base, userId: me.id });
|
|
377630
377713
|
writeLog("auth", `Agent credentials written for user ${me.id}`);
|
|
377631
377714
|
return { registrationId: registration.id, claimDeadlineAt: new Date(info.claimDeadlineAt) };
|
|
@@ -377650,14 +377733,14 @@ function isExpiredRegistrationError(err) {
|
|
|
377650
377733
|
return err instanceof AgentRegistrationExpiredError || err instanceof ApiError && err.code === "AGENT_REGISTRATION_EXPIRED";
|
|
377651
377734
|
}
|
|
377652
377735
|
async function describeAgentAccount(credentials) {
|
|
377653
|
-
const
|
|
377736
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken, ...freebuffAttributionOptions() });
|
|
377654
377737
|
try {
|
|
377655
|
-
const info = await
|
|
377738
|
+
const info = await client.getAgentRegistration();
|
|
377656
377739
|
if (info.status === "expired") return { status: "expired" };
|
|
377657
377740
|
if (info.status === "unclaimed") {
|
|
377658
377741
|
return { status: "unclaimed", claimDeadlineAt: new Date(info.claimDeadlineAt) };
|
|
377659
377742
|
}
|
|
377660
|
-
const me = await
|
|
377743
|
+
const me = await client.getMe();
|
|
377661
377744
|
const current = readAgentCredentials() ?? credentials;
|
|
377662
377745
|
if (!current.claimed) {
|
|
377663
377746
|
writeUserCredentials({ ...current, claimVerified: void 0, claimed: true, userId: me.id });
|
|
@@ -377698,8 +377781,8 @@ function requireAgentCredentials() {
|
|
|
377698
377781
|
async function startClaim(email) {
|
|
377699
377782
|
const credentials = requireAgentCredentials();
|
|
377700
377783
|
if (credentials.claimed) {
|
|
377701
|
-
const
|
|
377702
|
-
const me = await
|
|
377784
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken, ...freebuffAttributionOptions() });
|
|
377785
|
+
const me = await client.getMe();
|
|
377703
377786
|
return { phase: "completed", email: me.email, alreadyClaimed: true };
|
|
377704
377787
|
}
|
|
377705
377788
|
if (credentials.claimVerified) {
|
|
@@ -377716,8 +377799,8 @@ async function startClaim(email) {
|
|
|
377716
377799
|
async function completeClaim(userCode) {
|
|
377717
377800
|
let credentials = requireAgentCredentials();
|
|
377718
377801
|
if (credentials.claimed) {
|
|
377719
|
-
const
|
|
377720
|
-
const me = await
|
|
377802
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken, ...freebuffAttributionOptions() });
|
|
377803
|
+
const me = await client.getMe();
|
|
377721
377804
|
return { phase: "completed", email: me.email, alreadyClaimed: true };
|
|
377722
377805
|
}
|
|
377723
377806
|
if (credentials.claimVerified) {
|
|
@@ -377732,8 +377815,8 @@ async function completeClaim(userCode) {
|
|
|
377732
377815
|
return await handOverToPlatform(credentials);
|
|
377733
377816
|
}
|
|
377734
377817
|
async function handOverToPlatform(credentials) {
|
|
377735
|
-
const
|
|
377736
|
-
const result = await
|
|
377818
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken, ...freebuffAttributionOptions() });
|
|
377819
|
+
const result = await client.claimAgentRegistration();
|
|
377737
377820
|
writeUserCredentials({ ...credentials, claimVerified: void 0, claimed: true, userId: result.user.id });
|
|
377738
377821
|
writeLog("auth", `Agent registration claimed by ${result.user.email}`);
|
|
377739
377822
|
return { phase: "completed", email: result.user.email, alreadyClaimed: false };
|
|
@@ -377759,25 +377842,10 @@ function describeClaimError(err) {
|
|
|
377759
377842
|
return err instanceof Error ? err.message : String(err);
|
|
377760
377843
|
}
|
|
377761
377844
|
|
|
377762
|
-
// src/lib/deployments/format.ts
|
|
377763
|
-
function formatErrorCode(code) {
|
|
377764
|
-
const labels = {
|
|
377765
|
-
build_failed: "Build failed",
|
|
377766
|
-
pre_deploy_failed: "Pre-deploy hook failed",
|
|
377767
|
-
deploy_failed: "Service failed to deploy",
|
|
377768
|
-
provisioning_failed: "Resource provisioning failed",
|
|
377769
|
-
health_check_failed: "Health check failed",
|
|
377770
|
-
post_deploy_failed: "Post-deploy hook failed",
|
|
377771
|
-
volume_reset_failed: "Volume reset failed",
|
|
377772
|
-
internal_error: "Internal error"
|
|
377773
|
-
};
|
|
377774
|
-
return labels[code] || code;
|
|
377775
|
-
}
|
|
377776
|
-
|
|
377777
377845
|
// src/lib/deployments/inputs.ts
|
|
377778
|
-
async function submitProvidedDeploymentSecrets(
|
|
377846
|
+
async function submitProvidedDeploymentSecrets(client, deploymentId, secrets) {
|
|
377779
377847
|
if (Object.keys(secrets).length === 0) return;
|
|
377780
|
-
await
|
|
377848
|
+
await client.submitSecrets(deploymentId, secrets);
|
|
377781
377849
|
}
|
|
377782
377850
|
|
|
377783
377851
|
// src/lib/deployments/target.ts
|
|
@@ -377786,8 +377854,8 @@ function validateDeployTargetOptions(options2) {
|
|
|
377786
377854
|
throw new Error("--preview cannot be combined with --environment");
|
|
377787
377855
|
}
|
|
377788
377856
|
}
|
|
377789
|
-
async function resolveExplicitDeployEnvironment(
|
|
377790
|
-
const status = await
|
|
377857
|
+
async function resolveExplicitDeployEnvironment(client, projectId, target) {
|
|
377858
|
+
const status = await client.getProjectStatus(projectId);
|
|
377791
377859
|
const environments = [
|
|
377792
377860
|
...status.environments,
|
|
377793
377861
|
...status.previewEnvironments ?? []
|
|
@@ -377848,6 +377916,12 @@ function formatCliDeploymentsDisabledError(projectId, environmentId, detail) {
|
|
|
377848
377916
|
"Once they have, run this command again."
|
|
377849
377917
|
].join("\n");
|
|
377850
377918
|
}
|
|
377919
|
+
function formatPlanLimitExceededError(projectId, environmentId, deploymentId, action) {
|
|
377920
|
+
return `This deployment exceeds the ${action.planName} plan's limits: ${formatPlanLimitViolations(action.violations)}. Upgrade at ${dashboardBillingUrl(projectId)}, then start it from ${dashboardDeploymentUrl(projectId, environmentId, deploymentId)}, or remove the extra resources from specific.hcl and deploy again.`;
|
|
377921
|
+
}
|
|
377922
|
+
function formatUnknownPendingActionError(projectId, environmentId, deploymentId, type) {
|
|
377923
|
+
return `This deployment is waiting on "${type}", which this CLI version doesn't understand. Update the CLI or continue from ${dashboardDeploymentUrl(projectId, environmentId, deploymentId)}.`;
|
|
377924
|
+
}
|
|
377851
377925
|
function formatBytes2(bytes) {
|
|
377852
377926
|
if (bytes < 1024) return `${bytes} B`;
|
|
377853
377927
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -378026,6 +378100,23 @@ function getFailedBuild(pendingActions) {
|
|
|
378026
378100
|
if (!pendingActions) return void 0;
|
|
378027
378101
|
return pendingActions.find((a) => a.type === "build_failed");
|
|
378028
378102
|
}
|
|
378103
|
+
function getPlanLimitAction(pendingActions) {
|
|
378104
|
+
if (!pendingActions) return void 0;
|
|
378105
|
+
return pendingActions.find(
|
|
378106
|
+
(a) => a.type === "plan_limit_exceeded"
|
|
378107
|
+
);
|
|
378108
|
+
}
|
|
378109
|
+
var KNOWN_PENDING_ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
378110
|
+
"build_in_progress",
|
|
378111
|
+
"build_failed",
|
|
378112
|
+
"missing_secrets",
|
|
378113
|
+
"missing_configs",
|
|
378114
|
+
"plan_limit_exceeded"
|
|
378115
|
+
]);
|
|
378116
|
+
function getUnknownPendingAction(pendingActions) {
|
|
378117
|
+
if (!pendingActions) return void 0;
|
|
378118
|
+
return pendingActions.find((a) => !KNOWN_PENDING_ACTION_TYPES.has(a.type));
|
|
378119
|
+
}
|
|
378029
378120
|
function StructuredError({ error }) {
|
|
378030
378121
|
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, formatErrorCode(error.code), ": ", error.message), error.resource && /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Resource: ", error.resource), error.output && /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Output:"), /* @__PURE__ */ React7.createElement(Text7, null, error.output)));
|
|
378031
378122
|
}
|
|
@@ -378117,10 +378208,10 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378117
378208
|
let cancelled = false;
|
|
378118
378209
|
async function loadProjects() {
|
|
378119
378210
|
try {
|
|
378120
|
-
const
|
|
378211
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
378121
378212
|
const [projects2, organizations] = await Promise.all([
|
|
378122
|
-
|
|
378123
|
-
|
|
378213
|
+
client.listProjects(),
|
|
378214
|
+
client.listOrganizations()
|
|
378124
378215
|
]);
|
|
378125
378216
|
if (cancelled) return;
|
|
378126
378217
|
const items = buildSelectorItems(projects2, organizations);
|
|
@@ -378176,8 +378267,8 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378176
378267
|
let cancelled = false;
|
|
378177
378268
|
async function createProject() {
|
|
378178
378269
|
try {
|
|
378179
|
-
const
|
|
378180
|
-
const project = await
|
|
378270
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
378271
|
+
const project = await client.createProject(state.newProjectName, state.selectedOrganizationId);
|
|
378181
378272
|
if (cancelled) return;
|
|
378182
378273
|
writeProjectId(project.id);
|
|
378183
378274
|
setState({
|
|
@@ -378189,7 +378280,7 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378189
378280
|
if (cancelled) return;
|
|
378190
378281
|
setState({
|
|
378191
378282
|
phase: "error",
|
|
378192
|
-
error: err instanceof Error ? err.message : String(err)
|
|
378283
|
+
error: formatProjectQuotaError(err) ?? (err instanceof Error ? err.message : String(err))
|
|
378193
378284
|
});
|
|
378194
378285
|
}
|
|
378195
378286
|
}
|
|
@@ -378203,10 +378294,10 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378203
378294
|
let cancelled = false;
|
|
378204
378295
|
async function loadEnvironments() {
|
|
378205
378296
|
try {
|
|
378206
|
-
const
|
|
378297
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
378207
378298
|
let environments = state.environments;
|
|
378208
378299
|
if (!environments) {
|
|
378209
|
-
const projects2 = await
|
|
378300
|
+
const projects2 = await client.listProjects();
|
|
378210
378301
|
const project = projects2.find((p) => p.id === state.projectId);
|
|
378211
378302
|
if (!project) {
|
|
378212
378303
|
if (cancelled) return;
|
|
@@ -378233,7 +378324,7 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378233
378324
|
if (envFlag) {
|
|
378234
378325
|
try {
|
|
378235
378326
|
const match = await resolveExplicitDeployEnvironment(
|
|
378236
|
-
|
|
378327
|
+
client,
|
|
378237
378328
|
state.projectId,
|
|
378238
378329
|
envFlag
|
|
378239
378330
|
);
|
|
@@ -378319,19 +378410,19 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378319
378410
|
let cancelled = false;
|
|
378320
378411
|
async function createPreview() {
|
|
378321
378412
|
try {
|
|
378322
|
-
const
|
|
378413
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
378323
378414
|
const projectDir = process.cwd();
|
|
378324
378415
|
const previousPreviewId = readPreviewEnvironmentId(projectDir);
|
|
378325
378416
|
if (previousPreviewId) {
|
|
378326
378417
|
setState((s) => ({ ...s, previewStatus: "Tearing down previous preview environment" }));
|
|
378327
378418
|
try {
|
|
378328
|
-
await
|
|
378419
|
+
await client.deletePreviewEnvironment(previousPreviewId);
|
|
378329
378420
|
} catch {
|
|
378330
378421
|
}
|
|
378331
378422
|
}
|
|
378332
378423
|
if (cancelled) return;
|
|
378333
378424
|
setState((s) => ({ ...s, previewStatus: "Creating preview environment" }));
|
|
378334
|
-
const previewEnv = await
|
|
378425
|
+
const previewEnv = await client.createPreviewEnvironment(state.projectId);
|
|
378335
378426
|
writePreviewEnvironmentId(previewEnv.id, projectDir);
|
|
378336
378427
|
if (cancelled) return;
|
|
378337
378428
|
setState((s) => ({
|
|
@@ -378441,15 +378532,15 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378441
378532
|
(secret) => secretValues[secret]
|
|
378442
378533
|
);
|
|
378443
378534
|
if (!allSecretsCollected) return;
|
|
378444
|
-
const
|
|
378445
|
-
if (!
|
|
378535
|
+
const client = clientRef.current;
|
|
378536
|
+
if (!client) return;
|
|
378446
378537
|
(async () => {
|
|
378447
378538
|
try {
|
|
378448
378539
|
writeLog(
|
|
378449
378540
|
"deploy",
|
|
378450
378541
|
`Submitting secrets: ${Object.keys(secretValues).join(", ")}`
|
|
378451
378542
|
);
|
|
378452
|
-
await
|
|
378543
|
+
await client.submitSecrets(deployment2.id, secretValues);
|
|
378453
378544
|
writeLog("deploy", "Secrets submitted successfully");
|
|
378454
378545
|
setState((s) => ({
|
|
378455
378546
|
...s,
|
|
@@ -378483,15 +378574,15 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378483
378574
|
(config2) => configValues[config2]
|
|
378484
378575
|
);
|
|
378485
378576
|
if (!allConfigsCollected) return;
|
|
378486
|
-
const
|
|
378487
|
-
if (!
|
|
378577
|
+
const client = clientRef.current;
|
|
378578
|
+
if (!client) return;
|
|
378488
378579
|
(async () => {
|
|
378489
378580
|
try {
|
|
378490
378581
|
writeLog(
|
|
378491
378582
|
"deploy",
|
|
378492
378583
|
`Submitting configs: ${Object.keys(configValues).join(", ")}`
|
|
378493
378584
|
);
|
|
378494
|
-
await
|
|
378585
|
+
await client.submitConfigs(deployment2.id, configValues);
|
|
378495
378586
|
writeLog("deploy", "Configs submitted successfully");
|
|
378496
378587
|
setState((s) => ({
|
|
378497
378588
|
...s,
|
|
@@ -378518,8 +378609,8 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378518
378609
|
const projectDir = process.cwd();
|
|
378519
378610
|
writeLog("deploy", `Starting deployment to "${state.environmentName}"`);
|
|
378520
378611
|
writeLog("deploy", `Project directory: ${projectDir}`);
|
|
378521
|
-
const
|
|
378522
|
-
clientRef.current =
|
|
378612
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
378613
|
+
clientRef.current = client;
|
|
378523
378614
|
if (cancelled) return;
|
|
378524
378615
|
let tarball;
|
|
378525
378616
|
let appPath;
|
|
@@ -378548,7 +378639,7 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378548
378639
|
try {
|
|
378549
378640
|
writeLog("deploy", `Creating deployment for project ${state.projectId}`);
|
|
378550
378641
|
const gitInfo = getGitInfo(projectDir);
|
|
378551
|
-
deployment2 = await
|
|
378642
|
+
deployment2 = await client.createDeployment(state.projectId, state.environmentId, {
|
|
378552
378643
|
triggeredBy: "cli",
|
|
378553
378644
|
...gitInfo && {
|
|
378554
378645
|
gitCommitSha: gitInfo.commitSha,
|
|
@@ -378614,7 +378705,7 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378614
378705
|
setState((s) => ({ ...s, phase: "uploading", deployment: deployment2 }));
|
|
378615
378706
|
try {
|
|
378616
378707
|
writeLog("deploy", `Uploading tarball (${tarball.length} bytes, appPath: ${appPath})`);
|
|
378617
|
-
deployment2 = await
|
|
378708
|
+
deployment2 = await client.uploadTarball(deployment2.id, tarball, appPath, {
|
|
378618
378709
|
uploadUrl: deployment2.uploadUrl,
|
|
378619
378710
|
maxTarballBytes: deployment2.maxTarballBytes,
|
|
378620
378711
|
onProgress: makeUploadProgressHandler(setState)
|
|
@@ -378644,12 +378735,12 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378644
378735
|
if (state.phase !== "pending" || !state.deployment) return;
|
|
378645
378736
|
let pollInterval;
|
|
378646
378737
|
let cancelled = false;
|
|
378647
|
-
const
|
|
378648
|
-
if (!
|
|
378738
|
+
const client = clientRef.current;
|
|
378739
|
+
if (!client) return;
|
|
378649
378740
|
const pollForPendingActions = async () => {
|
|
378650
378741
|
if (cancelled) return;
|
|
378651
378742
|
try {
|
|
378652
|
-
const status = await
|
|
378743
|
+
const status = await client.getDeployment(state.deployment.id);
|
|
378653
378744
|
if (cancelled) return;
|
|
378654
378745
|
writeLog(
|
|
378655
378746
|
"deploy",
|
|
@@ -378679,6 +378770,24 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378679
378770
|
}));
|
|
378680
378771
|
return;
|
|
378681
378772
|
}
|
|
378773
|
+
const planLimit = getPlanLimitAction(status.pendingActions);
|
|
378774
|
+
if (planLimit) {
|
|
378775
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
378776
|
+
const message = formatPlanLimitExceededError(
|
|
378777
|
+
state.projectId,
|
|
378778
|
+
state.environmentId,
|
|
378779
|
+
status.id,
|
|
378780
|
+
planLimit
|
|
378781
|
+
);
|
|
378782
|
+
writeLog("deploy:error", message);
|
|
378783
|
+
setState((s) => ({
|
|
378784
|
+
...s,
|
|
378785
|
+
phase: "error",
|
|
378786
|
+
deployment: status,
|
|
378787
|
+
error: message
|
|
378788
|
+
}));
|
|
378789
|
+
return;
|
|
378790
|
+
}
|
|
378682
378791
|
const missingSecrets2 = getMissingSecrets(status.pendingActions);
|
|
378683
378792
|
if (missingSecrets2.length > 0) {
|
|
378684
378793
|
if (pollInterval) clearInterval(pollInterval);
|
|
@@ -378721,6 +378830,24 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378721
378830
|
}));
|
|
378722
378831
|
return;
|
|
378723
378832
|
}
|
|
378833
|
+
const unknownAction = getUnknownPendingAction(status.pendingActions);
|
|
378834
|
+
if (unknownAction) {
|
|
378835
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
378836
|
+
const message = formatUnknownPendingActionError(
|
|
378837
|
+
state.projectId,
|
|
378838
|
+
state.environmentId,
|
|
378839
|
+
status.id,
|
|
378840
|
+
unknownAction.type
|
|
378841
|
+
);
|
|
378842
|
+
writeLog("deploy:error", message);
|
|
378843
|
+
setState((s) => ({
|
|
378844
|
+
...s,
|
|
378845
|
+
phase: "error",
|
|
378846
|
+
deployment: status,
|
|
378847
|
+
error: message
|
|
378848
|
+
}));
|
|
378849
|
+
return;
|
|
378850
|
+
}
|
|
378724
378851
|
if (!status.pendingActions || status.pendingActions.length === 0) {
|
|
378725
378852
|
if (pollInterval) clearInterval(pollInterval);
|
|
378726
378853
|
pollInterval = void 0;
|
|
@@ -378752,12 +378879,12 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378752
378879
|
useEffect6(() => {
|
|
378753
378880
|
if (state.phase !== "starting" || !state.deployment) return;
|
|
378754
378881
|
let cancelled = false;
|
|
378755
|
-
const
|
|
378756
|
-
if (!
|
|
378882
|
+
const client = clientRef.current;
|
|
378883
|
+
if (!client) return;
|
|
378757
378884
|
(async () => {
|
|
378758
378885
|
try {
|
|
378759
378886
|
writeLog("deploy", "Calling /start endpoint");
|
|
378760
|
-
await
|
|
378887
|
+
await client.startDeployment(state.deployment.id);
|
|
378761
378888
|
writeLog("deploy", "Deployment started successfully");
|
|
378762
378889
|
if (cancelled) return;
|
|
378763
378890
|
setState((s) => ({
|
|
@@ -378787,12 +378914,12 @@ function DeployUI({ envFlag, preview, config }) {
|
|
|
378787
378914
|
if (state.phase !== "queued" && state.phase !== "deploying" || !state.deployment) return;
|
|
378788
378915
|
let pollInterval;
|
|
378789
378916
|
let cancelled = false;
|
|
378790
|
-
const
|
|
378791
|
-
if (!
|
|
378917
|
+
const client = clientRef.current;
|
|
378918
|
+
if (!client) return;
|
|
378792
378919
|
const pollForCompletion = async () => {
|
|
378793
378920
|
if (cancelled) return;
|
|
378794
378921
|
try {
|
|
378795
|
-
const status = await
|
|
378922
|
+
const status = await client.getDeployment(state.deployment.id);
|
|
378796
378923
|
if (cancelled) return;
|
|
378797
378924
|
writeLog(
|
|
378798
378925
|
"deploy",
|
|
@@ -379039,7 +379166,7 @@ async function runDeployPipeline(options2) {
|
|
|
379039
379166
|
console.error(`Error: ${message}`);
|
|
379040
379167
|
process.exit(1);
|
|
379041
379168
|
}
|
|
379042
|
-
const
|
|
379169
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
379043
379170
|
let projectId = options2.projectId;
|
|
379044
379171
|
let projectIdFromLinkedFile = false;
|
|
379045
379172
|
if (!projectId) {
|
|
@@ -379061,17 +379188,17 @@ async function runDeployPipeline(options2) {
|
|
|
379061
379188
|
if (previousPreviewId) {
|
|
379062
379189
|
console.log("Cleaning up previous preview environment...");
|
|
379063
379190
|
try {
|
|
379064
|
-
await
|
|
379191
|
+
await client.deletePreviewEnvironment(previousPreviewId);
|
|
379065
379192
|
} catch {
|
|
379066
379193
|
}
|
|
379067
379194
|
}
|
|
379068
379195
|
console.log("Creating preview environment...");
|
|
379069
|
-
const preview = await
|
|
379196
|
+
const preview = await client.createPreviewEnvironment(projectId);
|
|
379070
379197
|
writePreviewEnvironmentId(preview.id, projectDir);
|
|
379071
379198
|
console.log(`Preview environment "${preview.name}" created (expires: ${new Date(preview.expiresAt).toLocaleString()})`);
|
|
379072
379199
|
previewEnvironmentId = preview.id;
|
|
379073
379200
|
}
|
|
379074
|
-
const projects = await
|
|
379201
|
+
const projects = await client.listProjects();
|
|
379075
379202
|
const project = projects.find((p) => p.id === projectId);
|
|
379076
379203
|
if (!project) {
|
|
379077
379204
|
if (projectIdFromLinkedFile) {
|
|
@@ -379094,7 +379221,7 @@ async function runDeployPipeline(options2) {
|
|
|
379094
379221
|
} else if (options2.environment) {
|
|
379095
379222
|
try {
|
|
379096
379223
|
const match = await resolveExplicitDeployEnvironment(
|
|
379097
|
-
|
|
379224
|
+
client,
|
|
379098
379225
|
projectId,
|
|
379099
379226
|
options2.environment
|
|
379100
379227
|
);
|
|
@@ -379176,7 +379303,7 @@ async function runDeployPipeline(options2) {
|
|
|
379176
379303
|
let deployment;
|
|
379177
379304
|
try {
|
|
379178
379305
|
const gitInfo = getGitInfo(projectDir);
|
|
379179
|
-
deployment = await
|
|
379306
|
+
deployment = await client.createDeployment(projectId, environmentId, {
|
|
379180
379307
|
triggeredBy: "cli",
|
|
379181
379308
|
...gitInfo && {
|
|
379182
379309
|
gitCommitSha: gitInfo.commitSha,
|
|
@@ -379221,7 +379348,7 @@ async function runDeployPipeline(options2) {
|
|
|
379221
379348
|
console.log("Uploading...");
|
|
379222
379349
|
try {
|
|
379223
379350
|
let lastPct = -1;
|
|
379224
|
-
deployment = await
|
|
379351
|
+
deployment = await client.uploadTarball(deployment.id, tarball, appPath, {
|
|
379225
379352
|
uploadUrl: deployment.uploadUrl,
|
|
379226
379353
|
maxTarballBytes: deployment.maxTarballBytes,
|
|
379227
379354
|
onProgress: (bytesSent, totalBytes) => {
|
|
@@ -379238,7 +379365,7 @@ async function runDeployPipeline(options2) {
|
|
|
379238
379365
|
process.exit(1);
|
|
379239
379366
|
}
|
|
379240
379367
|
try {
|
|
379241
|
-
await submitProvidedDeploymentSecrets(
|
|
379368
|
+
await submitProvidedDeploymentSecrets(client, deployment.id, parsedSecrets);
|
|
379242
379369
|
} catch (err) {
|
|
379243
379370
|
console.error(`Error: Failed to submit secrets: ${err instanceof Error ? err.message : String(err)}`);
|
|
379244
379371
|
process.exit(1);
|
|
@@ -379246,7 +379373,7 @@ async function runDeployPipeline(options2) {
|
|
|
379246
379373
|
console.log("Waiting for build...");
|
|
379247
379374
|
while (true) {
|
|
379248
379375
|
await new Promise((resolve10) => setTimeout(resolve10, 2e3));
|
|
379249
|
-
const status = await
|
|
379376
|
+
const status = await client.getDeployment(deployment.id);
|
|
379250
379377
|
deployment = status;
|
|
379251
379378
|
if (status.state === "failed") {
|
|
379252
379379
|
console.error(`Error: Deployment failed: ${status.stateMessage || "Unknown error"}`);
|
|
@@ -379262,6 +379389,13 @@ ${failedBuild.output}`);
|
|
|
379262
379389
|
}
|
|
379263
379390
|
process.exit(1);
|
|
379264
379391
|
}
|
|
379392
|
+
const planLimit = getPlanLimitAction(status.pendingActions);
|
|
379393
|
+
if (planLimit) {
|
|
379394
|
+
console.error(
|
|
379395
|
+
`Error: ${formatPlanLimitExceededError(projectId, environmentId, deployment.id, planLimit)}`
|
|
379396
|
+
);
|
|
379397
|
+
process.exit(1);
|
|
379398
|
+
}
|
|
379265
379399
|
const missingSecrets = getMissingSecrets(status.pendingActions);
|
|
379266
379400
|
if (missingSecrets.length > 0) {
|
|
379267
379401
|
const secretsToSubmit = {};
|
|
@@ -379280,7 +379414,7 @@ ${failedBuild.output}`);
|
|
|
379280
379414
|
);
|
|
379281
379415
|
process.exit(1);
|
|
379282
379416
|
}
|
|
379283
|
-
await
|
|
379417
|
+
await client.submitSecrets(deployment.id, secretsToSubmit);
|
|
379284
379418
|
continue;
|
|
379285
379419
|
}
|
|
379286
379420
|
const missingConfigs = getMissingConfigs(status.pendingActions);
|
|
@@ -379301,19 +379435,26 @@ ${failedBuild.output}`);
|
|
|
379301
379435
|
);
|
|
379302
379436
|
process.exit(1);
|
|
379303
379437
|
}
|
|
379304
|
-
await
|
|
379438
|
+
await client.submitConfigs(deployment.id, configsToSubmit);
|
|
379305
379439
|
continue;
|
|
379306
379440
|
}
|
|
379307
379441
|
if (hasBuildsInProgress(status.pendingActions)) {
|
|
379308
379442
|
continue;
|
|
379309
379443
|
}
|
|
379444
|
+
const unknownAction = getUnknownPendingAction(status.pendingActions);
|
|
379445
|
+
if (unknownAction) {
|
|
379446
|
+
console.error(
|
|
379447
|
+
`Error: ${formatUnknownPendingActionError(projectId, environmentId, deployment.id, unknownAction.type)}`
|
|
379448
|
+
);
|
|
379449
|
+
process.exit(1);
|
|
379450
|
+
}
|
|
379310
379451
|
if (!status.pendingActions || status.pendingActions.length === 0) {
|
|
379311
379452
|
break;
|
|
379312
379453
|
}
|
|
379313
379454
|
}
|
|
379314
379455
|
console.log("Starting deployment...");
|
|
379315
379456
|
try {
|
|
379316
|
-
await
|
|
379457
|
+
await client.startDeployment(deployment.id);
|
|
379317
379458
|
} catch (err) {
|
|
379318
379459
|
if (err instanceof ApiError && err.code === CLI_DEPLOYMENTS_DISABLED_CODE) {
|
|
379319
379460
|
console.error(
|
|
@@ -379335,7 +379476,7 @@ ${failedBuild.output}`);
|
|
|
379335
379476
|
);
|
|
379336
379477
|
console.log("Cleaning up preview environment...");
|
|
379337
379478
|
try {
|
|
379338
|
-
await
|
|
379479
|
+
await client.deletePreviewEnvironment(previewEnvironmentId);
|
|
379339
379480
|
} catch {
|
|
379340
379481
|
}
|
|
379341
379482
|
clearPreviewEnvironmentId(projectDir);
|
|
@@ -379347,7 +379488,7 @@ ${failedBuild.output}`);
|
|
|
379347
379488
|
console.log("Deploying...");
|
|
379348
379489
|
while (true) {
|
|
379349
379490
|
await new Promise((resolve10) => setTimeout(resolve10, 2e3));
|
|
379350
|
-
const status = await
|
|
379491
|
+
const status = await client.getDeployment(deployment.id);
|
|
379351
379492
|
deployment = status;
|
|
379352
379493
|
if (status.state === "failed") {
|
|
379353
379494
|
if (status.error) {
|
|
@@ -380413,7 +380554,7 @@ function compareVersions(a, b) {
|
|
|
380413
380554
|
return 0;
|
|
380414
380555
|
}
|
|
380415
380556
|
async function checkForUpdate() {
|
|
380416
|
-
const currentVersion = "0.1.
|
|
380557
|
+
const currentVersion = "0.1.224";
|
|
380417
380558
|
const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
|
|
380418
380559
|
if (!response.ok) {
|
|
380419
380560
|
throw new Error(`Failed to check for updates: HTTP ${response.status}`);
|
|
@@ -380611,10 +380752,10 @@ function updateCommand() {
|
|
|
380611
380752
|
// src/commands/project.tsx
|
|
380612
380753
|
async function projectNewCommand(name, options2) {
|
|
380613
380754
|
try {
|
|
380614
|
-
const
|
|
380755
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
380615
380756
|
let orgId = options2.org;
|
|
380616
380757
|
if (!orgId) {
|
|
380617
|
-
const organizations = await
|
|
380758
|
+
const organizations = await client.listOrganizations();
|
|
380618
380759
|
if (organizations.length === 0) {
|
|
380619
380760
|
console.error(
|
|
380620
380761
|
"You don't belong to any organizations. Please create one first."
|
|
@@ -380634,20 +380775,25 @@ async function projectNewCommand(name, options2) {
|
|
|
380634
380775
|
process.exit(1);
|
|
380635
380776
|
}
|
|
380636
380777
|
}
|
|
380637
|
-
const project = await
|
|
380778
|
+
const project = await client.createProject(name, orgId);
|
|
380638
380779
|
console.log(`Project created: ${project.id}`);
|
|
380639
380780
|
} catch (error) {
|
|
380781
|
+
const quotaMessage = formatProjectQuotaError(error);
|
|
380782
|
+
if (quotaMessage) {
|
|
380783
|
+
console.error(quotaMessage);
|
|
380784
|
+
process.exit(1);
|
|
380785
|
+
}
|
|
380640
380786
|
const message = error instanceof Error ? error.message : "Unknown error occurred";
|
|
380641
|
-
console.error(`
|
|
380787
|
+
console.error(`Error: ${message}`);
|
|
380642
380788
|
process.exit(1);
|
|
380643
380789
|
}
|
|
380644
380790
|
}
|
|
380645
380791
|
async function projectListCommand() {
|
|
380646
380792
|
try {
|
|
380647
|
-
const
|
|
380793
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
380648
380794
|
const [projects, organizations] = await Promise.all([
|
|
380649
|
-
|
|
380650
|
-
|
|
380795
|
+
client.listProjects(),
|
|
380796
|
+
client.listOrganizations()
|
|
380651
380797
|
]);
|
|
380652
380798
|
if (projects.length === 0) {
|
|
380653
380799
|
console.log("No projects found.");
|
|
@@ -380743,8 +380889,8 @@ function StatusUI({ previews = false }) {
|
|
|
380743
380889
|
(async () => {
|
|
380744
380890
|
try {
|
|
380745
380891
|
const projectId = readProjectId();
|
|
380746
|
-
const
|
|
380747
|
-
const status2 = await
|
|
380892
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
380893
|
+
const status2 = await client.getProjectStatus(projectId);
|
|
380748
380894
|
setState({ phase: "success", status: status2 });
|
|
380749
380895
|
} catch (err) {
|
|
380750
380896
|
setState({
|
|
@@ -380791,8 +380937,8 @@ async function statusCommand(options2 = {}) {
|
|
|
380791
380937
|
return;
|
|
380792
380938
|
}
|
|
380793
380939
|
const projectId = readProjectId();
|
|
380794
|
-
const
|
|
380795
|
-
const status = await
|
|
380940
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
380941
|
+
const status = await client.getProjectStatus(projectId);
|
|
380796
380942
|
process.stdout.write(JSON.stringify(status, null, 2) + "\n");
|
|
380797
380943
|
} catch (err) {
|
|
380798
380944
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -380802,8 +380948,8 @@ async function statusCommand(options2 = {}) {
|
|
|
380802
380948
|
}
|
|
380803
380949
|
|
|
380804
380950
|
// src/lib/project/resolve-env.ts
|
|
380805
|
-
async function resolveEnvironmentStatus(
|
|
380806
|
-
const status = await
|
|
380951
|
+
async function resolveEnvironmentStatus(client, projectId, envFlag) {
|
|
380952
|
+
const status = await client.getProjectStatus(projectId);
|
|
380807
380953
|
const environments = status.environments;
|
|
380808
380954
|
const previewEnvironments = status.previewEnvironments ?? [];
|
|
380809
380955
|
if (envFlag) {
|
|
@@ -380839,8 +380985,8 @@ async function resolveEnvironmentStatus(client2, projectId, envFlag) {
|
|
|
380839
380985
|
`Project has multiple environments (${names}). Pass --environment <name|id>.`
|
|
380840
380986
|
);
|
|
380841
380987
|
}
|
|
380842
|
-
async function resolveEnvironmentId(
|
|
380843
|
-
const match = await resolveEnvironmentStatus(
|
|
380988
|
+
async function resolveEnvironmentId(client, projectId, envFlag) {
|
|
380989
|
+
const match = await resolveEnvironmentStatus(client, projectId, envFlag);
|
|
380844
380990
|
return match.id;
|
|
380845
380991
|
}
|
|
380846
380992
|
|
|
@@ -381034,9 +381180,9 @@ async function queryCommand(sqlArg, options2) {
|
|
|
381034
381180
|
const format = resolveOutputFormat2(options2.format);
|
|
381035
381181
|
const sql = await resolveSql(sqlArg);
|
|
381036
381182
|
const projectId = readProjectId();
|
|
381037
|
-
const
|
|
381038
|
-
const environmentId = await resolveEnvironmentId(
|
|
381039
|
-
const result = options2.db ? await
|
|
381183
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
381184
|
+
const environmentId = await resolveEnvironmentId(client, projectId, options2.environment);
|
|
381185
|
+
const result = options2.db ? await client.runDatabaseQuery(environmentId, options2.db, sql) : await client.runObservabilityQuery(environmentId, sql);
|
|
381040
381186
|
if (result.lookback) {
|
|
381041
381187
|
process.stderr.write(
|
|
381042
381188
|
`\x1B[2mResults exclude data older than ${result.lookback.cutoff} (${result.lookback.days}-day lookback on your plan).\x1B[0m
|
|
@@ -381097,13 +381243,13 @@ async function deploymentShowCommand(idArg, options2) {
|
|
|
381097
381243
|
try {
|
|
381098
381244
|
const format = resolveOutputFormat3(options2.format);
|
|
381099
381245
|
const includeOutput = options2.output ?? false;
|
|
381100
|
-
const
|
|
381246
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
381101
381247
|
let deploymentId = idArg;
|
|
381102
381248
|
if (!deploymentId) {
|
|
381103
|
-
const
|
|
381249
|
+
const projectId2 = readProjectId();
|
|
381104
381250
|
const env2 = await resolveEnvironmentStatus(
|
|
381105
|
-
|
|
381106
|
-
|
|
381251
|
+
client,
|
|
381252
|
+
projectId2,
|
|
381107
381253
|
options2.environment
|
|
381108
381254
|
);
|
|
381109
381255
|
const latest = env2.latestDeployment ?? env2.inProgressDeployment ?? env2.activeDeployment;
|
|
@@ -381114,13 +381260,18 @@ async function deploymentShowCommand(idArg, options2) {
|
|
|
381114
381260
|
}
|
|
381115
381261
|
deploymentId = latest.id;
|
|
381116
381262
|
}
|
|
381117
|
-
const deployment = await
|
|
381263
|
+
const deployment = await client.getDeployment(deploymentId);
|
|
381118
381264
|
if (format === "json") {
|
|
381119
381265
|
const payload = includeOutput ? deployment : stripOutput(deployment);
|
|
381120
381266
|
process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
|
|
381121
381267
|
return;
|
|
381122
381268
|
}
|
|
381123
|
-
|
|
381269
|
+
let projectId = null;
|
|
381270
|
+
try {
|
|
381271
|
+
projectId = readProjectId();
|
|
381272
|
+
} catch {
|
|
381273
|
+
}
|
|
381274
|
+
process.stdout.write(renderDeployment(deployment, includeOutput, projectId));
|
|
381124
381275
|
} catch (err) {
|
|
381125
381276
|
const message = err instanceof Error ? err.message : "Unknown error occurred";
|
|
381126
381277
|
console.error(`Error: ${message}`);
|
|
@@ -381130,12 +381281,12 @@ async function deploymentShowCommand(idArg, options2) {
|
|
|
381130
381281
|
async function deploymentRetryCommand(idArg, options2) {
|
|
381131
381282
|
try {
|
|
381132
381283
|
const format = resolveOutputFormat3(options2.format);
|
|
381133
|
-
const
|
|
381284
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
381134
381285
|
let deploymentId = idArg;
|
|
381135
381286
|
if (!deploymentId) {
|
|
381136
381287
|
const projectId = readProjectId();
|
|
381137
381288
|
const env2 = await resolveEnvironmentStatus(
|
|
381138
|
-
|
|
381289
|
+
client,
|
|
381139
381290
|
projectId,
|
|
381140
381291
|
options2.environment
|
|
381141
381292
|
);
|
|
@@ -381145,7 +381296,7 @@ async function deploymentRetryCommand(idArg, options2) {
|
|
|
381145
381296
|
}
|
|
381146
381297
|
deploymentId = latest.id;
|
|
381147
381298
|
}
|
|
381148
|
-
const result = await
|
|
381299
|
+
const result = await client.retryDeployment(deploymentId);
|
|
381149
381300
|
if (format === "json") {
|
|
381150
381301
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
381151
381302
|
return;
|
|
@@ -381219,7 +381370,7 @@ function formatBytes3(bytes) {
|
|
|
381219
381370
|
if (bytes < 1024) return `${bytes} B`;
|
|
381220
381371
|
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
381221
381372
|
}
|
|
381222
|
-
function renderDeployment(deployment, includeOutput) {
|
|
381373
|
+
function renderDeployment(deployment, includeOutput, projectId) {
|
|
381223
381374
|
const lines = [];
|
|
381224
381375
|
lines.push(
|
|
381225
381376
|
`${ANSI2.bold}Deployment ${deployment.id}${ANSI2.reset} ${ANSI2.dim}(${deployment.environment})${ANSI2.reset}`
|
|
@@ -381283,15 +381434,26 @@ function renderDeployment(deployment, includeOutput) {
|
|
|
381283
381434
|
}
|
|
381284
381435
|
}
|
|
381285
381436
|
const pendingActions = deployment.pendingActions ?? [];
|
|
381437
|
+
const planLimit = pendingActions.find(
|
|
381438
|
+
(a) => a.type === "plan_limit_exceeded"
|
|
381439
|
+
);
|
|
381286
381440
|
const missingSecrets = pendingActions.flatMap(
|
|
381287
381441
|
(a) => a.type === "missing_secrets" ? a.secrets : []
|
|
381288
381442
|
);
|
|
381289
381443
|
const missingConfigs = pendingActions.flatMap(
|
|
381290
381444
|
(a) => a.type === "missing_configs" ? a.configs : []
|
|
381291
381445
|
);
|
|
381292
|
-
if (missingSecrets.length > 0 || missingConfigs.length > 0) {
|
|
381446
|
+
if (planLimit || missingSecrets.length > 0 || missingConfigs.length > 0) {
|
|
381293
381447
|
lines.push("");
|
|
381294
381448
|
lines.push(colored(ANSI2.yellow, `${ANSI2.bold}Action required${ANSI2.reset}`));
|
|
381449
|
+
if (planLimit) {
|
|
381450
|
+
lines.push(
|
|
381451
|
+
` This deployment exceeds the ${planLimit.planName} plan's limits: ${formatPlanLimitViolations(planLimit.violations)}.`
|
|
381452
|
+
);
|
|
381453
|
+
lines.push(
|
|
381454
|
+
` Upgrade at ${projectId ? dashboardBillingUrl(projectId) : DASHBOARD_URL}, or remove the extra resources from specific.hcl and deploy again.`
|
|
381455
|
+
);
|
|
381456
|
+
}
|
|
381295
381457
|
if (missingSecrets.length > 0) {
|
|
381296
381458
|
lines.push(` Missing secrets: ${missingSecrets.join(", ")}`);
|
|
381297
381459
|
}
|
|
@@ -381400,13 +381562,13 @@ async function domainAddCommand(service, domain, options2) {
|
|
|
381400
381562
|
try {
|
|
381401
381563
|
const projectId = readProjectId();
|
|
381402
381564
|
const token = await getValidAccessToken();
|
|
381403
|
-
const
|
|
381565
|
+
const client = new SpecificClient({ accessToken: token });
|
|
381404
381566
|
const environmentId = await resolveEnvironmentId(
|
|
381405
|
-
|
|
381567
|
+
client,
|
|
381406
381568
|
projectId,
|
|
381407
381569
|
options2.environment
|
|
381408
381570
|
);
|
|
381409
|
-
const result = await
|
|
381571
|
+
const result = await client.createCustomDomain(environmentId, {
|
|
381410
381572
|
domain,
|
|
381411
381573
|
serviceName: service
|
|
381412
381574
|
});
|
|
@@ -381445,11 +381607,11 @@ async function feedbackCommand(message) {
|
|
|
381445
381607
|
} catch {
|
|
381446
381608
|
}
|
|
381447
381609
|
try {
|
|
381448
|
-
const
|
|
381449
|
-
await
|
|
381610
|
+
const client = new SpecificClient({ tokenProvider: getValidAccessToken });
|
|
381611
|
+
await client.submitFeedback({
|
|
381450
381612
|
message: trimmed,
|
|
381451
381613
|
projectId,
|
|
381452
|
-
cliVersion: "0.1.
|
|
381614
|
+
cliVersion: "0.1.224"
|
|
381453
381615
|
});
|
|
381454
381616
|
trackEvent("feedback_submitted", { hasProject: !!projectId });
|
|
381455
381617
|
console.log("Thanks! We will take a look at your feedback shortly.");
|
|
@@ -381468,7 +381630,7 @@ async function feedbackCommand(message) {
|
|
|
381468
381630
|
var program = new Command();
|
|
381469
381631
|
var env = "production";
|
|
381470
381632
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
381471
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
381633
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.224").enablePositionalOptions();
|
|
381472
381634
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
|
|
381473
381635
|
Examples:
|
|
381474
381636
|
$ specific init
|