@graftland/package-manager 0.1.0 → 0.2.0-beta.1
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/README.md +237 -4
- package/README.zh-CN.md +183 -0
- package/README.zh-TW.md +184 -0
- package/dist/PackageManagerDeclaration.d.ts +6 -0
- package/dist/PackageManagerDeclaration.d.ts.map +1 -0
- package/dist/PackageManagerDeclaration.js +24 -0
- package/dist/PackageManagerDeclaration.js.map +1 -0
- package/dist/index.d.ts +46 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +177 -53
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +128 -19
- package/dist/manifest.js.map +1 -1
- package/dist/process.js +50 -0
- package/dist/process.js.map +1 -0
- package/dist/snapshot.d.ts +15 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +104 -0
- package/dist/snapshot.js.map +1 -0
- package/package.json +9 -3
- package/src/PackageManagerDeclaration.ts +42 -0
- package/src/index.ts +413 -131
- package/src/manifest.ts +231 -27
- package/src/process.ts +122 -0
- package/src/snapshot.ts +261 -0
package/README.md
CHANGED
|
@@ -1,14 +1,229 @@
|
|
|
1
1
|
# @graftland/package-manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
English |
|
|
4
|
+
[简体中文](https://github.com/graftland/graft/blob/main/packages/package-manager/README.zh-CN.md)
|
|
5
|
+
|
|
|
6
|
+
[繁體中文](https://github.com/graftland/graft/blob/main/packages/package-manager/README.zh-TW.md)
|
|
7
|
+
|
|
8
|
+
Installs dependencies with npm, pnpm, or Yarn, and rolls back on failure.
|
|
9
|
+
|
|
10
|
+
The minimum supported Node.js version is 22.19. Windows is provided as is.
|
|
11
|
+
Process-tree cleanup and rollback on Windows are not verified, and they are not
|
|
12
|
+
promised.
|
|
4
13
|
|
|
5
14
|
```sh
|
|
6
15
|
npm install @graftland/package-manager effect
|
|
7
16
|
```
|
|
8
17
|
|
|
9
|
-
`make` detects the project's package manager. Its `install` adds, updates or
|
|
10
|
-
removes dependencies,
|
|
11
|
-
|
|
18
|
+
`make` detects the project's package manager. Its `install` adds, updates, or
|
|
19
|
+
removes dependencies. If the install fails, it restores `package.json` and the
|
|
20
|
+
lockfile. `graft add` and `graft remove` use it.
|
|
21
|
+
|
|
22
|
+
## Installation ownership and recovery
|
|
23
|
+
|
|
24
|
+
Use one manager per project. The caller must give the manager and its child
|
|
25
|
+
processes exclusive write access to the project. This lasts from the start of an
|
|
26
|
+
`install` call until it finishes, including recovery.
|
|
27
|
+
|
|
28
|
+
- Do not edit project files during this time.
|
|
29
|
+
- Do not run another installer at the same time.
|
|
30
|
+
- Calls are serialized within one manager. Graft does not enforce a lock across
|
|
31
|
+
managers, editors, or processes.
|
|
32
|
+
|
|
33
|
+
On POSIX, process cleanup covers only the installer's original process group.
|
|
34
|
+
Installation scripts and recovery scripts must not create unmanaged writers.
|
|
35
|
+
Examples are children in independent process groups, and daemons that keep
|
|
36
|
+
writing project files. Graft does not provide OS-level containment. It does not
|
|
37
|
+
discover escaped writers. Confirming that the original group has stopped does
|
|
38
|
+
not prove that every possible descendant has stopped. Scripts that break this
|
|
39
|
+
rule are outside the rollback guarantee.
|
|
40
|
+
|
|
41
|
+
Managed paths must be regular files, or must be absent. `make` and each
|
|
42
|
+
`install` use `lstat` to check the snapshot set. The snapshot set is
|
|
43
|
+
`package.json`, lockfiles, and tracked configuration and installation-state
|
|
44
|
+
files.
|
|
45
|
+
|
|
46
|
+
- Symbolic links are rejected, including dangling links. Other file types are
|
|
47
|
+
rejected too.
|
|
48
|
+
- The error is `UnsupportedFileTypeError`. It is raised before any transaction
|
|
49
|
+
write and before any installer starts.
|
|
50
|
+
- The error shows the `path` and the `fileType`. The link and its target stay
|
|
51
|
+
unchanged.
|
|
52
|
+
- A rejection before the transaction begins does not need recovery. It does not
|
|
53
|
+
make the manager unusable.
|
|
54
|
+
|
|
55
|
+
### Rollback
|
|
56
|
+
|
|
57
|
+
Rollback runs when installation fails or is interrupted before commit. It needs
|
|
58
|
+
confirmation that the original process group has stopped. Then it does these
|
|
59
|
+
things:
|
|
60
|
+
|
|
61
|
+
- It restores the backed-up package files byte for byte. It keeps their recorded
|
|
62
|
+
permission bits and ownership.
|
|
63
|
+
- It removes tracked files that were absent before installation.
|
|
64
|
+
|
|
65
|
+
The tracked files include `package.json`, lockfiles, and the package-manager
|
|
66
|
+
configuration and installation-state files that the manager tracks.
|
|
67
|
+
|
|
68
|
+
Rollback overwrites changes made during installation. It does not detect
|
|
69
|
+
conflicts. It does not merge edits.
|
|
70
|
+
|
|
71
|
+
When the project already had a lockfile for the selected package manager,
|
|
72
|
+
recovery also tries to repair `node_modules`. Recovery errors are kept together
|
|
73
|
+
with the original failure. Recovery after a process crash is not promised.
|
|
74
|
+
|
|
75
|
+
### File writes and process cleanup
|
|
76
|
+
|
|
77
|
+
Accepted file writes have a completion boundary. Cancellation waits for the
|
|
78
|
+
native operation to finish. This happens before rollback, before snapshot
|
|
79
|
+
cleanup, and before the manager's lock is released. The transaction tracks its
|
|
80
|
+
own file writes and the original installer group. Snapshot creation and rollback
|
|
81
|
+
writes have the same completion guarantee.
|
|
82
|
+
|
|
83
|
+
Each installer process and each recovery process has a ten-minute exit wait.
|
|
84
|
+
Cancellation or expiry closes its process scope before files are restored.
|
|
85
|
+
|
|
86
|
+
- The process receives SIGTERM.
|
|
87
|
+
- If it has not stopped after five seconds, it receives SIGKILL.
|
|
88
|
+
- On POSIX, even a successful kill must be followed by evidence that the
|
|
89
|
+
original process group no longer exists. Checks run every 20 milliseconds,
|
|
90
|
+
with at most 100 additional checks (two seconds of waiting) for short-lived
|
|
91
|
+
zombie groups to be reaped. EPERM is treated as continued presence, never as
|
|
92
|
+
absence.
|
|
93
|
+
- If the group remains or a check fails, termination is unconfirmed: the manager
|
|
94
|
+
keeps its snapshot, skips rollback and recovery, and enters
|
|
95
|
+
`RecoveryRequired`.
|
|
96
|
+
- Process cleanup failures stay in the returned cause, together with
|
|
97
|
+
installation and recovery failures.
|
|
98
|
+
- The exit timeout does not include process cleanup or file restoration. It is
|
|
99
|
+
not a deadline for the whole install-and-recover operation.
|
|
100
|
+
|
|
101
|
+
The Node adapter may replace the original OS errno with a generic kill failure.
|
|
102
|
+
Only after a POSIX group check confirms absence does PackageManager resolve
|
|
103
|
+
signal failures carrying ESRCH or the adapter's specific `Unknown` kill error
|
|
104
|
+
with cause `Failed to kill child process`. This does not resolve other reasons
|
|
105
|
+
in the same Cause: join failures, other kill errors, defects, and interruption
|
|
106
|
+
remain failures. If the group still exists, the original Cause is preserved; if
|
|
107
|
+
the group check fails, both complete Causes are retained.
|
|
108
|
+
|
|
109
|
+
## Committed installs and snapshot cleanup
|
|
110
|
+
|
|
111
|
+
A successful `install` result means the dependency changes are committed.
|
|
112
|
+
|
|
113
|
+
`result.snapshotCleanupFailure` is an `Option<SnapshotCleanupFailure>`:
|
|
114
|
+
|
|
115
|
+
- `None` means snapshot deletion succeeded.
|
|
116
|
+
- `Some` contains `snapshotDirectory` and the complete cleanup `cause`,
|
|
117
|
+
including defects.
|
|
118
|
+
|
|
119
|
+
A failure to delete the snapshot after commit does not turn the install into a
|
|
120
|
+
failure. It does not trigger rollback. The manager stays usable, and
|
|
121
|
+
`recoveryRequired` stays `None`.
|
|
122
|
+
|
|
123
|
+
What callers should do:
|
|
124
|
+
|
|
125
|
+
- Inspect this field. Report or record its Cause.
|
|
126
|
+
- Retry the deletion of that snapshot directory after the filesystem problem is
|
|
127
|
+
fixed. The directory may be partly removed.
|
|
128
|
+
- Do not restore the old snapshot. Do not repeat the install only because
|
|
129
|
+
snapshot deletion failed. Those changes are already committed.
|
|
130
|
+
- The kept data may contain credentials, so make sure it is removed in the end.
|
|
131
|
+
|
|
132
|
+
Failures before commit still fail the operation and run rollback. Any snapshot
|
|
133
|
+
cleanup failure is combined with the original failure.
|
|
134
|
+
|
|
135
|
+
Cancellation can stop a result from being delivered after commit. It is not
|
|
136
|
+
proof that the changes were undone. In that case, cleanup failures are kept in
|
|
137
|
+
the interrupted Cause.
|
|
138
|
+
|
|
139
|
+
## When manual recovery is required
|
|
140
|
+
|
|
141
|
+
Before an install changes project files, it saves a snapshot. The snapshot is in
|
|
142
|
+
a private `graft-recovery-*` directory in the OS temporary directory.
|
|
143
|
+
|
|
144
|
+
- Only a successful install or a complete rollback allows the snapshot to be
|
|
145
|
+
deleted and another install to run.
|
|
146
|
+
- A committed install with a failed snapshot deletion is reported as described
|
|
147
|
+
above.
|
|
148
|
+
- Process termination and transaction completion are separate conditions.
|
|
149
|
+
Stopping the writer lets rollback begin. It does not prove that rollback
|
|
150
|
+
succeeded.
|
|
151
|
+
|
|
152
|
+
If any rollback step fails, the manager keeps the snapshot and needs manual
|
|
153
|
+
recovery. This includes restoring files before or after recovery, and running
|
|
154
|
+
the recovery installer. It applies even when the final file restoration
|
|
155
|
+
succeeds, because failed recovery may have left `node_modules` incomplete.
|
|
156
|
+
|
|
157
|
+
How the manager restores a file:
|
|
158
|
+
|
|
159
|
+
1. It creates a temporary file in the target directory, exclusively and with
|
|
160
|
+
mode `0600`.
|
|
161
|
+
2. It restores the saved uid/gid when the platform reports them. Then it
|
|
162
|
+
restores the permission bits.
|
|
163
|
+
3. It syncs and closes the file.
|
|
164
|
+
4. It renames the file over the target.
|
|
165
|
+
|
|
166
|
+
Metadata failures and temporary-file cleanup failures also need manual recovery.
|
|
167
|
+
They stay in the Cause. Timestamps, ACLs, and extended attributes are not
|
|
168
|
+
recorded.
|
|
169
|
+
|
|
170
|
+
If process termination cannot be confirmed, no further restoration or recovery
|
|
171
|
+
runs. This avoids a conflict with a process that may still be writing.
|
|
172
|
+
|
|
173
|
+
### The recovery error
|
|
174
|
+
|
|
175
|
+
The Cause of the failed call keeps the original failure and all rollback and
|
|
176
|
+
termination failures. It includes a `RecoveryRequiredError`, which has these
|
|
177
|
+
fields:
|
|
178
|
+
|
|
179
|
+
- `snapshotDirectory` gives the saved location.
|
|
180
|
+
- `directory` identifies the project.
|
|
181
|
+
- `recoveryCause` keeps the complete original and recovery Cause.
|
|
182
|
+
- `operation` is `rollback` for an incomplete rollback with stopped writers. For
|
|
183
|
+
unconfirmed termination, it is `install` or `recover`. In that case,
|
|
184
|
+
`processId` and `terminationCause` give the process details.
|
|
185
|
+
|
|
186
|
+
After cancellation, callers can also read `manager.recoveryRequired`. It is an
|
|
187
|
+
Effect that yields `Option<RecoveryRequiredError>`. Callers do not need to catch
|
|
188
|
+
an interrupted call.
|
|
189
|
+
|
|
190
|
+
The manager rejects all later `install` calls for good, with this typed error.
|
|
191
|
+
This includes calls that are already queued and calls with empty change sets.
|
|
192
|
+
`readState` stays a read-only diagnostic operation. It may fail while project
|
|
193
|
+
files are incomplete.
|
|
194
|
+
|
|
195
|
+
### Steps to recover manually
|
|
196
|
+
|
|
197
|
+
1. Identify the failed installer and all of its descendants, and stop them. The
|
|
198
|
+
recorded process ID is for diagnosis only. It does not prove that a later
|
|
199
|
+
process with the same ID belongs to the installation. Do not restore files or
|
|
200
|
+
start another installer until all writers have stopped.
|
|
201
|
+
2. Fix the filesystem problem that stopped the restoration, such as file
|
|
202
|
+
permissions. Then restore the files:
|
|
203
|
+
- Open `snapshot.json` in `snapshotDirectory`. Check its project `directory`
|
|
204
|
+
and `agent`.
|
|
205
|
+
- For each `files` entry, copy the bytes from the named `backup` into a
|
|
206
|
+
temporary file beside the project's `name`. Create the temporary file
|
|
207
|
+
privately and exclusively.
|
|
208
|
+
- Restore the recorded `uid` and `gid` when they are not null. Then restore
|
|
209
|
+
`mode`. Do this before you replace the target.
|
|
210
|
+
- These metadata values are JSON integers. `mode` is the numeric permission
|
|
211
|
+
bitmask, not an octal-formatted string.
|
|
212
|
+
- Create parent directories as needed.
|
|
213
|
+
- A null `backup` means that the file was absent. Remove it if it exists now.
|
|
214
|
+
3. Repair `node_modules` with the selected package manager. Use the restored
|
|
215
|
+
manifest and lockfile. After that process has stopped, restore the snapshot
|
|
216
|
+
files again if it rewrote them. The snapshot does not contain `node_modules`.
|
|
217
|
+
4. Verify the project. Then delete the snapshot and create a new manager with
|
|
218
|
+
`make`. The old manager has no reset operation.
|
|
219
|
+
|
|
220
|
+
Snapshots can contain credentials from package-manager configuration files. Keep
|
|
221
|
+
them private. They survive the closing of the manager and of the Effect scope.
|
|
222
|
+
But the OS may clean temporary directories. If manual recovery will be delayed,
|
|
223
|
+
copy a kept snapshot to a safe, private place.
|
|
224
|
+
|
|
225
|
+
This mechanism is not crash recovery. It is not a project lock across processes.
|
|
226
|
+
Creating a new manager does not make a still-live installer safe.
|
|
12
227
|
|
|
13
228
|
## Documentation
|
|
14
229
|
|
|
@@ -16,3 +231,21 @@ fails. `graft add` and `graft remove` use it.
|
|
|
16
231
|
|
|
17
232
|
Part of [Graft](https://github.com/graftland/graft). Licensed under
|
|
18
233
|
[Apache 2.0](https://github.com/graftland/graft/blob/main/LICENSE).
|
|
234
|
+
|
|
235
|
+
## Package manager declarations
|
|
236
|
+
|
|
237
|
+
The shared `PackageManagerDeclaration` Schema accepts `npm`, `pnpm`, or `yarn`
|
|
238
|
+
followed by an exact SemVer version (at most 256 characters), including optional
|
|
239
|
+
prerelease identifiers. It rejects empty suffixes, leading zeros in numeric
|
|
240
|
+
version/prerelease components, ranges, tags, URLs, and surrounding whitespace. A
|
|
241
|
+
`+` suffix is reserved for a
|
|
242
|
+
[Corepack hash](https://github.com/nodejs/corepack#when-authoring-packages):
|
|
243
|
+
`sha224`, `sha256`, `sha384`, or `sha512`, followed by a dot and exactly 56, 64,
|
|
244
|
+
96, or 128 lowercase hexadecimal characters respectively. Arbitrary SemVer build
|
|
245
|
+
metadata is not supported here. Hash validation checks the declaration's syntax;
|
|
246
|
+
it does not download or authenticate the package-manager archive.
|
|
247
|
+
|
|
248
|
+
Both project creation and package-manager detection use this Schema, exported
|
|
249
|
+
from `@graftland/package-manager/PackageManagerDeclaration`. Creation preserves
|
|
250
|
+
the supplied declaration verbatim. An explicit detection `agent` still overrides
|
|
251
|
+
the manifest declaration.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# @graftland/package-manager
|
|
2
|
+
|
|
3
|
+
[English](https://github.com/graftland/graft/blob/main/packages/package-manager/README.md)
|
|
4
|
+
| 简体中文 |
|
|
5
|
+
[繁體中文](https://github.com/graftland/graft/blob/main/packages/package-manager/README.zh-TW.md)
|
|
6
|
+
|
|
7
|
+
使用 npm、pnpm 或 Yarn 安装依赖,并在失败时回滚。
|
|
8
|
+
|
|
9
|
+
支持的最低 Node.js 版本是 22.19。Windows 按现状提供。Windows 上的进程树清理和回滚没有经过验证,也不作承诺。
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @graftland/package-manager effect
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`make` 会检测项目所用的包管理器。它的 `install`
|
|
16
|
+
可以添加、更新或移除依赖。如果安装失败,它会恢复 `package.json`
|
|
17
|
+
和锁文件。`graft add` 和 `graft remove` 使用它。
|
|
18
|
+
|
|
19
|
+
## 安装的所有权与恢复
|
|
20
|
+
|
|
21
|
+
每个项目只使用一个管理器。调用方必须让管理器及其子进程独占项目的写入权限。这从一次
|
|
22
|
+
`install` 调用开始,持续到它结束,包括恢复阶段。
|
|
23
|
+
|
|
24
|
+
- 在此期间,不要编辑项目文件。
|
|
25
|
+
- 不要同时运行另一个安装程序。
|
|
26
|
+
- 同一个管理器内的调用是串行的。Graft 不会在多个管理器、编辑器或进程之间强制加锁。
|
|
27
|
+
|
|
28
|
+
在 POSIX 上,进程清理只覆盖安装程序最初的进程组。安装脚本和恢复脚本不得创建不受管理的写入者。例如,处于独立进程组的子进程,以及持续写入项目文件的守护进程。Graft 不提供操作系统级别的隔离,也不会发现逃逸的写入者。确认最初的进程组已经停止,并不能证明所有可能的后代都已经停止。违反这条规则的脚本不在回滚保证的范围内。
|
|
29
|
+
|
|
30
|
+
受管理的路径必须是普通文件,或者不存在。`make` 和每次 `install` 都使用 `lstat`
|
|
31
|
+
检查快照集合。快照集合包括
|
|
32
|
+
`package.json`、锁文件,以及被跟踪的配置文件和安装状态文件。
|
|
33
|
+
|
|
34
|
+
- 符号链接会被拒绝,包括悬空链接。其他文件类型也会被拒绝。
|
|
35
|
+
- 错误是
|
|
36
|
+
`UnsupportedFileTypeError`。它在任何事务写入之前、任何安装程序启动之前抛出。
|
|
37
|
+
- 错误会给出 `path` 和 `fileType`。链接及其目标保持不变。
|
|
38
|
+
- 在事务开始之前的拒绝,不需要恢复,也不会让管理器不可用。
|
|
39
|
+
|
|
40
|
+
### 回滚
|
|
41
|
+
|
|
42
|
+
当安装在提交之前失败或被中断时,会执行回滚。回滚需要先确认最初的进程组已经停止。然后它会做这些事:
|
|
43
|
+
|
|
44
|
+
- 把已备份的包文件逐字节恢复,并保留它们记录下来的权限位和所有者。
|
|
45
|
+
- 移除安装之前不存在的被跟踪文件。
|
|
46
|
+
|
|
47
|
+
被跟踪的文件包括
|
|
48
|
+
`package.json`、锁文件,以及管理器所跟踪的包管理器配置文件和安装状态文件。
|
|
49
|
+
|
|
50
|
+
回滚会覆盖安装期间所做的更改。它不会检测冲突,也不会合并编辑。
|
|
51
|
+
|
|
52
|
+
如果项目已经有所选包管理器的锁文件,恢复阶段还会尝试修复
|
|
53
|
+
`node_modules`。恢复错误会与原始失败一起保留。不承诺在进程崩溃之后恢复。
|
|
54
|
+
|
|
55
|
+
### 文件写入与进程清理
|
|
56
|
+
|
|
57
|
+
已接受的文件写入有一个完成边界。取消会等待原生操作完成,然后才进行回滚、清理快照,以及释放管理器的锁。事务会跟踪它自己的文件写入以及最初的安装程序进程组。创建快照和回滚写入也有同样的完成保证。
|
|
58
|
+
|
|
59
|
+
每个安装进程和每个恢复进程都有十分钟的退出等待时间。取消或超时会在恢复文件之前关闭它的进程 scope。
|
|
60
|
+
|
|
61
|
+
- 进程会收到 SIGTERM。
|
|
62
|
+
- 如果五秒后它还没有停止,就会收到 SIGKILL。
|
|
63
|
+
- 在 POSIX 上,即使 kill 成功,也必须确认原进程组已不存在。每 20 毫秒检查一次,最多追加 100 次检查(等待两秒),给短暂残留的僵尸进程组留出回收窗口。EPERM 视为仍然存在,不视为已消失。
|
|
64
|
+
- 如果进程组仍存在或检查失败,则终止未获确认:管理器保留快照,不执行回滚和恢复安装,并进入
|
|
65
|
+
`RecoveryRequired`。
|
|
66
|
+
- 进程清理失败会与安装和恢复的失败一起保留在返回的 cause 中。
|
|
67
|
+
- 退出超时不包括进程清理和文件恢复,也不是整个“安装并恢复”操作的截止时间。
|
|
68
|
+
|
|
69
|
+
Node 适配器可能会把原始的操作系统 errno 替换为通用的 kill 失败。只有 POSIX 检查确认进程组不存在后,PackageManager 才消解携带 ESRCH 的信号失败,或适配器特定的
|
|
70
|
+
`Unknown` kill 错误(cause 为
|
|
71
|
+
`Failed to kill child process`)。同一 Cause 中的其他原因仍然保留,包括 join 失败、其他 kill 错误、defect 和中断。进程组仍存在时保留原始 Cause;检查失败时保留两个完整 Cause。
|
|
72
|
+
|
|
73
|
+
## 已提交的安装与快照清理
|
|
74
|
+
|
|
75
|
+
`install` 成功的结果表示依赖更改已经提交。
|
|
76
|
+
|
|
77
|
+
`result.snapshotCleanupFailure` 是 `Option<SnapshotCleanupFailure>`:
|
|
78
|
+
|
|
79
|
+
- `None` 表示快照删除成功。
|
|
80
|
+
- `Some` 包含 `snapshotDirectory` 和完整的清理 `cause`,包括 defect。
|
|
81
|
+
|
|
82
|
+
提交之后删除快照失败,不会让这次安装变成失败,也不会触发回滚。管理器仍然可用,`recoveryRequired`
|
|
83
|
+
仍然是 `None`。
|
|
84
|
+
|
|
85
|
+
调用方应该这样做:
|
|
86
|
+
|
|
87
|
+
- 检查这个字段,报告或记录它的 Cause。
|
|
88
|
+
- 在文件系统问题解决之后,重试删除该快照目录。该目录可能已被部分删除。
|
|
89
|
+
- 不要恢复旧的快照,也不要仅仅因为快照删除失败就重复安装。那些更改已经提交了。
|
|
90
|
+
- 保留下来的数据可能包含凭据,所以要确保它最终被删除。
|
|
91
|
+
|
|
92
|
+
提交之前的失败仍然会使操作失败并执行回滚。任何快照清理失败都会与原始失败合并。
|
|
93
|
+
|
|
94
|
+
取消可能会使提交之后的结果无法送达。这并不能证明更改已被撤销。这种情况下,清理失败会保留在被中断的 Cause 中。
|
|
95
|
+
|
|
96
|
+
## 何时需要手动恢复
|
|
97
|
+
|
|
98
|
+
在安装更改项目文件之前,会先保存一份快照。快照位于操作系统临时目录中一个私有的
|
|
99
|
+
`graft-recovery-*` 目录里。
|
|
100
|
+
|
|
101
|
+
- 只有成功的安装或完整的回滚,才允许删除快照并运行下一次安装。
|
|
102
|
+
- 已提交但快照删除失败的安装,按上文所述报告。
|
|
103
|
+
- 进程终止和事务完成是两个独立的条件。停止写入者,回滚才能开始,但这并不证明回滚成功。
|
|
104
|
+
|
|
105
|
+
只要有任何一个回滚步骤失败,管理器就会保留快照,并需要手动恢复。这包括在恢复之前或之后恢复文件,以及运行恢复安装程序。即使最后的文件恢复成功,这条规则也适用,因为失败的恢复可能让
|
|
106
|
+
`node_modules` 不完整。
|
|
107
|
+
|
|
108
|
+
管理器如何恢复一个文件:
|
|
109
|
+
|
|
110
|
+
1. 在目标目录中以独占方式创建临时文件,模式为 `0600`。
|
|
111
|
+
2. 当平台报告了保存的 uid/gid 时,先恢复它们,然后恢复权限位。
|
|
112
|
+
3. 对文件执行 sync 并关闭。
|
|
113
|
+
4. 把该文件重命名覆盖到目标上。
|
|
114
|
+
|
|
115
|
+
元数据失败和临时文件清理失败同样需要手动恢复,并保留在 Cause 中。时间戳、ACL 和扩展属性不会被记录。
|
|
116
|
+
|
|
117
|
+
如果无法确认进程已经终止,就不会再进行任何恢复。这是为了避免与可能仍在写入的进程发生冲突。
|
|
118
|
+
|
|
119
|
+
### 恢复错误
|
|
120
|
+
|
|
121
|
+
失败调用的 Cause 会保留原始失败以及所有回滚和终止的失败。它包含一个
|
|
122
|
+
`RecoveryRequiredError`,其字段如下:
|
|
123
|
+
|
|
124
|
+
- `snapshotDirectory` 给出保存的位置。
|
|
125
|
+
- `directory` 标识项目。
|
|
126
|
+
- `recoveryCause` 保留完整的原始 Cause 和恢复 Cause。
|
|
127
|
+
- `operation`:在写入者已停止但回滚不完整时是 `rollback`;在无法确认终止时是
|
|
128
|
+
`install` 或 `recover`,此时 `processId` 和 `terminationCause`
|
|
129
|
+
给出进程的详细信息。
|
|
130
|
+
|
|
131
|
+
取消之后,调用方还可以读取 `manager.recoveryRequired`。它是一个产出
|
|
132
|
+
`Option<RecoveryRequiredError>` 的 Effect。调用方不需要去捕获被中断的调用。
|
|
133
|
+
|
|
134
|
+
管理器会永久拒绝之后所有的 `install`
|
|
135
|
+
调用,并返回这个带类型的错误。这包括已经排队的调用,以及变更集为空的调用。`readState`
|
|
136
|
+
仍然是只读的诊断操作。在项目文件不完整时,它可能失败。
|
|
137
|
+
|
|
138
|
+
### 手动恢复的步骤
|
|
139
|
+
|
|
140
|
+
1. 找出失败的安装程序及其所有后代,并停止它们。记录下来的进程 ID 只用于诊断,不能证明之后具有相同 ID 的进程属于这次安装。在所有写入者停止之前,不要恢复文件,也不要启动另一个安装程序。
|
|
141
|
+
2. 解决阻止恢复的文件系统问题,例如文件权限。然后恢复文件:
|
|
142
|
+
- 打开 `snapshotDirectory` 中的 `snapshot.json`。检查其中的项目 `directory`
|
|
143
|
+
和 `agent`。
|
|
144
|
+
- 对每个 `files` 条目,把指定的 `backup` 中的字节复制到项目 `name`
|
|
145
|
+
旁边的临时文件中。以私有、独占的方式创建该临时文件。
|
|
146
|
+
- 当 `uid` 和 `gid` 不为 null 时,恢复记录下来的值,然后恢复
|
|
147
|
+
`mode`。请在替换目标之前完成这些。
|
|
148
|
+
- 这些元数据值是 JSON 整数。`mode`
|
|
149
|
+
是数值形式的权限位掩码,不是八进制格式的字符串。
|
|
150
|
+
- 按需创建父目录。
|
|
151
|
+
- `backup` 为 null 表示该文件原本不存在。如果它现在存在,就删除它。
|
|
152
|
+
3. 使用所选的包管理器,基于已恢复的清单文件和锁文件修复
|
|
153
|
+
`node_modules`。该进程停止之后,如果它重写了快照中的文件,请再次恢复这些文件。快照不包含
|
|
154
|
+
`node_modules`。
|
|
155
|
+
4. 验证项目。然后删除快照,并用 `make`
|
|
156
|
+
创建一个新的管理器。旧的管理器没有重置操作。
|
|
157
|
+
|
|
158
|
+
快照可能包含来自包管理器配置文件的凭据。请保持私有。它们在管理器和 Effect
|
|
159
|
+
scope 关闭之后依然存在。但是操作系统可能会清理临时目录。如果手动恢复会被推迟,请把保留的快照复制到一个安全的私有位置。
|
|
160
|
+
|
|
161
|
+
这个机制不是崩溃恢复,也不是跨进程的项目锁。创建新的管理器,并不会让仍在运行的安装程序变得安全。
|
|
162
|
+
|
|
163
|
+
## 文档
|
|
164
|
+
|
|
165
|
+
- [命令行](https://graftland.github.io/graft/zh-cn/cli/)
|
|
166
|
+
|
|
167
|
+
属于 [Graft](https://github.com/graftland/graft)。基于
|
|
168
|
+
[Apache 2.0](https://github.com/graftland/graft/blob/main/LICENSE) 许可。
|
|
169
|
+
|
|
170
|
+
## 包管理器声明
|
|
171
|
+
|
|
172
|
+
共享的 `PackageManagerDeclaration` Schema 接受 `npm`、`pnpm` 或
|
|
173
|
+
`yarn`,后跟精确的 SemVer 版本(版本部分最多 256 个字符),可包含预发布标识。它拒绝空后缀、版本及预发布数字标识的前导零、版本范围、标签、URL 和首尾空白。
|
|
174
|
+
|
|
175
|
+
`+` 后缀仅用于
|
|
176
|
+
[Corepack hash](https://github.com/nodejs/corepack#when-authoring-packages):支持
|
|
177
|
+
`sha224`、`sha256`、`sha384`、`sha512`,后跟点号及分别为 56、64、96、128 个字符的小写十六进制摘要。不支持普通 SemVer
|
|
178
|
+
build metadata。这里只校验声明语法,不下载或验证包管理器压缩包的真实性。
|
|
179
|
+
|
|
180
|
+
创建项目与检测包管理器使用同一个 Schema,可从
|
|
181
|
+
`@graftland/package-manager/PackageManagerDeclaration`
|
|
182
|
+
导入。创建时逐字保留传入的声明;检测时显式指定的 `agent`
|
|
183
|
+
仍优先于 manifest 声明。
|
package/README.zh-TW.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# @graftland/package-manager
|
|
2
|
+
|
|
3
|
+
[English](https://github.com/graftland/graft/blob/main/packages/package-manager/README.md)
|
|
4
|
+
|
|
|
5
|
+
[简体中文](https://github.com/graftland/graft/blob/main/packages/package-manager/README.zh-CN.md)
|
|
6
|
+
| 繁體中文
|
|
7
|
+
|
|
8
|
+
使用 npm、pnpm 或 Yarn 安裝相依套件,並在失敗時還原。
|
|
9
|
+
|
|
10
|
+
支援的最低 Node.js 版本是 22.19。Windows 依現況提供。Windows 上的行程樹清理和還原沒有經過驗證,也不作承諾。
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install @graftland/package-manager effect
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`make` 會偵測專案所用的套件管理器。它的 `install`
|
|
17
|
+
可以新增、更新或移除相依套件。如果安裝失敗,它會還原 `package.json`
|
|
18
|
+
和鎖定檔。`graft add` 和 `graft remove` 使用它。
|
|
19
|
+
|
|
20
|
+
## 安裝的所有權與復原
|
|
21
|
+
|
|
22
|
+
每個專案只使用一個管理器。呼叫端必須讓管理器及其子行程獨占專案的寫入權限。這從一次
|
|
23
|
+
`install` 呼叫開始,持續到它結束,包括復原階段。
|
|
24
|
+
|
|
25
|
+
- 在此期間,不要編輯專案檔案。
|
|
26
|
+
- 不要同時執行另一個安裝程式。
|
|
27
|
+
- 同一個管理器內的呼叫是循序的。Graft 不會在多個管理器、編輯器或行程之間強制加鎖。
|
|
28
|
+
|
|
29
|
+
在 POSIX 上,行程清理只涵蓋安裝程式最初的行程群組。安裝腳本和復原腳本不得建立不受管理的寫入者。例如,處於獨立行程群組的子行程,以及持續寫入專案檔案的常駐程式。Graft 不提供作業系統層級的隔離,也不會發現逃逸的寫入者。確認最初的行程群組已經停止,並不能證明所有可能的後代都已經停止。違反這條規則的腳本不在還原保證的範圍內。
|
|
30
|
+
|
|
31
|
+
受管理的路徑必須是一般檔案,或者不存在。`make` 和每次 `install` 都使用 `lstat`
|
|
32
|
+
檢查快照集合。快照集合包括
|
|
33
|
+
`package.json`、鎖定檔,以及被追蹤的設定檔和安裝狀態檔。
|
|
34
|
+
|
|
35
|
+
- 符號連結會被拒絕,包括懸空連結。其他檔案類型也會被拒絕。
|
|
36
|
+
- 錯誤是
|
|
37
|
+
`UnsupportedFileTypeError`。它在任何交易寫入之前、任何安裝程式啟動之前擲出。
|
|
38
|
+
- 錯誤會給出 `path` 和 `fileType`。連結及其目標保持不變。
|
|
39
|
+
- 在交易開始之前的拒絕,不需要復原,也不會讓管理器無法使用。
|
|
40
|
+
|
|
41
|
+
### 還原
|
|
42
|
+
|
|
43
|
+
當安裝在提交之前失敗或被中斷時,會執行還原。還原需要先確認最初的行程群組已經停止。然後它會做這些事:
|
|
44
|
+
|
|
45
|
+
- 把已備份的套件檔案逐位元組還原,並保留它們記錄下來的權限位元和擁有者。
|
|
46
|
+
- 移除安裝之前不存在的被追蹤檔案。
|
|
47
|
+
|
|
48
|
+
被追蹤的檔案包括
|
|
49
|
+
`package.json`、鎖定檔,以及管理器所追蹤的套件管理器設定檔和安裝狀態檔。
|
|
50
|
+
|
|
51
|
+
還原會覆蓋安裝期間所做的變更。它不會偵測衝突,也不會合併編輯。
|
|
52
|
+
|
|
53
|
+
如果專案已經有所選套件管理器的鎖定檔,復原階段還會嘗試修復
|
|
54
|
+
`node_modules`。復原錯誤會與原始失敗一起保留。不承諾在行程當機之後復原。
|
|
55
|
+
|
|
56
|
+
### 檔案寫入與行程清理
|
|
57
|
+
|
|
58
|
+
已接受的檔案寫入有一個完成邊界。取消會等待原生操作完成,然後才進行還原、清理快照,以及釋放管理器的鎖。交易會追蹤它自己的檔案寫入以及最初的安裝程式行程群組。建立快照和還原寫入也有同樣的完成保證。
|
|
59
|
+
|
|
60
|
+
每個安裝行程和每個復原行程都有十分鐘的結束等待時間。取消或逾時會在還原檔案之前關閉它的行程 scope。
|
|
61
|
+
|
|
62
|
+
- 行程會收到 SIGTERM。
|
|
63
|
+
- 如果五秒後它還沒有停止,就會收到 SIGKILL。
|
|
64
|
+
- 在 POSIX 上,即使 kill 成功,也必須確認原行程群組已不存在。每 20 毫秒檢查一次,最多追加 100 次檢查(等待兩秒),給短暫殘留的殭屍行程群組留出回收時間。EPERM 視為仍然存在,不視為已消失。
|
|
65
|
+
- 如果行程群組仍存在或檢查失敗,則終止未獲確認:管理器保留快照,不執行回復和復原安裝,並進入
|
|
66
|
+
`RecoveryRequired`。
|
|
67
|
+
- 行程清理失敗會與安裝和復原的失敗一起保留在回傳的 cause 中。
|
|
68
|
+
- 結束逾時不包括行程清理和檔案還原,也不是整個「安裝並復原」操作的截止時間。
|
|
69
|
+
|
|
70
|
+
Node 轉接器可能會把原始的作業系統 errno 取代為通用的 kill 失敗。只有 POSIX 檢查確認行程群組不存在後,PackageManager 才消解帶有 ESRCH 的訊號失敗,或轉接器特定的
|
|
71
|
+
`Unknown` kill 錯誤(cause 為
|
|
72
|
+
`Failed to kill child process`)。同一 Cause 中的其他原因仍然保留,包括 join 失敗、其他 kill 錯誤、defect 和中斷。行程群組仍存在時保留原始 Cause;檢查失敗時保留兩個完整 Cause。
|
|
73
|
+
|
|
74
|
+
## 已提交的安裝與快照清理
|
|
75
|
+
|
|
76
|
+
`install` 成功的結果表示相依套件的變更已經提交。
|
|
77
|
+
|
|
78
|
+
`result.snapshotCleanupFailure` 是 `Option<SnapshotCleanupFailure>`:
|
|
79
|
+
|
|
80
|
+
- `None` 表示快照刪除成功。
|
|
81
|
+
- `Some` 包含 `snapshotDirectory` 和完整的清理 `cause`,包括 defect。
|
|
82
|
+
|
|
83
|
+
提交之後刪除快照失敗,不會讓這次安裝變成失敗,也不會觸發還原。管理器仍然可用,`recoveryRequired`
|
|
84
|
+
仍然是 `None`。
|
|
85
|
+
|
|
86
|
+
呼叫端應該這樣做:
|
|
87
|
+
|
|
88
|
+
- 檢查這個欄位,回報或記錄它的 Cause。
|
|
89
|
+
- 在檔案系統問題解決之後,重試刪除該快照目錄。該目錄可能已被部分刪除。
|
|
90
|
+
- 不要還原舊的快照,也不要僅僅因為快照刪除失敗就重複安裝。那些變更已經提交了。
|
|
91
|
+
- 保留下來的資料可能包含憑證,所以要確保它最終被刪除。
|
|
92
|
+
|
|
93
|
+
提交之前的失敗仍然會使操作失敗並執行還原。任何快照清理失敗都會與原始失敗合併。
|
|
94
|
+
|
|
95
|
+
取消可能會使提交之後的結果無法送達。這並不能證明變更已被撤銷。這種情況下,清理失敗會保留在被中斷的 Cause 中。
|
|
96
|
+
|
|
97
|
+
## 何時需要手動復原
|
|
98
|
+
|
|
99
|
+
在安裝變更專案檔案之前,會先儲存一份快照。快照位於作業系統暫存目錄中一個私有的
|
|
100
|
+
`graft-recovery-*` 目錄裡。
|
|
101
|
+
|
|
102
|
+
- 只有成功的安裝或完整的還原,才允許刪除快照並執行下一次安裝。
|
|
103
|
+
- 已提交但快照刪除失敗的安裝,依上文所述回報。
|
|
104
|
+
- 行程終止和交易完成是兩個獨立的條件。停止寫入者,還原才能開始,但這並不證明還原成功。
|
|
105
|
+
|
|
106
|
+
只要有任何一個還原步驟失敗,管理器就會保留快照,並需要手動復原。這包括在復原之前或之後還原檔案,以及執行復原安裝程式。即使最後的檔案還原成功,這條規則也適用,因為失敗的復原可能讓
|
|
107
|
+
`node_modules` 不完整。
|
|
108
|
+
|
|
109
|
+
管理器如何還原一個檔案:
|
|
110
|
+
|
|
111
|
+
1. 在目標目錄中以獨占方式建立暫存檔,模式為 `0600`。
|
|
112
|
+
2. 當平台回報了儲存的 uid/gid 時,先還原它們,然後還原權限位元。
|
|
113
|
+
3. 對檔案執行 sync 並關閉。
|
|
114
|
+
4. 把該檔案重新命名覆蓋到目標上。
|
|
115
|
+
|
|
116
|
+
中繼資料失敗和暫存檔清理失敗同樣需要手動復原,並保留在 Cause 中。時間戳記、ACL 和擴充屬性不會被記錄。
|
|
117
|
+
|
|
118
|
+
如果無法確認行程已經終止,就不會再進行任何還原或復原。這是為了避免與可能仍在寫入的行程發生衝突。
|
|
119
|
+
|
|
120
|
+
### 復原錯誤
|
|
121
|
+
|
|
122
|
+
失敗呼叫的 Cause 會保留原始失敗以及所有還原和終止的失敗。它包含一個
|
|
123
|
+
`RecoveryRequiredError`,其欄位如下:
|
|
124
|
+
|
|
125
|
+
- `snapshotDirectory` 給出儲存的位置。
|
|
126
|
+
- `directory` 識別專案。
|
|
127
|
+
- `recoveryCause` 保留完整的原始 Cause 和復原 Cause。
|
|
128
|
+
- `operation`:在寫入者已停止但還原不完整時是 `rollback`;在無法確認終止時是
|
|
129
|
+
`install` 或 `recover`,此時 `processId` 和 `terminationCause`
|
|
130
|
+
給出行程的詳細資訊。
|
|
131
|
+
|
|
132
|
+
取消之後,呼叫端還可以讀取 `manager.recoveryRequired`。它是一個產出
|
|
133
|
+
`Option<RecoveryRequiredError>` 的 Effect。呼叫端不需要去攔截被中斷的呼叫。
|
|
134
|
+
|
|
135
|
+
管理器會永久拒絕之後所有的 `install`
|
|
136
|
+
呼叫,並回傳這個帶型別的錯誤。這包括已經排隊的呼叫,以及變更集為空的呼叫。`readState`
|
|
137
|
+
仍然是唯讀的診斷操作。在專案檔案不完整時,它可能失敗。
|
|
138
|
+
|
|
139
|
+
### 手動復原的步驟
|
|
140
|
+
|
|
141
|
+
1. 找出失敗的安裝程式及其所有後代,並停止它們。記錄下來的行程 ID 只用於診斷,不能證明之後具有相同 ID 的行程屬於這次安裝。在所有寫入者停止之前,不要還原檔案,也不要啟動另一個安裝程式。
|
|
142
|
+
2. 解決阻止還原的檔案系統問題,例如檔案權限。然後還原檔案:
|
|
143
|
+
- 開啟 `snapshotDirectory` 中的 `snapshot.json`。檢查其中的專案 `directory`
|
|
144
|
+
和 `agent`。
|
|
145
|
+
- 對每個 `files` 項目,把指定的 `backup` 中的位元組複製到專案 `name`
|
|
146
|
+
旁邊的暫存檔中。以私有、獨占的方式建立該暫存檔。
|
|
147
|
+
- 當 `uid` 和 `gid` 不為 null 時,還原記錄下來的值,然後還原
|
|
148
|
+
`mode`。請在取代目標之前完成這些。
|
|
149
|
+
- 這些中繼資料值是 JSON 整數。`mode`
|
|
150
|
+
是數值形式的權限位元遮罩,不是八進位格式的字串。
|
|
151
|
+
- 視需要建立父目錄。
|
|
152
|
+
- `backup` 為 null 表示該檔案原本不存在。如果它現在存在,就刪除它。
|
|
153
|
+
3. 使用所選的套件管理器,基於已還原的清單檔和鎖定檔修復
|
|
154
|
+
`node_modules`。該行程停止之後,如果它重寫了快照中的檔案,請再次還原這些檔案。快照不包含
|
|
155
|
+
`node_modules`。
|
|
156
|
+
4. 驗證專案。然後刪除快照,並用 `make`
|
|
157
|
+
建立一個新的管理器。舊的管理器沒有重設操作。
|
|
158
|
+
|
|
159
|
+
快照可能包含來自套件管理器設定檔的憑證。請保持私有。它們在管理器和 Effect
|
|
160
|
+
scope 關閉之後依然存在。但是作業系統可能會清理暫存目錄。如果手動復原會被延後,請把保留的快照複製到一個安全的私有位置。
|
|
161
|
+
|
|
162
|
+
這個機制不是當機復原,也不是跨行程的專案鎖。建立新的管理器,並不會讓仍在執行的安裝程式變得安全。
|
|
163
|
+
|
|
164
|
+
## 文件
|
|
165
|
+
|
|
166
|
+
- [命令列](https://graftland.github.io/graft/zh-tw/cli/)
|
|
167
|
+
|
|
168
|
+
屬於 [Graft](https://github.com/graftland/graft)。依
|
|
169
|
+
[Apache 2.0](https://github.com/graftland/graft/blob/main/LICENSE) 授權。
|
|
170
|
+
|
|
171
|
+
## 套件管理器宣告
|
|
172
|
+
|
|
173
|
+
共用的 `PackageManagerDeclaration` Schema 接受 `npm`、`pnpm` 或
|
|
174
|
+
`yarn`,後接精確的 SemVer 版本(版本部分最多 256 個字元),可包含預發布識別碼。它拒絕空後綴、版本及預發布數字識別碼的前置零、版本範圍、標籤、URL 和首尾空白。
|
|
175
|
+
|
|
176
|
+
`+` 後綴僅用於
|
|
177
|
+
[Corepack hash](https://github.com/nodejs/corepack#when-authoring-packages):支援
|
|
178
|
+
`sha224`、`sha256`、`sha384`、`sha512`,後接點號及分別為 56、64、96、128 個字元的小寫十六進位摘要。不支援一般 SemVer
|
|
179
|
+
build metadata。這裡只檢查宣告語法,不下載或驗證套件管理器壓縮檔的真實性。
|
|
180
|
+
|
|
181
|
+
建立專案與偵測套件管理器使用同一個 Schema,可從
|
|
182
|
+
`@graftland/package-manager/PackageManagerDeclaration`
|
|
183
|
+
匯入。建立時完整保留傳入的宣告;偵測時明確指定的 `agent`
|
|
184
|
+
仍優先於 manifest 宣告。
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const PackageManagerName: Schema.Literals<readonly ["npm", "pnpm", "yarn"]>;
|
|
3
|
+
/** Exact SemVer with optional prerelease and Corepack hash; ranges, URLs and arbitrary build metadata are unsupported. */
|
|
4
|
+
export declare const PackageManagerDeclaration: Schema.TemplateLiteralParser<readonly [Schema.Literals<readonly ["npm", "pnpm", "yarn"]>, "@", Schema.decodeTo<Schema.SemVerFromString, Schema.String, never, never>]>;
|
|
5
|
+
export type PackageManagerDeclaration = typeof PackageManagerDeclaration.Type;
|
|
6
|
+
//# sourceMappingURL=PackageManagerDeclaration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackageManagerDeclaration.d.ts","names":[],"sources":["../src/PackageManagerDeclaration.ts"],"mappings":";qBAEa,oBAAkB,OAAA;;qBAkClB,2BAAyB,OAAA,gCAAA,OAAA,iDAAA,OAAA,SAAA,OAAA,kBAAA,OAAA;YAK1B,mCAAmC,0BAA0B"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
// src/PackageManagerDeclaration.ts
|
|
3
|
+
const PackageManagerName = Schema.Literals([
|
|
4
|
+
"npm",
|
|
5
|
+
"pnpm",
|
|
6
|
+
"yarn"
|
|
7
|
+
]);
|
|
8
|
+
const CorepackHash = Schema.Union([
|
|
9
|
+
Schema.Tuple([Schema.Literal("sha224"), Schema.String.check(Schema.isPattern(/^[0-9a-f]{56}$/))]),
|
|
10
|
+
Schema.Tuple([Schema.Literal("sha256"), Schema.String.check(Schema.isPattern(/^[0-9a-f]{64}$/))]),
|
|
11
|
+
Schema.Tuple([Schema.Literal("sha384"), Schema.String.check(Schema.isPattern(/^[0-9a-f]{96}$/))]),
|
|
12
|
+
Schema.Tuple([Schema.Literal("sha512"), Schema.String.check(Schema.isPattern(/^[0-9a-f]{128}$/))])
|
|
13
|
+
]);
|
|
14
|
+
const isCorepackHash = Schema.is(CorepackHash);
|
|
15
|
+
const Version = Schema.String.check(Schema.isMaxLength(256)).pipe(Schema.decodeTo(Schema.SemVerFromString)).check(Schema.makeFilter((version) => version.build.length === 0 || isCorepackHash(version.build), { expected: "no build metadata, or a Corepack sha224/sha256/sha384/sha512 lowercase hexadecimal hash" }));
|
|
16
|
+
/** Exact SemVer with optional prerelease and Corepack hash; ranges, URLs and arbitrary build metadata are unsupported. */
|
|
17
|
+
const PackageManagerDeclaration = Schema.TemplateLiteralParser([
|
|
18
|
+
PackageManagerName,
|
|
19
|
+
"@",
|
|
20
|
+
Version
|
|
21
|
+
]);
|
|
22
|
+
export { PackageManagerDeclaration, PackageManagerName };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=PackageManagerDeclaration.js.map
|