@specific.dev/cli 0.1.59 → 0.1.61
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 +1 -1
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +1 -1
- package/dist/admin/__next._tree.txt +1 -1
- package/dist/admin/_not-found/__next._full.txt +1 -1
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +1 -1
- 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 +1 -1
- package/dist/admin/_not-found/index.html +1 -1
- package/dist/admin/_not-found/index.txt +1 -1
- 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 +1 -1
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +1 -1
- package/dist/admin/databases/__next._tree.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +1 -1
- package/dist/admin/fullscreen/__next._full.txt +1 -1
- package/dist/admin/fullscreen/__next._head.txt +1 -1
- package/dist/admin/fullscreen/__next._index.txt +1 -1
- package/dist/admin/fullscreen/__next._tree.txt +1 -1
- 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 +1 -1
- package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
- 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 +1 -1
- package/dist/admin/fullscreen/index.html +1 -1
- package/dist/admin/fullscreen/index.txt +1 -1
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +1 -1
- package/dist/cli.js +105 -36
- package/dist/postinstall.js +1 -1
- package/package.json +2 -3
- /package/dist/admin/_next/static/{3NwOLK8EcVipT46jmh2HP → ko53a3ptYl472sHJWxbir}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{3NwOLK8EcVipT46jmh2HP → ko53a3ptYl472sHJWxbir}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{3NwOLK8EcVipT46jmh2HP → ko53a3ptYl472sHJWxbir}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -183873,7 +183873,7 @@ function trackEvent(event, properties) {
|
|
|
183873
183873
|
event,
|
|
183874
183874
|
properties: {
|
|
183875
183875
|
...properties,
|
|
183876
|
-
cli_version: "0.1.
|
|
183876
|
+
cli_version: "0.1.61",
|
|
183877
183877
|
platform: process.platform,
|
|
183878
183878
|
node_version: process.version,
|
|
183879
183879
|
project_id: getProjectId(),
|
|
@@ -189380,54 +189380,123 @@ var StableSubdomainAllocator = class {
|
|
|
189380
189380
|
}
|
|
189381
189381
|
};
|
|
189382
189382
|
|
|
189383
|
-
//
|
|
189384
|
-
import
|
|
189385
|
-
|
|
189386
|
-
|
|
189387
|
-
|
|
189388
|
-
|
|
189389
|
-
|
|
189390
|
-
|
|
189391
|
-
|
|
189392
|
-
|
|
189393
|
-
|
|
189383
|
+
// node_modules/.pnpm/@specific+tunnel-client@file+..+tunnel+client/node_modules/@specific/tunnel-client/dist/index.js
|
|
189384
|
+
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
189385
|
+
import * as net4 from "node:net";
|
|
189386
|
+
var DEFAULT_HOST = "https://tunnel.spcf.app";
|
|
189387
|
+
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
189388
|
+
async function register(baseUrl, subdomain) {
|
|
189389
|
+
const res = await fetch(`${baseUrl}/${subdomain}`);
|
|
189390
|
+
if (!res.ok) {
|
|
189391
|
+
const body = await res.text();
|
|
189392
|
+
throw new Error(`Registration failed (${res.status}): ${body}`);
|
|
189393
|
+
}
|
|
189394
|
+
return await res.json();
|
|
189395
|
+
}
|
|
189396
|
+
var TunnelClientImpl = class extends EventEmitter2 {
|
|
189397
|
+
info;
|
|
189398
|
+
localPort;
|
|
189399
|
+
tunnelHost;
|
|
189400
|
+
baseUrl;
|
|
189401
|
+
url;
|
|
189402
|
+
subdomain;
|
|
189403
|
+
pool = /* @__PURE__ */ new Set();
|
|
189404
|
+
closed = false;
|
|
189405
|
+
constructor(info, localPort, tunnelHost, baseUrl) {
|
|
189406
|
+
super();
|
|
189407
|
+
this.info = info;
|
|
189408
|
+
this.localPort = localPort;
|
|
189409
|
+
this.tunnelHost = tunnelHost;
|
|
189410
|
+
this.baseUrl = baseUrl;
|
|
189411
|
+
this.url = info.url;
|
|
189412
|
+
this.subdomain = info.id;
|
|
189413
|
+
this.fillPool();
|
|
189414
|
+
}
|
|
189415
|
+
close() {
|
|
189416
|
+
this.closed = true;
|
|
189417
|
+
for (const c of this.pool)
|
|
189418
|
+
c.destroy();
|
|
189419
|
+
this.pool.clear();
|
|
189420
|
+
}
|
|
189421
|
+
fillPool() {
|
|
189422
|
+
while (!this.closed && this.pool.size < this.info.max_conn_count) {
|
|
189423
|
+
this.addPoolConnection();
|
|
189424
|
+
}
|
|
189425
|
+
}
|
|
189426
|
+
addPoolConnection() {
|
|
189427
|
+
const remote = net4.connect({ host: this.tunnelHost, port: this.info.port });
|
|
189428
|
+
remote.setKeepAlive(true, 3e4);
|
|
189429
|
+
this.pool.add(remote);
|
|
189430
|
+
remote.once("data", (firstChunk) => {
|
|
189431
|
+
this.pool.delete(remote);
|
|
189432
|
+
this.pipeToLocal(remote, firstChunk);
|
|
189394
189433
|
});
|
|
189395
|
-
|
|
189396
|
-
|
|
189434
|
+
let errored = false;
|
|
189435
|
+
remote.on("error", (err) => {
|
|
189436
|
+
errored = true;
|
|
189437
|
+
this.emit("error", err);
|
|
189397
189438
|
});
|
|
189398
|
-
|
|
189399
|
-
|
|
189400
|
-
|
|
189401
|
-
|
|
189402
|
-
|
|
189439
|
+
remote.on("close", () => this.onIdleClose(remote, errored));
|
|
189440
|
+
}
|
|
189441
|
+
pipeToLocal(remote, firstChunk) {
|
|
189442
|
+
const local = net4.connect({ host: "127.0.0.1", port: this.localPort }, () => {
|
|
189443
|
+
local.write(firstChunk);
|
|
189444
|
+
remote.pipe(local);
|
|
189445
|
+
local.pipe(remote);
|
|
189446
|
+
});
|
|
189447
|
+
local.on("error", () => remote.destroy());
|
|
189448
|
+
remote.on("close", () => {
|
|
189449
|
+
if (!this.closed)
|
|
189450
|
+
this.fillPool();
|
|
189403
189451
|
});
|
|
189404
|
-
return tunnel;
|
|
189405
189452
|
}
|
|
189406
|
-
|
|
189407
|
-
|
|
189408
|
-
|
|
189409
|
-
|
|
189453
|
+
onIdleClose(remote, errored) {
|
|
189454
|
+
if (!this.pool.delete(remote) || this.closed)
|
|
189455
|
+
return;
|
|
189456
|
+
if (errored) {
|
|
189457
|
+
if (this.pool.size === 0)
|
|
189458
|
+
this.reconnect();
|
|
189459
|
+
} else {
|
|
189460
|
+
this.fillPool();
|
|
189461
|
+
}
|
|
189462
|
+
}
|
|
189463
|
+
async reconnect() {
|
|
189464
|
+
this.emit("close");
|
|
189465
|
+
for (let attempt = 0; !this.closed; attempt++) {
|
|
189466
|
+
const delay = RECONNECT_DELAYS[Math.min(attempt, RECONNECT_DELAYS.length - 1)];
|
|
189410
189467
|
await new Promise((r) => setTimeout(r, delay));
|
|
189411
|
-
if (
|
|
189468
|
+
if (this.closed)
|
|
189469
|
+
return;
|
|
189412
189470
|
try {
|
|
189413
|
-
|
|
189414
|
-
|
|
189471
|
+
this.info = await register(this.baseUrl, this.subdomain);
|
|
189472
|
+
this.fillPool();
|
|
189473
|
+
this.emit("reconnect");
|
|
189415
189474
|
return;
|
|
189416
189475
|
} catch {
|
|
189417
189476
|
}
|
|
189418
189477
|
}
|
|
189419
189478
|
}
|
|
189420
|
-
|
|
189479
|
+
};
|
|
189480
|
+
async function connect2(options2) {
|
|
189481
|
+
const host = options2.host ?? DEFAULT_HOST;
|
|
189482
|
+
const tunnelHost = new URL(host).hostname;
|
|
189483
|
+
const info = await register(host, options2.subdomain);
|
|
189484
|
+
return new TunnelClientImpl(info, options2.port, tunnelHost, host);
|
|
189485
|
+
}
|
|
189486
|
+
|
|
189487
|
+
// src/lib/dev/tunnel-manager.ts
|
|
189488
|
+
async function startTunnel(serviceName, endpointName, port, subdomain, callbacks) {
|
|
189489
|
+
const tunnel = await connect2({ port, subdomain });
|
|
189490
|
+
tunnel.on("error", (err) => callbacks?.onError?.(serviceName, endpointName, err));
|
|
189491
|
+
tunnel.on("close", () => callbacks?.onClose?.(serviceName, endpointName));
|
|
189492
|
+
tunnel.on("reconnect", () => callbacks?.onReconnect?.(serviceName, endpointName));
|
|
189421
189493
|
return {
|
|
189422
189494
|
serviceName,
|
|
189423
189495
|
endpointName,
|
|
189424
189496
|
localPort: port,
|
|
189425
|
-
url:
|
|
189497
|
+
url: tunnel.url,
|
|
189426
189498
|
subdomain,
|
|
189427
|
-
stop: async () =>
|
|
189428
|
-
stopped = true;
|
|
189429
|
-
currentTunnel?.close();
|
|
189430
|
-
}
|
|
189499
|
+
stop: async () => tunnel.close()
|
|
189431
189500
|
};
|
|
189432
189501
|
}
|
|
189433
189502
|
|
|
@@ -189435,7 +189504,7 @@ async function startTunnel(serviceName, endpointName, port, subdomain, callbacks
|
|
|
189435
189504
|
import * as fs20 from "fs";
|
|
189436
189505
|
import * as path17 from "path";
|
|
189437
189506
|
import * as os7 from "os";
|
|
189438
|
-
import * as
|
|
189507
|
+
import * as net5 from "net";
|
|
189439
189508
|
var ProxyRegistryManager = class {
|
|
189440
189509
|
proxyDir;
|
|
189441
189510
|
ownerPath;
|
|
@@ -189469,7 +189538,7 @@ var ProxyRegistryManager = class {
|
|
|
189469
189538
|
*/
|
|
189470
189539
|
isProxyListening(port, timeoutMs = 1e3) {
|
|
189471
189540
|
return new Promise((resolve10) => {
|
|
189472
|
-
const socket = new
|
|
189541
|
+
const socket = new net5.Socket();
|
|
189473
189542
|
let resolved = false;
|
|
189474
189543
|
const cleanup = () => {
|
|
189475
189544
|
if (!resolved) {
|
|
@@ -193103,7 +193172,7 @@ function betaCommand() {
|
|
|
193103
193172
|
var program = new Command();
|
|
193104
193173
|
var env = "production";
|
|
193105
193174
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
193106
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
193175
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.61").enablePositionalOptions();
|
|
193107
193176
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").action((options2) => initCommand(options2));
|
|
193108
193177
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
193109
193178
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|
package/dist/postinstall.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specific.dev/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.61",
|
|
4
4
|
"description": "CLI for Specific infrastructure-as-code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
"http-proxy": "^1.18.1",
|
|
42
42
|
"ink": "^6.5.1",
|
|
43
43
|
"ink-spinner": "^5.0.0",
|
|
44
|
-
"localtunnel": "^2.0.2",
|
|
45
44
|
"node-forge": "^1.3.1",
|
|
46
45
|
"open": "^11.0.0",
|
|
47
46
|
"posthog-node": "^5.24.1",
|
|
@@ -52,8 +51,8 @@
|
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
53
|
"@specific/config": "file:../config",
|
|
54
|
+
"@specific/tunnel-client": "file:../tunnel/client",
|
|
55
55
|
"@types/http-proxy": "^1.17.17",
|
|
56
|
-
"@types/localtunnel": "^2.0.4",
|
|
57
56
|
"@types/node": "^25.0.1",
|
|
58
57
|
"@types/node-forge": "^1.3.11",
|
|
59
58
|
"@types/react": "^19.2.7",
|
/package/dist/admin/_next/static/{3NwOLK8EcVipT46jmh2HP → ko53a3ptYl472sHJWxbir}/_buildManifest.js
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/admin/_next/static/{3NwOLK8EcVipT46jmh2HP → ko53a3ptYl472sHJWxbir}/_ssgManifest.js
RENAMED
|
File without changes
|