Skip to content

Commit 43e3168

Browse files
authoredOct 8, 2024
devEngines proposal (#27)
1 parent d6e3f2b commit 43e3168

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed
 

‎devengines-field-proposal.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Proposal: `package.json` `devEngines` Field
2+
3+
This is a specification a `package.json` field to define the runtime and package manager for _developing_ a project or package (_not_ consuming/installing it as a dependency in another project). The field is named `devEngines` and is a new top-level field defined with this schema:
4+
5+
```typescript
6+
interface DevEngines {
7+
os?: DevEngineDependency | DevEngineDependency[];
8+
cpu?: DevEngineDependency | DevEngineDependency[];
9+
libc?: DevEngineDependency | DevEngineDependency[];
10+
runtime?: DevEngineDependency | DevEngineDependency[];
11+
packageManager?: DevEngineDependency | DevEngineDependency[];
12+
}
13+
14+
interface DevEngineDependency {
15+
name: string;
16+
version?: string;
17+
onFail?: 'ignore' | 'warn' | 'error' | 'download';
18+
}
19+
```
20+
21+
The `os`, `cpu`, `libc`, `runtime`, and `packageManager` sub-fields could either be an object or an array of objects, if the user wants to define multiple acceptable OSes, CPUs, C compilers, runtimes or package managers. The first acceptable option would be used, and `onFail` would be triggered for the last defined option if none validate. If unspecified, `onFail` defaults to `error` for the non-array notation; or it defaults to `error` for the last element in the array and `ignore` for all prior elements, for the array notation. Validation would check the name and version ranges.
22+
23+
The `name` field would be a string, corresponding to different sources depending on the parent field:
24+
25+
- `os`: [NPM docs for `engines.os`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#os).
26+
- `cpu`: [NPM docs for `engines.cpu`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#cpu).
27+
- `libc`: `glibc` or `musl`; see [NPM docs for `config.libc`](https://docs.npmjs.com/cli/v10/using-npm/config#libc).
28+
- `runtime`: [WinterCG Runtime Keys](https://runtime-keys.proposal.wintercg.org/).
29+
- `packageManager` . . . I don’t know, we could define the list as part of the spec, or perhaps it would need to correspond to an npm registry package name. Suggestions welcome.
30+
31+
The `version` field syntax would match that defined for [`engines.node`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines), so something like `">= 16.0.0 < 22"` or `">= 20"`. If unspecified, any version matches.
32+
33+
The `onFail` field defines what should happen if validation fails:
34+
35+
- `ignore`: nothing.
36+
- `warn`: print something and continue.
37+
- `error`: print something and exit.
38+
- `download`: remediate the validation failure by downloading the requested tool/version.
39+
40+
In the event of `onFail: 'download'`, it would be the responsibility of the tool to determine what and how to download, perhaps by looking in the tool’s associated lockfile for a specific version and integrity hash. It could also be supported on a case-by-case basis, like perhaps Yarn and pnpm could support downloading a satisfactory version while npm would error.
41+
42+
## Examples
43+
44+
### Typical example
45+
46+
```json
47+
"devEngines": {
48+
"runtime": {
49+
"name": "node",
50+
"version": ">= 20.0.0",
51+
"onFail": "error"
52+
},
53+
"packageManager": {
54+
"name": "yarn",
55+
"version": "3.2.3",
56+
"onFail": "download"
57+
}
58+
}
59+
```
60+
61+
### “Uses every possible field” example:
62+
63+
```json
64+
"devEngines": {
65+
"os": {
66+
"name": "darwin",
67+
"version": ">= 23.0.0"
68+
},
69+
"cpu": [
70+
{
71+
"name": "arm"
72+
}, {
73+
"name": "x86"
74+
}
75+
],
76+
"libc": {
77+
"name": "glibc"
78+
},
79+
"runtime": [
80+
{
81+
"name": "bun",
82+
"version": ">= 1.0.0",
83+
"onFail": "ignore"
84+
},
85+
{
86+
"name": "node",
87+
"version": ">= 20.0.0",
88+
"onFail": "error"
89+
},
90+
],
91+
"packageManager": [
92+
{
93+
"name": "bun",
94+
"version": ">= 1.0.0",
95+
"onFail": "ignore"
96+
},
97+
{
98+
"name": "yarn",
99+
"version": "3.2.3",
100+
"onFail": "download"
101+
}
102+
]
103+
}
104+
```
105+
106+
## Future Expansions
107+
108+
Some potential future expansions of this spec that have been discussed are:
109+
110+
- `runtime` and `packageManager` might take shorthand string values defining the desired name or name with version/version range.
111+
112+
## References
113+
114+
- Inspiration: https://github.com/nodejs/node/issues/51888#issuecomment-1967102442
115+
116+
- Initial discussion: https://github.com/openjs-foundation/package-metadata-interoperability-collab-space/issues/15
117+
118+
## Implementations
119+
120+
- https://github.com/npm/npm-install-checks/pull/116
121+
122+
- https://github.com/npm/cli/pull/7766

0 commit comments

Comments
 (0)