@superyachttimes/cli 1.1.0 → 1.2.0
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/aws/ec2.d.ts +26 -0
- package/dist/aws/ec2.d.ts.map +1 -0
- package/dist/aws/ec2.js +98 -0
- package/dist/aws/ec2.js.map +1 -0
- package/dist/cloudflare/api.d.ts +39 -0
- package/dist/cloudflare/api.d.ts.map +1 -0
- package/dist/cloudflare/api.js +108 -0
- package/dist/cloudflare/api.js.map +1 -0
- package/dist/cloudflare/urls.d.ts +4 -0
- package/dist/cloudflare/urls.d.ts.map +1 -0
- package/dist/cloudflare/urls.js +11 -0
- package/dist/cloudflare/urls.js.map +1 -0
- package/dist/commands/collapse-last-modified.d.ts.map +1 -1
- package/dist/commands/collapse-last-modified.js +3 -3
- package/dist/commands/collapse-last-modified.js.map +1 -1
- package/dist/commands/create-api-key.d.ts.map +1 -1
- package/dist/commands/create-api-key.js +18 -25
- package/dist/commands/create-api-key.js.map +1 -1
- package/dist/commands/restart-ec2.d.ts +2 -0
- package/dist/commands/restart-ec2.d.ts.map +1 -0
- package/dist/commands/restart-ec2.js +56 -0
- package/dist/commands/restart-ec2.js.map +1 -0
- package/dist/commands/sync-ec2-ips-cloudflare.d.ts +2 -0
- package/dist/commands/sync-ec2-ips-cloudflare.d.ts.map +1 -0
- package/dist/commands/sync-ec2-ips-cloudflare.js +58 -0
- package/dist/commands/sync-ec2-ips-cloudflare.js.map +1 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +25 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface AwsOptions {
|
|
2
|
+
region: string;
|
|
3
|
+
profile: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Ec2Instance {
|
|
6
|
+
instanceId: string;
|
|
7
|
+
name: string;
|
|
8
|
+
state: string;
|
|
9
|
+
publicIp: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface InstanceHealth {
|
|
12
|
+
systemStatus: string;
|
|
13
|
+
instanceStatus: string;
|
|
14
|
+
}
|
|
15
|
+
export interface RebootResult {
|
|
16
|
+
instanceId: string;
|
|
17
|
+
ok: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function listInstances(opts: AwsOptions): Promise<Ec2Instance[]>;
|
|
21
|
+
export declare function getInstanceStatuses(opts: AwsOptions): Promise<Map<string, InstanceHealth>>;
|
|
22
|
+
export declare function rebootInstances(opts: AwsOptions & {
|
|
23
|
+
instanceIds: string[];
|
|
24
|
+
}): Promise<RebootResult[]>;
|
|
25
|
+
export declare function collectEgressIps(opts: AwsOptions): Promise<string[]>;
|
|
26
|
+
//# sourceMappingURL=ec2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ec2.d.ts","sourceRoot":"","sources":["../../src/aws/ec2.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AASD,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAsB5E;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAqBtC;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,GAAG;IAAE,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,GAC3C,OAAO,CAAC,YAAY,EAAE,CAAC,CAkBzB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmC1E"}
|
package/dist/aws/ec2.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { EC2Client, DescribeInstancesCommand, DescribeInstanceStatusCommand, DescribeNatGatewaysCommand, RebootInstancesCommand, } from "@aws-sdk/client-ec2";
|
|
2
|
+
import { fromIni } from "@aws-sdk/credential-providers";
|
|
3
|
+
function createClient(opts) {
|
|
4
|
+
return new EC2Client({
|
|
5
|
+
region: opts.region,
|
|
6
|
+
credentials: fromIni({ profile: opts.profile }),
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export async function listInstances(opts) {
|
|
10
|
+
const client = createClient(opts);
|
|
11
|
+
const instances = [];
|
|
12
|
+
let nextToken;
|
|
13
|
+
do {
|
|
14
|
+
const res = await client.send(new DescribeInstancesCommand({ NextToken: nextToken }));
|
|
15
|
+
for (const reservation of res.Reservations ?? []) {
|
|
16
|
+
for (const instance of reservation.Instances ?? []) {
|
|
17
|
+
instances.push({
|
|
18
|
+
instanceId: instance.InstanceId ?? "",
|
|
19
|
+
name: instance.Tags?.find((t) => t.Key === "Name")?.Value ?? "(no name)",
|
|
20
|
+
state: instance.State?.Name ?? "unknown",
|
|
21
|
+
publicIp: instance.PublicIpAddress ?? null,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
nextToken = res.NextToken;
|
|
26
|
+
} while (nextToken);
|
|
27
|
+
return instances;
|
|
28
|
+
}
|
|
29
|
+
export async function getInstanceStatuses(opts) {
|
|
30
|
+
const client = createClient(opts);
|
|
31
|
+
const statuses = new Map();
|
|
32
|
+
let nextToken;
|
|
33
|
+
do {
|
|
34
|
+
const res = await client.send(new DescribeInstanceStatusCommand({
|
|
35
|
+
IncludeAllInstances: true,
|
|
36
|
+
NextToken: nextToken,
|
|
37
|
+
}));
|
|
38
|
+
for (const s of res.InstanceStatuses ?? []) {
|
|
39
|
+
if (!s.InstanceId)
|
|
40
|
+
continue;
|
|
41
|
+
statuses.set(s.InstanceId, {
|
|
42
|
+
systemStatus: s.SystemStatus?.Status ?? "unknown",
|
|
43
|
+
instanceStatus: s.InstanceStatus?.Status ?? "unknown",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
nextToken = res.NextToken;
|
|
47
|
+
} while (nextToken);
|
|
48
|
+
return statuses;
|
|
49
|
+
}
|
|
50
|
+
export async function rebootInstances(opts) {
|
|
51
|
+
const client = createClient(opts);
|
|
52
|
+
return Promise.all(opts.instanceIds.map(async (instanceId) => {
|
|
53
|
+
try {
|
|
54
|
+
await client.send(new RebootInstancesCommand({ InstanceIds: [instanceId] }));
|
|
55
|
+
return { instanceId, ok: true };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return {
|
|
59
|
+
instanceId,
|
|
60
|
+
ok: false,
|
|
61
|
+
error: err instanceof Error ? err.message : String(err),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
export async function collectEgressIps(opts) {
|
|
67
|
+
const client = createClient(opts);
|
|
68
|
+
const ips = new Set();
|
|
69
|
+
// Instance public IPs (instances that have one assigned).
|
|
70
|
+
let instanceToken;
|
|
71
|
+
do {
|
|
72
|
+
const res = await client.send(new DescribeInstancesCommand({ NextToken: instanceToken }));
|
|
73
|
+
for (const reservation of res.Reservations ?? []) {
|
|
74
|
+
for (const instance of reservation.Instances ?? []) {
|
|
75
|
+
if (instance.PublicIpAddress)
|
|
76
|
+
ips.add(instance.PublicIpAddress);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
instanceToken = res.NextToken;
|
|
80
|
+
} while (instanceToken);
|
|
81
|
+
// NAT gateway public IPs (covers private instances, Lambdas, etc. egressing
|
|
82
|
+
// through a NAT gateway). All available NAT gateways in the region.
|
|
83
|
+
let natToken;
|
|
84
|
+
do {
|
|
85
|
+
const res = await client.send(new DescribeNatGatewaysCommand({ NextToken: natToken }));
|
|
86
|
+
for (const nat of res.NatGateways ?? []) {
|
|
87
|
+
if (nat.State !== "available")
|
|
88
|
+
continue;
|
|
89
|
+
for (const addr of nat.NatGatewayAddresses ?? []) {
|
|
90
|
+
if (addr.PublicIp)
|
|
91
|
+
ips.add(addr.PublicIp);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
natToken = res.NextToken;
|
|
95
|
+
} while (natToken);
|
|
96
|
+
return Array.from(ips).sort();
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=ec2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ec2.js","sourceRoot":"","sources":["../../src/aws/ec2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface CloudflareRule {
|
|
2
|
+
id: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
expression: string;
|
|
5
|
+
action: string;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
action_parameters?: Record<string, unknown>;
|
|
8
|
+
logging?: Record<string, unknown>;
|
|
9
|
+
ref?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveZoneId(opts: {
|
|
12
|
+
apiToken: string;
|
|
13
|
+
zoneName: string;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
export declare function getCustomRuleByDescription(opts: {
|
|
16
|
+
apiToken: string;
|
|
17
|
+
zoneId: string;
|
|
18
|
+
description: string;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
rulesetId: string;
|
|
21
|
+
rule: CloudflareRule;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function updateRuleExpression(opts: {
|
|
24
|
+
apiToken: string;
|
|
25
|
+
zoneId: string;
|
|
26
|
+
rulesetId: string;
|
|
27
|
+
rule: CloudflareRule;
|
|
28
|
+
expression: string;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
/** Builds a Cloudflare firewall expression matching the given source IPs. */
|
|
31
|
+
export declare function buildIpExpression(ips: string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Extracts the IPs from a rule expression. Handles both forms Cloudflare uses:
|
|
34
|
+
* - set membership: `ip.src in {1.2.3.4 5.6.7.8}`
|
|
35
|
+
* - chained equality: `(ip.src eq 1.2.3.4) or (ip.src eq 5.6.7.8)`
|
|
36
|
+
* Returns null if neither form is present (caller falls back to showing the new set).
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseIpsFromExpression(expression: string): string[] | null;
|
|
39
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/cloudflare/api.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IAGjB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAkDD,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlB;AAED,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC,CAsBvD;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhB;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAoB1E"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as urls from "./urls.js";
|
|
2
|
+
async function request(url, options) {
|
|
3
|
+
const headers = {
|
|
4
|
+
Authorization: `Bearer ${options.apiToken}`,
|
|
5
|
+
};
|
|
6
|
+
if (options.body !== undefined) {
|
|
7
|
+
headers["Content-Type"] = "application/json";
|
|
8
|
+
}
|
|
9
|
+
const res = await fetch(url, {
|
|
10
|
+
method: options.method ?? "GET",
|
|
11
|
+
headers,
|
|
12
|
+
body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
|
|
13
|
+
});
|
|
14
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
15
|
+
const payload = contentType.includes("application/json")
|
|
16
|
+
? await res.json()
|
|
17
|
+
: await res.text();
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
const detail = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
20
|
+
throw new Error(`Cloudflare API error: ${options.method ?? "GET"} ${url} → ${res.status} ${res.statusText}\n${detail}`);
|
|
21
|
+
}
|
|
22
|
+
const envelope = payload;
|
|
23
|
+
if (envelope && envelope.success === false) {
|
|
24
|
+
const msg = (envelope.errors ?? [])
|
|
25
|
+
.map((e) => `${e.code}: ${e.message}`)
|
|
26
|
+
.join("; ");
|
|
27
|
+
throw new Error(`Cloudflare API error: ${options.method ?? "GET"} ${url} → ${msg || "request unsuccessful"}`);
|
|
28
|
+
}
|
|
29
|
+
return envelope.result;
|
|
30
|
+
}
|
|
31
|
+
export async function resolveZoneId(opts) {
|
|
32
|
+
const zones = await request(urls.zonesByName(opts.zoneName), {
|
|
33
|
+
apiToken: opts.apiToken,
|
|
34
|
+
});
|
|
35
|
+
if (!zones || zones.length === 0) {
|
|
36
|
+
throw new Error(`No Cloudflare zone found for "${opts.zoneName}"`);
|
|
37
|
+
}
|
|
38
|
+
return zones[0].id;
|
|
39
|
+
}
|
|
40
|
+
export async function getCustomRuleByDescription(opts) {
|
|
41
|
+
const ruleset = await request(urls.customRulesEntrypoint(opts.zoneId), { apiToken: opts.apiToken });
|
|
42
|
+
const rules = ruleset.rules ?? [];
|
|
43
|
+
const matches = rules.filter((r) => r.description === opts.description);
|
|
44
|
+
if (matches.length === 0) {
|
|
45
|
+
const available = rules
|
|
46
|
+
.map((r) => `"${r.description ?? "(no description)"}"`)
|
|
47
|
+
.join(", ") || "(none)";
|
|
48
|
+
throw new Error(`No custom rule with description "${opts.description}" found. Available: ${available}`);
|
|
49
|
+
}
|
|
50
|
+
if (matches.length > 1) {
|
|
51
|
+
throw new Error(`Multiple custom rules match description "${opts.description}" (${matches.length}). Refusing to guess.`);
|
|
52
|
+
}
|
|
53
|
+
return { rulesetId: ruleset.id, rule: matches[0] };
|
|
54
|
+
}
|
|
55
|
+
export async function updateRuleExpression(opts) {
|
|
56
|
+
const body = {
|
|
57
|
+
action: opts.rule.action,
|
|
58
|
+
description: opts.rule.description,
|
|
59
|
+
enabled: opts.rule.enabled,
|
|
60
|
+
expression: opts.expression,
|
|
61
|
+
};
|
|
62
|
+
// Preserve fields that Cloudflare requires/keeps for the existing action.
|
|
63
|
+
// A "skip" rule, for example, is rejected without its action_parameters.
|
|
64
|
+
if (opts.rule.action_parameters !== undefined) {
|
|
65
|
+
body.action_parameters = opts.rule.action_parameters;
|
|
66
|
+
}
|
|
67
|
+
if (opts.rule.logging !== undefined) {
|
|
68
|
+
body.logging = opts.rule.logging;
|
|
69
|
+
}
|
|
70
|
+
if (opts.rule.ref !== undefined) {
|
|
71
|
+
body.ref = opts.rule.ref;
|
|
72
|
+
}
|
|
73
|
+
await request(urls.ruleUrl(opts.zoneId, opts.rulesetId, opts.rule.id), {
|
|
74
|
+
method: "PATCH",
|
|
75
|
+
apiToken: opts.apiToken,
|
|
76
|
+
body,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Builds a Cloudflare firewall expression matching the given source IPs. */
|
|
80
|
+
export function buildIpExpression(ips) {
|
|
81
|
+
return `(ip.src in {${ips.join(" ")}})`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Extracts the IPs from a rule expression. Handles both forms Cloudflare uses:
|
|
85
|
+
* - set membership: `ip.src in {1.2.3.4 5.6.7.8}`
|
|
86
|
+
* - chained equality: `(ip.src eq 1.2.3.4) or (ip.src eq 5.6.7.8)`
|
|
87
|
+
* Returns null if neither form is present (caller falls back to showing the new set).
|
|
88
|
+
*/
|
|
89
|
+
export function parseIpsFromExpression(expression) {
|
|
90
|
+
// Set membership form: ip.src in { ... }
|
|
91
|
+
const groupMatch = expression.match(/\{([^}]*)\}/);
|
|
92
|
+
if (groupMatch) {
|
|
93
|
+
return groupMatch[1]
|
|
94
|
+
.trim()
|
|
95
|
+
.split(/\s+/)
|
|
96
|
+
.filter((token) => token.length > 0);
|
|
97
|
+
}
|
|
98
|
+
// Chained equality form: ip.src eq <ip> [or ...]. The IP token allows
|
|
99
|
+
// digits/dots (IPv4), colons/hex (IPv6), and an optional /prefix (CIDR).
|
|
100
|
+
const eqMatches = [
|
|
101
|
+
...expression.matchAll(/ip\.src\s+eq\s+([0-9a-fA-F:.]+(?:\/\d+)?)/g),
|
|
102
|
+
];
|
|
103
|
+
if (eqMatches.length > 0) {
|
|
104
|
+
return eqMatches.map((m) => m[1]);
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/cloudflare/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/cloudflare/urls.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,CAER"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const BASE = "https://api.cloudflare.com/client/v4";
|
|
2
|
+
export function zonesByName(name) {
|
|
3
|
+
return `${BASE}/zones?name=${encodeURIComponent(name)}`;
|
|
4
|
+
}
|
|
5
|
+
export function customRulesEntrypoint(zoneId) {
|
|
6
|
+
return `${BASE}/zones/${zoneId}/rulesets/phases/http_request_firewall_custom/entrypoint`;
|
|
7
|
+
}
|
|
8
|
+
export function ruleUrl(zoneId, rulesetId, ruleId) {
|
|
9
|
+
return `${BASE}/zones/${zoneId}/rulesets/${rulesetId}/rules/${ruleId}`;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=urls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/cloudflare/urls.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,sCAAsC,CAAC;AAEpD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,GAAG,IAAI,eAAe,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,GAAG,IAAI,UAAU,MAAM,0DAA0D,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,MAAc,EACd,SAAiB,EACjB,MAAc;IAEd,OAAO,GAAG,IAAI,UAAU,MAAM,aAAa,SAAS,UAAU,MAAM,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapse-last-modified.d.ts","sourceRoot":"","sources":["../../src/commands/collapse-last-modified.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collapse-last-modified.d.ts","sourceRoot":"","sources":["../../src/commands/collapse-last-modified.ts"],"names":[],"mappings":"AAEA,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0B1D"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { loadConfig } from "../config.js";
|
|
2
|
-
const URL = "https://api0.superyachtapi.com/api/yachtlikes/last-modified/collapse";
|
|
3
2
|
export async function collapseLastModified() {
|
|
4
3
|
const config = loadConfig();
|
|
4
|
+
const url = `${config.sytApiUrl}/api/yachtlikes/last-modified/collapse`;
|
|
5
5
|
console.log("Collapsing last-modified yacht likes...");
|
|
6
|
-
const res = await fetch(
|
|
6
|
+
const res = await fetch(url, {
|
|
7
7
|
method: "POST",
|
|
8
8
|
headers: {
|
|
9
9
|
Authorization: `Bearer ${config.sytApiKey}`,
|
|
@@ -11,7 +11,7 @@ export async function collapseLastModified() {
|
|
|
11
11
|
});
|
|
12
12
|
if (!res.ok) {
|
|
13
13
|
const body = await res.text().catch(() => "");
|
|
14
|
-
throw new Error(`POST ${
|
|
14
|
+
throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${body ? ` — ${body}` : ""}`);
|
|
15
15
|
}
|
|
16
16
|
const contentType = res.headers.get("content-type") ?? "";
|
|
17
17
|
const result = contentType.includes("application/json")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapse-last-modified.js","sourceRoot":"","sources":["../../src/commands/collapse-last-modified.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,
|
|
1
|
+
{"version":3,"file":"collapse-last-modified.js","sourceRoot":"","sources":["../../src/commands/collapse-last-modified.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,wCAAwC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,CAAC,SAAS,EAAE;SAC5C;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,YAAY,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE;QAClB,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAErB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-api-key.d.ts","sourceRoot":"","sources":["../../src/commands/create-api-key.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-api-key.d.ts","sourceRoot":"","sources":["../../src/commands/create-api-key.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAsDlD"}
|
|
@@ -1,59 +1,52 @@
|
|
|
1
|
-
import { input, number, checkbox } from
|
|
2
|
-
import { loadConfig } from
|
|
3
|
-
const
|
|
4
|
-
const AVAILABLE_SCOPES = [
|
|
5
|
-
"internal",
|
|
6
|
-
"yachteye",
|
|
7
|
-
"position_data",
|
|
8
|
-
"extended-yacht-data",
|
|
9
|
-
];
|
|
1
|
+
import { input, number, checkbox } from '@inquirer/prompts';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
const AVAILABLE_SCOPES = ['internal', 'yachteye', 'position_data', 'extended_yacht_data'];
|
|
10
4
|
export async function createApiKey() {
|
|
11
5
|
const config = loadConfig();
|
|
6
|
+
const url = `${config.sytApiUrl}/api/api-keys/create`;
|
|
12
7
|
const comment = await input({
|
|
13
|
-
message:
|
|
8
|
+
message: 'Comment (required)',
|
|
14
9
|
validate: (value) => {
|
|
15
10
|
if (!value.trim())
|
|
16
|
-
return
|
|
11
|
+
return 'Comment is required';
|
|
17
12
|
return true;
|
|
18
13
|
},
|
|
19
14
|
});
|
|
20
15
|
const recordLimit = await number({
|
|
21
|
-
message:
|
|
16
|
+
message: 'Record limit (leave empty to skip)',
|
|
22
17
|
required: false,
|
|
23
18
|
validate: (value) => {
|
|
24
19
|
if (value === undefined)
|
|
25
20
|
return true;
|
|
26
21
|
if (!Number.isInteger(value) || value < 1 || value > 100) {
|
|
27
|
-
return
|
|
22
|
+
return 'Record limit must be a number between 1 and 100';
|
|
28
23
|
}
|
|
29
24
|
return true;
|
|
30
25
|
},
|
|
31
26
|
});
|
|
32
27
|
const scopes = await checkbox({
|
|
33
|
-
message:
|
|
28
|
+
message: 'Select scopes',
|
|
34
29
|
choices: AVAILABLE_SCOPES.map((scope) => ({ name: scope, value: scope })),
|
|
35
30
|
});
|
|
36
31
|
const body = { comment, scopes };
|
|
37
32
|
if (recordLimit !== undefined) {
|
|
38
|
-
body.
|
|
33
|
+
body.record_limit = recordLimit;
|
|
39
34
|
}
|
|
40
|
-
console.log(
|
|
41
|
-
const res = await fetch(
|
|
42
|
-
method:
|
|
35
|
+
console.log('Creating API key...');
|
|
36
|
+
const res = await fetch(url, {
|
|
37
|
+
method: 'POST',
|
|
43
38
|
headers: {
|
|
44
39
|
Authorization: `Bearer ${config.sytApiKey}`,
|
|
45
|
-
|
|
40
|
+
'Content-Type': 'application/json',
|
|
46
41
|
},
|
|
47
42
|
body: JSON.stringify(body),
|
|
48
43
|
});
|
|
49
44
|
if (!res.ok) {
|
|
50
|
-
const text = await res.text().catch(() =>
|
|
51
|
-
throw new Error(`POST ${
|
|
45
|
+
const text = await res.text().catch(() => '');
|
|
46
|
+
throw new Error(`POST ${url} failed: ${res.status} ${res.statusText}${text ? ` — ${text}` : ''}`);
|
|
52
47
|
}
|
|
53
|
-
const contentType = res.headers.get(
|
|
54
|
-
const result = contentType.includes(
|
|
55
|
-
? await res.json()
|
|
56
|
-
: await res.text();
|
|
48
|
+
const contentType = res.headers.get('content-type') ?? '';
|
|
49
|
+
const result = contentType.includes('application/json') ? await res.json() : await res.text();
|
|
57
50
|
console.log(result);
|
|
58
51
|
}
|
|
59
52
|
//# sourceMappingURL=create-api-key.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-api-key.js","sourceRoot":"","sources":["../../src/commands/create-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"create-api-key.js","sourceRoot":"","sources":["../../src/commands/create-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,CAAU,CAAA;AAElG,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,sBAAsB,CAAA;IAErD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC;QAC1B,OAAO,EAAE,oBAAoB;QAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBAAE,OAAO,qBAAqB,CAAA;YAC/C,OAAO,IAAI,CAAA;QACb,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC;QAC/B,OAAO,EAAE,oCAAoC;QAC7C,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA;YACpC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;gBACzD,OAAO,iDAAiD,CAAA;YAC1D,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;QAC5B,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;KAC1E,CAAC,CAAA;IAEF,MAAM,IAAI,GAA4B,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IACzD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAElC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,CAAC,SAAS,EAAE;YAC3C,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAA;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QAC7C,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,YAAY,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACnG,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;IACzD,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;IAE7F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-ec2.d.ts","sourceRoot":"","sources":["../../src/commands/restart-ec2.ts"],"names":[],"mappings":"AAIA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA0DhD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { checkbox, confirm } from "@inquirer/prompts";
|
|
2
|
+
import { loadConfig, getAwsConfig } from "../config.js";
|
|
3
|
+
import * as ec2 from "../aws/ec2.js";
|
|
4
|
+
export async function restartEc2() {
|
|
5
|
+
const config = loadConfig();
|
|
6
|
+
const aws = getAwsConfig(config);
|
|
7
|
+
console.log(`Fetching EC2 instances in ${aws.region}...`);
|
|
8
|
+
const instances = await ec2.listInstances(aws);
|
|
9
|
+
if (instances.length === 0) {
|
|
10
|
+
console.log(`No EC2 instances found in ${aws.region}.`);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const statuses = await ec2.getInstanceStatuses(aws);
|
|
14
|
+
const selected = await checkbox({
|
|
15
|
+
message: "Select instance(s) to reboot (space to toggle, enter to confirm)",
|
|
16
|
+
choices: instances.map((instance) => {
|
|
17
|
+
const health = statuses.get(instance.instanceId);
|
|
18
|
+
const status = health
|
|
19
|
+
? `${health.systemStatus}/${health.instanceStatus}`
|
|
20
|
+
: "n/a";
|
|
21
|
+
return {
|
|
22
|
+
name: `${instance.name} (${instance.instanceId}) — ${instance.state}, status: ${status}`,
|
|
23
|
+
value: instance.instanceId,
|
|
24
|
+
};
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
if (selected.length === 0) {
|
|
28
|
+
console.log("Nothing selected.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const confirmed = await confirm({
|
|
32
|
+
message: `Reboot ${selected.length} instance(s)? [${selected.join(", ")}]`,
|
|
33
|
+
default: false,
|
|
34
|
+
});
|
|
35
|
+
if (!confirmed) {
|
|
36
|
+
console.log("Aborted.");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
console.log("Rebooting...");
|
|
40
|
+
const results = await ec2.rebootInstances({ ...aws, instanceIds: selected });
|
|
41
|
+
let failed = 0;
|
|
42
|
+
for (const result of results) {
|
|
43
|
+
if (result.ok) {
|
|
44
|
+
console.log(` ✓ ${result.instanceId} reboot requested`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
failed++;
|
|
48
|
+
console.error(` ✗ ${result.instanceId} failed: ${result.error}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (failed > 0) {
|
|
52
|
+
throw new Error(`${failed}/${results.length} instance(s) failed to reboot`);
|
|
53
|
+
}
|
|
54
|
+
console.log(`All ${results.length} instance(s) reboot requested successfully.`);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=restart-ec2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-ec2.js","sourceRoot":"","sources":["../../src/commands/restart-ec2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-ec2-ips-cloudflare.d.ts","sourceRoot":"","sources":["../../src/commands/sync-ec2-ips-cloudflare.ts"],"names":[],"mappings":"AAKA,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwD5D"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { confirm } from "@inquirer/prompts";
|
|
2
|
+
import { loadConfig, getAwsConfig, getCloudflareConfig } from "../config.js";
|
|
3
|
+
import * as ec2 from "../aws/ec2.js";
|
|
4
|
+
import * as cloudflare from "../cloudflare/api.js";
|
|
5
|
+
export async function syncEc2IpsToCloudflare() {
|
|
6
|
+
const config = loadConfig();
|
|
7
|
+
const aws = getAwsConfig(config);
|
|
8
|
+
const cf = getCloudflareConfig(config);
|
|
9
|
+
console.log(`Collecting EC2 egress IPs in ${aws.region}...`);
|
|
10
|
+
const ips = await ec2.collectEgressIps(aws);
|
|
11
|
+
if (ips.length === 0) {
|
|
12
|
+
throw new Error("No EC2 egress IPs found; refusing to write an empty rule.");
|
|
13
|
+
}
|
|
14
|
+
console.log(`Found ${ips.length} IP(s): ${ips.join(", ")}`);
|
|
15
|
+
console.log(`Resolving Cloudflare zone "${cf.zoneName}"...`);
|
|
16
|
+
const zoneId = await cloudflare.resolveZoneId(cf);
|
|
17
|
+
const { rulesetId, rule } = await cloudflare.getCustomRuleByDescription({
|
|
18
|
+
apiToken: cf.apiToken,
|
|
19
|
+
zoneId,
|
|
20
|
+
description: cf.ruleDescription,
|
|
21
|
+
});
|
|
22
|
+
const currentIps = cloudflare.parseIpsFromExpression(rule.expression);
|
|
23
|
+
if (currentIps === null) {
|
|
24
|
+
console.log(`Could not parse current IPs from expression: ${rule.expression}`);
|
|
25
|
+
console.log(`New IP set: ${ips.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const added = ips.filter((ip) => !currentIps.includes(ip));
|
|
29
|
+
const removed = currentIps.filter((ip) => !ips.includes(ip));
|
|
30
|
+
if (added.length === 0 && removed.length === 0) {
|
|
31
|
+
console.log("Already up to date — no changes.");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log(`Changes to "${cf.ruleDescription}":`);
|
|
35
|
+
for (const ip of added)
|
|
36
|
+
console.log(` + ${ip}`);
|
|
37
|
+
for (const ip of removed)
|
|
38
|
+
console.log(` - ${ip}`);
|
|
39
|
+
}
|
|
40
|
+
const confirmed = await confirm({
|
|
41
|
+
message: `Apply update to "${cf.ruleDescription}" (${ips.length} IP(s) total)?`,
|
|
42
|
+
default: false,
|
|
43
|
+
});
|
|
44
|
+
if (!confirmed) {
|
|
45
|
+
console.log("Aborted.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const expression = cloudflare.buildIpExpression(ips);
|
|
49
|
+
await cloudflare.updateRuleExpression({
|
|
50
|
+
apiToken: cf.apiToken,
|
|
51
|
+
zoneId,
|
|
52
|
+
rulesetId,
|
|
53
|
+
rule,
|
|
54
|
+
expression,
|
|
55
|
+
});
|
|
56
|
+
console.log(`Updated rule "${cf.ruleDescription}" with ${ips.length} IP(s).`);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=sync-ec2-ips-cloudflare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-ec2-ips-cloudflare.js","sourceRoot":"","sources":["../../src/commands/sync-ec2-ips-cloudflare.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -5,9 +5,32 @@ export interface PortainerInstance {
|
|
|
5
5
|
portainerRegistryAuth?: string;
|
|
6
6
|
portainerContainerName: string;
|
|
7
7
|
}
|
|
8
|
+
export interface AwsConfig {
|
|
9
|
+
profile?: string;
|
|
10
|
+
region?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CloudflareConfig {
|
|
13
|
+
apiToken: string;
|
|
14
|
+
zoneName?: string;
|
|
15
|
+
ruleDescription?: string;
|
|
16
|
+
}
|
|
8
17
|
export interface Config {
|
|
18
|
+
sytApiUrl: string;
|
|
9
19
|
sytApiKey: string;
|
|
10
20
|
nodejsApi: PortainerInstance[];
|
|
21
|
+
aws?: AwsConfig;
|
|
22
|
+
cloudflare?: CloudflareConfig;
|
|
11
23
|
}
|
|
12
24
|
export declare function loadConfig(): Config;
|
|
25
|
+
export interface ResolvedAwsConfig {
|
|
26
|
+
profile: string;
|
|
27
|
+
region: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ResolvedCloudflareConfig {
|
|
30
|
+
apiToken: string;
|
|
31
|
+
zoneName: string;
|
|
32
|
+
ruleDescription: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function getAwsConfig(config: Config): ResolvedAwsConfig;
|
|
35
|
+
export declare function getCloudflareConfig(config: Config): ResolvedCloudflareConfig;
|
|
13
36
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAID,wBAAgB,UAAU,IAAI,MAAM,CAmDnC;AAOD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAK9D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAa5E"}
|
package/dist/config.js
CHANGED
|
@@ -11,6 +11,10 @@ export function loadConfig() {
|
|
|
11
11
|
throw new Error(`Config file not found at ${CONFIG_PATH}`);
|
|
12
12
|
}
|
|
13
13
|
const config = JSON.parse(raw);
|
|
14
|
+
if (config.sytApiUrl == null ||
|
|
15
|
+
String(config.sytApiUrl).trim().length === 0) {
|
|
16
|
+
throw new Error(`Config file at ${CONFIG_PATH} must contain a non-empty "sytApiUrl" string`);
|
|
17
|
+
}
|
|
14
18
|
if (config.sytApiKey == null ||
|
|
15
19
|
String(config.sytApiKey).trim().length === 0) {
|
|
16
20
|
throw new Error(`Config file at ${CONFIG_PATH} must contain a non-empty "sytApiKey" string`);
|
|
@@ -35,4 +39,25 @@ export function loadConfig() {
|
|
|
35
39
|
}
|
|
36
40
|
return config;
|
|
37
41
|
}
|
|
42
|
+
const DEFAULT_AWS_PROFILE = "syt";
|
|
43
|
+
const DEFAULT_AWS_REGION = "eu-west-1";
|
|
44
|
+
const DEFAULT_CLOUDFLARE_ZONE = "superyachttimes.com";
|
|
45
|
+
const DEFAULT_CLOUDFLARE_RULE = "Whitelist SYT EC2 Servers";
|
|
46
|
+
export function getAwsConfig(config) {
|
|
47
|
+
return {
|
|
48
|
+
profile: config.aws?.profile?.trim() || DEFAULT_AWS_PROFILE,
|
|
49
|
+
region: config.aws?.region?.trim() || DEFAULT_AWS_REGION,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function getCloudflareConfig(config) {
|
|
53
|
+
const apiToken = config.cloudflare?.apiToken;
|
|
54
|
+
if (apiToken == null || String(apiToken).trim().length === 0) {
|
|
55
|
+
throw new Error(`Config file at ${CONFIG_PATH} must contain a non-empty "cloudflare.apiToken" string`);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
apiToken: String(apiToken).trim(),
|
|
59
|
+
zoneName: config.cloudflare?.zoneName?.trim() || DEFAULT_CLOUDFLARE_ZONE,
|
|
60
|
+
ruleDescription: config.cloudflare?.ruleDescription?.trim() || DEFAULT_CLOUDFLARE_RULE,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
38
63
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA6BlC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AAErD,MAAM,UAAU,UAAU;IACxB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEvC,IACE,MAAM,CAAC,SAAS,IAAI,IAAI;QACxB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kBAAkB,WAAW,8CAA8C,CAC5E,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,SAAS,IAAI,IAAI;QACxB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kBAAkB,WAAW,8CAA8C,CAC5E,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CACb,kBAAkB,WAAW,6CAA6C,CAC3E,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,KAAK,MAAM,GAAG,IAAI;YAChB,cAAc;YACd,qBAAqB;YACrB,iBAAiB;YACjB,wBAAwB;SAChB,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,gCAAgC,GAAG,GAAG,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QACD,gEAAgE;QAChE,QAAQ,CAAC,mBAAmB,GAAG,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAClC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AACvC,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AACtD,MAAM,uBAAuB,GAAG,2BAA2B,CAAC;AAa5D,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,mBAAmB;QAC3D,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,kBAAkB;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC7C,IAAI,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,kBAAkB,WAAW,wDAAwD,CACtF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE;QACjC,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,uBAAuB;QACxE,eAAe,EACb,MAAM,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,uBAAuB;KACxE,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { select } from "@inquirer/prompts";
|
|
|
6
6
|
import { collapseLastModified } from "./commands/collapse-last-modified.js";
|
|
7
7
|
import { createApiKey } from "./commands/create-api-key.js";
|
|
8
8
|
import { recreateNodejsApi } from "./commands/recreate-nodejs-api.js";
|
|
9
|
+
import { restartEc2 } from "./commands/restart-ec2.js";
|
|
10
|
+
import { syncEc2IpsToCloudflare } from "./commands/sync-ec2-ips-cloudflare.js";
|
|
9
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
12
|
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
11
13
|
function printHelp() {
|
|
@@ -17,6 +19,8 @@ function printHelp() {
|
|
|
17
19
|
console.log(" collapse-last-modified Collapse last-modified yacht likes");
|
|
18
20
|
console.log(" create-api-key Create a new API key");
|
|
19
21
|
console.log(" recreate-nodejs-api Recreate Node.js API containers via Portainer");
|
|
22
|
+
console.log(" restart-ec2 Restart (reboot) one or more EC2 servers");
|
|
23
|
+
console.log(" sync-ec2-ips-cloudflare Sync EC2 egress IPs to a Cloudflare WAF rule");
|
|
20
24
|
console.log();
|
|
21
25
|
console.log("Options:");
|
|
22
26
|
console.log(" -v, --version Show version");
|
|
@@ -43,6 +47,12 @@ async function runCommand(cmd) {
|
|
|
43
47
|
case "recreate-nodejs-api":
|
|
44
48
|
await recreateNodejsApi();
|
|
45
49
|
break;
|
|
50
|
+
case "restart-ec2":
|
|
51
|
+
await restartEc2();
|
|
52
|
+
break;
|
|
53
|
+
case "sync-ec2-ips-cloudflare":
|
|
54
|
+
await syncEc2IpsToCloudflare();
|
|
55
|
+
break;
|
|
46
56
|
default:
|
|
47
57
|
console.error(`Unknown command: ${cmd}`);
|
|
48
58
|
printHelp();
|
|
@@ -68,6 +78,16 @@ async function showMenu() {
|
|
|
68
78
|
value: "recreate-nodejs-api",
|
|
69
79
|
description: "Recreate Node.js API containers via Portainer",
|
|
70
80
|
},
|
|
81
|
+
{
|
|
82
|
+
name: "Restart EC2 servers",
|
|
83
|
+
value: "restart-ec2",
|
|
84
|
+
description: "Restart (reboot) one or more EC2 servers",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "Sync EC2 IPs to Cloudflare",
|
|
88
|
+
value: "sync-ec2-ips-cloudflare",
|
|
89
|
+
description: "Sync EC2 egress IPs to a Cloudflare WAF rule",
|
|
90
|
+
},
|
|
71
91
|
],
|
|
72
92
|
});
|
|
73
93
|
await runCommand(chosen);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superyachttimes/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "SuperYachtTimes CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"dev": "tsc --watch",
|
|
15
15
|
"clean": "rm -rf dist",
|
|
16
16
|
"prepublishOnly": "npm run clean && npm run build",
|
|
17
|
-
"push": "npm login && npm publish --scope @superyachttimes --access public"
|
|
17
|
+
"push": "npm login && npm publish --scope @superyachttimes --access public",
|
|
18
|
+
"ship": "bash scripts/ship.sh"
|
|
18
19
|
},
|
|
19
20
|
"engines": {
|
|
20
21
|
"node": ">=20"
|
|
@@ -24,6 +25,8 @@
|
|
|
24
25
|
"typescript": "^5"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
28
|
+
"@aws-sdk/client-ec2": "^3.1053.0",
|
|
29
|
+
"@aws-sdk/credential-providers": "^3.1053.0",
|
|
27
30
|
"@inquirer/prompts": "^8.2.0"
|
|
28
31
|
}
|
|
29
32
|
}
|