ninedeploy 0.3.0 → 0.5.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/commands/branding.d.ts +31 -0
- package/dist/commands/branding.d.ts.map +1 -0
- package/dist/commands/branding.js +48 -0
- package/dist/commands/branding.js.map +1 -0
- package/dist/commands/buildCache.d.ts +27 -0
- package/dist/commands/buildCache.d.ts.map +1 -0
- package/dist/commands/buildCache.js +46 -0
- package/dist/commands/buildCache.js.map +1 -0
- package/dist/commands/certificates.d.ts +15 -0
- package/dist/commands/certificates.d.ts.map +1 -0
- package/dist/commands/certificates.js +57 -0
- package/dist/commands/certificates.js.map +1 -0
- package/dist/commands/communityTemplates.d.ts +24 -0
- package/dist/commands/communityTemplates.d.ts.map +1 -0
- package/dist/commands/communityTemplates.js +79 -0
- package/dist/commands/communityTemplates.js.map +1 -0
- package/dist/commands/configPresets.d.ts +51 -0
- package/dist/commands/configPresets.d.ts.map +1 -0
- package/dist/commands/configPresets.js +166 -0
- package/dist/commands/configPresets.js.map +1 -0
- package/dist/commands/domains.d.ts +70 -0
- package/dist/commands/domains.d.ts.map +1 -0
- package/dist/commands/domains.js +97 -0
- package/dist/commands/domains.js.map +1 -0
- package/dist/commands/egress.d.ts +43 -0
- package/dist/commands/egress.d.ts.map +1 -0
- package/dist/commands/egress.js +80 -0
- package/dist/commands/egress.js.map +1 -0
- package/dist/commands/emailTemplates.d.ts +19 -0
- package/dist/commands/emailTemplates.d.ts.map +1 -0
- package/dist/commands/emailTemplates.js +86 -0
- package/dist/commands/emailTemplates.js.map +1 -0
- package/dist/commands/housekeeping.d.ts +24 -0
- package/dist/commands/housekeeping.d.ts.map +1 -1
- package/dist/commands/housekeeping.js +62 -1
- package/dist/commands/housekeeping.js.map +1 -1
- package/dist/commands/logs.d.ts +15 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +58 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/manage.d.ts +45 -0
- package/dist/commands/manage.d.ts.map +1 -1
- package/dist/commands/manage.js +153 -0
- package/dist/commands/manage.js.map +1 -1
- package/dist/commands/manifest.d.ts +12 -6
- package/dist/commands/manifest.d.ts.map +1 -1
- package/dist/commands/manifest.js +87 -12
- package/dist/commands/manifest.js.map +1 -1
- package/dist/commands/metrics.d.ts +37 -0
- package/dist/commands/metrics.d.ts.map +1 -0
- package/dist/commands/metrics.js +43 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/misc.d.ts +35 -0
- package/dist/commands/misc.d.ts.map +1 -1
- package/dist/commands/misc.js +135 -1
- package/dist/commands/misc.js.map +1 -1
- package/dist/commands/notifications.d.ts +59 -0
- package/dist/commands/notifications.d.ts.map +1 -0
- package/dist/commands/notifications.js +157 -0
- package/dist/commands/notifications.js.map +1 -0
- package/dist/commands/pgbouncer.d.ts +17 -0
- package/dist/commands/pgbouncer.d.ts.map +1 -0
- package/dist/commands/pgbouncer.js +46 -0
- package/dist/commands/pgbouncer.js.map +1 -0
- package/dist/commands/plugins.d.ts +3 -0
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +20 -1
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/services.d.ts +14 -0
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +29 -0
- package/dist/commands/services.js.map +1 -1
- package/dist/commands/sso.d.ts +31 -0
- package/dist/commands/sso.d.ts.map +1 -0
- package/dist/commands/sso.js +77 -0
- package/dist/commands/sso.js.map +1 -0
- package/dist/commands/templates.d.ts +22 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +122 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/token.d.ts +10 -0
- package/dist/commands/token.d.ts.map +1 -1
- package/dist/commands/token.js +24 -1
- package/dist/commands/token.js.map +1 -1
- package/dist/index.js +292 -9
- package/dist/index.js.map +1 -1
- package/dist/lib/format.d.ts.map +1 -1
- package/dist/lib/format.js +18 -3
- package/dist/lib/format.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ninedeploy domains preset {list,apply}` — Sprint 2, Gap G-07, PR-D.
|
|
3
|
+
*
|
|
4
|
+
* The plugin (G-07 PR-C) reacts to the audit firehose so a `domain.add`
|
|
5
|
+
* from the panel can create the matching DNS record on its own. This
|
|
6
|
+
* CLI subcommand lets an operator do the same thing on demand without
|
|
7
|
+
* having to round-trip through the panel's domain flow — useful when a
|
|
8
|
+
* record is missing after a partial outage, or when an operator is
|
|
9
|
+
* testing the DNS pipeline against a fresh hostname.
|
|
10
|
+
*
|
|
11
|
+
* Split:
|
|
12
|
+
* - `list` calls `GET /v1/domain-presets` and prints the registered
|
|
13
|
+
* `IDomainProvider` names so the operator can sanity-check the
|
|
14
|
+
* kernel boot before chasing a misconfiguration on the provider
|
|
15
|
+
* side.
|
|
16
|
+
* - `apply <hostname>` calls `POST /v1/domain-presets/apply`, which
|
|
17
|
+
* resolves the active provider from the existing
|
|
18
|
+
* `dns_records_provider` setting, calls `findZoneForHost` +
|
|
19
|
+
* `createRecord` on it, and emits a `domain.preset.manual` audit
|
|
20
|
+
* event so the panel's activity log mirrors what the audit-bus path
|
|
21
|
+
* produces. The `--content` flag lets the operator override the
|
|
22
|
+
* resolved record content (handy for CNAME setups or smoke tests).
|
|
23
|
+
*/
|
|
24
|
+
import type { NineDeployClient } from '../client.js';
|
|
25
|
+
export interface DomainsPresetApplyOptions {
|
|
26
|
+
/** Optional override for the record content (e.g. an explicit CNAME target). */
|
|
27
|
+
content?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Pure entry point — same shape used by the CLI action and the unit
|
|
31
|
+
* test. Returns the parsed provider list so the test can assert it
|
|
32
|
+
* without depending on stdout framing.
|
|
33
|
+
*/
|
|
34
|
+
export declare function domainsPresetList(client: NineDeployClient): Promise<{
|
|
35
|
+
providers: string[];
|
|
36
|
+
}>;
|
|
37
|
+
export declare function domainsPresetListAction(client: NineDeployClient): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Pure entry point — same shape used by the CLI action and the unit
|
|
40
|
+
* test. Returns the upstream response so the test can assert it
|
|
41
|
+
* without depending on stdout framing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function domainsPresetApply(client: NineDeployClient, hostname: string, opts?: DomainsPresetApplyOptions): Promise<{
|
|
44
|
+
hostname: string;
|
|
45
|
+
provider: string;
|
|
46
|
+
zone: string;
|
|
47
|
+
recordId: string;
|
|
48
|
+
type: 'A' | 'CNAME';
|
|
49
|
+
content: string;
|
|
50
|
+
}>;
|
|
51
|
+
export declare function domainsPresetApplyAction(client: NineDeployClient, hostname: string, opts?: DomainsPresetApplyOptions): Promise<void>;
|
|
52
|
+
export interface DomainsPresetAddNamecheapOptions {
|
|
53
|
+
/** Namecheap username (the account owner). */
|
|
54
|
+
apiUser?: string;
|
|
55
|
+
/** Namecheap API key (encrypted at rest by the server). */
|
|
56
|
+
apiKey?: string;
|
|
57
|
+
/** Whitelisted public IP of the server. */
|
|
58
|
+
clientIp?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Pure entry point for the Namecheap credential upsert. The handler
|
|
62
|
+
* shape mirrors the rest of the file (returns the upstream response,
|
|
63
|
+
* the action layer frames stdout/exit-code).
|
|
64
|
+
*/
|
|
65
|
+
export declare function domainsPresetAddNamecheap(client: NineDeployClient, opts: DomainsPresetAddNamecheapOptions): Promise<{
|
|
66
|
+
ok: boolean;
|
|
67
|
+
apiUser: string;
|
|
68
|
+
}>;
|
|
69
|
+
export declare function domainsPresetAddNamecheapAction(client: NineDeployClient, opts: DomainsPresetAddNamecheapOptions): Promise<void>;
|
|
70
|
+
//# sourceMappingURL=domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../src/commands/domains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,MAAM,WAAW,yBAAyB;IACxC,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAElC;AAED,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBrF;AAID;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC;IACT,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAED;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,IAAI,CAAC,CAuBf;AAID,MAAM,WAAW,gCAAgC;IAC/C,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,gCAAgC,GACrC,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS3C;AAED,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,gCAAgC,GACrC,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { error, header, info, success } from '../lib/format.js';
|
|
2
|
+
// ── `ninedeploy domains preset list` ────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* Pure entry point — same shape used by the CLI action and the unit
|
|
5
|
+
* test. Returns the parsed provider list so the test can assert it
|
|
6
|
+
* without depending on stdout framing.
|
|
7
|
+
*/
|
|
8
|
+
export async function domainsPresetList(client) {
|
|
9
|
+
return await client.domainPresets.list();
|
|
10
|
+
}
|
|
11
|
+
export async function domainsPresetListAction(client) {
|
|
12
|
+
header('Domain presets');
|
|
13
|
+
let result;
|
|
14
|
+
try {
|
|
15
|
+
result = await domainsPresetList(client);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
error(err instanceof Error ? err.message : String(err));
|
|
19
|
+
process.exitCode = 1;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (result.providers.length === 0) {
|
|
23
|
+
info('No IDomainProvider drivers are registered on this kernel.');
|
|
24
|
+
info('Set dns_records_provider in Settings → DNS to enable one.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const name of result.providers) {
|
|
28
|
+
info(`• ${name}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// ── `ninedeploy domains preset apply <hostname>` ────────────────────────────
|
|
32
|
+
/**
|
|
33
|
+
* Pure entry point — same shape used by the CLI action and the unit
|
|
34
|
+
* test. Returns the upstream response so the test can assert it
|
|
35
|
+
* without depending on stdout framing.
|
|
36
|
+
*/
|
|
37
|
+
export async function domainsPresetApply(client, hostname, opts = {}) {
|
|
38
|
+
return await client.domainPresets.apply({ hostname, content: opts.content });
|
|
39
|
+
}
|
|
40
|
+
export async function domainsPresetApplyAction(client, hostname, opts = {}) {
|
|
41
|
+
header('Domain preset apply');
|
|
42
|
+
if (!hostname) {
|
|
43
|
+
error('Usage: ninedeploy domains preset apply <hostname> [--content <value>]');
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let result;
|
|
48
|
+
try {
|
|
49
|
+
result = await domainsPresetApply(client, hostname, opts);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
error(err instanceof Error ? err.message : String(err));
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
success(`Applied ${result.type} record for ${result.hostname}`);
|
|
57
|
+
info(`Provider: ${result.provider}`);
|
|
58
|
+
info(`Zone: ${result.zone}`);
|
|
59
|
+
info(`Record: ${result.recordId}`);
|
|
60
|
+
info(`Content: ${result.content}`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Pure entry point for the Namecheap credential upsert. The handler
|
|
64
|
+
* shape mirrors the rest of the file (returns the upstream response,
|
|
65
|
+
* the action layer frames stdout/exit-code).
|
|
66
|
+
*/
|
|
67
|
+
export async function domainsPresetAddNamecheap(client, opts) {
|
|
68
|
+
if (!opts.apiUser || !opts.apiKey || !opts.clientIp) {
|
|
69
|
+
throw new Error('Missing required flags: --api-user, --api-key, --client-ip');
|
|
70
|
+
}
|
|
71
|
+
return await client.settings.namecheap.set({
|
|
72
|
+
apiUser: opts.apiUser,
|
|
73
|
+
apiKey: opts.apiKey,
|
|
74
|
+
clientIp: opts.clientIp,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export async function domainsPresetAddNamecheapAction(client, opts) {
|
|
78
|
+
header('Domain preset add (Namecheap)');
|
|
79
|
+
if (!opts.apiUser || !opts.apiKey || !opts.clientIp) {
|
|
80
|
+
error('Usage: ninedeploy domains preset add namecheap --api-user <u> --api-key <k> --client-ip <ip>');
|
|
81
|
+
error('The client IP must already be whitelisted on the Namecheap account panel.');
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let result;
|
|
86
|
+
try {
|
|
87
|
+
result = await domainsPresetAddNamecheap(client, opts);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
error(err instanceof Error ? err.message : String(err));
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
success(`Saved Namecheap credentials for ${result.apiUser}`);
|
|
95
|
+
info('Set dns_records_provider=namecheap in Settings → DNS to use them.');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.js","sourceRoot":"","sources":["../../src/commands/domains.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ninedeploy egress {list,set,clear}` — Sprint 5, Gap G-15.
|
|
3
|
+
*
|
|
4
|
+
* Operator-side wrapper around the active `IEgressIpDriver`. The
|
|
5
|
+
* CLI is the canonical way to attach a stable outbound IP to a
|
|
6
|
+
* project: hosting providers run `ninedeploy egress set <projectId>
|
|
7
|
+
* <ip>` after the project is created, and the next deploy's
|
|
8
|
+
* `service.deployed` event fires the matching iptables SNAT.
|
|
9
|
+
*/
|
|
10
|
+
import type { NineDeployClient } from '../client.js';
|
|
11
|
+
export interface EgressRule {
|
|
12
|
+
selector: {
|
|
13
|
+
projectId: number;
|
|
14
|
+
sourceCidr?: string;
|
|
15
|
+
};
|
|
16
|
+
ip: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface EgressDriverView {
|
|
20
|
+
name: string;
|
|
21
|
+
rules: EgressRule[];
|
|
22
|
+
}
|
|
23
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
24
|
+
export declare function egressList(client: NineDeployClient): Promise<{
|
|
25
|
+
drivers: EgressDriverView[];
|
|
26
|
+
}>;
|
|
27
|
+
export declare function egressListAction(client: NineDeployClient): Promise<void>;
|
|
28
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
29
|
+
export declare function egressSet(client: NineDeployClient, projectId: number, ip: string, driver?: string): Promise<{
|
|
30
|
+
ok: boolean;
|
|
31
|
+
driver: string;
|
|
32
|
+
rule: EgressRule;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function egressSetAction(client: NineDeployClient, projectIdStr: string, ip: string, opts?: {
|
|
35
|
+
driver?: string;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
38
|
+
export declare function egressClear(client: NineDeployClient, projectId: number): Promise<{
|
|
39
|
+
ok: boolean;
|
|
40
|
+
driver: string;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function egressClearAction(client: NineDeployClient, projectIdStr: string): Promise<void>;
|
|
43
|
+
//# sourceMappingURL=egress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress.d.ts","sourceRoot":"","sources":["../../src/commands/egress.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAID,8EAA8E;AAC9E,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,CAEnG;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB9E;AAID,8EAA8E;AAC9E,wBAAsB,SAAS,CAC7B,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAE5D;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,gBAAgB,EACxB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,MAAM,EACV,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,CAgBf;AAID,8EAA8E;AAC9E,wBAAsB,WAAW,CAC/B,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAE1C;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,gBAAgB,EACxB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { error, header, info, success } from '../lib/format.js';
|
|
2
|
+
// ── `ninedeploy egress list` ──────────────────────────────────────────────
|
|
3
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
4
|
+
export async function egressList(client) {
|
|
5
|
+
return await client.egress.list();
|
|
6
|
+
}
|
|
7
|
+
export async function egressListAction(client) {
|
|
8
|
+
header('Egress IP rules');
|
|
9
|
+
let result;
|
|
10
|
+
try {
|
|
11
|
+
result = await egressList(client);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
error(err instanceof Error ? err.message : String(err));
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (result.drivers.length === 0) {
|
|
19
|
+
info('No egress IP drivers are registered. Install one via Settings → Plugins.');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const d of result.drivers) {
|
|
23
|
+
info(`Driver: ${d.name}`);
|
|
24
|
+
if (d.rules.length === 0) {
|
|
25
|
+
info(' (no rules)');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
for (const r of d.rules) {
|
|
29
|
+
info(` project ${r.selector.projectId} → ${r.ip} (since ${r.createdAt})`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ── `ninedeploy egress set <projectId> <ip>` ──────────────────────────────
|
|
35
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
36
|
+
export async function egressSet(client, projectId, ip, driver) {
|
|
37
|
+
return await client.egress.set({ projectId, ip, driver });
|
|
38
|
+
}
|
|
39
|
+
export async function egressSetAction(client, projectIdStr, ip, opts = {}) {
|
|
40
|
+
const projectId = Number(projectIdStr);
|
|
41
|
+
if (!Number.isFinite(projectId)) {
|
|
42
|
+
error('Usage: ninedeploy egress set <projectId> <ip> [--driver <name>]');
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let result;
|
|
47
|
+
try {
|
|
48
|
+
result = await egressSet(client, projectId, ip, opts.driver);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
error(err instanceof Error ? err.message : String(err));
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
success(`Egress IP ${result.rule.ip} attached to project ${projectId} via ${result.driver}`);
|
|
56
|
+
}
|
|
57
|
+
// ── `ninedeploy egress clear <projectId>` ────────────────────────────────
|
|
58
|
+
/** Pure entry point — same shape used by the CLI action and the unit test. */
|
|
59
|
+
export async function egressClear(client, projectId) {
|
|
60
|
+
return await client.egress.clear(projectId);
|
|
61
|
+
}
|
|
62
|
+
export async function egressClearAction(client, projectIdStr) {
|
|
63
|
+
const projectId = Number(projectIdStr);
|
|
64
|
+
if (!Number.isFinite(projectId)) {
|
|
65
|
+
error('Usage: ninedeploy egress clear <projectId>');
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
let result;
|
|
70
|
+
try {
|
|
71
|
+
result = await egressClear(client, projectId);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
error(err instanceof Error ? err.message : String(err));
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
success(`Egress IP cleared for project ${projectId} via ${result.driver}`);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=egress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress.js","sourceRoot":"","sources":["../../src/commands/egress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ninedeploy email-templates {list,set,reset,preview}` —
|
|
3
|
+
* G-30 transactional email template overrides.
|
|
4
|
+
*
|
|
5
|
+
* The CLI is a thin wrapper around the SDK; the heavy
|
|
6
|
+
* lifting is `lib/emailTemplates.ts`. The `set` and
|
|
7
|
+
* `reset` commands require the workspace's admin role
|
|
8
|
+
* server-side, so a non-admin operator gets a clean
|
|
9
|
+
* 403 rather than a silent no-op.
|
|
10
|
+
*/
|
|
11
|
+
import type { NineDeployClient } from '@ninedeploy/sdk';
|
|
12
|
+
export declare function emailTemplatesList(client: NineDeployClient, widStr: string): Promise<void>;
|
|
13
|
+
export declare function emailTemplatesPreview(client: NineDeployClient, widStr: string, name: string, vars?: string[]): Promise<void>;
|
|
14
|
+
export declare function emailTemplatesSet(client: NineDeployClient, widStr: string, name: string, opts: {
|
|
15
|
+
subject: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function emailTemplatesReset(client: NineDeployClient, widStr: string, name: string): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=emailTemplates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailTemplates.d.ts","sourceRoot":"","sources":["../../src/commands/emailTemplates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,iBAAiB,CAAC;AAuB3E,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhG;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAM,EAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACtC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/G"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { c, error, header, info, spinner, success, table } from '../lib/format.js';
|
|
2
|
+
const num = (v, usage) => {
|
|
3
|
+
const n = Number(v);
|
|
4
|
+
if (!n) {
|
|
5
|
+
error(usage);
|
|
6
|
+
throw new Error(usage);
|
|
7
|
+
}
|
|
8
|
+
return n;
|
|
9
|
+
};
|
|
10
|
+
const fail = (err) => {
|
|
11
|
+
error(err instanceof Error ? err.message : String(err));
|
|
12
|
+
};
|
|
13
|
+
const NAMES = [
|
|
14
|
+
'password-reset',
|
|
15
|
+
'workspace-invitation',
|
|
16
|
+
'domain-transfer',
|
|
17
|
+
'backup-drill-failed',
|
|
18
|
+
];
|
|
19
|
+
export async function emailTemplatesList(client, widStr) {
|
|
20
|
+
const wid = num(widStr, 'Usage: ninedeploy email-templates list <workspaceId>');
|
|
21
|
+
const res = await spinner('Fetching', () => client.emailTemplates.list(wid));
|
|
22
|
+
header(`Email templates (workspace ${wid})`);
|
|
23
|
+
table(res.templates.map((t) => ({
|
|
24
|
+
name: t.name,
|
|
25
|
+
overridden: t.overridden ? 'yes' : c.dim('no'),
|
|
26
|
+
subject: t.subject ?? c.dim('(default)'),
|
|
27
|
+
})), ['name', 'overridden', 'subject']);
|
|
28
|
+
}
|
|
29
|
+
export async function emailTemplatesPreview(client, widStr, name, vars = []) {
|
|
30
|
+
const wid = num(widStr, 'Usage: ninedeploy email-templates preview <workspaceId> <name> [key=value ...]');
|
|
31
|
+
if (!NAMES.includes(name)) {
|
|
32
|
+
error(`Unknown template: ${name}. Valid names: ${NAMES.join(', ')}`);
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const parsed = {};
|
|
37
|
+
for (const raw of vars) {
|
|
38
|
+
const eq = raw.indexOf('=');
|
|
39
|
+
if (eq <= 0) {
|
|
40
|
+
error(`--var expects key=value pairs, got: ${raw}`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
parsed[raw.slice(0, eq)] = raw.slice(eq + 1);
|
|
44
|
+
}
|
|
45
|
+
const res = await spinner('Rendering', () => client.emailTemplates.preview(wid, name, parsed));
|
|
46
|
+
header(`Preview: ${name}${res.overridden ? c.cyan(' (overridden)') : ''}`);
|
|
47
|
+
info(`Subject: ${res.subject}`);
|
|
48
|
+
console.log();
|
|
49
|
+
console.log(res.text);
|
|
50
|
+
}
|
|
51
|
+
export async function emailTemplatesSet(client, widStr, name, opts) {
|
|
52
|
+
const wid = num(widStr, 'Usage: ninedeploy email-templates set <workspaceId> <name> --subject <s> --text <t>');
|
|
53
|
+
if (!NAMES.includes(name)) {
|
|
54
|
+
error(`Unknown template: ${name}. Valid names: ${NAMES.join(', ')}`);
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!opts.subject || !opts.text) {
|
|
59
|
+
error('Both --subject and --text are required');
|
|
60
|
+
process.exitCode = 1;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
await client.emailTemplates.set(wid, name, opts.subject, opts.text);
|
|
65
|
+
success(`Override set for ${name}.`);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
fail(err);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export async function emailTemplatesReset(client, widStr, name) {
|
|
72
|
+
const wid = num(widStr, 'Usage: ninedeploy email-templates reset <workspaceId> <name>');
|
|
73
|
+
if (!NAMES.includes(name)) {
|
|
74
|
+
error(`Unknown template: ${name}. Valid names: ${NAMES.join(', ')}`);
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await client.emailTemplates.reset(wid, name);
|
|
80
|
+
success(`Override removed for ${name}.`);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
fail(err);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=emailTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emailTemplates.js","sourceRoot":"","sources":["../../src/commands/emailTemplates.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,27 @@
|
|
|
1
1
|
import type { NineDeployClient } from '@ninedeploy/sdk';
|
|
2
2
|
export declare function housekeepingPrune(client: NineDeployClient): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* `ninedeploy images ls` — every image on the host, with
|
|
5
|
+
* repo / tag / size / age / dangling / in-use columns. The
|
|
6
|
+
* default sort is by size descending so the operator sees
|
|
7
|
+
* the biggest offenders first; `--sort age` switches to
|
|
8
|
+
* "oldest first" which is what the panel usually wants for
|
|
9
|
+
* a prune sweep.
|
|
10
|
+
*/
|
|
11
|
+
export declare function imagesList(client: NineDeployClient, opts?: {
|
|
12
|
+
sort?: 'size' | 'age';
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* `ninedeploy images prune` — fine-grained retention.
|
|
16
|
+
* The CLI builds a small opts object from flags and posts
|
|
17
|
+
* to `/v1/housekeeping/images/prune`. `--dry-run` is the
|
|
18
|
+
* default expectation on a first run: the operator
|
|
19
|
+
* eyeballs the would-delete set, then re-runs without it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function imagesPrune(client: NineDeployClient, opts?: {
|
|
22
|
+
keepLast?: number;
|
|
23
|
+
olderThan?: number;
|
|
24
|
+
dangling?: boolean;
|
|
25
|
+
dryRun?: boolean;
|
|
26
|
+
}): Promise<void>;
|
|
3
27
|
//# sourceMappingURL=housekeeping.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"housekeeping.d.ts","sourceRoot":"","sources":["../../src/commands/housekeeping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/E"}
|
|
1
|
+
{"version":3,"file":"housekeeping.d.ts","sourceRoot":"","sources":["../../src/commands/housekeeping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/E;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,EACxB,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAAO,GACnC,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,gBAAgB,EACxB,IAAI,GAAE;IACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CACb,GACL,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fmtBytes, spinner } from '../lib/format.js';
|
|
1
|
+
import { error, fmtBytes, header, info, spinner, success, table } from '../lib/format.js';
|
|
2
2
|
export async function housekeepingPrune(client) {
|
|
3
3
|
const res = await spinner('Running system prune', () => client.housekeeping.runPrune());
|
|
4
4
|
console.log(' ✓ System housekeeping prune completed.');
|
|
@@ -8,4 +8,65 @@ export async function housekeepingPrune(client) {
|
|
|
8
8
|
console.log(` Images freed: ${res.details.imagesFreed}`);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* `ninedeploy images ls` — every image on the host, with
|
|
13
|
+
* repo / tag / size / age / dangling / in-use columns. The
|
|
14
|
+
* default sort is by size descending so the operator sees
|
|
15
|
+
* the biggest offenders first; `--sort age` switches to
|
|
16
|
+
* "oldest first" which is what the panel usually wants for
|
|
17
|
+
* a prune sweep.
|
|
18
|
+
*/
|
|
19
|
+
export async function imagesList(client, opts = {}) {
|
|
20
|
+
header('Images');
|
|
21
|
+
const { images, totalBytes } = await spinner('Listing', () => client.housekeeping.listImages());
|
|
22
|
+
if (images.length === 0) {
|
|
23
|
+
info('No images on the host.');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const sorted = [...images].sort((a, b) => {
|
|
27
|
+
if (opts.sort === 'age')
|
|
28
|
+
return b.ageHours - a.ageHours;
|
|
29
|
+
return b.sizeBytes - a.sizeBytes;
|
|
30
|
+
});
|
|
31
|
+
table(sorted.map((i) => ({
|
|
32
|
+
repository: i.repository,
|
|
33
|
+
tag: i.tag,
|
|
34
|
+
size: i.size,
|
|
35
|
+
ageHours: i.ageHours.toFixed(1),
|
|
36
|
+
dangling: i.dangling ? 'yes' : '',
|
|
37
|
+
inUse: i.inUse ? 'yes' : '',
|
|
38
|
+
})), ['repository', 'tag', 'size', 'ageHours', 'dangling', 'inUse']);
|
|
39
|
+
info(`${images.length} images, total ${fmtBytes(totalBytes)}.`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `ninedeploy images prune` — fine-grained retention.
|
|
43
|
+
* The CLI builds a small opts object from flags and posts
|
|
44
|
+
* to `/v1/housekeeping/images/prune`. `--dry-run` is the
|
|
45
|
+
* default expectation on a first run: the operator
|
|
46
|
+
* eyeballs the would-delete set, then re-runs without it.
|
|
47
|
+
*/
|
|
48
|
+
export async function imagesPrune(client, opts = {}) {
|
|
49
|
+
header('Image prune');
|
|
50
|
+
if (!opts.dangling && !opts.keepLast && !opts.olderThan) {
|
|
51
|
+
error('Refusing to prune with no filter. Set --dangling, --keep-last <N>, or --older-than <hours>.');
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const res = await spinner(opts.dryRun ? 'Computing candidate set' : 'Pruning', () => client.housekeeping.pruneImages({
|
|
56
|
+
keepLast: opts.keepLast,
|
|
57
|
+
olderThanHours: opts.olderThan,
|
|
58
|
+
danglingOnly: opts.dangling,
|
|
59
|
+
dryRun: opts.dryRun,
|
|
60
|
+
}));
|
|
61
|
+
if (res.dryRun) {
|
|
62
|
+
info(`dryRun: would remove ${res.removed.length} images, freeing ${fmtBytes(res.freedBytes)}.`);
|
|
63
|
+
for (const label of res.removedLabels.slice(0, 25))
|
|
64
|
+
console.log(` ${label}`);
|
|
65
|
+
if (res.removedLabels.length > 25)
|
|
66
|
+
info(` …and ${res.removedLabels.length - 25} more.`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
success(`Removed ${res.removed.length} images, freed ${fmtBytes(res.freedBytes)}.`);
|
|
70
|
+
console.log(res.output);
|
|
71
|
+
}
|
|
11
72
|
//# sourceMappingURL=housekeeping.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"housekeeping.js","sourceRoot":"","sources":["../../src/commands/housekeeping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"housekeeping.js","sourceRoot":"","sources":["../../src/commands/housekeeping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ninedeploy logs search` — G-16 cluster log search via
|
|
3
|
+
* the configured Loki drain. The CLI is a thin renderer
|
|
4
|
+
* around `client.logDrains.search(...)`: the heavy
|
|
5
|
+
* lifting is the upstream Loki query.
|
|
6
|
+
*/
|
|
7
|
+
import type { NineDeployClient } from '../client.js';
|
|
8
|
+
export declare function logsSearch(client: NineDeployClient, query: string, opts?: {
|
|
9
|
+
service?: string;
|
|
10
|
+
since?: string;
|
|
11
|
+
limit?: string;
|
|
12
|
+
drain?: string;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAYrD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9F,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { c, error, header, info, spinner } from '../lib/format.js';
|
|
2
|
+
const num = (v, usage) => {
|
|
3
|
+
const n = Number(v);
|
|
4
|
+
if (!n) {
|
|
5
|
+
error(usage);
|
|
6
|
+
throw new Error(usage);
|
|
7
|
+
}
|
|
8
|
+
return n;
|
|
9
|
+
};
|
|
10
|
+
export async function logsSearch(client, query, opts = {}) {
|
|
11
|
+
if (!query) {
|
|
12
|
+
error('Usage: ninedeploy logs search <query> [--service <id>] [--since 15m] [--drain <id>]');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const sinceMinutes = parseSinceMinutes(opts.since ?? '15m');
|
|
16
|
+
const limit = opts.limit ? num(opts.limit, 'Usage: --limit <N>') : undefined;
|
|
17
|
+
const drainId = opts.drain ? num(opts.drain, 'Usage: --drain <id>') : undefined;
|
|
18
|
+
const serviceId = opts.service ? num(opts.service, 'Usage: --service <id>') : undefined;
|
|
19
|
+
const result = await spinner('Searching logs', () => client.logDrains.search({ query, serviceId, sinceMinutes, limit, drainId }));
|
|
20
|
+
if (opts.json) {
|
|
21
|
+
console.log(JSON.stringify(result, null, 2));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
header('Log search');
|
|
25
|
+
info(`Drain: ${result.drain.name} (${result.drain.type})`);
|
|
26
|
+
info(`Window: ${result.window.since} → ${result.window.until}`);
|
|
27
|
+
if (result.serviceId != null)
|
|
28
|
+
info(`Service ID: ${result.serviceId}`);
|
|
29
|
+
info(`Matches: ${result.lines.length}`);
|
|
30
|
+
if (result.lines.length === 0) {
|
|
31
|
+
info('(no matches in the window)');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log();
|
|
35
|
+
for (const line of result.lines) {
|
|
36
|
+
const ts = new Date(line.ts).toISOString();
|
|
37
|
+
const svc = line.service ? c.dim(`[${line.service}]`) : '';
|
|
38
|
+
console.log(`${c.dim(ts)} ${svc} ${line.line}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Parse `15m` / `2h` / `30s` / `1d` into minutes. The
|
|
42
|
+
* search route caps at 7d, so anything larger is clamped. */
|
|
43
|
+
function parseSinceMinutes(input) {
|
|
44
|
+
const m = /^(\d+)([smhd])$/.exec(input.trim());
|
|
45
|
+
if (!m) {
|
|
46
|
+
error(`Invalid --since value "${input}" (expected e.g. 15m, 2h, 1d)`);
|
|
47
|
+
throw new Error(`Invalid --since value: ${input}`);
|
|
48
|
+
}
|
|
49
|
+
const n = Number(m[1]);
|
|
50
|
+
switch (m[2]) {
|
|
51
|
+
case 's': return Math.max(1, Math.ceil(n / 60));
|
|
52
|
+
case 'm': return n;
|
|
53
|
+
case 'h': return Math.min(7 * 24 * 60, n * 60);
|
|
54
|
+
case 'd': return Math.min(7 * 24 * 60, n * 24 * 60);
|
|
55
|
+
default: return 15;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
|