camstack 1.2.213 → 1.2.214
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/CHANGELOG.md +7 -0
- package/README.md +6 -0
- package/dist/chunk-37A556YF.js +822 -0
- package/dist/{chunk-MJJWVAEM.js → chunk-4Y3CBGOY.js} +53 -109
- package/dist/chunk-BYNP7S4W.js +56 -0
- package/dist/chunk-JPGJK5DC.js +75 -0
- package/dist/cli.js +127 -70
- package/dist/doctor-command-S7Q2U6HO.js +227 -0
- package/dist/{launcher-6TBFW332.js → launcher-JAOMC5YY.js} +716 -243
- package/dist/{server-EFXGQ7FD.js → server-TZCZTLBW.js} +215 -1007
- package/package.json +1 -1
|
@@ -6783,17 +6783,17 @@ function enumerateSchemaFields(schema, prefix = "") {
|
|
|
6783
6783
|
const out = [];
|
|
6784
6784
|
const shape = root.shape;
|
|
6785
6785
|
for (const [key, field] of Object.entries(shape)) {
|
|
6786
|
-
const
|
|
6786
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
6787
6787
|
const inner = unwrapSchema(field);
|
|
6788
6788
|
if (inner instanceof z4.ZodObject) {
|
|
6789
|
-
out.push(...enumerateSchemaFields(inner,
|
|
6789
|
+
out.push(...enumerateSchemaFields(inner, path));
|
|
6790
6790
|
continue;
|
|
6791
6791
|
}
|
|
6792
6792
|
const leaf = leafKind(field);
|
|
6793
6793
|
if (leaf) {
|
|
6794
6794
|
const quantity = quantityOfField(field);
|
|
6795
6795
|
out.push({
|
|
6796
|
-
path
|
|
6796
|
+
path,
|
|
6797
6797
|
kind: leaf.kind,
|
|
6798
6798
|
...leaf.enumValues ? { enumValues: leaf.enumValues } : {},
|
|
6799
6799
|
...quantity !== void 0 ? { quantity } : {}
|
|
@@ -7605,17 +7605,17 @@ function countWhenLeaves(node) {
|
|
|
7605
7605
|
for (const child of node.children) total += countWhenLeaves(child);
|
|
7606
7606
|
return total;
|
|
7607
7607
|
}
|
|
7608
|
-
function forEachLeaf(node, visit,
|
|
7608
|
+
function forEachLeaf(node, visit, path = "when") {
|
|
7609
7609
|
if (isLeaf(node)) {
|
|
7610
|
-
visit(node,
|
|
7610
|
+
visit(node, path);
|
|
7611
7611
|
return;
|
|
7612
7612
|
}
|
|
7613
7613
|
if (node.kind === "not") {
|
|
7614
|
-
forEachLeaf(node.child, visit, `${
|
|
7614
|
+
forEachLeaf(node.child, visit, `${path}.0`);
|
|
7615
7615
|
return;
|
|
7616
7616
|
}
|
|
7617
7617
|
node.children.forEach((child, i) => {
|
|
7618
|
-
forEachLeaf(child, visit, `${
|
|
7618
|
+
forEachLeaf(child, visit, `${path}.${i}`);
|
|
7619
7619
|
});
|
|
7620
7620
|
}
|
|
7621
7621
|
function hasEventLeaves(node) {
|
|
@@ -7643,22 +7643,22 @@ var LEAF_WORDS = {
|
|
|
7643
7643
|
function say(kind) {
|
|
7644
7644
|
return LEAF_WORDS[kind] ?? kind;
|
|
7645
7645
|
}
|
|
7646
|
-
function eventNeed(node,
|
|
7646
|
+
function eventNeed(node, path, negated) {
|
|
7647
7647
|
if (isLeaf(node)) {
|
|
7648
7648
|
if (!isEventLeaf(node)) return { paths: [] };
|
|
7649
|
-
if (negated) return { error: `"not" is applied to ${say(node.kind)} (${
|
|
7649
|
+
if (negated) return { error: `"not" is applied to ${say(node.kind)} (${path}) \u2014 an event is an instant, so "it did not happen" is true at every other moment and can never start a run. Negate a state ("is") instead, or remove the "not"` };
|
|
7650
7650
|
return { paths: [{
|
|
7651
|
-
path
|
|
7651
|
+
path,
|
|
7652
7652
|
kind: node.kind
|
|
7653
7653
|
}] };
|
|
7654
7654
|
}
|
|
7655
|
-
if (node.kind === "not") return eventNeed(node.child, `${
|
|
7655
|
+
if (node.kind === "not") return eventNeed(node.child, `${path}.0`, !negated);
|
|
7656
7656
|
const conjunctive = node.kind === "all" !== negated;
|
|
7657
7657
|
const parts = [];
|
|
7658
7658
|
for (let i = 0; i < node.children.length; i += 1) {
|
|
7659
7659
|
const child = node.children[i];
|
|
7660
7660
|
if (child === void 0) continue;
|
|
7661
|
-
const need = eventNeed(child, `${
|
|
7661
|
+
const need = eventNeed(child, `${path}.${i}`, negated);
|
|
7662
7662
|
if ("error" in need) return need;
|
|
7663
7663
|
parts.push(need);
|
|
7664
7664
|
}
|
|
@@ -7957,11 +7957,11 @@ function stepMetaOf(action) {
|
|
|
7957
7957
|
function j(value) {
|
|
7958
7958
|
return JSON.stringify(value);
|
|
7959
7959
|
}
|
|
7960
|
-
function emitLeaf(trigger,
|
|
7961
|
-
const at = j(
|
|
7960
|
+
function emitLeaf(trigger, path) {
|
|
7961
|
+
const at = j(path);
|
|
7962
7962
|
switch (trigger.kind) {
|
|
7963
7963
|
case "schedule":
|
|
7964
|
-
return ` // event leaf ${
|
|
7964
|
+
return ` // event leaf ${path}: schedule \u2014 armed to the next minute boundary and
|
|
7965
7965
|
// RE-ARMED from the wall clock every tick, so it cannot drift the way a
|
|
7966
7966
|
// setInterval(24h) does. No cron library: a block cannot resolve one.
|
|
7967
7967
|
{
|
|
@@ -7978,7 +7978,7 @@ function emitLeaf(trigger, path2) {
|
|
|
7978
7978
|
disposers.push(() => { if (timer !== undefined) clearTimeout(timer) })
|
|
7979
7979
|
}`;
|
|
7980
7980
|
case "device-event":
|
|
7981
|
-
return ` // event leaf ${
|
|
7981
|
+
return ` // event leaf ${path}: device event
|
|
7982
7982
|
disposers.push(
|
|
7983
7983
|
ctx.eventBus.subscribe(
|
|
7984
7984
|
{ category: ${j(trigger.category)}${trigger.deviceId === void 0 ? "" : `, deviceId: ${j(trigger.deviceId)}`} },
|
|
@@ -7995,7 +7995,7 @@ function emitLeaf(trigger, path2) {
|
|
|
7995
7995
|
)`;
|
|
7996
7996
|
case "device-becomes": {
|
|
7997
7997
|
const becomes = trigger.becomes === void 0 ? "undefined" : j(trigger.becomes);
|
|
7998
|
-
return ` // event leaf ${
|
|
7998
|
+
return ` // event leaf ${path}: device state \u2014 the mirror is the authority, the
|
|
7999
7999
|
// event only WAKES the evaluation, so a dropped event delays and never loses.
|
|
8000
8000
|
{
|
|
8001
8001
|
let previous: unknown = undefined
|
|
@@ -8037,11 +8037,11 @@ function emitLeaf(trigger, path2) {
|
|
|
8037
8037
|
}`;
|
|
8038
8038
|
}
|
|
8039
8039
|
case "manual":
|
|
8040
|
-
return ` // event leaf ${
|
|
8040
|
+
return ` // event leaf ${path}: manual \u2014 fired by automation-control.trigger
|
|
8041
8041
|
// ("Run actions"), which runs the THEN half with an EMPTY vars bag. A manual
|
|
8042
8042
|
// run bypasses only the cooldown wait, never the single/queued limits.`;
|
|
8043
8043
|
case "interval":
|
|
8044
|
-
return ` // event leaf ${
|
|
8044
|
+
return ` // event leaf ${path}: interval \u2014 every ${trigger.minutes} min, first run jittered so
|
|
8045
8045
|
// blocks restarted together do not all fire on the same second.
|
|
8046
8046
|
{
|
|
8047
8047
|
let interval: ReturnType<typeof setInterval> | undefined
|
|
@@ -8055,7 +8055,7 @@ function emitLeaf(trigger, path2) {
|
|
|
8055
8055
|
})
|
|
8056
8056
|
}`;
|
|
8057
8057
|
case "detection":
|
|
8058
|
-
return ` // event leaf ${
|
|
8058
|
+
return ` // event leaf ${path}: detection \u2014 ONE fire per (device, track); a rejected event is
|
|
8059
8059
|
// traced with its reason and never fires.
|
|
8060
8060
|
{
|
|
8061
8061
|
const filter = new DetectionTriggerFilter(${j(trigger)})
|
|
@@ -8081,7 +8081,7 @@ function emitLeaf(trigger, path2) {
|
|
|
8081
8081
|
)
|
|
8082
8082
|
}`;
|
|
8083
8083
|
case "stationary":
|
|
8084
|
-
return ` // event leaf ${
|
|
8084
|
+
return ` // event leaf ${path}: stationary \u2014 a parked object appeared / departed. Stateless:
|
|
8085
8085
|
// the registry emits one event per transition. A dropped event only misses a fire;
|
|
8086
8086
|
// the stationary-present STATE leaf reads the registry, not this event.
|
|
8087
8087
|
{
|
|
@@ -8152,10 +8152,10 @@ function generateAutomationBlock(input) {
|
|
|
8152
8152
|
const runMode = recipe.runMode ?? { mode: "single" };
|
|
8153
8153
|
const stepMeta = recipe.actions.map(stepMetaOf);
|
|
8154
8154
|
const eventLeaves = [];
|
|
8155
|
-
forEachLeaf(recipe.when, (leaf,
|
|
8155
|
+
forEachLeaf(recipe.when, (leaf, path) => {
|
|
8156
8156
|
if (isEventLeaf(leaf)) eventLeaves.push({
|
|
8157
8157
|
leaf,
|
|
8158
|
-
path
|
|
8158
|
+
path
|
|
8159
8159
|
});
|
|
8160
8160
|
});
|
|
8161
8161
|
return `import type {
|
|
@@ -8689,7 +8689,7 @@ ${recipe.actions.map((a, i) => emitAction(a, i)).join("\n")}
|
|
|
8689
8689
|
disposers.push(() => clearInterval(mirrorReconcile))
|
|
8690
8690
|
}
|
|
8691
8691
|
|
|
8692
|
-
${eventLeaves.map(({ leaf, path
|
|
8692
|
+
${eventLeaves.map(({ leaf, path }) => emitLeaf(leaf, path)).join("\n\n")}
|
|
8693
8693
|
|
|
8694
8694
|
return () => {
|
|
8695
8695
|
stopped = true
|
|
@@ -9007,7 +9007,7 @@ function checkPickedUnit(unit, target) {
|
|
|
9007
9007
|
target
|
|
9008
9008
|
});
|
|
9009
9009
|
}
|
|
9010
|
-
function normalizeLeaf(leaf, resolver,
|
|
9010
|
+
function normalizeLeaf(leaf, resolver, path) {
|
|
9011
9011
|
const quantity = resolver.fieldQuantity(leaf.cap, leaf.fieldPath);
|
|
9012
9012
|
const base = quantity === void 0 ? void 0 : baseUnitForQuantity(quantity);
|
|
9013
9013
|
const wantsUnit = isQuantityValue(leaf.value) || leaf.unit !== void 0;
|
|
@@ -9051,7 +9051,7 @@ function normalizeLeaf(leaf, resolver, path2) {
|
|
|
9051
9051
|
return {
|
|
9052
9052
|
leaf,
|
|
9053
9053
|
warnings: [bareWarning({
|
|
9054
|
-
path
|
|
9054
|
+
path,
|
|
9055
9055
|
deviceId: leaf.deviceId,
|
|
9056
9056
|
field: leaf.fieldPath,
|
|
9057
9057
|
value: leaf.value,
|
|
@@ -9059,17 +9059,17 @@ function normalizeLeaf(leaf, resolver, path2) {
|
|
|
9059
9059
|
})]
|
|
9060
9060
|
};
|
|
9061
9061
|
}
|
|
9062
|
-
function normalizeConditionUnits(condition, resolver,
|
|
9062
|
+
function normalizeConditionUnits(condition, resolver, path = "when") {
|
|
9063
9063
|
switch (condition.kind) {
|
|
9064
9064
|
case "device-is": {
|
|
9065
|
-
const { leaf, warnings } = normalizeLeaf(condition, resolver,
|
|
9065
|
+
const { leaf, warnings } = normalizeLeaf(condition, resolver, path);
|
|
9066
9066
|
return {
|
|
9067
9067
|
value: leaf,
|
|
9068
9068
|
warnings
|
|
9069
9069
|
};
|
|
9070
9070
|
}
|
|
9071
9071
|
case "not": {
|
|
9072
|
-
const inner = normalizeConditionUnits(condition.child, resolver, `${
|
|
9072
|
+
const inner = normalizeConditionUnits(condition.child, resolver, `${path}.child`);
|
|
9073
9073
|
return {
|
|
9074
9074
|
value: {
|
|
9075
9075
|
...condition,
|
|
@@ -9080,7 +9080,7 @@ function normalizeConditionUnits(condition, resolver, path2 = "when") {
|
|
|
9080
9080
|
}
|
|
9081
9081
|
case "all":
|
|
9082
9082
|
case "any": {
|
|
9083
|
-
const children = condition.children.map((child, i) => normalizeConditionUnits(child, resolver, `${
|
|
9083
|
+
const children = condition.children.map((child, i) => normalizeConditionUnits(child, resolver, `${path}.children.${i}`));
|
|
9084
9084
|
return {
|
|
9085
9085
|
value: {
|
|
9086
9086
|
...condition,
|
|
@@ -9096,7 +9096,7 @@ function normalizeConditionUnits(condition, resolver, path2 = "when") {
|
|
|
9096
9096
|
};
|
|
9097
9097
|
}
|
|
9098
9098
|
}
|
|
9099
|
-
function normalizeCapStep(step, resolver,
|
|
9099
|
+
function normalizeCapStep(step, resolver, path) {
|
|
9100
9100
|
const deviceId = typeof step.deviceId === "number" ? step.deviceId : void 0;
|
|
9101
9101
|
const args = { ...step.args };
|
|
9102
9102
|
const argUnits = { ...step.argUnits };
|
|
@@ -9117,7 +9117,7 @@ function normalizeCapStep(step, resolver, path2) {
|
|
|
9117
9117
|
});
|
|
9118
9118
|
argUnits[arg] = pickedUnit(given.unit);
|
|
9119
9119
|
} else if (typeof given === "number" && argUnits[arg] === void 0 && hasUnitChoice(meta.quantity)) warnings.push(bareWarning({
|
|
9120
|
-
path: `${
|
|
9120
|
+
path: `${path}.args.${arg}`,
|
|
9121
9121
|
...deviceId === void 0 ? {} : { deviceId },
|
|
9122
9122
|
field: arg,
|
|
9123
9123
|
value: given,
|
|
@@ -9134,7 +9134,7 @@ function normalizeCapStep(step, resolver, path2) {
|
|
|
9134
9134
|
warnings
|
|
9135
9135
|
};
|
|
9136
9136
|
}
|
|
9137
|
-
function normalizeActionUnits(actions, resolver,
|
|
9137
|
+
function normalizeActionUnits(actions, resolver, path = "steps") {
|
|
9138
9138
|
const out = [];
|
|
9139
9139
|
const warnings = [];
|
|
9140
9140
|
actions.forEach((action, i) => {
|
|
@@ -9142,7 +9142,7 @@ function normalizeActionUnits(actions, resolver, path2 = "steps") {
|
|
|
9142
9142
|
out.push(action);
|
|
9143
9143
|
return;
|
|
9144
9144
|
}
|
|
9145
|
-
const normalized = normalizeCapStep(action, resolver, `${
|
|
9145
|
+
const normalized = normalizeCapStep(action, resolver, `${path}.${i}`);
|
|
9146
9146
|
out.push(normalized.value);
|
|
9147
9147
|
warnings.push(...normalized.warnings);
|
|
9148
9148
|
});
|
|
@@ -50400,6 +50400,12 @@ var TerminalInstanceInfoSchema = z4.object({
|
|
|
50400
50400
|
instanceId: z4.string(),
|
|
50401
50401
|
cameraStableId: z4.string(),
|
|
50402
50402
|
nodeId: z4.string(),
|
|
50403
|
+
/**
|
|
50404
|
+
* False while the node the instance is bound to is not in the cluster
|
|
50405
|
+
* topology (forgotten, renamed, re-paired). The instance is kept; the
|
|
50406
|
+
* operator re-points it with `updateInstance({ targetNodeId })`.
|
|
50407
|
+
*/
|
|
50408
|
+
nodeInCluster: z4.boolean(),
|
|
50403
50409
|
profileId: z4.string(),
|
|
50404
50410
|
profileLabel: z4.string(),
|
|
50405
50411
|
name: z4.string(),
|
|
@@ -50459,6 +50465,8 @@ var terminalSessionCapability = {
|
|
|
50459
50465
|
}),
|
|
50460
50466
|
updateInstance: method(z4.object({
|
|
50461
50467
|
instanceId: z4.string().min(1),
|
|
50468
|
+
/** Re-point the instance to another node; the profile must exist there. */
|
|
50469
|
+
targetNodeId: z4.string().min(1).max(256).optional(),
|
|
50462
50470
|
name: z4.string().trim().min(1).max(160).optional(),
|
|
50463
50471
|
executable: z4.string().max(1024).optional(),
|
|
50464
50472
|
args: z4.array(z4.string().max(2048)).max(64).optional(),
|
|
@@ -53618,7 +53626,14 @@ var RemoteLayoutGroupSchema = z4.object({
|
|
|
53618
53626
|
col: z4.number().int().min(0).max(24),
|
|
53619
53627
|
rowSpan: z4.number().int().min(1).max(24),
|
|
53620
53628
|
colSpan: z4.number().int().min(1).max(24),
|
|
53621
|
-
title: z4.string().min(1).max(40).optional()
|
|
53629
|
+
title: z4.string().min(1).max(40).optional(),
|
|
53630
|
+
/**
|
|
53631
|
+
* How much room a divider takes: `compact` (the default) is a slim rule,
|
|
53632
|
+
* `normal` a full grid row. Other frames ignore it.
|
|
53633
|
+
*/
|
|
53634
|
+
size: z4.enum(["compact", "normal"]).optional(),
|
|
53635
|
+
/** Keep the title in the layout but draw only the rule. */
|
|
53636
|
+
hideTitle: z4.boolean().optional()
|
|
53622
53637
|
});
|
|
53623
53638
|
function rectsOverlap(a, b) {
|
|
53624
53639
|
return a.row < b.row + b.rowSpan && b.row < a.row + a.rowSpan && a.col < b.col + b.colSpan && b.col < a.col + a.colSpan;
|
|
@@ -53629,11 +53644,11 @@ function rectContains(outer, inner) {
|
|
|
53629
53644
|
function refineGroups(grid, ctx) {
|
|
53630
53645
|
const groups = grid.groups ?? [];
|
|
53631
53646
|
const byId = /* @__PURE__ */ new Map();
|
|
53632
|
-
const fail = (message,
|
|
53647
|
+
const fail = (message, path) => {
|
|
53633
53648
|
ctx.addIssue({
|
|
53634
53649
|
code: "custom",
|
|
53635
53650
|
message,
|
|
53636
|
-
path
|
|
53651
|
+
path
|
|
53637
53652
|
});
|
|
53638
53653
|
};
|
|
53639
53654
|
groups.forEach((group, index) => {
|
|
@@ -86041,74 +86056,6 @@ var SmartIrDocumentSchema = z4.object({
|
|
|
86041
86056
|
commands: z4.record(z4.string(), z4.unknown())
|
|
86042
86057
|
});
|
|
86043
86058
|
|
|
86044
|
-
// src/discovery/hub-finder.ts
|
|
86045
|
-
import * as fs from "fs";
|
|
86046
|
-
import * as path from "path";
|
|
86047
|
-
import {
|
|
86048
|
-
defaultSessionDir,
|
|
86049
|
-
isSessionFile,
|
|
86050
|
-
resolveHubUrl,
|
|
86051
|
-
validateHubAddress
|
|
86052
|
-
} from "@camstack/develop";
|
|
86053
|
-
import {
|
|
86054
|
-
discoverHubs
|
|
86055
|
-
} from "@camstack/develop/hub-discovery";
|
|
86056
|
-
function validateManualHubUrl(value) {
|
|
86057
|
-
return validateHubAddress(value);
|
|
86058
|
-
}
|
|
86059
|
-
function knownHubCandidates(deps) {
|
|
86060
|
-
const dir = deps.sessionDir ?? defaultSessionDir();
|
|
86061
|
-
const env = deps.env ?? process.env;
|
|
86062
|
-
const out = [];
|
|
86063
|
-
let files = [];
|
|
86064
|
-
try {
|
|
86065
|
-
files = fs.readdirSync(dir);
|
|
86066
|
-
} catch {
|
|
86067
|
-
files = [];
|
|
86068
|
-
}
|
|
86069
|
-
for (const file of files) {
|
|
86070
|
-
if (file.endsWith(".json")) {
|
|
86071
|
-
try {
|
|
86072
|
-
const parsed = JSON.parse(fs.readFileSync(path.join(dir, file), "utf8"));
|
|
86073
|
-
if (isSessionFile(parsed)) {
|
|
86074
|
-
out.push({
|
|
86075
|
-
url: parsed.server,
|
|
86076
|
-
source: `saved session ${parsed.username}`
|
|
86077
|
-
});
|
|
86078
|
-
}
|
|
86079
|
-
} catch {
|
|
86080
|
-
}
|
|
86081
|
-
}
|
|
86082
|
-
}
|
|
86083
|
-
const fromEnv = resolveHubUrl({ env, session: null });
|
|
86084
|
-
if (fromEnv) {
|
|
86085
|
-
const name = (env["CAMSTACK_HUB_URL"] ?? "").trim() === "" ? "CAMSTACK_SERVER" : "CAMSTACK_HUB_URL";
|
|
86086
|
-
out.push({ url: fromEnv.url, source: name });
|
|
86087
|
-
}
|
|
86088
|
-
if (deps.workspaceRoot !== void 0) {
|
|
86089
|
-
const scratch = resolveHubUrl({
|
|
86090
|
-
env: {},
|
|
86091
|
-
workspaceRoot: deps.workspaceRoot,
|
|
86092
|
-
session: null
|
|
86093
|
-
});
|
|
86094
|
-
if (scratch) out.push({ url: scratch.url, source: "scratchpad/.hub-url" });
|
|
86095
|
-
}
|
|
86096
|
-
return out;
|
|
86097
|
-
}
|
|
86098
|
-
async function findHubs(deps = {}) {
|
|
86099
|
-
return discoverHubs({
|
|
86100
|
-
known: knownHubCandidates(deps),
|
|
86101
|
-
...deps.browse ? { browse: deps.browse } : {},
|
|
86102
|
-
...deps.probe ? { probe: deps.probe } : {},
|
|
86103
|
-
...deps.mdnsTimeoutMs !== void 0 ? { mdnsTimeoutMs: deps.mdnsTimeoutMs } : {},
|
|
86104
|
-
...deps.onProblem ? { onProblem: deps.onProblem } : {}
|
|
86105
|
-
});
|
|
86106
|
-
}
|
|
86107
|
-
function describeHub(hub) {
|
|
86108
|
-
const identity = [hub.nodeId, hub.version === null ? null : `v${hub.version}`].filter((p) => p !== null).join(" ");
|
|
86109
|
-
return `${hub.url}${identity === "" ? "" : ` ${identity}`} (${hub.sources.join(", ")})`;
|
|
86110
|
-
}
|
|
86111
|
-
|
|
86112
86059
|
export {
|
|
86113
86060
|
isReadingQuantity,
|
|
86114
86061
|
FFMPEG_PATH_ENV,
|
|
@@ -86128,8 +86075,5 @@ export {
|
|
|
86128
86075
|
DETECTOR_PERF,
|
|
86129
86076
|
ALL_CAPABILITY_DEFINITIONS,
|
|
86130
86077
|
classifyInferenceHardware,
|
|
86131
|
-
acceleratorKindOf
|
|
86132
|
-
validateManualHubUrl,
|
|
86133
|
-
findHubs,
|
|
86134
|
-
describeHub
|
|
86078
|
+
acceleratorKindOf
|
|
86135
86079
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/http/hub-http.ts
|
|
4
|
+
import * as http from "http";
|
|
5
|
+
import * as https from "https";
|
|
6
|
+
import { Buffer } from "buffer";
|
|
7
|
+
import { createHubAgent, explainTlsFailure, resolveHubTls } from "@camstack/develop";
|
|
8
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
9
|
+
function hubRequest(url, opts = {}) {
|
|
10
|
+
const parsed = new URL(url);
|
|
11
|
+
const isHttps = parsed.protocol === "https:";
|
|
12
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const requestOptions = {
|
|
15
|
+
protocol: parsed.protocol,
|
|
16
|
+
hostname: parsed.hostname,
|
|
17
|
+
port: parsed.port || (isHttps ? 443 : 80),
|
|
18
|
+
path: `${parsed.pathname}${parsed.search}`,
|
|
19
|
+
method: opts.method ?? "GET",
|
|
20
|
+
headers: { ...opts.headers },
|
|
21
|
+
timeout: timeoutMs,
|
|
22
|
+
...isHttps ? { agent: createHubAgent(resolveHubTls(parsed.origin, opts.env, opts.sessionDir)) } : {}
|
|
23
|
+
};
|
|
24
|
+
const onResponse = (res) => {
|
|
25
|
+
const chunks = [];
|
|
26
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
27
|
+
res.on("end", () => {
|
|
28
|
+
const buffer = Buffer.concat(chunks);
|
|
29
|
+
const status = res.statusCode ?? 0;
|
|
30
|
+
resolve({
|
|
31
|
+
ok: status >= 200 && status < 300,
|
|
32
|
+
status,
|
|
33
|
+
statusText: res.statusMessage ?? "",
|
|
34
|
+
headers: res.headers,
|
|
35
|
+
text: () => Promise.resolve(buffer.toString("utf8")),
|
|
36
|
+
json: () => Promise.resolve().then(() => JSON.parse(buffer.toString("utf8")))
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
res.on("error", reject);
|
|
40
|
+
};
|
|
41
|
+
const req = isHttps ? https.request(requestOptions, onResponse) : http.request(requestOptions, onResponse);
|
|
42
|
+
req.on("error", (err) => {
|
|
43
|
+
const explained = isHttps ? explainTlsFailure(`${parsed.protocol}//${parsed.host}`, err) : null;
|
|
44
|
+
reject(explained === null ? err : new Error(explained, { cause: err }));
|
|
45
|
+
});
|
|
46
|
+
req.on("timeout", () => {
|
|
47
|
+
req.destroy(new Error(`Hub request to ${parsed.host} timed out after ${timeoutMs}ms`));
|
|
48
|
+
});
|
|
49
|
+
if (opts.body !== void 0) req.write(opts.body);
|
|
50
|
+
req.end();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
hubRequest
|
|
56
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/discovery/hub-finder.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import {
|
|
7
|
+
defaultSessionDir,
|
|
8
|
+
isSessionFile,
|
|
9
|
+
resolveHubUrl,
|
|
10
|
+
validateHubAddress
|
|
11
|
+
} from "@camstack/develop";
|
|
12
|
+
import {
|
|
13
|
+
discoverHubs
|
|
14
|
+
} from "@camstack/develop/hub-discovery";
|
|
15
|
+
function validateManualHubUrl(value) {
|
|
16
|
+
return validateHubAddress(value);
|
|
17
|
+
}
|
|
18
|
+
function knownHubCandidates(deps) {
|
|
19
|
+
const dir = deps.sessionDir ?? defaultSessionDir();
|
|
20
|
+
const env = deps.env ?? process.env;
|
|
21
|
+
const out = [];
|
|
22
|
+
let files = [];
|
|
23
|
+
try {
|
|
24
|
+
files = fs.readdirSync(dir);
|
|
25
|
+
} catch {
|
|
26
|
+
files = [];
|
|
27
|
+
}
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
if (file.endsWith(".json")) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(fs.readFileSync(path.join(dir, file), "utf8"));
|
|
32
|
+
if (isSessionFile(parsed)) {
|
|
33
|
+
out.push({
|
|
34
|
+
url: parsed.server,
|
|
35
|
+
source: `saved session ${parsed.username}`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const fromEnv = resolveHubUrl({ env, session: null });
|
|
43
|
+
if (fromEnv) {
|
|
44
|
+
const name = (env["CAMSTACK_HUB_URL"] ?? "").trim() === "" ? "CAMSTACK_SERVER" : "CAMSTACK_HUB_URL";
|
|
45
|
+
out.push({ url: fromEnv.url, source: name });
|
|
46
|
+
}
|
|
47
|
+
if (deps.workspaceRoot !== void 0) {
|
|
48
|
+
const scratch = resolveHubUrl({
|
|
49
|
+
env: {},
|
|
50
|
+
workspaceRoot: deps.workspaceRoot,
|
|
51
|
+
session: null
|
|
52
|
+
});
|
|
53
|
+
if (scratch) out.push({ url: scratch.url, source: "scratchpad/.hub-url" });
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
async function findHubs(deps = {}) {
|
|
58
|
+
return discoverHubs({
|
|
59
|
+
known: knownHubCandidates(deps),
|
|
60
|
+
...deps.browse ? { browse: deps.browse } : {},
|
|
61
|
+
...deps.probe ? { probe: deps.probe } : {},
|
|
62
|
+
...deps.mdnsTimeoutMs !== void 0 ? { mdnsTimeoutMs: deps.mdnsTimeoutMs } : {},
|
|
63
|
+
...deps.onProblem ? { onProblem: deps.onProblem } : {}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function describeHub(hub) {
|
|
67
|
+
const identity = [hub.nodeId, hub.version === null ? null : `v${hub.version}`].filter((p) => p !== null).join(" ");
|
|
68
|
+
return `${hub.url}${identity === "" ? "" : ` ${identity}`} (${hub.sources.join(", ")})`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export {
|
|
72
|
+
validateManualHubUrl,
|
|
73
|
+
findHubs,
|
|
74
|
+
describeHub
|
|
75
|
+
};
|