@git.zone/cli 2.23.0 → 2.25.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.
Files changed (38) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/gitzone.cli.js +11 -2
  3. package/dist_ts/mod_services/classes.dockercontainer.d.ts +81 -0
  4. package/dist_ts/mod_services/classes.dockercontainer.js +205 -10
  5. package/dist_ts/mod_services/classes.globalregistry.d.ts +10 -0
  6. package/dist_ts/mod_services/classes.globalregistry.js +23 -1
  7. package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +52 -1
  8. package/dist_ts/mod_services/classes.serviceconfiguration.js +116 -20
  9. package/dist_ts/mod_services/classes.servicedatamarker.d.ts +93 -0
  10. package/dist_ts/mod_services/classes.servicedatamarker.js +166 -0
  11. package/dist_ts/mod_services/classes.servicemanager.d.ts +91 -5
  12. package/dist_ts/mod_services/classes.servicemanager.js +274 -64
  13. package/dist_ts/mod_services/classes.serviceoptions.d.ts +58 -0
  14. package/dist_ts/mod_services/classes.serviceoptions.js +93 -0
  15. package/dist_ts/mod_services/classes.servicepruner.d.ts +102 -0
  16. package/dist_ts/mod_services/classes.servicepruner.js +410 -0
  17. package/dist_ts/mod_services/helpers.d.ts +15 -0
  18. package/dist_ts/mod_services/helpers.js +57 -1
  19. package/dist_ts/mod_services/index.js +307 -53
  20. package/dist_ts/mod_tools/classes.packagemanager.d.ts +13 -0
  21. package/dist_ts/mod_tools/classes.packagemanager.js +42 -1
  22. package/dist_ts/mod_tools/index.js +4 -1
  23. package/package.json +3 -2
  24. package/readme.hints.md +105 -0
  25. package/readme.md +123 -5
  26. package/ts/00_commitinfo_data.ts +1 -1
  27. package/ts/gitzone.cli.ts +10 -0
  28. package/ts/mod_services/classes.dockercontainer.ts +244 -13
  29. package/ts/mod_services/classes.globalregistry.ts +27 -0
  30. package/ts/mod_services/classes.serviceconfiguration.ts +148 -27
  31. package/ts/mod_services/classes.servicedatamarker.ts +228 -0
  32. package/ts/mod_services/classes.servicemanager.ts +394 -72
  33. package/ts/mod_services/classes.serviceoptions.ts +135 -0
  34. package/ts/mod_services/classes.servicepruner.ts +532 -0
  35. package/ts/mod_services/helpers.ts +60 -0
  36. package/ts/mod_services/index.ts +437 -58
  37. package/ts/mod_tools/classes.packagemanager.ts +54 -0
  38. package/ts/mod_tools/index.ts +5 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Committed, per-service configuration.
3
+ *
4
+ * Deliberately a SIBLING of `@git.zone/cli.services` rather than a richer
5
+ * `services` value. `@git.zone/tsdeploy` derives a workload's
6
+ * `requiredCapabilities` from that array and **throws** on any element that is
7
+ * not a canonical lowercase string, so an array of objects — or a mixed array —
8
+ * would hard-fail real deployments. `services` therefore stays exactly
9
+ * `string[]`, and configuration lives here where TsDeploy never looks.
10
+ *
11
+ * Config path: `@git.zone/cli.serviceOptions`.
12
+ */
13
+ export declare const serviceOptionsConfigKey = "serviceOptions";
14
+ export interface IMongodbServiceOptions {
15
+ /**
16
+ * When false, mongod runs without authentication and is published on
17
+ * loopback only. Opt-in, for runtimes whose `node:crypto` cannot complete a
18
+ * SCRAM handshake (notably Deno). Absent means enabled.
19
+ */
20
+ auth?: boolean;
21
+ }
22
+ export interface IServiceOptions {
23
+ mongodb?: IMongodbServiceOptions;
24
+ }
25
+ /**
26
+ * Read declared service options from `.smartconfig.json`.
27
+ *
28
+ * Unknown or malformed values are ignored rather than throwing: this file is
29
+ * hand-edited, and a typo must not make every services command unusable. The
30
+ * effect of ignoring is always the safe default (auth enabled).
31
+ */
32
+ export declare const readServiceOptions: (cwd?: string) => Promise<IServiceOptions>;
33
+ /**
34
+ * Declare whether MongoDB enforces authentication for this project.
35
+ *
36
+ * Writing `true` removes the declaration instead of recording it: the default
37
+ * is already "enabled", and an absent key keeps committed config free of noise
38
+ * while remaining unambiguous to an older CLI that ignores this key entirely.
39
+ */
40
+ export declare const writeMongodbAuthOption: (authEnabledArg: boolean, cwd?: string) => Promise<void>;
41
+ /**
42
+ * Where an effective setting came from, so the CLI can say so out loud.
43
+ */
44
+ export type TServiceOptionSource = 'declared' | 'local' | 'default';
45
+ export interface IResolvedMongoAuth {
46
+ authEnabled: boolean;
47
+ source: TServiceOptionSource;
48
+ }
49
+ /**
50
+ * Resolve the effective MongoDB auth mode.
51
+ *
52
+ * A committed declaration wins over `.nogit/env.json`. That ordering is what
53
+ * makes a fresh checkout reproducible: without it, a stale local env.json would
54
+ * silently diverge from what the repository declares. When nothing is declared,
55
+ * an existing local value is preserved so projects configured before
56
+ * `serviceOptions` existed keep working.
57
+ */
58
+ export declare const resolveMongoAuth: (declaredOptionsArg: IServiceOptions, localValueArg: boolean | undefined) => IResolvedMongoAuth;
@@ -0,0 +1,93 @@
1
+ import * as plugins from './mod.plugins.js';
2
+ import { getCliConfigValueFromData, readSmartconfigFile, setCliConfigValueInData, writeSmartconfigFile, } from '../helpers.smartconfig.js';
3
+ /**
4
+ * Committed, per-service configuration.
5
+ *
6
+ * Deliberately a SIBLING of `@git.zone/cli.services` rather than a richer
7
+ * `services` value. `@git.zone/tsdeploy` derives a workload's
8
+ * `requiredCapabilities` from that array and **throws** on any element that is
9
+ * not a canonical lowercase string, so an array of objects — or a mixed array —
10
+ * would hard-fail real deployments. `services` therefore stays exactly
11
+ * `string[]`, and configuration lives here where TsDeploy never looks.
12
+ *
13
+ * Config path: `@git.zone/cli.serviceOptions`.
14
+ */
15
+ export const serviceOptionsConfigKey = 'serviceOptions';
16
+ const isPlainObject = (value) => {
17
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
18
+ };
19
+ /**
20
+ * Read declared service options from `.smartconfig.json`.
21
+ *
22
+ * Unknown or malformed values are ignored rather than throwing: this file is
23
+ * hand-edited, and a typo must not make every services command unusable. The
24
+ * effect of ignoring is always the safe default (auth enabled).
25
+ */
26
+ export const readServiceOptions = async (cwd = process.cwd()) => {
27
+ const smartconfigData = await readSmartconfigFile(cwd);
28
+ const rawOptions = getCliConfigValueFromData(smartconfigData, serviceOptionsConfigKey);
29
+ if (!isPlainObject(rawOptions)) {
30
+ return {};
31
+ }
32
+ const options = {};
33
+ if (isPlainObject(rawOptions.mongodb) && typeof rawOptions.mongodb.auth === 'boolean') {
34
+ options.mongodb = { auth: rawOptions.mongodb.auth };
35
+ }
36
+ return options;
37
+ };
38
+ /**
39
+ * Declare whether MongoDB enforces authentication for this project.
40
+ *
41
+ * Writing `true` removes the declaration instead of recording it: the default
42
+ * is already "enabled", and an absent key keeps committed config free of noise
43
+ * while remaining unambiguous to an older CLI that ignores this key entirely.
44
+ */
45
+ export const writeMongodbAuthOption = async (authEnabledArg, cwd = process.cwd()) => {
46
+ const smartconfigData = await readSmartconfigFile(cwd);
47
+ const rawOptions = getCliConfigValueFromData(smartconfigData, serviceOptionsConfigKey);
48
+ const nextOptions = isPlainObject(rawOptions) ? { ...rawOptions } : {};
49
+ if (authEnabledArg) {
50
+ if (isPlainObject(nextOptions.mongodb)) {
51
+ const { auth, ...restOfMongodb } = nextOptions.mongodb;
52
+ if (Object.keys(restOfMongodb).length > 0) {
53
+ nextOptions.mongodb = restOfMongodb;
54
+ }
55
+ else {
56
+ delete nextOptions.mongodb;
57
+ }
58
+ }
59
+ }
60
+ else {
61
+ nextOptions.mongodb = { ...(isPlainObject(nextOptions.mongodb) ? nextOptions.mongodb : {}), auth: false };
62
+ }
63
+ if (Object.keys(nextOptions).length === 0) {
64
+ // Drop the key entirely rather than leaving an empty object behind.
65
+ const cliConfig = smartconfigData['@git.zone/cli'];
66
+ if (isPlainObject(cliConfig)) {
67
+ delete cliConfig[serviceOptionsConfigKey];
68
+ }
69
+ }
70
+ else {
71
+ setCliConfigValueInData(smartconfigData, serviceOptionsConfigKey, nextOptions);
72
+ }
73
+ await writeSmartconfigFile(smartconfigData, cwd);
74
+ };
75
+ /**
76
+ * Resolve the effective MongoDB auth mode.
77
+ *
78
+ * A committed declaration wins over `.nogit/env.json`. That ordering is what
79
+ * makes a fresh checkout reproducible: without it, a stale local env.json would
80
+ * silently diverge from what the repository declares. When nothing is declared,
81
+ * an existing local value is preserved so projects configured before
82
+ * `serviceOptions` existed keep working.
83
+ */
84
+ export const resolveMongoAuth = (declaredOptionsArg, localValueArg) => {
85
+ if (typeof declaredOptionsArg.mongodb?.auth === 'boolean') {
86
+ return { authEnabled: declaredOptionsArg.mongodb.auth, source: 'declared' };
87
+ }
88
+ if (typeof localValueArg === 'boolean') {
89
+ return { authEnabled: localValueArg, source: 'local' };
90
+ }
91
+ return { authEnabled: true, source: 'default' };
92
+ };
93
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXJ2aWNlb3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9zZXJ2aWNlcy9jbGFzc2VzLnNlcnZpY2VvcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixtQkFBbUIsRUFDbkIsdUJBQXVCLEVBQ3ZCLG9CQUFvQixHQUNyQixNQUFNLDJCQUEyQixDQUFDO0FBR25DOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsZ0JBQWdCLENBQUM7QUFleEQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxLQUFjLEVBQWdDLEVBQUU7SUFDckUsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUUsQ0FBQyxDQUFDO0FBRUY7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxFQUNyQyxNQUFjLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFDRCxFQUFFO0lBQzVCLE1BQU0sZUFBZSxHQUFHLE1BQU0sbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkQsTUFBTSxVQUFVLEdBQUcseUJBQXlCLENBQUMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLENBQUM7SUFDdkYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQy9CLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFvQixFQUFFLENBQUM7SUFDcEMsSUFBSSxhQUFhLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDdEYsT0FBTyxDQUFDLE9BQU8sR0FBRyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxLQUFLLEVBQ3pDLGNBQXVCLEVBQ3ZCLE1BQWMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUNaLEVBQUU7SUFDakIsTUFBTSxlQUFlLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2RCxNQUFNLFVBQVUsR0FBRyx5QkFBeUIsQ0FBQyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztJQUN2RixNQUFNLFdBQVcsR0FBd0IsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUU1RixJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ25CLElBQUksYUFBYSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxhQUFhLEVBQUUsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDO1lBQ3ZELElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLFdBQVcsQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDO1lBQ3RDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLFdBQVcsQ0FBQyxPQUFPLENBQUM7WUFDN0IsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLFdBQVcsQ0FBQyxPQUFPLEdBQUcsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQzVHLENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzFDLG9FQUFvRTtRQUNwRSxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDbkQsSUFBSSxhQUFhLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUM3QixPQUFPLFNBQVMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzVDLENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLHVCQUF1QixDQUFDLGVBQWUsRUFBRSx1QkFBdUIsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNqRixDQUFDO0lBRUQsTUFBTSxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDbkQsQ0FBQyxDQUFDO0FBWUY7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUM5QixrQkFBbUMsRUFDbkMsYUFBa0MsRUFDZCxFQUFFO0lBQ3RCLElBQUksT0FBTyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzFELE9BQU8sRUFBRSxXQUFXLEVBQUUsa0JBQWtCLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUM7SUFDOUUsQ0FBQztJQUNELElBQUksT0FBTyxhQUFhLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDdkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3pELENBQUM7SUFDRCxPQUFPLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUM7QUFDbEQsQ0FBQyxDQUFDIn0=
@@ -0,0 +1,102 @@
1
+ import { type TServiceName } from './classes.servicedatamarker.js';
2
+ /** Default inactivity threshold before a project is even considered stale. */
3
+ export declare const defaultStaleDays = 30;
4
+ /**
5
+ * How a project was classified.
6
+ *
7
+ * - `live` — recent activity; never a reclamation candidate.
8
+ * - `stale` — project still on disk but inactive past the threshold.
9
+ * - `orphaned` — project directory no longer exists.
10
+ * - `unknown` — insufficient evidence to classify; never reclaimed.
11
+ */
12
+ export type TServiceProjectState = 'live' | 'stale' | 'orphaned' | 'unknown';
13
+ /** Why a candidate was left alone. */
14
+ export interface IServiceSkipReason {
15
+ target: string;
16
+ reason: string;
17
+ }
18
+ export interface IServiceDataDirReport {
19
+ service: TServiceName;
20
+ path: string;
21
+ exists: boolean;
22
+ sizeBytes: number;
23
+ reclaimable: boolean;
24
+ reason: string;
25
+ }
26
+ export interface IServiceContainerReport {
27
+ id: string;
28
+ name: string;
29
+ state: string;
30
+ running: boolean;
31
+ reclaimable: boolean;
32
+ reason: string;
33
+ }
34
+ export interface IServiceProjectReport {
35
+ projectPath: string;
36
+ projectName: string;
37
+ state: TServiceProjectState;
38
+ stateReason: string;
39
+ lastActive: number | null;
40
+ inactiveDays: number | null;
41
+ projectDirExists: boolean;
42
+ registered: boolean;
43
+ markerPresent: boolean;
44
+ containers: IServiceContainerReport[];
45
+ dataDirectories: IServiceDataDirReport[];
46
+ totalDataBytes: number;
47
+ reclaimableDataBytes: number;
48
+ }
49
+ export interface IServicePrunePlan {
50
+ staleDays: number;
51
+ dockerAvailable: boolean;
52
+ projects: IServiceProjectReport[];
53
+ registryEntriesToRemove: string[];
54
+ containersToRemove: Array<{
55
+ id: string;
56
+ name: string;
57
+ projectPath: string;
58
+ }>;
59
+ dataDirsToRemove: Array<{
60
+ projectPath: string;
61
+ service: TServiceName;
62
+ path: string;
63
+ sizeBytes: number;
64
+ }>;
65
+ skipped: IServiceSkipReason[];
66
+ totals: {
67
+ projects: number;
68
+ totalDataBytes: number;
69
+ reclaimableDataBytes: number;
70
+ /** Bytes that would be reclaimable if the holding containers were stopped first. */
71
+ blockedByRunningBytes: number;
72
+ };
73
+ }
74
+ export interface IServicePrunerOptions {
75
+ staleDays?: number;
76
+ }
77
+ /**
78
+ * Plans and applies reclamation of resources created by `gitzone services`.
79
+ *
80
+ * Design mirrors `@git.zone/tsdocker`'s `TsDockerPruner`: build an explicit
81
+ * plan, print it, and only mutate on an explicit apply that re-verifies every
82
+ * single item. Nothing is ever matched by image or by bare name pattern, and
83
+ * every ambiguity resolves to "skip".
84
+ */
85
+ export declare class ServicePruner {
86
+ private docker;
87
+ private globalRegistry;
88
+ private staleDays;
89
+ constructor(optionsArg?: IServicePrunerOptions);
90
+ /**
91
+ * Build a reclamation plan. Read-only: touches nothing.
92
+ */
93
+ createPlan(): Promise<IServicePrunePlan>;
94
+ /**
95
+ * Apply a plan, re-verifying every item immediately before it is removed.
96
+ *
97
+ * Any drift between plan and current reality aborts with an error rather than
98
+ * removing something that may since have become live.
99
+ */
100
+ applyPlan(planArg: IServicePrunePlan): Promise<void>;
101
+ private isClaimedByExactlyOneProject;
102
+ }