@venn-lang/project 0.1.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/LICENSE +21 -0
- package/README.md +176 -0
- package/dist/index.d.ts +599 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +970 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
- package/src/discover/conventional-targets.ts +49 -0
- package/src/discover/find-project.ts +126 -0
- package/src/discover/index.ts +4 -0
- package/src/discover/load-package.ts +60 -0
- package/src/discover/read-manifest.ts +23 -0
- package/src/glob/expand-members.ts +45 -0
- package/src/glob/index.ts +2 -0
- package/src/glob/matches-member.ts +32 -0
- package/src/index.ts +67 -0
- package/src/model/project.types.ts +55 -0
- package/src/npm/hash-package.ts +65 -0
- package/src/npm/index.ts +12 -0
- package/src/npm/lockfile.ts +49 -0
- package/src/npm/lockfile.types.ts +42 -0
- package/src/npm/manager-command.ts +85 -0
- package/src/npm/package-json.ts +59 -0
- package/src/npm/read-installed.ts +72 -0
- package/src/npm/verify-lock.ts +78 -0
- package/src/paths/index.ts +10 -0
- package/src/paths/paths.ts +103 -0
- package/src/scaffold/index.ts +2 -0
- package/src/scaffold/scaffold.ts +61 -0
- package/src/scaffold/scaffold.types.ts +23 -0
- package/src/target/build-record.ts +45 -0
- package/src/target/index.ts +15 -0
- package/src/target/layout.ts +50 -0
- package/src/workspace/index.ts +2 -0
- package/src/workspace/inherit.ts +60 -0
- package/src/workspace/member-dirs.ts +34 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import { BuildTarget, BuildTarget as BuildTarget$1, Dependency, FileSystem, Manifest, Manifest as Manifest$1, PackageInfo, PackageManagerName, Profile, WorkspaceSettings } from "@venn-lang/contracts";
|
|
2
|
+
//#region src/discover/conventional-targets.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* What a package builds when its manifest does not say.
|
|
5
|
+
*
|
|
6
|
+
* `src/lib.vn` is a library, `src/main.vn` is a program, and each file in
|
|
7
|
+
* `src/bin/` is another program. A package that builds the obvious thing should
|
|
8
|
+
* not have to write it down. A declared target always wins, matched by kind and
|
|
9
|
+
* name, so writing `[lib]` with a different `path` moves the library rather
|
|
10
|
+
* than adding a second one.
|
|
11
|
+
*
|
|
12
|
+
* @param args.declared What the manifest spelled out.
|
|
13
|
+
* @param args.packageName Names the `lib` and the `src/main.vn` program.
|
|
14
|
+
* @returns The declared targets, followed by every convention found on disk.
|
|
15
|
+
*/
|
|
16
|
+
declare function conventionalTargets(args: {
|
|
17
|
+
fs: FileSystem;
|
|
18
|
+
dir: string;
|
|
19
|
+
declared: readonly BuildTarget$1[];
|
|
20
|
+
packageName: string;
|
|
21
|
+
}): Promise<BuildTarget$1[]>;
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/model/project.types.d.ts
|
|
24
|
+
/**
|
|
25
|
+
* A package on disk: one `venn.toml`, and what it turned out to describe.
|
|
26
|
+
*
|
|
27
|
+
* `targets` is what the manifest declared plus what the conventions filled in.
|
|
28
|
+
* The difference between the two matters to whoever writes a manifest and to
|
|
29
|
+
* nobody downstream, so it is settled here rather than carried further.
|
|
30
|
+
*/
|
|
31
|
+
interface Package {
|
|
32
|
+
/** The directory holding the `venn.toml`, with no trailing separator. */
|
|
33
|
+
dir: string;
|
|
34
|
+
manifest: Manifest$1;
|
|
35
|
+
targets: readonly BuildTarget$1[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* What a command is acting on: one root, and every package under it.
|
|
39
|
+
*
|
|
40
|
+
* A lone package is a workspace of one, so nothing downstream has to ask which
|
|
41
|
+
* it is. `isWorkspace` is for the two places that genuinely differ: where
|
|
42
|
+
* `target/` goes, and what a bare command means.
|
|
43
|
+
*/
|
|
44
|
+
interface Project {
|
|
45
|
+
/** The workspace root, or the package's own directory when there is none. */
|
|
46
|
+
root: string;
|
|
47
|
+
isWorkspace: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The manifest at the root, carried whether or not the root is a package.
|
|
50
|
+
*
|
|
51
|
+
* A workspace root often declares no `[package]` at all and still carries the
|
|
52
|
+
* `[env]` tables and path aliases everything under it uses, so it cannot be
|
|
53
|
+
* inferred from the member list.
|
|
54
|
+
*/
|
|
55
|
+
rootManifest: Manifest$1;
|
|
56
|
+
/** Every member, in the order the globs found them. A lone package is one. */
|
|
57
|
+
packages: readonly Package[];
|
|
58
|
+
/** What a command with no target acts on: `default-members`, or all of them. */
|
|
59
|
+
defaultPackages: readonly Package[];
|
|
60
|
+
}
|
|
61
|
+
/** Reading a project failed, and why. Never a raw error from the disk. */
|
|
62
|
+
interface ProjectProblem {
|
|
63
|
+
code: string;
|
|
64
|
+
title: string;
|
|
65
|
+
/** The path the problem is about, when there is one. */
|
|
66
|
+
path?: string;
|
|
67
|
+
}
|
|
68
|
+
/** The result of a lookup: the project, or why there is none. */
|
|
69
|
+
interface FoundProject {
|
|
70
|
+
/** Absent when no manifest was found, in which case `problems` says so. */
|
|
71
|
+
project?: Project;
|
|
72
|
+
problems: readonly ProjectProblem[];
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/discover/find-project.d.ts
|
|
76
|
+
/**
|
|
77
|
+
* The project a path belongs to: the nearest package, and the root that owns it.
|
|
78
|
+
*
|
|
79
|
+
* Walking up is what lets a command run from anywhere inside a project, the way
|
|
80
|
+
* `cargo` and `git` do. A package is claimed by an ancestor workspace only when
|
|
81
|
+
* that workspace's members name it, so a project checked out inside another
|
|
82
|
+
* never joins it by accident.
|
|
83
|
+
*
|
|
84
|
+
* @param args.fs Where the manifests are read from.
|
|
85
|
+
* @param args.from Any path inside the project; the walk starts here.
|
|
86
|
+
* @returns The project with its members loaded and inheritance applied, or one
|
|
87
|
+
* `VN2101` problem when no `venn.toml` sits here or above. Reading a project
|
|
88
|
+
* never throws: a failure comes back as a problem.
|
|
89
|
+
*/
|
|
90
|
+
declare function findProject(args: {
|
|
91
|
+
fs: FileSystem;
|
|
92
|
+
from: string;
|
|
93
|
+
}): Promise<FoundProject>;
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/discover/load-package.d.ts
|
|
96
|
+
/**
|
|
97
|
+
* One package: its manifest, whatever it inherits, and what it builds.
|
|
98
|
+
*
|
|
99
|
+
* Inheritance is applied here rather than at the point of use, so nothing
|
|
100
|
+
* downstream ever holds a manifest that is only half the answer.
|
|
101
|
+
*
|
|
102
|
+
* @param args.dir The directory holding the `venn.toml`.
|
|
103
|
+
* @returns The package, or `undefined` when that directory has no manifest.
|
|
104
|
+
*/
|
|
105
|
+
declare function loadPackage(args: {
|
|
106
|
+
fs: FileSystem;
|
|
107
|
+
dir: string;
|
|
108
|
+
/** The workspace this package belongs to, when it belongs to one. */
|
|
109
|
+
workspace?: Manifest$1;
|
|
110
|
+
/** Where that workspace's manifest lives, which is what its paths mean. */
|
|
111
|
+
workspaceDir?: string;
|
|
112
|
+
}): Promise<Package | undefined>;
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/discover/read-manifest.d.ts
|
|
115
|
+
/** The file that makes a directory a package or a workspace root. */
|
|
116
|
+
declare const MANIFEST_FILE = "venn.toml";
|
|
117
|
+
/**
|
|
118
|
+
* Reads and parses the `venn.toml` in one directory.
|
|
119
|
+
*
|
|
120
|
+
* @returns The manifest, or `undefined` when the file is absent or unreadable.
|
|
121
|
+
* A directory that cannot be read is a directory without a manifest, so the
|
|
122
|
+
* caller keeps walking instead of failing.
|
|
123
|
+
*/
|
|
124
|
+
declare function readManifest(args: {
|
|
125
|
+
fs: FileSystem;
|
|
126
|
+
dir: string;
|
|
127
|
+
}): Promise<Manifest$1 | undefined>;
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/glob/expand-members.d.ts
|
|
130
|
+
/**
|
|
131
|
+
* Expands a workspace's `members` patterns against the disk.
|
|
132
|
+
*
|
|
133
|
+
* `*` stands for one path segment, the way Cargo reads it, so `packages/*` is
|
|
134
|
+
* every package one level down and nothing deeper. `**` is deliberately not
|
|
135
|
+
* read: a member list that can reach arbitrarily far is one nobody can predict.
|
|
136
|
+
*
|
|
137
|
+
* @param args.root The workspace root the patterns are written against.
|
|
138
|
+
* @returns The directories matched, duplicates dropped, in pattern order with
|
|
139
|
+
* names sorted inside each pattern, so two machines list a workspace alike.
|
|
140
|
+
*/
|
|
141
|
+
declare function expandMembers(args: {
|
|
142
|
+
fs: FileSystem;
|
|
143
|
+
root: string;
|
|
144
|
+
patterns: readonly string[];
|
|
145
|
+
}): Promise<string[]>;
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/glob/matches-member.d.ts
|
|
148
|
+
/**
|
|
149
|
+
* Whether a path would be caught by a workspace's `members`, without looking at
|
|
150
|
+
* the disk.
|
|
151
|
+
*
|
|
152
|
+
* Needed before the directory exists: creating `packages/api` inside a
|
|
153
|
+
* workspace should produce a manifest that inherits, and expanding the globs
|
|
154
|
+
* cannot answer that yet because there is nothing there to find.
|
|
155
|
+
*
|
|
156
|
+
* @returns `true` when some pattern matches segment for segment, `*` standing
|
|
157
|
+
* for exactly one segment.
|
|
158
|
+
*/
|
|
159
|
+
declare function matchesMember(args: {
|
|
160
|
+
/** The candidate directory, written relative to the workspace root. */
|
|
161
|
+
path: string;
|
|
162
|
+
patterns: readonly string[];
|
|
163
|
+
}): boolean;
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/npm/hash-package.d.ts
|
|
166
|
+
/**
|
|
167
|
+
* A hash of everything a package installed.
|
|
168
|
+
*
|
|
169
|
+
* Not the registry's integrity hash, which lives in each manager's own lock in
|
|
170
|
+
* each manager's format. This is computed from what landed on disk, which every
|
|
171
|
+
* manager produces the same way. The guarantee differs: the registry's hash
|
|
172
|
+
* says "this is the tarball that was served", this one says "this is the tree
|
|
173
|
+
* that was installed when the lock was written". Trust on first use, and any
|
|
174
|
+
* divergence after that is caught.
|
|
175
|
+
*
|
|
176
|
+
* A hash of hashes rather than of the concatenated bytes, because a package can
|
|
177
|
+
* hold tens of megabytes and digesting it in one buffer costs more than the
|
|
178
|
+
* answer is worth.
|
|
179
|
+
*
|
|
180
|
+
* @param args.dir The installed package directory.
|
|
181
|
+
* @returns `sha256-…` over every file under `dir`, sorted by path, with
|
|
182
|
+
* `node_modules`, `.git` and `.bin` skipped. A file that cannot be read is left
|
|
183
|
+
* out rather than raising.
|
|
184
|
+
*/
|
|
185
|
+
declare function hashPackage(args: {
|
|
186
|
+
fs: FileSystem;
|
|
187
|
+
dir: string;
|
|
188
|
+
}): Promise<string>;
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/npm/lockfile.types.d.ts
|
|
191
|
+
/** One package that ended up installed. */
|
|
192
|
+
interface LockedPackage {
|
|
193
|
+
name: string;
|
|
194
|
+
version: string;
|
|
195
|
+
/**
|
|
196
|
+
* `sha256-…` over the files this package installed.
|
|
197
|
+
*
|
|
198
|
+
* Not the registry's integrity hash, which lives in each manager's own lock
|
|
199
|
+
* in each manager's format. This is computed from what landed on disk and
|
|
200
|
+
* catches any divergence from the moment the lock was written. Absent in a
|
|
201
|
+
* lock written before hashes existed. See `hashPackage`.
|
|
202
|
+
*/
|
|
203
|
+
integrity?: string;
|
|
204
|
+
/** What it says it needs, so the graph can be read without the disk. */
|
|
205
|
+
dependencies?: Record<string, string>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* `venn.lock`: what this project resolved to, in a form no tool owns.
|
|
209
|
+
*
|
|
210
|
+
* Read from what is actually installed rather than translated out of whichever
|
|
211
|
+
* manager's lock produced it, because tracking three formats that change
|
|
212
|
+
* without asking would mean two machines building different things the day the
|
|
213
|
+
* translation drifts.
|
|
214
|
+
*
|
|
215
|
+
* It pins the exact version of every package and a hash of the files each one
|
|
216
|
+
* installed, so `venn install --frozen` can refuse a tree that has drifted,
|
|
217
|
+
* whether a registry answered differently or something was changed by hand.
|
|
218
|
+
*/
|
|
219
|
+
interface Lockfile {
|
|
220
|
+
version: 1;
|
|
221
|
+
/** Which tool did the resolving. The answer can differ between them. */
|
|
222
|
+
manager: string;
|
|
223
|
+
/** Every package installed, in name order. */
|
|
224
|
+
packages: readonly LockedPackage[];
|
|
225
|
+
}
|
|
226
|
+
/** The lock file's name, at the project root beside the manifest. */
|
|
227
|
+
declare const LOCK_FILE = "venn.lock";
|
|
228
|
+
/** The format version written into every lock. */
|
|
229
|
+
declare const LOCK_VERSION = 1;
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/npm/lockfile.d.ts
|
|
232
|
+
/**
|
|
233
|
+
* Writes `venn.lock` from what is installed.
|
|
234
|
+
*
|
|
235
|
+
* It goes at the project root, beside the manifest, and is meant to be
|
|
236
|
+
* committed. The manager's own lock stays inside `target/`, which is derived
|
|
237
|
+
* and thrown away.
|
|
238
|
+
*
|
|
239
|
+
* @param args.manager Which tool did the resolving, recorded in the file.
|
|
240
|
+
* @returns The lock as written.
|
|
241
|
+
* @throws Whatever the file system raises when the write fails.
|
|
242
|
+
*/
|
|
243
|
+
declare function writeLockfile(args: {
|
|
244
|
+
fs: FileSystem;
|
|
245
|
+
root: string;
|
|
246
|
+
manager: string;
|
|
247
|
+
}): Promise<Lockfile>;
|
|
248
|
+
/**
|
|
249
|
+
* Reads the lock this project committed.
|
|
250
|
+
*
|
|
251
|
+
* @returns The lock, or `undefined` when the file is absent or will not parse.
|
|
252
|
+
* A lock nobody can read is a project without one, which `install` can fix.
|
|
253
|
+
*/
|
|
254
|
+
declare function readLockfile(args: {
|
|
255
|
+
fs: FileSystem;
|
|
256
|
+
root: string;
|
|
257
|
+
}): Promise<Lockfile | undefined>;
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/npm/manager-command.d.ts
|
|
260
|
+
/** The four verbs Venn proxies to whichever package manager the project chose. */
|
|
261
|
+
type ProxiedVerb = "add" | "remove" | "update" | "install";
|
|
262
|
+
/** A package manager invocation, ready to spawn. */
|
|
263
|
+
interface ManagerCommand {
|
|
264
|
+
command: string;
|
|
265
|
+
args: readonly string[];
|
|
266
|
+
/**
|
|
267
|
+
* Whether it has to go through a shell.
|
|
268
|
+
*
|
|
269
|
+
* Every one of these managers ships as a script, and on Windows that means a
|
|
270
|
+
* `.cmd`, which Node refuses to spawn directly because `.cmd` files were used
|
|
271
|
+
* to slip arguments past programs that believed they were spawning an
|
|
272
|
+
* executable. So a shell it is, and because a shell re-reads what it is
|
|
273
|
+
* handed, what goes in is checked first. See {@link isSafeSpec}.
|
|
274
|
+
*/
|
|
275
|
+
shell: boolean;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* The command a verb becomes, in the manager this project chose.
|
|
279
|
+
*
|
|
280
|
+
* The interface is ours, the resolution is not: working out which versions
|
|
281
|
+
* satisfy which ranges is years of work against three moving targets, so the
|
|
282
|
+
* four verbs are spelled once here and handed to the tool the project named.
|
|
283
|
+
*
|
|
284
|
+
* @param args.packages Specifiers to act on. Pass each through
|
|
285
|
+
* {@link isSafeSpec} first when `shell` comes back `true`.
|
|
286
|
+
* @returns The command, its arguments, and whether a shell is required.
|
|
287
|
+
*/
|
|
288
|
+
declare function managerCommand(args: {
|
|
289
|
+
manager: PackageManagerName;
|
|
290
|
+
verb: ProxiedVerb;
|
|
291
|
+
packages?: readonly string[];
|
|
292
|
+
dev?: boolean;
|
|
293
|
+
/** `process.platform`. It decides whether a shell is needed. */
|
|
294
|
+
platform: string;
|
|
295
|
+
}): ManagerCommand;
|
|
296
|
+
/**
|
|
297
|
+
* Whether a string is a package specifier and nothing else.
|
|
298
|
+
*
|
|
299
|
+
* The command goes through a shell on Windows, and a shell reads `&`, `|` and
|
|
300
|
+
* `>` as instructions rather than text, so `venn add "x & del /q ."` would
|
|
301
|
+
* delete a directory while looking like an install. A real package name holds
|
|
302
|
+
* none of those characters, so checking costs nothing and closes the hole
|
|
303
|
+
* instead of documenting it.
|
|
304
|
+
*
|
|
305
|
+
* @returns `true` when the string is safe to hand to a shell.
|
|
306
|
+
*/
|
|
307
|
+
declare function isSafeSpec(spec: string): boolean;
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/npm/package-json.d.ts
|
|
310
|
+
/**
|
|
311
|
+
* The `package.json` a package manager is shown, generated from `venn.toml`.
|
|
312
|
+
*
|
|
313
|
+
* Nobody edits it and nobody commits it: the manifest is the source, this is
|
|
314
|
+
* what the tool underneath happens to read. It is written into `target/`, and
|
|
315
|
+
* that placement is the whole trick: a manager writes `node_modules` beside the
|
|
316
|
+
* `package.json` it was pointed at, so the modules land in
|
|
317
|
+
* `target/node_modules` with nothing fighting anything.
|
|
318
|
+
*
|
|
319
|
+
* @param args.members Their dependencies are merged in too, when the root is a
|
|
320
|
+
* workspace.
|
|
321
|
+
* @returns The file's text, marked private, with path dependencies left out and
|
|
322
|
+
* `[patch]` turned into `overrides`.
|
|
323
|
+
*/
|
|
324
|
+
declare function packageJsonFor(args: {
|
|
325
|
+
manifest: Manifest$1;
|
|
326
|
+
/** Every member's dependencies as well, when the root is a workspace. */
|
|
327
|
+
members?: readonly Manifest$1[];
|
|
328
|
+
}): string;
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region src/npm/read-installed.d.ts
|
|
331
|
+
/**
|
|
332
|
+
* Every package installed, read from `target/node_modules`.
|
|
333
|
+
*
|
|
334
|
+
* The installed tree is the strongest statement there is about what a project
|
|
335
|
+
* resolved to: it is what will actually be imported, whichever tool put it
|
|
336
|
+
* there and whatever that tool's own lock says. One walk, the same for every
|
|
337
|
+
* manager. A scope is a directory of packages rather than a package, so
|
|
338
|
+
* `@types/node` is found one level further down.
|
|
339
|
+
*
|
|
340
|
+
* @param args.root The project root, not the modules directory.
|
|
341
|
+
* @returns Every package with its version and content hash, in name order.
|
|
342
|
+
* Dot-directories and anything without a readable `package.json` are skipped,
|
|
343
|
+
* because a directory that is not a package is not a package.
|
|
344
|
+
*/
|
|
345
|
+
declare function readInstalled(args: {
|
|
346
|
+
fs: FileSystem;
|
|
347
|
+
root: string;
|
|
348
|
+
}): Promise<LockedPackage[]>;
|
|
349
|
+
//#endregion
|
|
350
|
+
//#region src/npm/verify-lock.d.ts
|
|
351
|
+
/** How one package differs from what the lock recorded. */
|
|
352
|
+
interface Drift {
|
|
353
|
+
name: string;
|
|
354
|
+
/**
|
|
355
|
+
* In the lock but absent, installed but not locked, a different version, or
|
|
356
|
+
* the same version with different files.
|
|
357
|
+
*/
|
|
358
|
+
kind: "missing" | "unexpected" | "version" | "contents";
|
|
359
|
+
/** What the lock recorded: a version, or an `integrity` hash. */
|
|
360
|
+
expected?: string;
|
|
361
|
+
/** What is on disk, when the two can be compared side by side. */
|
|
362
|
+
found?: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Checks what is installed against what the lock says should be.
|
|
366
|
+
*
|
|
367
|
+
* This is what the hashes are for. Checked, they turn a registry that answered
|
|
368
|
+
* differently today, or a file edited by hand inside `node_modules`, into
|
|
369
|
+
* something a build refuses to start with rather than something found in
|
|
370
|
+
* production.
|
|
371
|
+
*
|
|
372
|
+
* @returns One `Drift` per difference, empty when the tree matches. A lock
|
|
373
|
+
* entry carrying no `integrity` is not checked for contents, so a lock written
|
|
374
|
+
* before hashes existed still passes.
|
|
375
|
+
*/
|
|
376
|
+
declare function verifyLock(args: {
|
|
377
|
+
fs: FileSystem;
|
|
378
|
+
root: string;
|
|
379
|
+
lock: Lockfile;
|
|
380
|
+
}): Promise<Drift[]>;
|
|
381
|
+
/**
|
|
382
|
+
* Renders drift for a person to read.
|
|
383
|
+
*
|
|
384
|
+
* @returns One indented line per package that differs, in the voice of what
|
|
385
|
+
* went wrong. Empty for an empty list.
|
|
386
|
+
*/
|
|
387
|
+
declare function describeDrift(drift: readonly Drift[]): string;
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/paths/paths.d.ts
|
|
390
|
+
/**
|
|
391
|
+
* Path arithmetic on manifest paths, with no `node:path`.
|
|
392
|
+
*
|
|
393
|
+
* This package runs in a Web Worker as well as in the CLI, so paths are handled
|
|
394
|
+
* as text with forward slashes. A Windows path arrives with backslashes and is
|
|
395
|
+
* normalised on the way in, which is the one place the difference is allowed to
|
|
396
|
+
* exist.
|
|
397
|
+
*/
|
|
398
|
+
/**
|
|
399
|
+
* One path, written the one way the rest of this package understands.
|
|
400
|
+
*
|
|
401
|
+
* @returns The path with backslashes turned into forward slashes, runs of
|
|
402
|
+
* separators collapsed, and any trailing separator dropped. `"/"` stays `"/"`.
|
|
403
|
+
*/
|
|
404
|
+
declare function normalise(path: string): string;
|
|
405
|
+
/**
|
|
406
|
+
* Joins path segments, ignoring empty ones.
|
|
407
|
+
*
|
|
408
|
+
* @returns The joined path, normalised. No `..` is resolved: these are manifest
|
|
409
|
+
* paths, and what a manifest wrote is what gets written down.
|
|
410
|
+
*/
|
|
411
|
+
declare function join(...parts: readonly string[]): string;
|
|
412
|
+
/**
|
|
413
|
+
* The directory holding this path.
|
|
414
|
+
*
|
|
415
|
+
* @returns The parent, or `undefined` when there is nothing above. A relative
|
|
416
|
+
* path with one segment has the empty string as its parent, which is the
|
|
417
|
+
* directory it was written against; stopping short of it would leave a walk up
|
|
418
|
+
* from `packages/api` never reaching the workspace root beside it.
|
|
419
|
+
*/
|
|
420
|
+
declare function parentOf(path: string): string | undefined;
|
|
421
|
+
/** The last segment of a path, which is the file or directory's own name. */
|
|
422
|
+
declare function baseName(path: string): string;
|
|
423
|
+
/**
|
|
424
|
+
* Every directory from `path` up to the top, `path` itself first.
|
|
425
|
+
*
|
|
426
|
+
* @returns The chain, ending in `""` for a relative path and `"/"` for an
|
|
427
|
+
* absolute one.
|
|
428
|
+
*/
|
|
429
|
+
declare function ancestors(path: string): string[];
|
|
430
|
+
/** Whether `path` is `base` or sits inside it. */
|
|
431
|
+
declare function isInside(path: string, base: string): boolean;
|
|
432
|
+
/** `path` written relative to `base`, or the path itself when it is not inside. */
|
|
433
|
+
declare function relativeTo(path: string, base: string): string;
|
|
434
|
+
/**
|
|
435
|
+
* A relative path written in one directory, rewritten to mean the same thing
|
|
436
|
+
* from another inside it.
|
|
437
|
+
*
|
|
438
|
+
* A workspace root writes `"#shared" = "./shared"` once and every member uses
|
|
439
|
+
* it, but a member reads it from further down, where `./shared` is somewhere
|
|
440
|
+
* else entirely.
|
|
441
|
+
*
|
|
442
|
+
* @param args.declaredIn Where the path was written.
|
|
443
|
+
* @param args.usedIn Where it will be read.
|
|
444
|
+
* @returns The path with one `../` per directory of depth. An absolute path is
|
|
445
|
+
* returned unchanged: it already means the same thing everywhere.
|
|
446
|
+
*/
|
|
447
|
+
declare function reanchor(args: {
|
|
448
|
+
path: string;
|
|
449
|
+
declaredIn: string;
|
|
450
|
+
usedIn: string;
|
|
451
|
+
}): string;
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/scaffold/scaffold.types.d.ts
|
|
454
|
+
/** What kind of thing is being started. */
|
|
455
|
+
type ScaffoldKind = "lib" | "bin" | "workspace";
|
|
456
|
+
/** What to start, and what the surroundings already provide. */
|
|
457
|
+
interface ScaffoldRequest {
|
|
458
|
+
kind: ScaffoldKind;
|
|
459
|
+
/** The package name, which is also the directory when one is created. */
|
|
460
|
+
name: string;
|
|
461
|
+
/**
|
|
462
|
+
* Whether a workspace above will claim this package as a member.
|
|
463
|
+
*
|
|
464
|
+
* Changes what is written rather than only where: a member leaves out what it
|
|
465
|
+
* would inherit and carries no ignore file, because the root already owns the
|
|
466
|
+
* one `target/` there is.
|
|
467
|
+
*/
|
|
468
|
+
insideWorkspace?: boolean;
|
|
469
|
+
}
|
|
470
|
+
/** One file to write, its path relative to the directory being started. */
|
|
471
|
+
interface ScaffoldFile {
|
|
472
|
+
path: string;
|
|
473
|
+
content: string;
|
|
474
|
+
}
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/scaffold/scaffold.d.ts
|
|
477
|
+
/**
|
|
478
|
+
* The files a new project starts as.
|
|
479
|
+
*
|
|
480
|
+
* Pure: it says what should exist and the caller writes it, so `--dry-run`, the
|
|
481
|
+
* tests and the disk all see one answer. What is generated is deliberately
|
|
482
|
+
* small, because a starting point that has to be deleted before it can be used
|
|
483
|
+
* is worse than one that is missing something.
|
|
484
|
+
*
|
|
485
|
+
* @returns The manifest, a source file for anything that is not a workspace,
|
|
486
|
+
* and a `.gitignore` unless a workspace above already owns one.
|
|
487
|
+
*/
|
|
488
|
+
declare function scaffold(request: ScaffoldRequest): ScaffoldFile[];
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/target/layout.d.ts
|
|
491
|
+
/**
|
|
492
|
+
* Where everything a build produces or fetches goes.
|
|
493
|
+
*
|
|
494
|
+
* One directory at the workspace root holds every derived thing, the way
|
|
495
|
+
* Cargo's `target/` does, so deleting it costs time and nothing else.
|
|
496
|
+
*
|
|
497
|
+
* The dependencies live inside it, and that placement is load-bearing rather
|
|
498
|
+
* than tidiness: Node resolves a package by walking up from the importing file
|
|
499
|
+
* looking for `node_modules`, and built output sits in `target/debug` or
|
|
500
|
+
* `target/release`, one level below `target/node_modules`. The ordinary
|
|
501
|
+
* resolver finds them with no loader and no symlink. Moving the output out of
|
|
502
|
+
* `target/` breaks that quietly.
|
|
503
|
+
*/
|
|
504
|
+
declare const TARGET_DIR = "target";
|
|
505
|
+
/** The names inside `target/`. */
|
|
506
|
+
declare const TARGET_LAYOUT: {
|
|
507
|
+
/** What the package manager installs, and what Node's resolver will find. */
|
|
508
|
+
readonly modules: "node_modules";
|
|
509
|
+
/** Compiled addons, kept apart because they are per-platform, not per-project. */
|
|
510
|
+
readonly native: "native_modules";
|
|
511
|
+
/** Built output, one directory per profile. */
|
|
512
|
+
readonly debug: "debug";
|
|
513
|
+
readonly release: "release";
|
|
514
|
+
};
|
|
515
|
+
/** Which build profile an output directory belongs to. */
|
|
516
|
+
type ProfileName = "debug" | "release";
|
|
517
|
+
/** The `target/` of a project, given its root. */
|
|
518
|
+
declare function targetDir(root: string): string;
|
|
519
|
+
/** Where the package manager installs, and where Node's resolver will look. */
|
|
520
|
+
declare function modulesDir(root: string): string;
|
|
521
|
+
/** Where compiled addons go, kept apart because they are per-platform. */
|
|
522
|
+
declare function nativeModulesDir(root: string): string;
|
|
523
|
+
/** Where a build of this profile is written. */
|
|
524
|
+
declare function outputDir(args: {
|
|
525
|
+
root: string;
|
|
526
|
+
profile: ProfileName;
|
|
527
|
+
}): string;
|
|
528
|
+
//#endregion
|
|
529
|
+
//#region src/target/build-record.d.ts
|
|
530
|
+
/** One target a build covered, and where it starts. */
|
|
531
|
+
interface BuiltTarget {
|
|
532
|
+
package: string;
|
|
533
|
+
kind: string;
|
|
534
|
+
name: string;
|
|
535
|
+
/** The entry file, relative to the workspace root. */
|
|
536
|
+
path: string;
|
|
537
|
+
}
|
|
538
|
+
/** What one build covered, and how it went. */
|
|
539
|
+
interface BuildRecord {
|
|
540
|
+
profile: ProfileName;
|
|
541
|
+
targets: readonly BuiltTarget[];
|
|
542
|
+
/** How many `.vn` files were read, and how many problems were found. */
|
|
543
|
+
files: number;
|
|
544
|
+
problems: number;
|
|
545
|
+
}
|
|
546
|
+
/** The record's name, inside the profile's output directory. */
|
|
547
|
+
declare const RECORD_FILE = "build.json";
|
|
548
|
+
/**
|
|
549
|
+
* Writes what a build produced, where that build's outputs go.
|
|
550
|
+
*
|
|
551
|
+
* It answers "what does this project build, and did it hold together", and it
|
|
552
|
+
* is what an incremental build compares against once there is generated code to
|
|
553
|
+
* skip.
|
|
554
|
+
*
|
|
555
|
+
* @returns The path written.
|
|
556
|
+
* @throws Whatever the file system raises when the write fails.
|
|
557
|
+
*/
|
|
558
|
+
declare function writeBuildRecord(args: {
|
|
559
|
+
fs: FileSystem;
|
|
560
|
+
root: string;
|
|
561
|
+
record: BuildRecord;
|
|
562
|
+
}): Promise<string>;
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/workspace/inherit.d.ts
|
|
565
|
+
/**
|
|
566
|
+
* A member manifest with what the workspace root supplies filled in.
|
|
567
|
+
*
|
|
568
|
+
* Two things are inherited and they work differently. `[workspace.package]` is
|
|
569
|
+
* a default: the member's own value wins wherever it wrote one. A dependency
|
|
570
|
+
* marked `{ workspace = true }` is a request, so the root's answer replaces
|
|
571
|
+
* whatever was there. Writing both a version and `workspace = true` is a
|
|
572
|
+
* contradiction, and the request is the deliberate half.
|
|
573
|
+
*
|
|
574
|
+
* @param args.from The workspace root's manifest. A root with no `[workspace]`
|
|
575
|
+
* table supplies nothing, and the member is returned untouched.
|
|
576
|
+
* @returns The merged manifest. The member's own `name` always survives.
|
|
577
|
+
*/
|
|
578
|
+
declare function inherit(args: {
|
|
579
|
+
manifest: Manifest$1;
|
|
580
|
+
from: Manifest$1;
|
|
581
|
+
}): Manifest$1;
|
|
582
|
+
//#endregion
|
|
583
|
+
//#region src/workspace/member-dirs.d.ts
|
|
584
|
+
/**
|
|
585
|
+
* The directories a workspace's members occupy, exclusions already applied.
|
|
586
|
+
*
|
|
587
|
+
* @returns The member directories, normalised. One holding no `venn.toml` is
|
|
588
|
+
* dropped rather than reported: a glob describes a shape, and `packages/*`
|
|
589
|
+
* catching a `dist` folder on the way past is the glob working, not the
|
|
590
|
+
* workspace being wrong.
|
|
591
|
+
*/
|
|
592
|
+
declare function memberDirs(args: {
|
|
593
|
+
fs: FileSystem;
|
|
594
|
+
root: string;
|
|
595
|
+
workspace: WorkspaceSettings;
|
|
596
|
+
}): Promise<string[]>;
|
|
597
|
+
//#endregion
|
|
598
|
+
export { type BuildRecord, type BuildTarget, type BuiltTarget, type Dependency, type Drift, type FoundProject, LOCK_FILE, LOCK_VERSION, type LockedPackage, type Lockfile, MANIFEST_FILE, type ManagerCommand, type Manifest, type Package, type PackageInfo, type Profile, type ProfileName, type Project, type ProjectProblem, type ProxiedVerb, RECORD_FILE, type ScaffoldFile, type ScaffoldKind, type ScaffoldRequest, TARGET_DIR, TARGET_LAYOUT, ancestors, baseName, conventionalTargets, describeDrift, expandMembers, findProject, hashPackage, inherit, isInside, isSafeSpec, join, loadPackage, managerCommand, matchesMember, memberDirs, modulesDir, nativeModulesDir, normalise, outputDir, packageJsonFor, parentOf, readInstalled, readLockfile, readManifest, reanchor, relativeTo, scaffold, targetDir, verifyLock, writeBuildRecord, writeLockfile };
|
|
599
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/discover/conventional-targets.ts","../src/model/project.types.ts","../src/discover/find-project.ts","../src/discover/load-package.ts","../src/discover/read-manifest.ts","../src/glob/expand-members.ts","../src/glob/matches-member.ts","../src/npm/hash-package.ts","../src/npm/lockfile.types.ts","../src/npm/lockfile.ts","../src/npm/manager-command.ts","../src/npm/package-json.ts","../src/npm/read-installed.ts","../src/npm/verify-lock.ts","../src/paths/paths.ts","../src/scaffold/scaffold.types.ts","../src/scaffold/scaffold.ts","../src/target/layout.ts","../src/target/build-record.ts","../src/workspace/inherit.ts","../src/workspace/member-dirs.ts"],"mappings":";;;;;;;;;;;;;;;iBAsBsB,oBAAoB;EACxC,IAAI;EACJ;EACA,mBAAmB;EACnB;IACE,QAAQ;;;;;;;;;;UClBK;;EAEf;EACA,UAAU;EACV,kBAAkB;;;;;;;;;UAUH;;EAEf;EACA;;;;;;;;EAQA,cAAc;;EAEd,mBAAmB;;EAEnB,0BAA0B;;;UAIX;EACf;EACA;;EAEA;;;UAIe;;EAEf,UAAU;EACV,mBAAmB;;;;;;;;;;;;;;;;;;iBChCC,YAAY;EAAQ,IAAI;EAAY;IAAiB,QAAQ;;;;;;;;;;;;iBCL7D,YAAY;EAChC,IAAI;EACJ;;EAEA,YAAY;;EAEZ;IACE,QAAQ;;;;cCnBC;;;;;;;;iBASS,aAAa;EACjC,IAAI;EACJ;IACE,QAAQ;;;;;;;;;;;;;;iBCFU,cAAc;EAClC,IAAI;EACJ;EACA;IACE;;;;;;;;;;;;;;iBCLY,cAAc;;EAE5B;EACA;;;;;;;;;;;;;;;;;;;;;;;iBCSoB,YAAY;EAAQ,IAAI;EAAY;IAAgB;;;;UCxBzD;EACf;EACA;;;;;;;;;EASA;;EAEA,eAAe;;;;;;;;;;;;;;UAeA;EACf;;EAEA;;EAEA,mBAAmB;;;cAIR;;cAGA;;;;;;;;;;;;;;iBCzBS,cAAc;EAClC,IAAI;EACJ;EACA;IACE,QAAQ;;;;;;;iBAiBU,aAAa;EACjC,IAAI;EACJ;IACE,QAAQ;;;;KCrCA;;UAGK;EACf;EACA;;;;;;;;;;EAUA;;;;;;;;;;;;;iBAcc,eAAe;EAC7B,SAAS;EACT,MAAM;EACN;EACA;;EAEA;IACE;;;;;;;;;;;;iBA2CY,WAAW;;;;;;;;;;;;;;;;;iBClEX,eAAe;EAC7B,UAAU;;EAEV,mBAAmB;;;;;;;;;;;;;;;;;;iBCCC,cAAc;EAClC,IAAI;EACJ;IACE,QAAQ;;;;UClBK;EACf;;;;;EAKA;;EAEA;;EAEA;;;;;;;;;;;;;;iBAeoB,WAAW;EAC/B,IAAI;EACJ;EACA,MAAM;IACJ,QAAQ;;;;;;;iBA8BI,cAAc,gBAAgB;;;;;;;;;;;;;;;;;iBCjD9B,UAAU;;;;;;;iBAWV,QAAQ;;;;;;;;;iBAaR,SAAS;;iBAST,SAAS;;;;;;;iBAWT,UAAU;;iBAWV,SAAS,cAAc;;iBAOvB,WAAW,cAAc;;;;;;;;;;;;;;iBAmBzB,SAAS;EAAQ;EAAc;EAAoB;;;;;KC/FvD;;UAGK;EACf,MAAM;;EAEN;;;;;;;;EAQA;;;UAIe;EACf;EACA;;;;;;;;;;;;;;;iBCNc,SAAS,SAAS,kBAAkB;;;;;;;;;;;;;;;;cCAvC;;cAGA;;WAEX;;WAEA;;WAEA;WACA;;;KAIU;;iBAGI,UAAU;;iBAKV,WAAW;;iBAKX,iBAAiB;;iBAKjB,UAAU;EAAQ;EAAc,SAAS;;;;;UC1CxC;EACf;EACA;EACA;;EAEA;;;UAIe;EACf,SAAS;EACT,kBAAkB;;EAElB;EACA;;;cAIW;;;;;;;;;;;iBAYS,iBAAiB;EACrC,IAAI;EACJ;EACA,QAAQ;IACN;;;;;;;;;;;;;;;;iBCxBY,QAAQ;EAAQ,UAAU;EAAU,MAAM;IAAa;;;;;;;;;;;iBCHjD,WAAW;EAC/B,IAAI;EACJ;EACA,WAAW;IACT"}
|