@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,166 @@
1
+ import * as plugins from './mod.plugins.js';
2
+ export const serviceNames = ['mongodb', 'minio', 'elasticsearch'];
3
+ /** Owner recorded in markers and container labels. */
4
+ export const serviceDataOwner = '@git.zone/cli';
5
+ /** Value of the `git.zone.tool` label on containers created by `gitzone services`. */
6
+ export const serviceToolLabel = 'gitzone-services';
7
+ /** Marker file name, stored in `<projectPath>/.nogit/`. */
8
+ export const serviceDataMarkerFile = '.gitzone-services.json';
9
+ /**
10
+ * Directory basename used below `.nogit/` for each service's bind-mounted data.
11
+ * This mapping is the only shape `gitzone services` ever creates, and prune
12
+ * refuses to touch anything that does not match it exactly.
13
+ */
14
+ export const serviceDataDirectoryNames = {
15
+ mongodb: 'mongodata',
16
+ minio: 'miniodata',
17
+ elasticsearch: 'esdata',
18
+ };
19
+ /**
20
+ * Image used to run each service, and therefore the image available to perform
21
+ * a privileged cleanup of that service's data directory: if the data exists,
22
+ * the service ran, so its image is present locally.
23
+ */
24
+ export const serviceImages = {
25
+ mongodb: 'mongo:7.0',
26
+ minio: 'minio/minio',
27
+ elasticsearch: 'elasticsearch:8.11.0',
28
+ };
29
+ const isPlainObject = (value) => {
30
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
31
+ };
32
+ /** Absolute path of the marker file for a project. */
33
+ export const getServiceDataMarkerPath = (projectPathArg) => {
34
+ return plugins.path.join(plugins.path.resolve(projectPathArg), '.nogit', serviceDataMarkerFile);
35
+ };
36
+ /**
37
+ * Expected absolute data directory path for a service in a project.
38
+ * `mod_services` must always derive data paths through this helper so that
39
+ * creation and reclamation agree on a single shape.
40
+ */
41
+ export const getServiceDataDirectory = (projectPathArg, serviceArg) => {
42
+ return plugins.path.join(plugins.path.resolve(projectPathArg), '.nogit', serviceDataDirectoryNames[serviceArg]);
43
+ };
44
+ /**
45
+ * True only when `candidatePathArg` is exactly one of the three data
46
+ * directories `gitzone services` creates for `projectPathArg`.
47
+ *
48
+ * This is an allowlist, not a denylist: any path that is not byte-for-byte one
49
+ * of the expected resolved paths is rejected. It is the last line of defence
50
+ * before a recursive delete.
51
+ */
52
+ export const isSafeServiceDataPath = (projectPathArg, candidatePathArg) => {
53
+ const candidate = plugins.path.resolve(candidatePathArg);
54
+ for (const service of serviceNames) {
55
+ if (getServiceDataDirectory(projectPathArg, service) === candidate) {
56
+ return true;
57
+ }
58
+ }
59
+ return false;
60
+ };
61
+ /** Validate an unknown value as a usable marker. */
62
+ export const isValidServiceDataMarker = (markerArg) => {
63
+ if (!isPlainObject(markerArg)) {
64
+ return false;
65
+ }
66
+ if (markerArg.owner !== serviceDataOwner) {
67
+ return false;
68
+ }
69
+ if (markerArg.kind !== 'service-data') {
70
+ return false;
71
+ }
72
+ if (markerArg.schemaVersion !== 1) {
73
+ return false;
74
+ }
75
+ if (markerArg.safeToPrune !== true) {
76
+ return false;
77
+ }
78
+ if (typeof markerArg.projectPath !== 'string' || !markerArg.projectPath) {
79
+ return false;
80
+ }
81
+ if (!Array.isArray(markerArg.dataDirectories)) {
82
+ return false;
83
+ }
84
+ for (const entry of markerArg.dataDirectories) {
85
+ if (!isPlainObject(entry)) {
86
+ return false;
87
+ }
88
+ if (!serviceNames.includes(entry.service)) {
89
+ return false;
90
+ }
91
+ if (typeof entry.path !== 'string' || !entry.path) {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ };
97
+ /** Read and validate the marker for a project, or undefined when absent/invalid. */
98
+ export const readServiceDataMarker = async (projectPathArg) => {
99
+ const markerPath = getServiceDataMarkerPath(projectPathArg);
100
+ try {
101
+ if (!(await plugins.smartfs.file(markerPath).exists())) {
102
+ return undefined;
103
+ }
104
+ const content = (await plugins.smartfs.file(markerPath).encoding('utf8').read());
105
+ const parsed = JSON.parse(content);
106
+ return isValidServiceDataMarker(parsed) ? parsed : undefined;
107
+ }
108
+ catch {
109
+ return undefined;
110
+ }
111
+ };
112
+ /**
113
+ * Record that `gitzone services` owns a data directory for this project.
114
+ *
115
+ * The marker lives in `.nogit/` rather than inside the bind-mounted data
116
+ * directory itself, so it can never confuse mongod, MinIO or Elasticsearch at
117
+ * runtime. Entries are merged so enabling a service later does not drop the
118
+ * claim on previously created directories.
119
+ */
120
+ export const recordServiceDataDirectory = async (projectPathArg, serviceArg) => {
121
+ const projectPath = plugins.path.resolve(projectPathArg);
122
+ const dataPath = getServiceDataDirectory(projectPath, serviceArg);
123
+ const existingMarker = await readServiceDataMarker(projectPath);
124
+ const entries = existingMarker
125
+ ? existingMarker.dataDirectories.filter((entry) => entry.service !== serviceArg)
126
+ : [];
127
+ entries.push({ service: serviceArg, path: dataPath });
128
+ entries.sort((entryA, entryB) => entryA.service.localeCompare(entryB.service));
129
+ const marker = {
130
+ owner: serviceDataOwner,
131
+ kind: 'service-data',
132
+ schemaVersion: 1,
133
+ projectPath,
134
+ safeToPrune: true,
135
+ createdAt: existingMarker?.createdAt || new Date().toISOString(),
136
+ dataDirectories: entries,
137
+ };
138
+ const markerPath = getServiceDataMarkerPath(projectPath);
139
+ await plugins.smartfs.directory(plugins.path.dirname(markerPath)).recursive().create();
140
+ await plugins.smartfs
141
+ .file(markerPath)
142
+ .encoding('utf8')
143
+ .write(`${JSON.stringify(marker, null, 2)}\n`);
144
+ };
145
+ /**
146
+ * Labels applied to every container `gitzone services` creates.
147
+ *
148
+ * Mirrors the `git.zone.*` namespace already established by
149
+ * `@git.zone/tsdocker` so prune logic can identify tool-owned resources
150
+ * without ever matching on image or bare name.
151
+ */
152
+ export const getServiceContainerLabels = (optionsArg) => {
153
+ return {
154
+ 'git.zone.tool': serviceToolLabel,
155
+ 'git.zone.service': optionsArg.service,
156
+ 'git.zone.project-path': plugins.path.resolve(optionsArg.projectPath),
157
+ 'git.zone.data-path': plugins.path.resolve(optionsArg.dataPath),
158
+ 'git.zone.safe-to-prune': 'true',
159
+ };
160
+ };
161
+ /** True when a container's labels prove `gitzone services` created it. */
162
+ export const isServiceOwnedByLabels = (labelsArg) => {
163
+ return (labelsArg['git.zone.tool'] === serviceToolLabel &&
164
+ labelsArg['git.zone.safe-to-prune'] === 'true');
165
+ };
166
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXJ2aWNlZGF0YW1hcmtlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9zZXJ2aWNlcy9jbGFzc2VzLnNlcnZpY2VkYXRhbWFya2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFZNUMsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFtQixDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFFbEYsc0RBQXNEO0FBQ3RELE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLGVBQWUsQ0FBQztBQUVoRCxzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsa0JBQWtCLENBQUM7QUFFbkQsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLHdCQUF3QixDQUFDO0FBRTlEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBc0M7SUFDMUUsT0FBTyxFQUFFLFdBQVc7SUFDcEIsS0FBSyxFQUFFLFdBQVc7SUFDbEIsYUFBYSxFQUFFLFFBQVE7Q0FDeEIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQXNDO0lBQzlELE9BQU8sRUFBRSxXQUFXO0lBQ3BCLEtBQUssRUFBRSxhQUFhO0lBQ3BCLGFBQWEsRUFBRSxzQkFBc0I7Q0FDdEMsQ0FBQztBQWlCRixNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQWMsRUFBZ0MsRUFBRTtJQUNyRSxPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM5RSxDQUFDLENBQUM7QUFFRixzREFBc0Q7QUFDdEQsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxjQUFzQixFQUFVLEVBQUU7SUFD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
@@ -1,3 +1,36 @@
1
+ import { ServiceConfiguration } from './classes.serviceconfiguration.js';
2
+ import { type TServiceName } from './classes.servicedatamarker.js';
3
+ import type { ContainerStatus } from './classes.dockercontainer.js';
4
+ import type { TServiceOptionSource } from './classes.serviceoptions.js';
5
+ export interface IServiceStatus {
6
+ service: TServiceName;
7
+ enabled: boolean;
8
+ container: string;
9
+ status: ContainerStatus;
10
+ port: string;
11
+ connectionString: string;
12
+ dataDirectory: string;
13
+ dataSizeBytes: number;
14
+ /** Only meaningful when the container does not exist yet. */
15
+ portAvailable: boolean | null;
16
+ /** MongoDB only: whether the instance enforces authentication. */
17
+ authEnabled?: boolean;
18
+ /** MongoDB only: whether the auth mode is declared in committed config. */
19
+ authSource?: TServiceOptionSource;
20
+ }
21
+ export interface IServicesStatus {
22
+ project: {
23
+ name: string;
24
+ path: string;
25
+ enabledServices: string[];
26
+ };
27
+ services: {
28
+ mongodb: IServiceStatus;
29
+ minio: IServiceStatus;
30
+ elasticsearch: IServiceStatus;
31
+ };
32
+ totalDataBytes: number;
33
+ }
1
34
  export declare class ServiceManager {
2
35
  private config;
3
36
  private docker;
@@ -8,6 +41,16 @@ export declare class ServiceManager {
8
41
  * Initialize the service manager
9
42
  */
10
43
  init(): Promise<void>;
44
+ /**
45
+ * Human phrasing for where the auth mode came from. A declared auth-off is
46
+ * committed to the repository and therefore affects everyone who clones it,
47
+ * so it must never read the same as a local-only choice.
48
+ */
49
+ private describeMongoAuthSource;
50
+ /**
51
+ * Expose the resolved service configuration to the command layer.
52
+ */
53
+ getConfiguration(): ServiceConfiguration;
11
54
  /**
12
55
  * Load service configuration from .smartconfig.json
13
56
  */
@@ -21,15 +64,31 @@ export declare class ServiceManager {
21
64
  */
22
65
  private isServiceEnabled;
23
66
  /**
24
- * Register this project with the global registry
67
+ * Prepare a service's data directory: create it and record tool ownership.
68
+ *
69
+ * The marker written here is what later allows `gitzone services prune` to
70
+ * prove the directory is reclaimable instead of guessing from its path.
71
+ */
72
+ private prepareDataDirectory;
73
+ /**
74
+ * Register this project with the global registry.
75
+ *
76
+ * Public and called from the command layer after any start path: previously
77
+ * only `startAll` registered, so `gitzone services start mongo` created a
78
+ * container the registry never knew about and prune could never account for.
25
79
  */
26
- private registerWithGlobalRegistry;
80
+ registerWithGlobalRegistry(): Promise<void>;
27
81
  /**
28
82
  * Start all enabled services
29
83
  */
30
84
  startAll(): Promise<void>;
31
85
  /**
32
- * Stop all enabled services
86
+ * Stop every service container belonging to this project.
87
+ *
88
+ * Deliberately not filtered by the enabled-service list: disabling a service
89
+ * previously left its container running with no command able to stop it,
90
+ * which is how projects accumulated forgotten containers. Stopping a service
91
+ * that is not running is a no-op, so covering all three is always safe.
33
92
  */
34
93
  stopAll(): Promise<void>;
35
94
  /**
@@ -52,9 +111,21 @@ export declare class ServiceManager {
52
111
  */
53
112
  private ensureMongoKeyfile;
54
113
  /**
55
- * Check whether the container was created with --replSet
114
+ * The mongod argv the container was created with
56
115
  */
57
- private mongoContainerHasReplSet;
116
+ private getMongoContainerCmd;
117
+ /**
118
+ * Make sure the configured root user exists when auth is enabled.
119
+ *
120
+ * `MONGO_INITDB_ROOT_USERNAME` only takes effect on an empty dbpath, so data
121
+ * that was first created with auth disabled has no user at all. Enabling auth
122
+ * over it would leave an unusable database. MongoDB's localhost exception is
123
+ * the designed bootstrap path for exactly this: while zero users exist, a
124
+ * connection from localhost — which, inside the container, is what this is —
125
+ * may create the first one. If users already exist the exception does not
126
+ * apply and creation fails, so this can never overwrite or escalate anything.
127
+ */
128
+ private ensureMongoRootUser;
58
129
  /**
59
130
  * Initiate the single-node replica set once mongod is reachable
60
131
  */
@@ -79,10 +150,25 @@ export declare class ServiceManager {
79
150
  * Stop Elasticsearch service
80
151
  */
81
152
  stopElasticsearch(): Promise<void>;
153
+ /**
154
+ * Collect service status as structured data.
155
+ *
156
+ * This is the machine-readable surface behind `gitzone services status
157
+ * --json`; consumers such as test suites can read a connection string from it
158
+ * without scraping human output or re-deriving it from `.nogit/env.json`.
159
+ */
160
+ collectStatus(): Promise<IServicesStatus>;
82
161
  /**
83
162
  * Show service status
84
163
  */
85
164
  showStatus(): Promise<void>;
165
+ /**
166
+ * Report on-disk size of this project's service data.
167
+ *
168
+ * Reporting comes before any deletion: knowing what a project holds is what
169
+ * makes reclaiming it a decision rather than a guess.
170
+ */
171
+ showDiskUsage(): Promise<void>;
86
172
  /**
87
173
  * Show configuration
88
174
  */