@agnostack/env 2.0.0-canary.1 → 2.0.0-canary.11

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
@@ -1,33 +1,3 @@
1
- # [2.0.0-canary.1](https://github.com/[secure]/env/compare/v1.3.0...v2.0.0-canary.1) (2026-08-16)
2
-
3
-
4
- ### Bug Fixes
5
-
6
- * check every exports target exists in verify:dist ([3cab3fa](https://github.com/[secure]/env/commit/3cab3fad76ab00c0acfc513f73e899f4707f246b))
7
- * drop rimraf for node's built-in recursive delete ([c8f99f9](https://github.com/[secure]/env/commit/c8f99f931d908a94febdb5a34b0f1c66a2d7c97c))
8
- * enable composite builds to match verifyd ([695de68](https://github.com/[secure]/env/commit/695de68d2e7142c43d0ac84a6c0cfcf05ee00249))
9
- * enable strict type checking and remove any from published types ([fa48be5](https://github.com/[secure]/env/commit/fa48be5c61d0842ea4e2b8fb150b39a5cf697cec))
10
- * enforce the ^_ unused-arg convention ([231ab05](https://github.com/[secure]/env/commit/231ab05e0c54b6775fd01ed4caf757569659dcd6))
11
- * keep argv values containing "=" intact ([0d0c656](https://github.com/[secure]/env/commit/0d0c6561755c17a40ad98836f0e7433c95de98c4))
12
- * make tsconfig.json the check config so editors cover the specs ([bd1c2fa](https://github.com/[secure]/env/commit/bd1c2fae335e752ae86a94720e8598bcc8be70cd))
13
- * resolve modules with node16 ([72da476](https://github.com/[secure]/env/commit/72da476837def9b5f6148673be21fa0e51f4648e))
14
- * run clean without depending on node_modules ([18dcbfe](https://github.com/[secure]/env/commit/18dcbfe6fb2ab19e1e63d449e2c8deff8a40e217))
15
-
16
-
17
- ### Features
18
-
19
- * add ./esm subpath export ([b8a9732](https://github.com/[secure]/env/commit/b8a9732800af1977598a906b35672366658bb25f))
20
- * declare the package side-effect free ([0a18234](https://github.com/[secure]/env/commit/0a18234a5ba2096783592fd79a51dc598f569f81))
21
- * guard publishes against source leaks and unloadable ESM ([dce6d83](https://github.com/[secure]/env/commit/dce6d837b4fe5151fa3d508aa1f1fe2b6e163a3b))
22
- * migrate eslint to v9 flat config ([eecca88](https://github.com/[secure]/env/commit/eecca88c9cd95cd792cd1d989cedf881affdeaaa))
23
- * migrate the test suite from jest to vitest ([1e49534](https://github.com/[secure]/env/commit/1e49534005201926aba758efb9314534bcc383a8))
24
- * require node 22 ([9c3f0d9](https://github.com/[secure]/env/commit/9c3f0d9eba1cf18356570bcc2897642ff065c0ce))
25
-
26
-
27
- ### BREAKING CHANGES
28
-
29
- * the minimum supported node is now 22.
30
-
31
1
  # [1.3.0](https://github.com/agnostack/env/compare/v1.2.6...v1.3.0) (2025-08-20)
32
2
 
33
3
 
package/dist/env.d.ts CHANGED
@@ -10,21 +10,21 @@ export function lowerKeyValidator(envKey: string): boolean;
10
10
  export function publicKeyValidator(envKey: string): boolean;
11
11
  export function cleanLowerEnv(_env: Record<string, string | undefined> | undefined, keyValidator?: (envKey: string) => boolean): Record<string, string | undefined>;
12
12
  export function cleanPublicEnv(_env: Record<string, string | undefined> | undefined, keyValidator?: (envKey: string) => boolean): Record<string, string | undefined>;
13
- export function parseEnvData(_env?: NodeJS.ProcessEnv): {
13
+ export function parseEnvData(_env?: Record<string, string | undefined>): {
14
+ args: string[];
14
15
  env: Record<string, string> & {
15
16
  ENVIRONMENT: string;
16
17
  };
17
18
  nextEnv: Record<string, string | undefined>;
18
19
  publicEnv: Record<string, string | undefined>;
19
20
  stringifiedEnv: Record<string, string>;
20
- argParams: {
21
- [x: string]: string | undefined;
22
- };
23
- params: {
24
- [x: string]: string | undefined;
25
- ENVIRONMENT: string;
26
- };
27
- args: string[];
21
+ argEntries: {
22
+ arg: string;
23
+ param: string;
24
+ value: string | undefined;
25
+ }[];
26
+ argParams: Record<string, string | undefined>;
27
+ params: Record<string, string | undefined>;
28
28
  };
29
29
  export function getPublicEnvValue(publicEnv: Record<string, string | undefined> | undefined, key: string): string | undefined;
30
30
  export function replaceEnvTemplate(replaceable: unknown, { env: _env, template, callback, }?: {
package/dist/env.js CHANGED
@@ -52,7 +52,7 @@ const cleanEnv = (_env, keyValidator = exports.nextKeyValidator) => (Object.entr
52
52
  * @param {(envKey: string) => boolean} [keyValidator]
53
53
  * @returns {Record<string, string | undefined>}
54
54
  */
55
- const cleanLowerEnv = (_env, keyValidator = exports.lowerKeyValidator) => (cleanEnv(process.env, keyValidator));
55
+ const cleanLowerEnv = (_env, keyValidator = exports.lowerKeyValidator) => (cleanEnv(_env, keyValidator));
56
56
  exports.cleanLowerEnv = cleanLowerEnv;
57
57
  /**
58
58
  * @param {Record<string, string | undefined> | undefined} _env
@@ -61,6 +61,39 @@ exports.cleanLowerEnv = cleanLowerEnv;
61
61
  */
62
62
  const cleanPublicEnv = (_env, keyValidator = exports.publicKeyValidator) => (cleanEnv(_env, keyValidator));
63
63
  exports.cleanPublicEnv = cleanPublicEnv;
64
+ /**
65
+ * The one place argv and the ambient env are read together, so a caller gets both from a single
66
+ * call rather than parsing argv itself.
67
+ *
68
+ * ENVIRONMENT is resolved rather than trusted: an explicit `ENVIRONMENT` wins, otherwise the first
69
+ * non-empty of SITE_ENV, BUILD_ENV, NODE_ENV, falling back to 'development'.
70
+ *
71
+ * ⚠️ The argv split is by FORM, not by meaning. `--key=value` becomes an `argParams` entry; a
72
+ * valueless `--flag` stays a string in `args`, which also still holds `process.argv[0]` (the node
73
+ * binary) and `[1]` (the script path). A caller reading positionals must skip those two, and one
74
+ * reading bare flags must look in `args` rather than `argParams`.
75
+ *
76
+ * `argEntries` is the third view: every argument in order — `arg` as typed, `param` and `value`
77
+ * already split out — so a
78
+ * caller can forward what it did not consume without re-deriving it. An ARRAY rather than a map
79
+ * because repeats are meaningful — `--context=a=1 --context=b=2` is two entries, and keying them
80
+ * would silently keep only the last.
81
+ *
82
+ * `stringifiedEnv` is a MAP, not a string — each value JSON-stringified, which is the shape
83
+ * webpack's DefinePlugin wants.
84
+ *
85
+ * @param {Record<string, string | undefined>} [_env] defaults to process.env
86
+ * @returns {{
87
+ * args: string[],
88
+ * env: Record<string, string> & { ENVIRONMENT: string },
89
+ * nextEnv: Record<string, string | undefined>,
90
+ * publicEnv: Record<string, string | undefined>,
91
+ * stringifiedEnv: Record<string, string>,
92
+ * argEntries: { arg: string, param: string, value: string | undefined }[],
93
+ * argParams: Record<string, string | undefined>,
94
+ * params: Record<string, string | undefined>,
95
+ * }}
96
+ */
64
97
  const parseEnvData = (_env = process.env) => {
65
98
  var _a;
66
99
  const { ENVIRONMENT, SITE_ENV, BUILD_ENV, NODE_ENV } = _env;
@@ -73,7 +106,10 @@ const parseEnvData = (_env = process.env) => {
73
106
  const mergedEnv = Object.assign(Object.assign({}, _env), {
74
107
  // NOTE: intentionally giving precedence to ENVIRONMENT
75
108
  ENVIRONMENT: ENVIRONMENT || _environment });
76
- const _b = process.argv.reduce(({ args: _args, argParams: _argParams, }, arg) => {
109
+ // NOTE: One pass over argv building both halves of the split `args` collects every entry that
110
+ // carried no value (bare flags, positionals, and argv[0]/[1]), `argParams` every `key=value` one
111
+ // with its leading `--` stripped. An entry is never in both.
112
+ const _b = process.argv.reduce(({ args: _args, argParams: _argParams, argEntries: _argEntries, }, arg, index) => {
77
113
  var _a, _b, _c, _d, _e;
78
114
  // NOTE: split on the FIRST '=' only — everything after it is the value, verbatim.
79
115
  // Splitting on every '=' truncated any value that contained one, so `--context=env=prod`
@@ -82,11 +118,14 @@ const parseEnvData = (_env = process.env) => {
82
118
  const [__param, _value] = (separatorIndex === -1)
83
119
  ? [arg, undefined]
84
120
  : [arg.slice(0, separatorIndex), arg.slice(separatorIndex + 1)];
85
- const _param = (_c = __param === null || __param === void 0 ? void 0 : __param.replace) === null || _c === void 0 ? void 0 : _c.call(__param, '--', '');
121
+ // NOTE: anchored. A bare `.replace('--', '')` strips the first `--` ANYWHERE, so
122
+ // `my--param=x` arrived as `myparam`. Only a leading `--` is a flag marker.
123
+ const _param = (_c = __param === null || __param === void 0 ? void 0 : __param.replace) === null || _c === void 0 ? void 0 : _c.call(__param, /^--/, '');
86
124
  if ((0, display_js_1.stringEmptyOnly)(_param)) {
87
125
  return {
88
126
  args: _args,
89
127
  argParams: _argParams,
128
+ argEntries: _argEntries,
90
129
  };
91
130
  }
92
131
  /** @type {[string, string | undefined]} */
@@ -108,10 +147,20 @@ const parseEnvData = (_env = process.env) => {
108
147
  argParams: Object.assign(Object.assign({}, _argParams), (0, display_js_1.stringNotEmptyOnly)(value) && {
109
148
  [param]: value,
110
149
  }),
150
+ // NOTE: index 0 is the node binary and 1 the script path — never arguments, so neither
151
+ // reaches argEntries. That is what lets a caller forward `arg` without re-deriving which
152
+ // entries were real arguments.
153
+ argEntries: [
154
+ ..._argEntries,
155
+ ...(index >= 2) ? [{ arg, param, value }] : []
156
+ ],
111
157
  };
112
158
  }, {
113
159
  args: /** @type {string[]} */ ([]),
114
- argParams: /** @type {Record<string, string>} */ ({}),
160
+ // NOTE: `string | undefined` because the conditional spread below can widen it — seeding it
161
+ // as `Record<string, string>` made the accumulator and the callback's return disagree.
162
+ argParams: /** @type {Record<string, string | undefined>} */ ({}),
163
+ argEntries: /** @type {{ arg: string, param: string, value: string | undefined }[]} */ ([]),
115
164
  }), { argParams } = _b, output = __rest(_b, ["argParams"]);
116
165
  const nextEnv = cleanEnv(mergedEnv);
117
166
  const publicEnv = (0, exports.cleanPublicEnv)(mergedEnv);
package/dist/esm/env.js CHANGED
@@ -46,13 +46,46 @@ const cleanEnv = (_env, keyValidator = nextKeyValidator) => (Object.entries(_env
46
46
  * @param {(envKey: string) => boolean} [keyValidator]
47
47
  * @returns {Record<string, string | undefined>}
48
48
  */
49
- export const cleanLowerEnv = (_env, keyValidator = lowerKeyValidator) => (cleanEnv(process.env, keyValidator));
49
+ export const cleanLowerEnv = (_env, keyValidator = lowerKeyValidator) => (cleanEnv(_env, keyValidator));
50
50
  /**
51
51
  * @param {Record<string, string | undefined> | undefined} _env
52
52
  * @param {(envKey: string) => boolean} [keyValidator]
53
53
  * @returns {Record<string, string | undefined>}
54
54
  */
55
55
  export const cleanPublicEnv = (_env, keyValidator = publicKeyValidator) => (cleanEnv(_env, keyValidator));
56
+ /**
57
+ * The one place argv and the ambient env are read together, so a caller gets both from a single
58
+ * call rather than parsing argv itself.
59
+ *
60
+ * ENVIRONMENT is resolved rather than trusted: an explicit `ENVIRONMENT` wins, otherwise the first
61
+ * non-empty of SITE_ENV, BUILD_ENV, NODE_ENV, falling back to 'development'.
62
+ *
63
+ * ⚠️ The argv split is by FORM, not by meaning. `--key=value` becomes an `argParams` entry; a
64
+ * valueless `--flag` stays a string in `args`, which also still holds `process.argv[0]` (the node
65
+ * binary) and `[1]` (the script path). A caller reading positionals must skip those two, and one
66
+ * reading bare flags must look in `args` rather than `argParams`.
67
+ *
68
+ * `argEntries` is the third view: every argument in order — `arg` as typed, `param` and `value`
69
+ * already split out — so a
70
+ * caller can forward what it did not consume without re-deriving it. An ARRAY rather than a map
71
+ * because repeats are meaningful — `--context=a=1 --context=b=2` is two entries, and keying them
72
+ * would silently keep only the last.
73
+ *
74
+ * `stringifiedEnv` is a MAP, not a string — each value JSON-stringified, which is the shape
75
+ * webpack's DefinePlugin wants.
76
+ *
77
+ * @param {Record<string, string | undefined>} [_env] defaults to process.env
78
+ * @returns {{
79
+ * args: string[],
80
+ * env: Record<string, string> & { ENVIRONMENT: string },
81
+ * nextEnv: Record<string, string | undefined>,
82
+ * publicEnv: Record<string, string | undefined>,
83
+ * stringifiedEnv: Record<string, string>,
84
+ * argEntries: { arg: string, param: string, value: string | undefined }[],
85
+ * argParams: Record<string, string | undefined>,
86
+ * params: Record<string, string | undefined>,
87
+ * }}
88
+ */
56
89
  export const parseEnvData = (_env = process.env) => {
57
90
  var _a;
58
91
  const { ENVIRONMENT, SITE_ENV, BUILD_ENV, NODE_ENV } = _env;
@@ -65,7 +98,10 @@ export const parseEnvData = (_env = process.env) => {
65
98
  const mergedEnv = Object.assign(Object.assign({}, _env), {
66
99
  // NOTE: intentionally giving precedence to ENVIRONMENT
67
100
  ENVIRONMENT: ENVIRONMENT || _environment });
68
- const _b = process.argv.reduce(({ args: _args, argParams: _argParams, }, arg) => {
101
+ // NOTE: One pass over argv building both halves of the split `args` collects every entry that
102
+ // carried no value (bare flags, positionals, and argv[0]/[1]), `argParams` every `key=value` one
103
+ // with its leading `--` stripped. An entry is never in both.
104
+ const _b = process.argv.reduce(({ args: _args, argParams: _argParams, argEntries: _argEntries, }, arg, index) => {
69
105
  var _a, _b, _c, _d, _e;
70
106
  // NOTE: split on the FIRST '=' only — everything after it is the value, verbatim.
71
107
  // Splitting on every '=' truncated any value that contained one, so `--context=env=prod`
@@ -74,11 +110,14 @@ export const parseEnvData = (_env = process.env) => {
74
110
  const [__param, _value] = (separatorIndex === -1)
75
111
  ? [arg, undefined]
76
112
  : [arg.slice(0, separatorIndex), arg.slice(separatorIndex + 1)];
77
- const _param = (_c = __param === null || __param === void 0 ? void 0 : __param.replace) === null || _c === void 0 ? void 0 : _c.call(__param, '--', '');
113
+ // NOTE: anchored. A bare `.replace('--', '')` strips the first `--` ANYWHERE, so
114
+ // `my--param=x` arrived as `myparam`. Only a leading `--` is a flag marker.
115
+ const _param = (_c = __param === null || __param === void 0 ? void 0 : __param.replace) === null || _c === void 0 ? void 0 : _c.call(__param, /^--/, '');
78
116
  if (stringEmptyOnly(_param)) {
79
117
  return {
80
118
  args: _args,
81
119
  argParams: _argParams,
120
+ argEntries: _argEntries,
82
121
  };
83
122
  }
84
123
  /** @type {[string, string | undefined]} */
@@ -100,10 +139,20 @@ export const parseEnvData = (_env = process.env) => {
100
139
  argParams: Object.assign(Object.assign({}, _argParams), stringNotEmptyOnly(value) && {
101
140
  [param]: value,
102
141
  }),
142
+ // NOTE: index 0 is the node binary and 1 the script path — never arguments, so neither
143
+ // reaches argEntries. That is what lets a caller forward `arg` without re-deriving which
144
+ // entries were real arguments.
145
+ argEntries: [
146
+ ..._argEntries,
147
+ ...(index >= 2) ? [{ arg, param, value }] : []
148
+ ],
103
149
  };
104
150
  }, {
105
151
  args: /** @type {string[]} */ ([]),
106
- argParams: /** @type {Record<string, string>} */ ({}),
152
+ // NOTE: `string | undefined` because the conditional spread below can widen it — seeding it
153
+ // as `Record<string, string>` made the accumulator and the callback's return disagree.
154
+ argParams: /** @type {Record<string, string | undefined>} */ ({}),
155
+ argEntries: /** @type {{ arg: string, param: string, value: string | undefined }[]} */ ([]),
107
156
  }), { argParams } = _b, output = __rest(_b, ["argParams"]);
108
157
  const nextEnv = cleanEnv(mergedEnv);
109
158
  const publicEnv = cleanPublicEnv(mergedEnv);
@@ -17,15 +17,17 @@ export const parseProjectName = (_name) => {
17
17
  * manifests, and the parser is deliberately tolerant of a missing or partial object.
18
18
  *
19
19
  * @typedef {object} PackageInfo
20
- * @property {string} [name]
20
+ * @property {string} [deployVersion]
21
+ * @property {string} [apiVersion]
21
22
  * @property {string} [version]
22
- * @property {string[]} [keywords]
23
+ * @property {string} [name]
23
24
  * @property {string} [owner]
24
25
  * @property {string} [appName]
25
26
  * @property {string} [siteName]
26
27
  * @property {string} [shortName]
27
28
  * @property {string} [siteHandle]
28
29
  * @property {string} [siteAuthor]
30
+ * @property {string[]} [keywords]
29
31
  * @property {Record<string, string>} [dependencies]
30
32
  * @property {Record<string, string>} [devDependencies]
31
33
  * @property {Record<string, string>} [peerDependencies]
@@ -34,19 +36,32 @@ export const parseProjectName = (_name) => {
34
36
  * @property {string[]} [bundledDependencies]
35
37
  * @property {string[]} [browserDependencies]
36
38
  */
37
- /** @param {PackageInfo} [packageInfo] */
39
+ /**
40
+ * Split a package.json into its resolved details, its organization and its full name.
41
+ *
42
+ * ⚠️ The return is declared as a TUPLE. An array literal infers as
43
+ * `(string | typeof packageDetails)[]`, so destructuring the first element would hand callers a
44
+ * union instead of the object.
45
+ *
46
+ * @param {PackageInfo} [packageInfo]
47
+ * @returns {[typeof packageDetails, string | undefined, string]}
48
+ */
38
49
  export const parsePackageInfo = (packageInfo) => {
39
- const { version, keywords, shortName, siteHandle, siteAuthor, devDependencies, peerDependencies, bundleDependencies, bundledDependencies = bundleDependencies, dependencies: runtimeDependencies, optionalDependencies, browserDependencies, name: _name, owner: _appOwner, appName: _appName, siteName: _siteName, } = packageInfo !== null && packageInfo !== void 0 ? packageInfo : {};
50
+ const { apiVersion, version, keywords, shortName, siteAuthor, siteHandle, devDependencies, peerDependencies, bundleDependencies, bundledDependencies = bundleDependencies, dependencies: runtimeDependencies, optionalDependencies, browserDependencies, name: _name, owner: _appOwner, appName: _appName, siteName: _siteName, deployVersion: _deployVersion, } = packageInfo !== null && packageInfo !== void 0 ? packageInfo : {};
40
51
  const { name, organization, projectName } = parseProjectName(_name);
52
+ // The deploy-time pin, when a manifest carries one. `version` stays the manifest's OWN value, so
53
+ // a caller can tell a real pin from the inert placeholder every workspace package declares.
54
+ const deployVersion = _deployVersion !== null && _deployVersion !== void 0 ? _deployVersion : apiVersion;
41
55
  const appName = _appName !== null && _appName !== void 0 ? _appName : projectName === null || projectName === void 0 ? void 0 : projectName.slice((projectName === null || projectName === void 0 ? void 0 : projectName.indexOf('-')) + 1);
42
56
  const siteName = _siteName !== null && _siteName !== void 0 ? _siteName : projectName === null || projectName === void 0 ? void 0 : projectName.slice((projectName === null || projectName === void 0 ? void 0 : projectName.indexOf('-')) + 1);
43
57
  const companyName = organization === null || organization === void 0 ? void 0 : organization.replace('@', '');
44
58
  const appOwner = _appOwner !== null && _appOwner !== void 0 ? _appOwner : companyName;
45
- const packageDetails = {
59
+ const packageDetails = Object.assign(Object.assign({}, deployVersion && {
60
+ deployVersion,
61
+ }), { version,
46
62
  keywords,
47
63
  appOwner,
48
64
  appName,
49
- version,
50
65
  siteName,
51
66
  shortName,
52
67
  siteHandle,
@@ -58,12 +73,6 @@ export const parsePackageInfo = (packageInfo) => {
58
73
  bundledDependencies,
59
74
  runtimeDependencies,
60
75
  browserDependencies,
61
- optionalDependencies,
62
- };
63
- // NOTE: declared as a tuple — an array literal infers as
64
- // (string | typeof packageDetails)[], so destructuring the first element
65
- // would hand callers a union instead of the object.
66
- /** @type {[typeof packageDetails, string | undefined, string]} */
67
- const packageParts = [packageDetails, organization, name];
68
- return packageParts;
76
+ optionalDependencies });
77
+ return [packageDetails, organization, name];
69
78
  };
package/dist/project.d.ts CHANGED
@@ -5,10 +5,10 @@ export function parseProjectName(_name: unknown): {
5
5
  projectName: string;
6
6
  };
7
7
  export function parsePackageInfo(packageInfo?: PackageInfo): [{
8
+ version: string | undefined;
8
9
  keywords: string[] | undefined;
9
10
  appOwner: string;
10
11
  appName: string;
11
- version: string | undefined;
12
12
  siteName: string;
13
13
  shortName: string | undefined;
14
14
  siteHandle: string | undefined;
@@ -21,21 +21,24 @@ export function parsePackageInfo(packageInfo?: PackageInfo): [{
21
21
  runtimeDependencies: Record<string, string> | undefined;
22
22
  browserDependencies: string[] | undefined;
23
23
  optionalDependencies: Record<string, string> | undefined;
24
+ deployVersion?: string | undefined;
24
25
  }, string | undefined, string];
25
26
  /**
26
27
  * The subset of a package.json this reads. Everything is optional — callers pass raw
27
28
  * manifests, and the parser is deliberately tolerant of a missing or partial object.
28
29
  */
29
30
  export type PackageInfo = {
30
- name?: string | undefined;
31
+ deployVersion?: string | undefined;
32
+ apiVersion?: string | undefined;
31
33
  version?: string | undefined;
32
- keywords?: string[] | undefined;
34
+ name?: string | undefined;
33
35
  owner?: string | undefined;
34
36
  appName?: string | undefined;
35
37
  siteName?: string | undefined;
36
38
  shortName?: string | undefined;
37
39
  siteHandle?: string | undefined;
38
40
  siteAuthor?: string | undefined;
41
+ keywords?: string[] | undefined;
39
42
  dependencies?: Record<string, string> | undefined;
40
43
  devDependencies?: Record<string, string> | undefined;
41
44
  peerDependencies?: Record<string, string> | undefined;
package/dist/project.js CHANGED
@@ -21,15 +21,17 @@ exports.parseProjectName = parseProjectName;
21
21
  * manifests, and the parser is deliberately tolerant of a missing or partial object.
22
22
  *
23
23
  * @typedef {object} PackageInfo
24
- * @property {string} [name]
24
+ * @property {string} [deployVersion]
25
+ * @property {string} [apiVersion]
25
26
  * @property {string} [version]
26
- * @property {string[]} [keywords]
27
+ * @property {string} [name]
27
28
  * @property {string} [owner]
28
29
  * @property {string} [appName]
29
30
  * @property {string} [siteName]
30
31
  * @property {string} [shortName]
31
32
  * @property {string} [siteHandle]
32
33
  * @property {string} [siteAuthor]
34
+ * @property {string[]} [keywords]
33
35
  * @property {Record<string, string>} [dependencies]
34
36
  * @property {Record<string, string>} [devDependencies]
35
37
  * @property {Record<string, string>} [peerDependencies]
@@ -38,19 +40,32 @@ exports.parseProjectName = parseProjectName;
38
40
  * @property {string[]} [bundledDependencies]
39
41
  * @property {string[]} [browserDependencies]
40
42
  */
41
- /** @param {PackageInfo} [packageInfo] */
43
+ /**
44
+ * Split a package.json into its resolved details, its organization and its full name.
45
+ *
46
+ * ⚠️ The return is declared as a TUPLE. An array literal infers as
47
+ * `(string | typeof packageDetails)[]`, so destructuring the first element would hand callers a
48
+ * union instead of the object.
49
+ *
50
+ * @param {PackageInfo} [packageInfo]
51
+ * @returns {[typeof packageDetails, string | undefined, string]}
52
+ */
42
53
  const parsePackageInfo = (packageInfo) => {
43
- const { version, keywords, shortName, siteHandle, siteAuthor, devDependencies, peerDependencies, bundleDependencies, bundledDependencies = bundleDependencies, dependencies: runtimeDependencies, optionalDependencies, browserDependencies, name: _name, owner: _appOwner, appName: _appName, siteName: _siteName, } = packageInfo !== null && packageInfo !== void 0 ? packageInfo : {};
54
+ const { apiVersion, version, keywords, shortName, siteAuthor, siteHandle, devDependencies, peerDependencies, bundleDependencies, bundledDependencies = bundleDependencies, dependencies: runtimeDependencies, optionalDependencies, browserDependencies, name: _name, owner: _appOwner, appName: _appName, siteName: _siteName, deployVersion: _deployVersion, } = packageInfo !== null && packageInfo !== void 0 ? packageInfo : {};
44
55
  const { name, organization, projectName } = (0, exports.parseProjectName)(_name);
56
+ // The deploy-time pin, when a manifest carries one. `version` stays the manifest's OWN value, so
57
+ // a caller can tell a real pin from the inert placeholder every workspace package declares.
58
+ const deployVersion = _deployVersion !== null && _deployVersion !== void 0 ? _deployVersion : apiVersion;
45
59
  const appName = _appName !== null && _appName !== void 0 ? _appName : projectName === null || projectName === void 0 ? void 0 : projectName.slice((projectName === null || projectName === void 0 ? void 0 : projectName.indexOf('-')) + 1);
46
60
  const siteName = _siteName !== null && _siteName !== void 0 ? _siteName : projectName === null || projectName === void 0 ? void 0 : projectName.slice((projectName === null || projectName === void 0 ? void 0 : projectName.indexOf('-')) + 1);
47
61
  const companyName = organization === null || organization === void 0 ? void 0 : organization.replace('@', '');
48
62
  const appOwner = _appOwner !== null && _appOwner !== void 0 ? _appOwner : companyName;
49
- const packageDetails = {
63
+ const packageDetails = Object.assign(Object.assign({}, deployVersion && {
64
+ deployVersion,
65
+ }), { version,
50
66
  keywords,
51
67
  appOwner,
52
68
  appName,
53
- version,
54
69
  siteName,
55
70
  shortName,
56
71
  siteHandle,
@@ -62,13 +77,7 @@ const parsePackageInfo = (packageInfo) => {
62
77
  bundledDependencies,
63
78
  runtimeDependencies,
64
79
  browserDependencies,
65
- optionalDependencies,
66
- };
67
- // NOTE: declared as a tuple — an array literal infers as
68
- // (string | typeof packageDetails)[], so destructuring the first element
69
- // would hand callers a union instead of the object.
70
- /** @type {[typeof packageDetails, string | undefined, string]} */
71
- const packageParts = [packageDetails, organization, name];
72
- return packageParts;
80
+ optionalDependencies });
81
+ return [packageDetails, organization, name];
73
82
  };
74
83
  exports.parsePackageInfo = parsePackageInfo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agnostack/env",
3
- "version": "2.0.0-canary.1",
3
+ "version": "2.0.0-canary.11",
4
4
  "author": "agnoStack Dev <developers@agnostack.com> (https://agnostack.com)",
5
5
  "owner": "agnoStack",
6
6
  "description": "Please contact agnoStack via info@agnostack.com for any questions",
@@ -39,21 +39,20 @@
39
39
  "node": ">=22.x"
40
40
  },
41
41
  "scripts": {
42
- "tsc": "npx -p typescript tsc",
43
- "watch": "yarn tsc -p tsconfig.build.json -w",
44
- "prebuild": "yarn tsc -b tsconfig.build.json --clean && node scripts/clean.mjs dist _storage",
45
- "build": "yarn tsc -p tsconfig.build.json && yarn tsc -p tsconfig.esm.json && node scripts/write-esm-pkg.mjs",
42
+ "watch": "tsc -p tsconfig.build.json -w",
43
+ "prebuild": "tsc -b tsconfig.build.json --clean && node scripts/clean.mjs dist _storage",
44
+ "build": "tsc -p tsconfig.build.json && tsc -p tsconfig.esm.json && node scripts/write-esm-pkg.mjs",
46
45
  "clean": "node scripts/clean.mjs dist node_modules _storage",
47
- "clean:install": "yarn clean && yarn install --force",
46
+ "clean:install": "pnpm clean && pnpm install --force",
48
47
  "lint:fix": "eslint . --fix",
49
48
  "lint": "eslint .",
50
- "typecheck": "yarn tsc",
49
+ "typecheck": "tsc --noEmit",
51
50
  "verify:dist": "node scripts/verify-dist.mjs",
52
51
  "test:watch": "vitest",
53
52
  "test": "vitest run",
54
53
  "release": "semantic-release",
55
- "release:debug": "yarn release --debug",
56
- "prepublishOnly": "yarn verify:dist",
54
+ "release:debug": "pnpm release --debug",
55
+ "prepublishOnly": "node scripts/verify-dist.mjs",
57
56
  "prepare": "husky"
58
57
  },
59
58
  "lint-staged": {
@@ -63,14 +62,11 @@
63
62
  },
64
63
  "sideEffects": false,
65
64
  "devDependencies": {
66
- "@commitlint/cli": "19.x",
67
- "@commitlint/config-conventional": "19.x",
65
+ "@commitlint/cli": "21.x",
66
+ "@commitlint/config-conventional": "21.x",
68
67
  "@eslint/js": "9.x",
69
- "@semantic-release/changelog": "6.0.3",
70
- "@semantic-release/git": "10.0.1",
71
- "@semantic-release/github": "11.x",
72
- "@semantic-release/npm": "12.x",
73
- "@semantic-release/release-notes-generator": "14.x",
68
+ "@semantic-release/changelog": "7.x",
69
+ "@semantic-release/git": "11.x",
74
70
  "@types/node": "22.x",
75
71
  "@typescript-eslint/eslint-plugin": "8.x",
76
72
  "@typescript-eslint/parser": "8.x",
@@ -78,13 +74,14 @@
78
74
  "eslint-plugin-import": "2.x",
79
75
  "globals": "16.x",
80
76
  "husky": "9.x",
81
- "lint-staged": "15.x",
77
+ "lint-staged": "17.x",
82
78
  "semantic-release": "25.x",
83
- "typescript": "5.9.3",
84
- "vitest": "3.x"
79
+ "semantic-release-export-data": "1.x",
80
+ "typescript": "5.x",
81
+ "vitest": "4.x"
85
82
  },
86
83
  "publishConfig": {
87
84
  "access": "public"
88
85
  },
89
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
86
+ "packageManager": "pnpm@9.15.4"
90
87
  }