@takodotid/circuit 0.43.1 → 1.0.0-rc.2
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/README.md +115 -37
- package/package.json +21 -58
- package/src/checks/across.ts +402 -0
- package/src/checks/built-in.ts +256 -0
- package/src/checks/device.ts +436 -0
- package/src/checks/index.ts +53 -0
- package/src/cli/advisories.ts +108 -0
- package/src/cli/app.ts +71 -0
- package/src/cli/editor-types.generated.ts +30 -0
- package/src/cli/editor-types.ts +69 -0
- package/src/cli/format.ts +124 -0
- package/src/cli/git-hooks.ts +79 -0
- package/src/cli/index.ts +350 -1170
- package/src/cli/migrate.ts +554 -0
- package/src/cli/project-commands.ts +656 -0
- package/src/cli/releases.ts +374 -0
- package/src/cli/remember.ts +339 -0
- package/src/cli/rename.ts +27 -33
- package/src/cli/secrets-password.ts +60 -0
- package/src/cli/secrets.ts +258 -0
- package/src/cli/setup.ts +300 -0
- package/src/cli/signing.ts +23 -0
- package/src/cli/text-editor.ts +268 -0
- package/src/cli/ui.ts +298 -0
- package/src/cli/version.ts +2 -0
- package/src/cli/versions.ts +158 -0
- package/src/config/address.ts +102 -0
- package/src/config/circuit.d.ts +30 -0
- package/src/config/common.ts +65 -0
- package/src/config/communities.ts +479 -0
- package/src/config/define.ts +684 -0
- package/src/config/device.ts +164 -0
- package/src/config/firewall.ts +150 -0
- package/src/config/index.ts +22 -0
- package/src/{schema → config}/interfaces.ts +121 -85
- package/src/config/keys.ts +434 -0
- package/src/config/management.ts +61 -0
- package/src/config/merge.ts +335 -0
- package/src/config/models.ts +70 -0
- package/src/config/monitoring.ts +64 -0
- package/src/config/network.ts +180 -0
- package/src/config/presets.ts +149 -0
- package/src/config/routing.ts +401 -0
- package/src/config/services.ts +51 -0
- package/src/config/switching.ts +84 -0
- package/src/config/system.ts +103 -0
- package/src/{schema → config}/time-zones.ts +1 -1
- package/src/core/address.ts +1 -1
- package/src/core/cabling.ts +8 -43
- package/src/core/graph.ts +40 -0
- package/src/{integrations → core}/registries.ts +5 -3
- package/src/core/secrets-file.ts +539 -0
- package/src/core/secrets.ts +83 -64
- package/src/core/topology.ts +103 -146
- package/src/core/utils.ts +12 -1
- package/src/model.ts +83 -0
- package/src/platforms/derive.ts +64 -37
- package/src/platforms/finding.ts +9 -0
- package/src/platforms/fortios/firewall.ts +76 -64
- package/src/platforms/fortios/index.ts +189 -125
- package/src/platforms/fortios/names.ts +51 -18
- package/src/platforms/fortios/render.ts +69 -62
- package/src/platforms/fortios/routing.ts +89 -58
- package/src/platforms/fortios/vdoms.ts +47 -16
- package/src/platforms/junos/TRAPS.md +2 -2
- package/src/platforms/junos/bgp.ts +63 -42
- package/src/platforms/junos/index.ts +122 -89
- package/src/platforms/junos/render.ts +139 -104
- package/src/platforms/platform.ts +10 -8
- package/src/platforms/raisecom-ros/TRAPS.md +1 -1
- package/src/platforms/raisecom-ros/index.ts +89 -70
- package/src/platforms/raisecom-ros/render.ts +49 -45
- package/src/platforms/routeros/TRAPS.md +3 -3
- package/src/platforms/routeros/index.ts +121 -60
- package/src/platforms/routeros/render.ts +214 -195
- package/src/platforms/vrp/TRAPS.md +1 -1
- package/src/platforms/vrp/index.ts +74 -50
- package/src/platforms/vrp/render.ts +67 -56
- package/src/project/project.ts +725 -0
- package/src/studio/app/env.d.ts +9 -0
- package/src/studio/app/index.html +18 -0
- package/src/studio/app/src/App.vue +95 -0
- package/src/studio/app/src/components/AddressesView.vue +38 -0
- package/src/studio/app/src/components/CablesView.vue +29 -0
- package/src/studio/app/src/components/CompareView.vue +160 -0
- package/src/studio/app/src/components/DataTable.vue +49 -0
- package/src/studio/app/src/components/DeviceView.vue +237 -0
- package/src/studio/app/src/components/DevicesView.vue +32 -0
- package/src/studio/app/src/components/Faceplate.vue +75 -0
- package/src/studio/app/src/components/GraphView.vue +282 -0
- package/src/studio/app/src/components/LineDiff.vue +24 -0
- package/src/studio/app/src/components/ProblemsView.vue +42 -0
- package/src/studio/app/src/components/SearchView.vue +72 -0
- package/src/studio/app/src/components/SecretsView.vue +112 -0
- package/src/studio/app/src/components/SessionsView.vue +35 -0
- package/src/studio/app/src/components/Settings.vue +95 -0
- package/src/studio/app/src/components/ToolsView.vue +118 -0
- package/src/studio/app/src/components/VlansView.vue +50 -0
- package/src/studio/app/src/lib/csv.ts +19 -0
- package/src/studio/{public/diff.js → app/src/lib/diff.ts} +40 -35
- package/src/studio/app/src/lib/format.ts +38 -0
- package/src/studio/app/src/lib/net.ts +68 -0
- package/src/studio/app/src/lib/secrets-crypto.ts +35 -0
- package/src/studio/app/src/lib/store.ts +71 -0
- package/src/studio/app/src/lib/tools.ts +217 -0
- package/src/studio/app/src/main.ts +9 -0
- package/src/studio/{public → app/src}/style.css +14 -4
- package/src/studio/app/tsconfig.json +17 -0
- package/src/studio/app/vite.config.ts +16 -0
- package/src/studio/assets.generated.ts +3 -0
- package/src/studio/data.ts +96 -188
- package/src/studio/git.ts +27 -43
- package/src/studio/server.ts +196 -107
- package/src/studio/types.ts +141 -0
- package/src/transport/console.ts +3 -3
- package/src/transport/ssh.ts +1 -1
- package/dist/chunks/index-3b343xva.js +0 -177
- package/dist/chunks/index-6wb41q67.js +0 -62
- package/dist/chunks/index-n7w3tg5y.js +0 -149
- package/dist/chunks/index-yzw86rc8.js +0 -921
- package/dist/chunks/new-w3zys5y4.js +0 -172
- package/dist/chunks/server-cxr9ynxc.js +0 -259
- package/dist/cli/index.js +0 -12922
- package/dist/helpers/index.js +0 -881
- package/dist/index.js +0 -28
- package/dist/types/core/address-space.d.ts +0 -62
- package/dist/types/core/address.d.ts +0 -44
- package/dist/types/core/cabling.d.ts +0 -41
- package/dist/types/core/cross-checks.d.ts +0 -28
- package/dist/types/core/define.d.ts +0 -79
- package/dist/types/core/project-files.d.ts +0 -12
- package/dist/types/core/schema-docs.d.ts +0 -25
- package/dist/types/core/secrets.d.ts +0 -62
- package/dist/types/core/topology.d.ts +0 -96
- package/dist/types/core/utils.d.ts +0 -10
- package/dist/types/core/validator.d.ts +0 -23
- package/dist/types/helpers/bgp.d.ts +0 -195
- package/dist/types/helpers/cables.d.ts +0 -69
- package/dist/types/helpers/checks.d.ts +0 -36
- package/dist/types/helpers/exchange.d.ts +0 -55
- package/dist/types/helpers/filters.d.ts +0 -51
- package/dist/types/helpers/index.d.ts +0 -14
- package/dist/types/helpers/route-server.d.ts +0 -52
- package/dist/types/helpers/upstreams.d.ts +0 -192
- package/dist/types/index.d.ts +0 -10
- package/dist/types/integrations/librenms.d.ts +0 -60
- package/dist/types/integrations/netbox.d.ts +0 -89
- package/dist/types/integrations/peeringdb.d.ts +0 -24
- package/dist/types/integrations/prometheus.d.ts +0 -24
- package/dist/types/integrations/registries.d.ts +0 -8
- package/dist/types/platforms/bgp-wait.d.ts +0 -24
- package/dist/types/platforms/catalog.d.ts +0 -109
- package/dist/types/platforms/derive.d.ts +0 -17
- package/dist/types/platforms/fortios/firewall.d.ts +0 -47
- package/dist/types/platforms/fortios/index.d.ts +0 -140
- package/dist/types/platforms/fortios/models.d.ts +0 -14
- package/dist/types/platforms/fortios/names.d.ts +0 -52
- package/dist/types/platforms/fortios/plan.d.ts +0 -114
- package/dist/types/platforms/fortios/render.d.ts +0 -77
- package/dist/types/platforms/fortios/routing.d.ts +0 -56
- package/dist/types/platforms/fortios/tree.d.ts +0 -37
- package/dist/types/platforms/fortios/vdoms.d.ts +0 -50
- package/dist/types/platforms/index.d.ts +0 -13
- package/dist/types/platforms/junos/bgp.d.ts +0 -44
- package/dist/types/platforms/junos/index.d.ts +0 -114
- package/dist/types/platforms/junos/models.d.ts +0 -14
- package/dist/types/platforms/junos/render.d.ts +0 -154
- package/dist/types/platforms/line-diff.d.ts +0 -67
- package/dist/types/platforms/platform.d.ts +0 -135
- package/dist/types/platforms/raisecom-ros/index.d.ts +0 -71
- package/dist/types/platforms/raisecom-ros/models.d.ts +0 -14
- package/dist/types/platforms/raisecom-ros/render.d.ts +0 -41
- package/dist/types/platforms/routeros/export.d.ts +0 -59
- package/dist/types/platforms/routeros/index.d.ts +0 -116
- package/dist/types/platforms/routeros/models.d.ts +0 -18
- package/dist/types/platforms/routeros/plan.d.ts +0 -58
- package/dist/types/platforms/routeros/render.d.ts +0 -250
- package/dist/types/platforms/vrp/index.d.ts +0 -83
- package/dist/types/platforms/vrp/models.d.ts +0 -12
- package/dist/types/platforms/vrp/render.d.ts +0 -96
- package/dist/types/schema/common.d.ts +0 -30
- package/dist/types/schema/device.d.ts +0 -126
- package/dist/types/schema/firewall.d.ts +0 -131
- package/dist/types/schema/index.d.ts +0 -8
- package/dist/types/schema/interfaces.d.ts +0 -205
- package/dist/types/schema/policy.d.ts +0 -107
- package/dist/types/schema/routing.d.ts +0 -161
- package/dist/types/schema/system.d.ts +0 -198
- package/dist/types/schema/time-zones.d.ts +0 -2
- package/dist/types/transport/console.d.ts +0 -115
- package/dist/types/transport/path-check.d.ts +0 -32
- package/dist/types/transport/ssh.d.ts +0 -27
- package/src/cli/graph-format.ts +0 -91
- package/src/cli/new.ts +0 -234
- package/src/core/address-space.ts +0 -320
- package/src/core/cross-checks.ts +0 -369
- package/src/core/define.ts +0 -124
- package/src/core/project-files.ts +0 -35
- package/src/core/schema-docs.ts +0 -174
- package/src/core/validator.ts +0 -508
- package/src/helpers/bgp.ts +0 -473
- package/src/helpers/cables.ts +0 -74
- package/src/helpers/checks.ts +0 -201
- package/src/helpers/exchange.ts +0 -123
- package/src/helpers/filters.ts +0 -107
- package/src/helpers/index.ts +0 -25
- package/src/helpers/route-server.ts +0 -212
- package/src/helpers/upstreams.ts +0 -369
- package/src/index.ts +0 -13
- package/src/integrations/librenms.ts +0 -291
- package/src/integrations/netbox.ts +0 -620
- package/src/integrations/peeringdb.ts +0 -173
- package/src/integrations/prometheus.ts +0 -90
- package/src/schema/common.ts +0 -41
- package/src/schema/device.ts +0 -145
- package/src/schema/firewall.ts +0 -140
- package/src/schema/index.ts +0 -8
- package/src/schema/policy.ts +0 -115
- package/src/schema/routing.ts +0 -173
- package/src/schema/system.ts +0 -203
- package/src/studio/public/app.js +0 -186
- package/src/studio/public/compare.js +0 -250
- package/src/studio/public/dom.js +0 -138
- package/src/studio/public/evaluate.js +0 -687
- package/src/studio/public/export.js +0 -130
- package/src/studio/public/graph.js +0 -1541
- package/src/studio/public/index.html +0 -83
- package/src/studio/public/net.js +0 -134
- package/src/studio/public/tables.js +0 -1289
- package/src/studio/public/tools.js +0 -610
- package/templates/colocation/checks.ts +0 -53
- package/templates/colocation/circuit.config.ts +0 -9
- package/templates/colocation/edge-01.ts +0 -133
- package/templates/colocation/routing.ts +0 -13
- package/templates/colocation/tenancy.ts +0 -76
- package/templates/colocation/tenants/acme.ts +0 -19
- package/templates/colocation/tenants/index.ts +0 -6
- package/templates/colocation/tor-01.ts +0 -33
- package/templates/edge-router/checks.ts +0 -20
- package/templates/edge-router/circuit.config.ts +0 -8
- package/templates/edge-router/edge-01.ts +0 -110
- package/templates/edge-router/routing.ts +0 -13
- package/templates/project/AGENTS.md +0 -51
- package/templates/project/CLAUDE.md +0 -1
- package/templates/project/README.md +0 -16
- package/templates/project/gitignore +0 -5
- package/templates/project/tsconfig.json +0 -13
- package/templates/single-site/checks.ts +0 -26
- package/templates/single-site/circuit.config.ts +0 -8
- package/templates/single-site/router.ts +0 -86
- package/templates/single-site/site.ts +0 -18
- package/templates/single-site/switch.ts +0 -34
- /package/src/studio/{public → app/public}/favicon.svg +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin-ext.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-license.txt +0 -0
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
// src/core/utils.ts
|
|
2
|
-
class Utils2 {
|
|
3
|
-
static merge(...records) {
|
|
4
|
-
const result = {};
|
|
5
|
-
for (const record of records) {
|
|
6
|
-
for (const [key, value] of Object.entries(record)) {
|
|
7
|
-
if (key in result)
|
|
8
|
-
throw new Error(`Utils.merge: ${key} is declared twice`);
|
|
9
|
-
result[key] = value;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return result;
|
|
13
|
-
}
|
|
14
|
-
static otherTable(table) {
|
|
15
|
-
return table === "main" ? undefined : table;
|
|
16
|
-
}
|
|
17
|
-
static timeZoneOffset(zone) {
|
|
18
|
-
const name = new Intl.DateTimeFormat("en-US", {
|
|
19
|
-
timeZone: zone,
|
|
20
|
-
timeZoneName: "longOffset"
|
|
21
|
-
}).formatToParts(new Date).find((entry) => entry.type === "timeZoneName").value;
|
|
22
|
-
const found = /GMT([+-])(\d{2}):(\d{2})/.exec(name);
|
|
23
|
-
if (!found)
|
|
24
|
-
return 0;
|
|
25
|
-
const [, sign, hours, minutes] = found;
|
|
26
|
-
const sizeInMinutes = Number(hours) * 60 + Number(minutes);
|
|
27
|
-
return sign === "-" ? -sizeInMinutes : sizeInMinutes;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// src/core/secrets.ts
|
|
32
|
-
import { spawnSync } from "node:child_process";
|
|
33
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
34
|
-
import { join } from "node:path";
|
|
35
|
-
import { parseEnv } from "node:util";
|
|
36
|
-
|
|
37
|
-
class Secrets2 {
|
|
38
|
-
static root = process.cwd();
|
|
39
|
-
static envFile;
|
|
40
|
-
static fromOnePassword = new Map;
|
|
41
|
-
static revealed = new Set;
|
|
42
|
-
static REDACTED = "<redacted>";
|
|
43
|
-
static SHORTEST_DOTENV_VALUE = 6;
|
|
44
|
-
static MARKER = /<secret:([A-Za-z0-9_./:-]+)>/g;
|
|
45
|
-
static useRoot(directory) {
|
|
46
|
-
Secrets2.root = directory;
|
|
47
|
-
Secrets2.envFile = undefined;
|
|
48
|
-
}
|
|
49
|
-
static dotenv() {
|
|
50
|
-
if (Secrets2.envFile)
|
|
51
|
-
return Secrets2.envFile;
|
|
52
|
-
const path = join(Secrets2.root, ".env");
|
|
53
|
-
const text = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
54
|
-
Secrets2.refuseCutValues(text);
|
|
55
|
-
Secrets2.envFile = parseEnv(text);
|
|
56
|
-
return Secrets2.envFile;
|
|
57
|
-
}
|
|
58
|
-
static refuseCutValues(text) {
|
|
59
|
-
for (const line of text.split(/\r?\n/)) {
|
|
60
|
-
const [, name, value] = /^\s*(?:export\s+)?([\w.-]+)\s*=\s*(.*)$/.exec(line) ?? [];
|
|
61
|
-
if (!name || !value || /^['"`]/.test(value) || !/\S#/.test(value))
|
|
62
|
-
continue;
|
|
63
|
-
throw new Error(`.env: the value of ${name} has a # in it, which starts a comment there; put the value in quotes`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
static readOnePassword(name, reference) {
|
|
67
|
-
const cached = Secrets2.fromOnePassword.get(reference);
|
|
68
|
-
if (cached !== undefined)
|
|
69
|
-
return cached;
|
|
70
|
-
const result = spawnSync("op", ["read", "--no-newline", reference], { encoding: "utf8" });
|
|
71
|
-
if (result.error)
|
|
72
|
-
throw new Error(`secret ${name} is a 1Password reference, and the 1Password CLI, op, is not installed`);
|
|
73
|
-
if (result.status !== 0) {
|
|
74
|
-
const reason = result.stderr.trim() || `op exited with ${result.status}`;
|
|
75
|
-
throw new Error(`secret ${name}: 1Password could not read ${reference}: ${reason}`);
|
|
76
|
-
}
|
|
77
|
-
const value = result.stdout;
|
|
78
|
-
Secrets2.fromOnePassword.set(reference, value);
|
|
79
|
-
return value;
|
|
80
|
-
}
|
|
81
|
-
static isSecret(value) {
|
|
82
|
-
return typeof value === "object" && value !== null && (("secret" in value) || ("secret_file" in value));
|
|
83
|
-
}
|
|
84
|
-
static referenceOf(secret) {
|
|
85
|
-
return "secret" in secret ? secret.secret : `file:${secret.secret_file}`;
|
|
86
|
-
}
|
|
87
|
-
static sourceOf(reference) {
|
|
88
|
-
if (reference.startsWith("file:"))
|
|
89
|
-
return existsSync(join(Secrets2.root, reference.slice("file:".length))) ? "a file" : undefined;
|
|
90
|
-
const fromFile = Secrets2.dotenv()[reference];
|
|
91
|
-
const value = process.env[reference] || fromFile;
|
|
92
|
-
if (!value)
|
|
93
|
-
return;
|
|
94
|
-
const where = process.env[reference] && process.env[reference] !== fromFile ? "the environment" : ".env";
|
|
95
|
-
return value.startsWith("op://") ? `1Password, through ${where}` : where;
|
|
96
|
-
}
|
|
97
|
-
static valueOf(reference) {
|
|
98
|
-
if (reference.startsWith("file:")) {
|
|
99
|
-
const path = reference.slice("file:".length);
|
|
100
|
-
const fullPath = join(Secrets2.root, path);
|
|
101
|
-
if (!existsSync(fullPath))
|
|
102
|
-
throw new Error(`secret file ${path} does not exist`);
|
|
103
|
-
const value = readFileSync(fullPath, "utf8").trimEnd();
|
|
104
|
-
if (!value)
|
|
105
|
-
throw new Error(`secret file ${path} is empty`);
|
|
106
|
-
Secrets2.revealed.add(value);
|
|
107
|
-
return value;
|
|
108
|
-
}
|
|
109
|
-
const fromFile = Secrets2.dotenv()[reference];
|
|
110
|
-
const value = process.env[reference] || fromFile;
|
|
111
|
-
if (!value)
|
|
112
|
-
throw new Error(`secret ${reference} is not set in the environment or in .env`);
|
|
113
|
-
const revealed = value.startsWith("op://") ? Secrets2.readOnePassword(reference, value) : value;
|
|
114
|
-
Secrets2.revealed.add(revealed);
|
|
115
|
-
return revealed;
|
|
116
|
-
}
|
|
117
|
-
static reveal(secret) {
|
|
118
|
-
return Secrets2.valueOf(typeof secret === "string" ? secret : Secrets2.referenceOf(secret));
|
|
119
|
-
}
|
|
120
|
-
static referencesIn(value, found = new Set) {
|
|
121
|
-
if (Secrets2.isSecret(value))
|
|
122
|
-
found.add(Secrets2.referenceOf(value));
|
|
123
|
-
else if (Array.isArray(value))
|
|
124
|
-
for (const item of value)
|
|
125
|
-
Secrets2.referencesIn(item, found);
|
|
126
|
-
else if (typeof value === "object" && value !== null)
|
|
127
|
-
for (const item of Object.values(value))
|
|
128
|
-
Secrets2.referencesIn(item, found);
|
|
129
|
-
return found;
|
|
130
|
-
}
|
|
131
|
-
static scrub(text, options = {}) {
|
|
132
|
-
const values = new Set(options.extra ?? []);
|
|
133
|
-
for (const value of Object.values(Secrets2.dotenv())) {
|
|
134
|
-
if (value.length >= Secrets2.SHORTEST_DOTENV_VALUE && !value.startsWith("op://"))
|
|
135
|
-
values.add(value);
|
|
136
|
-
}
|
|
137
|
-
for (const value of Secrets2.revealed)
|
|
138
|
-
values.add(value);
|
|
139
|
-
for (const reference of Secrets2.referencesIn(options.network)) {
|
|
140
|
-
const value = Secrets2.storedValueOf(reference);
|
|
141
|
-
if (value)
|
|
142
|
-
values.add(value);
|
|
143
|
-
}
|
|
144
|
-
const ordered = [...values].filter(Boolean).sort((a, b) => b.length - a.length);
|
|
145
|
-
return ordered.reduce((out, value) => out.split(value).join(Secrets2.REDACTED), text);
|
|
146
|
-
}
|
|
147
|
-
static storedValueOf(reference) {
|
|
148
|
-
if (reference.startsWith("file:")) {
|
|
149
|
-
const path = join(Secrets2.root, reference.slice("file:".length));
|
|
150
|
-
return existsSync(path) ? readFileSync(path, "utf8").trimEnd() : undefined;
|
|
151
|
-
}
|
|
152
|
-
const value = process.env[reference] || Secrets2.dotenv()[reference];
|
|
153
|
-
if (!value?.startsWith("op://"))
|
|
154
|
-
return value;
|
|
155
|
-
return Secrets2.fromOnePassword.get(value);
|
|
156
|
-
}
|
|
157
|
-
static loginOf(device) {
|
|
158
|
-
const user = device.users?.[device.connection.user];
|
|
159
|
-
if (!user)
|
|
160
|
-
throw new Error(`${device.name}: connection user ${device.connection.user} is not one of its users`);
|
|
161
|
-
return {
|
|
162
|
-
...device.connection.host ? { host: device.connection.host } : {},
|
|
163
|
-
port: device.connection.port ?? 22,
|
|
164
|
-
user: device.connection.user,
|
|
165
|
-
password: Secrets2.reveal(user.password),
|
|
166
|
-
...device.connection.console ? { console: device.connection.console } : {}
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
static marker(secret) {
|
|
170
|
-
return `<secret:${Secrets2.referenceOf(secret)}>`;
|
|
171
|
-
}
|
|
172
|
-
static substitute(text) {
|
|
173
|
-
return text.replace(Secrets2.MARKER, (_, reference) => Secrets2.valueOf(reference));
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export { Utils2, Secrets2 };
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// src/platforms/fortios/models.ts
|
|
2
|
-
var models = {
|
|
3
|
-
"FG-3700D": {
|
|
4
|
-
ports: { "40g": 4, "10g": 28, "1g": 2 },
|
|
5
|
-
spelling: { "40g": "port{n}", "10g": "port{n+4}", "1g": "mgmt{n}" }
|
|
6
|
-
}
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
// src/platforms/junos/models.ts
|
|
10
|
-
var models2 = {
|
|
11
|
-
"QFX5100-48S-6Q": {
|
|
12
|
-
ports: { "40g": 6, "10g": 48, "1g": 2 },
|
|
13
|
-
spelling: { "40g": "et-0/0/{n+47}", "10g": "xe-0/0/{n-1}", "1g": "em{n-1}" }
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// src/platforms/raisecom-ros/models.ts
|
|
18
|
-
var models3 = {
|
|
19
|
-
"RAX721-C-6C48": {
|
|
20
|
-
ports: { "100g": 6, "25g": 24, "10g": 24 },
|
|
21
|
-
spelling: { "100g": "hundredgige 1/1/{n}", "25g": "twenty-fivegige 1/2/{n}", "10g": "tengigabitethernet 1/3/{n}" }
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// src/platforms/routeros/models.ts
|
|
26
|
-
var models4 = {
|
|
27
|
-
"CCR2216-1G-12XS-2XQ": {
|
|
28
|
-
ports: { "100g": 2, "25g": 12, "1g": 1 },
|
|
29
|
-
spelling: { "100g": "qsfp28-{n}-1", "25g": "sfp28-{n}", "1g": "ether{n}" },
|
|
30
|
-
limits: { lag_members: 8, switch_port_ranges: 5 }
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// src/platforms/vrp/models.ts
|
|
35
|
-
var models5 = {
|
|
36
|
-
"CE6855-48S6Q-HI": { ports: { "10g": 48, "40g": 6 }, spelling: { "10g": "10GE1/0/{n}", "40g": "40GE1/0/{n}" } }
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// src/platforms/catalog.ts
|
|
40
|
-
class Catalog {
|
|
41
|
-
static MODELS = { routeros: models4, vrp: models5, "raisecom-ros": models3, junos: models2, fortios: models };
|
|
42
|
-
static ports(platform, model) {
|
|
43
|
-
const spec = Catalog.MODELS[platform]?.[model];
|
|
44
|
-
if (!spec)
|
|
45
|
-
throw new Error(`${platform} has no model ${model}`);
|
|
46
|
-
return Object.entries(spec.ports).flatMap(([speed, count]) => Array.from({ length: count }, (_, i) => `${speed}-${i + 1}`));
|
|
47
|
-
}
|
|
48
|
-
static limits(platform, model) {
|
|
49
|
-
const spec = Catalog.MODELS[platform]?.[model];
|
|
50
|
-
return spec?.limits ?? {};
|
|
51
|
-
}
|
|
52
|
-
static spell(platform, model, port) {
|
|
53
|
-
const spec = Catalog.MODELS[platform]?.[model];
|
|
54
|
-
const parts = /^(\d+[gm])-(\d+)$/.exec(port);
|
|
55
|
-
const template = parts && spec?.spelling[parts[1]];
|
|
56
|
-
if (!template)
|
|
57
|
-
throw new Error(`${model} has no port ${port}`);
|
|
58
|
-
return template.replace(/\{n([+-]\d+)?\}/, (_, shift) => String(Number(parts[2]) + Number(shift ?? 0)));
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export { Catalog };
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
// src/core/address.ts
|
|
2
|
-
class Address2 {
|
|
3
|
-
static NOT_GLOBAL_V4 = [
|
|
4
|
-
"0.0.0.0/8",
|
|
5
|
-
"10.0.0.0/8",
|
|
6
|
-
"100.64.0.0/10",
|
|
7
|
-
"127.0.0.0/8",
|
|
8
|
-
"169.254.0.0/16",
|
|
9
|
-
"172.16.0.0/12",
|
|
10
|
-
"192.0.2.0/24",
|
|
11
|
-
"192.168.0.0/16",
|
|
12
|
-
"198.18.0.0/15",
|
|
13
|
-
"198.51.100.0/24",
|
|
14
|
-
"203.0.113.0/24"
|
|
15
|
-
];
|
|
16
|
-
static family(address) {
|
|
17
|
-
return address.includes(":") ? "ipv6" : "ipv4";
|
|
18
|
-
}
|
|
19
|
-
static bits(family) {
|
|
20
|
-
return family === "ipv4" ? 32 : 128;
|
|
21
|
-
}
|
|
22
|
-
static toNumber(address) {
|
|
23
|
-
if (!address.includes(":")) {
|
|
24
|
-
const octets = address.split(".");
|
|
25
|
-
const valid = octets.length === 4 && octets.every((octet) => /^\d{1,3}$/.test(octet) && Number(octet) <= 255);
|
|
26
|
-
if (!valid)
|
|
27
|
-
return null;
|
|
28
|
-
return octets.reduce((value, octet) => value << 8n | BigInt(octet), 0n);
|
|
29
|
-
}
|
|
30
|
-
const [before, after, extra] = address.split("::");
|
|
31
|
-
if (extra !== undefined)
|
|
32
|
-
return null;
|
|
33
|
-
const groupsOf = (text) => text ? text.split(":") : [];
|
|
34
|
-
const leading = groupsOf(before);
|
|
35
|
-
const trailing = groupsOf(after);
|
|
36
|
-
const zeros = after === undefined ? 0 : 8 - leading.length - trailing.length;
|
|
37
|
-
const groups = [...leading, ...Array(zeros).fill("0"), ...trailing];
|
|
38
|
-
const valid = groups.length === 8 && groups.every((group) => /^[0-9a-fA-F]{1,4}$/.test(group));
|
|
39
|
-
if (!valid)
|
|
40
|
-
return null;
|
|
41
|
-
return groups.reduce((value, group) => value << 16n | BigInt(parseInt(group, 16)), 0n);
|
|
42
|
-
}
|
|
43
|
-
static split(cidr) {
|
|
44
|
-
const [address, lengthText] = cidr.split("/");
|
|
45
|
-
const family = Address2.family(address);
|
|
46
|
-
const length = Number(lengthText);
|
|
47
|
-
const valid = Address2.toNumber(address) !== null && lengthText !== undefined && Number.isInteger(length) && length >= 0 && length <= Address2.bits(family);
|
|
48
|
-
if (!valid)
|
|
49
|
-
throw new Error(`'${cidr}' is not an address with a length`);
|
|
50
|
-
return { addr: address, len: length, family };
|
|
51
|
-
}
|
|
52
|
-
static isValid(text) {
|
|
53
|
-
return Address2.toNumber(text) !== null;
|
|
54
|
-
}
|
|
55
|
-
static isCidr(text) {
|
|
56
|
-
try {
|
|
57
|
-
Address2.split(text);
|
|
58
|
-
return true;
|
|
59
|
-
} catch {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
static mask(length, family) {
|
|
64
|
-
const all = (1n << BigInt(Address2.bits(family))) - 1n;
|
|
65
|
-
const hostBits = (1n << BigInt(Address2.bits(family) - length)) - 1n;
|
|
66
|
-
return all ^ hostBits;
|
|
67
|
-
}
|
|
68
|
-
static fromNumber(value, family) {
|
|
69
|
-
if (family === "ipv4") {
|
|
70
|
-
return [24n, 16n, 8n, 0n].map((shift) => String(value >> shift & 255n)).join(".");
|
|
71
|
-
}
|
|
72
|
-
const groups = Array.from({ length: 8 }, (_, index) => (value >> BigInt(112 - index * 16) & 0xffffn).toString(16));
|
|
73
|
-
let longestStart = -1;
|
|
74
|
-
let longestLength = 0;
|
|
75
|
-
for (let start = 0;start < 8; ) {
|
|
76
|
-
let end = start;
|
|
77
|
-
while (end < 8 && groups[end] === "0")
|
|
78
|
-
end++;
|
|
79
|
-
const runLength = end - start;
|
|
80
|
-
if (runLength > longestLength && runLength > 1) {
|
|
81
|
-
longestStart = start;
|
|
82
|
-
longestLength = runLength;
|
|
83
|
-
}
|
|
84
|
-
start = end === start ? start + 1 : end;
|
|
85
|
-
}
|
|
86
|
-
if (longestStart < 0)
|
|
87
|
-
return groups.join(":");
|
|
88
|
-
const head = groups.slice(0, longestStart).join(":");
|
|
89
|
-
const tail = groups.slice(longestStart + longestLength).join(":");
|
|
90
|
-
return `${head}::${tail}`;
|
|
91
|
-
}
|
|
92
|
-
static canonical(text) {
|
|
93
|
-
const [address, length] = text.split("/");
|
|
94
|
-
const value = Address2.toNumber(address);
|
|
95
|
-
if (value === null)
|
|
96
|
-
return text;
|
|
97
|
-
const spelled = Address2.fromNumber(value, Address2.family(address));
|
|
98
|
-
return length === undefined ? spelled : `${spelled}/${length}`;
|
|
99
|
-
}
|
|
100
|
-
static prefixOf(cidr) {
|
|
101
|
-
const { addr, len, family } = Address2.split(cidr);
|
|
102
|
-
return `${Address2.fromNumber(Address2.toNumber(addr) & Address2.mask(len, family), family)}/${len}`;
|
|
103
|
-
}
|
|
104
|
-
static contains(outer, inner) {
|
|
105
|
-
const outerParts = Address2.split(outer);
|
|
106
|
-
const [innerAddress, innerLengthText] = inner.split("/");
|
|
107
|
-
if (Address2.family(innerAddress) !== outerParts.family)
|
|
108
|
-
return false;
|
|
109
|
-
const innerLength = innerLengthText === undefined ? Address2.bits(outerParts.family) : Number(innerLengthText);
|
|
110
|
-
if (innerLength < outerParts.len)
|
|
111
|
-
return false;
|
|
112
|
-
const outerMask = Address2.mask(outerParts.len, outerParts.family);
|
|
113
|
-
return (Address2.toNumber(innerAddress) & outerMask) === (Address2.toNumber(outerParts.addr) & outerMask);
|
|
114
|
-
}
|
|
115
|
-
static range(cidr) {
|
|
116
|
-
const { addr, len, family } = Address2.split(cidr);
|
|
117
|
-
const hostBits = Address2.mask(len, family) ^ (1n << BigInt(Address2.bits(family))) - 1n;
|
|
118
|
-
const first = Address2.toNumber(addr) & Address2.mask(len, family);
|
|
119
|
-
return { first, last: first | hostBits, family };
|
|
120
|
-
}
|
|
121
|
-
static prefixesBetween(first, last, family) {
|
|
122
|
-
const bits = Address2.bits(family);
|
|
123
|
-
const prefixes = [];
|
|
124
|
-
for (let start = first;start <= last; ) {
|
|
125
|
-
let size = 0;
|
|
126
|
-
while (size < bits && start % (1n << BigInt(size + 1)) === 0n && start + (1n << BigInt(size + 1)) - 1n <= last)
|
|
127
|
-
size++;
|
|
128
|
-
prefixes.push(`${Address2.fromNumber(start, family)}/${bits - size}`);
|
|
129
|
-
start += 1n << BigInt(size);
|
|
130
|
-
}
|
|
131
|
-
return prefixes;
|
|
132
|
-
}
|
|
133
|
-
static netmask(length) {
|
|
134
|
-
return Address2.fromNumber(Address2.mask(length, "ipv4"), "ipv4");
|
|
135
|
-
}
|
|
136
|
-
static wildcard(length) {
|
|
137
|
-
return Address2.fromNumber(Address2.mask(length, "ipv4") ^ 0xffffffffn, "ipv4");
|
|
138
|
-
}
|
|
139
|
-
static host(cidr) {
|
|
140
|
-
return cidr.split("/")[0];
|
|
141
|
-
}
|
|
142
|
-
static isGlobal(address) {
|
|
143
|
-
if (Address2.family(address) === "ipv6")
|
|
144
|
-
return Address2.contains("2000::/3", address) && !Address2.contains("2001:db8::/32", address);
|
|
145
|
-
return !Address2.NOT_GLOBAL_V4.some((prefix) => Address2.contains(prefix, address));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export { Address2 };
|