@ya-modbus/driver-loader 0.8.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.9.0](https://github.com/groupsky/ya-modbus/compare/@ya-modbus/driver-loader@0.8.1...@ya-modbus/driver-loader@0.9.0) (2026-10-12)
7
+
8
+ ### Features
9
+
10
+ - **driver-loader:** allow scoped third-party driver packages ([#573](https://github.com/groupsky/ya-modbus/issues/573)) ([63b2b83](https://github.com/groupsky/ya-modbus/commit/63b2b833dbb0b5198e8df7135f419793e32d95c3)), closes [#565](https://github.com/groupsky/ya-modbus/issues/565)
11
+
12
+ ## [0.8.1](https://github.com/groupsky/ya-modbus/compare/@ya-modbus/driver-loader@0.8.0...@ya-modbus/driver-loader@0.8.1) (2026-10-12)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **cli:** read CLI versions from package.json in ESM and CJS builds ([#539](https://github.com/groupsky/ya-modbus/issues/539)) ([f3275f3](https://github.com/groupsky/ya-modbus/commit/f3275f3ab3c0f4019304ca7abb0f0fdecc6faf11)), closes [#256](https://github.com/groupsky/ya-modbus/issues/256)
17
+
6
18
  # [0.8.0](https://github.com/groupsky/ya-modbus/compare/@ya-modbus/driver-loader@0.7.2...@ya-modbus/driver-loader@0.8.0) (2026-10-12)
7
19
 
8
20
  - feat!: drop Node.js 20 support (#516) ([70002ab](https://github.com/groupsky/ya-modbus/commit/70002ab28155432e0984c67a70d1469fc5be7cb3)), closes [#516](https://github.com/groupsky/ya-modbus/issues/516)
package/README.md CHANGED
@@ -167,6 +167,54 @@ await loadDriver({ driverPackage: 'my-driver' })
167
167
  console.log(getDriverCacheStats()) // { hits: 1, misses: 1, size: 1 }
168
168
  ```
169
169
 
170
+ ### `getCallerPackageInfo(): PackageInfo`
171
+
172
+ Returns the `version` and `description` from the package.json of the package that contains the calling module. CLIs use it to report their own version without hardcoding it.
173
+
174
+ It finds the caller from the call stack, so it works the same in the ESM and CommonJS builds of a package.
175
+
176
+ It does not work when the caller and driver-loader are bundled into one file, because both then appear as the same file on the call stack.
177
+
178
+ **Returns:**
179
+
180
+ - `PackageInfo` object containing:
181
+ - `version`: Version from the closest package.json that has one
182
+ - `description`: Description from that package.json (empty string if missing)
183
+
184
+ **Throws:**
185
+
186
+ - Error if the calling module cannot be determined
187
+ - Error if no package.json with a version is found above the calling module
188
+
189
+ ```typescript
190
+ import { getCallerPackageInfo } from '@ya-modbus/driver-loader'
191
+
192
+ program.version(getCallerPackageInfo().version)
193
+ ```
194
+
195
+ ### `isValidDriverPackageName(name: unknown): boolean`
196
+
197
+ Checks a driver package name against the shared naming rule for applications that read the driver name from a configuration, such as the MQTT bridge. Allowed forms:
198
+
199
+ - `@ya-modbus/driver-<name>`
200
+ - `ya-modbus-driver-<name>`
201
+ - `@<scope>/ya-modbus-driver-<name>`
202
+
203
+ `<name>` and `<scope>` use only lowercase letters, numbers and hyphens. Paths (`../x`, `/opt/x`), sub paths, backslashes and any other package name are rejected. `loadDriver` does not check this rule. If your tool reads the driver name from a config file, call `assertValidDriverPackageName` before `loadDriver`.
204
+
205
+ ### `assertValidDriverPackageName(name: string): void`
206
+
207
+ Same check as `isValidDriverPackageName`. Throws a `ValidationError` (field `driverPackage`) that shows the rejected name and lists the allowed forms.
208
+
209
+ `DRIVER_PACKAGE_NAME_RULE` is the text of the rule ("must be ..."), for applications that build their own error message.
210
+
211
+ ```typescript
212
+ import { assertValidDriverPackageName, loadDriver } from '@ya-modbus/driver-loader'
213
+
214
+ assertValidDriverPackageName(config.driver)
215
+ await loadDriver({ driverPackage: config.driver })
216
+ ```
217
+
170
218
  ## Testing Utilities
171
219
 
172
220
  The package provides testing utilities for applications using driver-loader.
@@ -230,7 +278,7 @@ If you encounter `Driver package not found` errors:
230
278
 
231
279
  3. **Check the package name:**
232
280
  - Ensure the package name in your code matches the actual npm package name
233
- - Driver packages typically follow the naming convention: `ya-modbus-driver-<device>`
281
+ - Driver packages follow the naming rule described under `isValidDriverPackageName` (for example `ya-modbus-driver-<device>` or `@<scope>/ya-modbus-driver-<device>`)
234
282
 
235
283
  ### Module Resolution Issues
236
284
 
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Describes the allowed driver package names, for error messages.
3
+ * Written to follow "name must be ...", so callers can put their own words in front.
4
+ */
5
+ export declare const DRIVER_PACKAGE_NAME_RULE: string;
6
+ /**
7
+ * Check a driver package name against the shared naming rule for drivers that are loaded
8
+ * from a configured name, such as in the MQTT bridge.
9
+ *
10
+ * Allowed forms: `@ya-modbus/driver-<name>`, `ya-modbus-driver-<name>` and
11
+ * `@<scope>/ya-modbus-driver-<name>`.
12
+ *
13
+ * @param name - Value to check
14
+ * @returns true if the value is an allowed driver package name
15
+ */
16
+ export declare function isValidDriverPackageName(name: unknown): boolean;
17
+ /**
18
+ * Throw if a driver package name does not follow the naming rule.
19
+ *
20
+ * @param name - Driver package name to check
21
+ * @throws ValidationError (field `driverPackage`) listing the allowed forms
22
+ */
23
+ export declare function assertValidDriverPackageName(name: string): void;
24
+ //# sourceMappingURL=driver-package-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver-package-name.d.ts","sourceRoot":"","sources":["../../../src/driver-package-name.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAEuC,CAAA;AAS5E;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAO/D"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DRIVER_PACKAGE_NAME_RULE = void 0;
4
+ exports.isValidDriverPackageName = isValidDriverPackageName;
5
+ exports.assertValidDriverPackageName = assertValidDriverPackageName;
6
+ const errors_js_1 = require("./errors.js");
7
+ /**
8
+ * Describes the allowed driver package names, for error messages.
9
+ * Written to follow "name must be ...", so callers can put their own words in front.
10
+ */
11
+ exports.DRIVER_PACKAGE_NAME_RULE = 'must be @ya-modbus/driver-<name>, ya-modbus-driver-<name> or @<scope>/ya-modbus-driver-<name>, ' +
12
+ 'where <name> and <scope> use only lowercase letters, numbers and hyphens';
13
+ /**
14
+ * The three allowed forms. Only lowercase letters, numbers and hyphens can follow the prefix,
15
+ * so a name can never contain a path separator, a dot, a backslash or a whitespace.
16
+ */
17
+ const DRIVER_PACKAGE_NAME_PATTERN = /^(?:@ya-modbus\/driver-|(?:@[a-z0-9][a-z0-9-]*\/)?ya-modbus-driver-)[a-z0-9-]+$/;
18
+ /**
19
+ * Check a driver package name against the shared naming rule for drivers that are loaded
20
+ * from a configured name, such as in the MQTT bridge.
21
+ *
22
+ * Allowed forms: `@ya-modbus/driver-<name>`, `ya-modbus-driver-<name>` and
23
+ * `@<scope>/ya-modbus-driver-<name>`.
24
+ *
25
+ * @param name - Value to check
26
+ * @returns true if the value is an allowed driver package name
27
+ */
28
+ function isValidDriverPackageName(name) {
29
+ return typeof name === 'string' && DRIVER_PACKAGE_NAME_PATTERN.test(name);
30
+ }
31
+ /**
32
+ * Throw if a driver package name does not follow the naming rule.
33
+ *
34
+ * @param name - Driver package name to check
35
+ * @throws ValidationError (field `driverPackage`) listing the allowed forms
36
+ */
37
+ function assertValidDriverPackageName(name) {
38
+ if (!isValidDriverPackageName(name)) {
39
+ throw new errors_js_1.ValidationError(`Invalid driver package name ${JSON.stringify(name)}: ${exports.DRIVER_PACKAGE_NAME_RULE}`, 'driverPackage');
40
+ }
41
+ }
42
+ //# sourceMappingURL=driver-package-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver-package-name.js","sourceRoot":"","sources":["../../../src/driver-package-name.ts"],"names":[],"mappings":";;;AA2BA,4DAEC;AAQD,oEAOC;AA5CD,2CAA6C;AAE7C;;;GAGG;AACU,QAAA,wBAAwB,GACnC,iGAAiG;IACjG,0EAA0E,CAAA;AAE5E;;;GAGG;AACH,MAAM,2BAA2B,GAC/B,iFAAiF,CAAA;AAEnF;;;;;;;;;GASG;AACH,SAAgB,wBAAwB,CAAC,IAAa;IACpD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3E,CAAC;AAED;;;;;GAKG;AACH,SAAgB,4BAA4B,CAAC,IAAY;IACvD,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,2BAAe,CACvB,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,gCAAwB,EAAE,EAClF,eAAe,CAChB,CAAA;IACH,CAAC;AACH,CAAC"}
@@ -1,5 +1,8 @@
1
1
  export { loadDriver, clearDriverCache, getDriverCacheStats } from './loader.js';
2
2
  export type { LoadedDriver, LoadDriverOptions, SystemDependencies, DriverCacheStats, Logger, } from './loader.js';
3
3
  export { validateDefaultConfig, validateSupportedConfig, validateDevices, crossValidateConfigs, } from './config-validator.js';
4
+ export { DRIVER_PACKAGE_NAME_RULE, assertValidDriverPackageName, isValidDriverPackageName, } from './driver-package-name.js';
4
5
  export { ValidationError, DriverNotFoundError, PackageJsonError } from './errors.js';
6
+ export { getCallerPackageInfo } from './package-info.js';
7
+ export type { PackageInfo } from './package-info.js';
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAC/E,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,MAAM,GACP,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAC/E,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,MAAM,GACP,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PackageJsonError = exports.DriverNotFoundError = exports.ValidationError = exports.crossValidateConfigs = exports.validateDevices = exports.validateSupportedConfig = exports.validateDefaultConfig = exports.getDriverCacheStats = exports.clearDriverCache = exports.loadDriver = void 0;
3
+ exports.getCallerPackageInfo = exports.PackageJsonError = exports.DriverNotFoundError = exports.ValidationError = exports.isValidDriverPackageName = exports.assertValidDriverPackageName = exports.DRIVER_PACKAGE_NAME_RULE = exports.crossValidateConfigs = exports.validateDevices = exports.validateSupportedConfig = exports.validateDefaultConfig = exports.getDriverCacheStats = exports.clearDriverCache = exports.loadDriver = void 0;
4
4
  var loader_js_1 = require("./loader.js");
5
5
  Object.defineProperty(exports, "loadDriver", { enumerable: true, get: function () { return loader_js_1.loadDriver; } });
6
6
  Object.defineProperty(exports, "clearDriverCache", { enumerable: true, get: function () { return loader_js_1.clearDriverCache; } });
@@ -10,8 +10,14 @@ Object.defineProperty(exports, "validateDefaultConfig", { enumerable: true, get:
10
10
  Object.defineProperty(exports, "validateSupportedConfig", { enumerable: true, get: function () { return config_validator_js_1.validateSupportedConfig; } });
11
11
  Object.defineProperty(exports, "validateDevices", { enumerable: true, get: function () { return config_validator_js_1.validateDevices; } });
12
12
  Object.defineProperty(exports, "crossValidateConfigs", { enumerable: true, get: function () { return config_validator_js_1.crossValidateConfigs; } });
13
+ var driver_package_name_js_1 = require("./driver-package-name.js");
14
+ Object.defineProperty(exports, "DRIVER_PACKAGE_NAME_RULE", { enumerable: true, get: function () { return driver_package_name_js_1.DRIVER_PACKAGE_NAME_RULE; } });
15
+ Object.defineProperty(exports, "assertValidDriverPackageName", { enumerable: true, get: function () { return driver_package_name_js_1.assertValidDriverPackageName; } });
16
+ Object.defineProperty(exports, "isValidDriverPackageName", { enumerable: true, get: function () { return driver_package_name_js_1.isValidDriverPackageName; } });
13
17
  var errors_js_1 = require("./errors.js");
14
18
  Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_js_1.ValidationError; } });
15
19
  Object.defineProperty(exports, "DriverNotFoundError", { enumerable: true, get: function () { return errors_js_1.DriverNotFoundError; } });
16
20
  Object.defineProperty(exports, "PackageJsonError", { enumerable: true, get: function () { return errors_js_1.PackageJsonError; } });
21
+ var package_info_js_1 = require("./package-info.js");
22
+ Object.defineProperty(exports, "getCallerPackageInfo", { enumerable: true, get: function () { return package_info_js_1.getCallerPackageInfo; } });
17
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA+E;AAAtE,uGAAA,UAAU,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,gHAAA,mBAAmB,OAAA;AAQ1D,6DAK8B;AAJ5B,4HAAA,qBAAqB,OAAA;AACrB,8HAAA,uBAAuB,OAAA;AACvB,sHAAA,eAAe,OAAA;AACf,2HAAA,oBAAoB,OAAA;AAEtB,yCAAoF;AAA3E,4GAAA,eAAe,OAAA;AAAE,gHAAA,mBAAmB,OAAA;AAAE,6GAAA,gBAAgB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA+E;AAAtE,uGAAA,UAAU,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,gHAAA,mBAAmB,OAAA;AAQ1D,6DAK8B;AAJ5B,4HAAA,qBAAqB,OAAA;AACrB,8HAAA,uBAAuB,OAAA;AACvB,sHAAA,eAAe,OAAA;AACf,2HAAA,oBAAoB,OAAA;AAEtB,mEAIiC;AAH/B,kIAAA,wBAAwB,OAAA;AACxB,sIAAA,4BAA4B,OAAA;AAC5B,kIAAA,wBAAwB,OAAA;AAE1B,yCAAoF;AAA3E,4GAAA,eAAe,OAAA;AAAE,gHAAA,mBAAmB,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAC/D,qDAAwD;AAA/C,uHAAA,oBAAoB,OAAA"}
@@ -59,7 +59,7 @@ export interface Logger {
59
59
  export interface LoadDriverOptions {
60
60
  /**
61
61
  * Explicit driver package name
62
- * e.g., 'ya-modbus-driver-xymd1' or '@org/driver-pkg'
62
+ * e.g., 'ya-modbus-driver-xymd1' or '@org/ya-modbus-driver-xymd1'
63
63
  */
64
64
  driverPackage?: string;
65
65
  /**
@@ -0,0 +1,43 @@
1
+ export interface PackageInfo {
2
+ version: string;
3
+ description: string;
4
+ }
5
+ type ReadTextFile = (path: string) => string;
6
+ /**
7
+ * Read the version and description from the closest package.json above a file
8
+ *
9
+ * package.json files without a version are skipped. This passes over the
10
+ * `{"type": "module"}` and `{"type": "commonjs"}` markers in `dist/esm` and `dist/cjs`.
11
+ *
12
+ * @param file - Path or `file:` URL of a module inside the package
13
+ * @param readFile - Reads a file as text and throws if it does not exist (replaceable in tests)
14
+ * @throws Error if no package.json with a version is found
15
+ */
16
+ export declare function readPackageInfo(file: string, readFile?: ReadTextFile): PackageInfo;
17
+ /**
18
+ * Pick the calling module from the file names of a stack, innermost first
19
+ *
20
+ * The first frame is this module. The caller is the first frame from another file that is a
21
+ * real module path or `file:` URL, which skips frames such as `node:internal/timers`.
22
+ *
23
+ * @throws Error if the stack has no such frame
24
+ */
25
+ export declare function findCallerFile(files: ReadonlyArray<string | undefined>): string;
26
+ /**
27
+ * Get the version and description of the package that contains the calling module
28
+ *
29
+ * Lets a CLI report its own package.json values without hardcoding them. The caller's
30
+ * location comes from the call stack, so it works the same in ES module and CommonJS
31
+ * builds, where `import.meta.url` and `__dirname` are each available in only one.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const { version } = getCallerPackageInfo()
36
+ * program.version(version)
37
+ * ```
38
+ *
39
+ * @throws Error if the calling module cannot be determined or has no package.json with a version
40
+ */
41
+ export declare function getCallerPackageInfo(): PackageInfo;
42
+ export {};
43
+ //# sourceMappingURL=package-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-info.d.ts","sourceRoot":"","sources":["../../../src/package-info.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACpB;AAwBD,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAiB5C;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,YAA2B,GAAG,WAAW,CAehG;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAY/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,IAAI,WAAW,CAIlD"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readPackageInfo = readPackageInfo;
4
+ exports.findCallerFile = findCallerFile;
5
+ exports.getCallerPackageInfo = getCallerPackageInfo;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const node_url_1 = require("node:url");
9
+ const MIN_STACK_TRACE_LIMIT = 10;
10
+ /**
11
+ * Call sites of the current stack, innermost first.
12
+ *
13
+ * V8 formats `stack` lazily, so it must be read while the formatter is replaced.
14
+ */
15
+ function getCallSites() {
16
+ // eslint-disable-next-line @typescript-eslint/unbound-method -- only restored, never called
17
+ const originalPrepare = Error.prepareStackTrace;
18
+ const originalLimit = Error.stackTraceLimit;
19
+ try {
20
+ Error.prepareStackTrace = (_error, callSites) => callSites;
21
+ // An application can lower the limit so far that the caller is not on the stack
22
+ Error.stackTraceLimit = Math.max(originalLimit, MIN_STACK_TRACE_LIMIT);
23
+ return new Error().stack;
24
+ }
25
+ finally {
26
+ Error.prepareStackTrace = originalPrepare;
27
+ Error.stackTraceLimit = originalLimit;
28
+ }
29
+ }
30
+ const readUtf8File = (path) => (0, node_fs_1.readFileSync)(path, 'utf-8');
31
+ function readPackageJson(path, readFile) {
32
+ let content;
33
+ try {
34
+ content = readFile(path);
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ return JSON.parse(content);
40
+ }
41
+ /**
42
+ * Read the version and description from the closest package.json above a file
43
+ *
44
+ * package.json files without a version are skipped. This passes over the
45
+ * `{"type": "module"}` and `{"type": "commonjs"}` markers in `dist/esm` and `dist/cjs`.
46
+ *
47
+ * @param file - Path or `file:` URL of a module inside the package
48
+ * @param readFile - Reads a file as text and throws if it does not exist (replaceable in tests)
49
+ * @throws Error if no package.json with a version is found
50
+ */
51
+ function readPackageInfo(file, readFile = readUtf8File) {
52
+ const path = file.startsWith('file:') ? (0, node_url_1.fileURLToPath)(file) : file;
53
+ for (let dir = (0, node_path_1.dirname)(path);; dir = (0, node_path_1.dirname)(dir)) {
54
+ const packageJson = readPackageJson((0, node_path_1.join)(dir, 'package.json'), readFile);
55
+ if (typeof packageJson?.version === 'string') {
56
+ return {
57
+ version: packageJson.version,
58
+ description: typeof packageJson.description === 'string' ? packageJson.description : '',
59
+ };
60
+ }
61
+ if ((0, node_path_1.dirname)(dir) === dir) {
62
+ throw new Error(`No package.json with a version found for ${path}`);
63
+ }
64
+ }
65
+ }
66
+ /**
67
+ * Pick the calling module from the file names of a stack, innermost first
68
+ *
69
+ * The first frame is this module. The caller is the first frame from another file that is a
70
+ * real module path or `file:` URL, which skips frames such as `node:internal/timers`.
71
+ *
72
+ * @throws Error if the stack has no such frame
73
+ */
74
+ function findCallerFile(files) {
75
+ const [ownFile] = files;
76
+ const callerFile = files.find((file) => file !== undefined && file !== ownFile && (file.startsWith('file:') || (0, node_path_1.isAbsolute)(file)));
77
+ if (callerFile === undefined) {
78
+ throw new Error('Cannot determine the calling module');
79
+ }
80
+ return callerFile;
81
+ }
82
+ /**
83
+ * Get the version and description of the package that contains the calling module
84
+ *
85
+ * Lets a CLI report its own package.json values without hardcoding them. The caller's
86
+ * location comes from the call stack, so it works the same in ES module and CommonJS
87
+ * builds, where `import.meta.url` and `__dirname` are each available in only one.
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const { version } = getCallerPackageInfo()
92
+ * program.version(version)
93
+ * ```
94
+ *
95
+ * @throws Error if the calling module cannot be determined or has no package.json with a version
96
+ */
97
+ function getCallerPackageInfo() {
98
+ const files = getCallSites().map((callSite) => callSite.getFileName() ?? undefined);
99
+ return readPackageInfo(findCallerFile(files));
100
+ }
101
+ //# sourceMappingURL=package-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-info.js","sourceRoot":"","sources":["../../../src/package-info.ts"],"names":[],"mappings":"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"}