@effected/workspaces 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/CatalogAssemblyError.js +43 -0
- package/ChangeDetector.js +154 -0
- package/ConfigDependencyHooks.js +153 -0
- package/DependencyGraph.js +241 -0
- package/LICENSE +21 -0
- package/LockfileReader.js +118 -0
- package/PackageManagerName.js +248 -0
- package/Publishability.js +73 -0
- package/README.md +165 -0
- package/WorkspaceCatalogs.js +392 -0
- package/WorkspaceDiscovery.js +338 -0
- package/WorkspacePackage.js +247 -0
- package/WorkspaceRoot.js +90 -0
- package/WorkspaceSnapshots.js +0 -0
- package/WorkspaceStateSnapshot.js +165 -0
- package/Workspaces.js +113 -0
- package/WorkspacesSync.js +205 -0
- package/index.d.ts +1559 -0
- package/index.js +17 -0
- package/internal/catalogs.js +70 -0
- package/internal/enumerate.js +75 -0
- package/internal/limits.js +20 -0
- package/internal/patterns.js +62 -0
- package/internal/traverse.js +94 -0
- package/package.json +61 -0
- package/tsdoc-metadata.json +11 -0
package/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CatalogAssemblyError } from "./CatalogAssemblyError.js";
|
|
2
|
+
import { PublishConfig, WorkspaceManifestError, WorkspacePackage } from "./WorkspacePackage.js";
|
|
3
|
+
import { WORKSPACE_MARKERS, WorkspaceRoot, WorkspaceRootNotFoundError } from "./WorkspaceRoot.js";
|
|
4
|
+
import { PackageNotFoundError, WorkspaceDiscovery, WorkspaceDiscoveryError, WorkspaceInfo, WorkspacePatternError } from "./WorkspaceDiscovery.js";
|
|
5
|
+
import { CyclicDependencyError, DependencyGraph } from "./DependencyGraph.js";
|
|
6
|
+
import { ChangeDetectionError, ChangeDetectionOptions, ChangeDetector } from "./ChangeDetector.js";
|
|
7
|
+
import { ConfigDependencyHooks } from "./ConfigDependencyHooks.js";
|
|
8
|
+
import { DetectedPackageManager, PackageManagerDetectionError, PackageManagerDetector, PackageManagerName } from "./PackageManagerName.js";
|
|
9
|
+
import { LockfileReadError, LockfileReader } from "./LockfileReader.js";
|
|
10
|
+
import { PublishTarget, PublishabilityDetector } from "./Publishability.js";
|
|
11
|
+
import { CatalogSet, WorkspaceCatalogs } from "./WorkspaceCatalogs.js";
|
|
12
|
+
import { PackageStateSnapshot, WorkspaceStateSnapshot } from "./WorkspaceStateSnapshot.js";
|
|
13
|
+
import { WorkspaceSnapshots } from "./WorkspaceSnapshots.js";
|
|
14
|
+
import { Workspaces } from "./Workspaces.js";
|
|
15
|
+
import { findWorkspaceRootSync, getWorkspacePackagesSync } from "./WorkspacesSync.js";
|
|
16
|
+
|
|
17
|
+
export { CatalogAssemblyError, CatalogSet, ChangeDetectionError, ChangeDetectionOptions, ChangeDetector, ConfigDependencyHooks, CyclicDependencyError, DependencyGraph, DetectedPackageManager, LockfileReadError, LockfileReader, PackageManagerDetectionError, PackageManagerDetector, PackageManagerName, PackageNotFoundError, PackageStateSnapshot, PublishConfig, PublishTarget, PublishabilityDetector, WORKSPACE_MARKERS, WorkspaceCatalogs, WorkspaceDiscovery, WorkspaceDiscoveryError, WorkspaceInfo, WorkspaceManifestError, WorkspacePackage, WorkspacePatternError, WorkspaceRoot, WorkspaceRootNotFoundError, WorkspaceSnapshots, WorkspaceStateSnapshot, Workspaces, findWorkspaceRootSync, getWorkspacePackagesSync };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getCatalogsFromWorkspaceManifest, mergeCatalogs } from "@pnpm/catalogs.config";
|
|
2
|
+
import { parseCatalogProtocol } from "@pnpm/catalogs.protocol-parser";
|
|
3
|
+
import { matchCatalogResolveResult, resolveFromCatalog } from "@pnpm/catalogs.resolver";
|
|
4
|
+
|
|
5
|
+
//#region src/internal/catalogs.ts
|
|
6
|
+
/** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
|
|
7
|
+
const inlineCatalogs = (manifest) => {
|
|
8
|
+
if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
|
|
9
|
+
try {
|
|
10
|
+
return getCatalogsFromWorkspaceManifest({
|
|
11
|
+
catalog: manifest.catalog,
|
|
12
|
+
catalogs: manifest.catalogs
|
|
13
|
+
});
|
|
14
|
+
} catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/** Merge catalog sources; later sources win per dependency within a catalog. */
|
|
19
|
+
const merge = (...sources) => mergeCatalogs(...sources);
|
|
20
|
+
/** Whether `specifier` is a `catalog:` protocol reference, and which catalog it names. */
|
|
21
|
+
const catalogNameOf = (specifier) => parseCatalogProtocol(specifier);
|
|
22
|
+
/** Normalize the arbitrary shape of a catalog map into `CatalogEntries`, dropping anything unusable. */
|
|
23
|
+
const normalize = (raw) => {
|
|
24
|
+
if (raw === null || typeof raw !== "object") return {};
|
|
25
|
+
const entries = {};
|
|
26
|
+
for (const [catalogName, catalog] of Object.entries(raw)) {
|
|
27
|
+
if (catalog === null || typeof catalog !== "object") continue;
|
|
28
|
+
const clean = {};
|
|
29
|
+
for (const [dependency, value] of Object.entries(catalog)) if (typeof value === "string") define(clean, dependency, value);
|
|
30
|
+
else if (value !== null && typeof value === "object" && "specifier" in value) {
|
|
31
|
+
const specifier = value.specifier;
|
|
32
|
+
if (typeof specifier === "string") define(clean, dependency, specifier);
|
|
33
|
+
}
|
|
34
|
+
define(entries, catalogName, clean);
|
|
35
|
+
}
|
|
36
|
+
return entries;
|
|
37
|
+
};
|
|
38
|
+
const define = (target, key, value) => {
|
|
39
|
+
if (key === "__proto__") Object.defineProperty(target, key, {
|
|
40
|
+
value,
|
|
41
|
+
writable: true,
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true
|
|
44
|
+
});
|
|
45
|
+
else target[key] = value;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Resolve one `catalog:` specifier against an assembled catalog set.
|
|
49
|
+
*
|
|
50
|
+
* Returns the range on a hit, `undefined` on a miss (the specifier names no
|
|
51
|
+
* catalog entry — an ordinary `Option.none()` to the caller), and a
|
|
52
|
+
* `CatalogMisconfiguration` when pnpm reports the catalog itself is malformed.
|
|
53
|
+
*/
|
|
54
|
+
const rangeOf = (catalogs, dependency, specifier) => {
|
|
55
|
+
if (catalogNameOf(specifier) === null) return void 0;
|
|
56
|
+
return matchCatalogResolveResult(resolveFromCatalog(catalogs, {
|
|
57
|
+
alias: dependency,
|
|
58
|
+
bareSpecifier: specifier
|
|
59
|
+
}), {
|
|
60
|
+
found: (hit) => hit.resolution.specifier,
|
|
61
|
+
misconfiguration: (bad) => ({
|
|
62
|
+
catalogName: bad.catalogName,
|
|
63
|
+
detail: bad.error.message
|
|
64
|
+
}),
|
|
65
|
+
unused: () => void 0
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { catalogNameOf, inlineCatalogs, merge, normalize, rangeOf };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Traversal, badMaxDepthMessage, isPruned, isValidMaxDepth, joinRelative } from "./traverse.js";
|
|
2
|
+
import { Effect, FileSystem, Path } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/enumerate.ts
|
|
5
|
+
/** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
|
|
6
|
+
const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
|
|
7
|
+
/**
|
|
8
|
+
* Enumerate the workspace directories a compiled `packages:` set selects.
|
|
9
|
+
*
|
|
10
|
+
* Every returned directory holds a `package.json`, matches at least one include
|
|
11
|
+
* (literal or wildcard), and is rejected by no exclude. Results are sorted by
|
|
12
|
+
* relative path.
|
|
13
|
+
*/
|
|
14
|
+
const enumerate = (root, globs, options) => Effect.gen(function* () {
|
|
15
|
+
const fs = yield* FileSystem.FileSystem;
|
|
16
|
+
const path = yield* Path.Path;
|
|
17
|
+
const maxDepth = options?.maxDepth ?? 32;
|
|
18
|
+
if (!isValidMaxDepth(maxDepth)) return yield* Effect.die(/* @__PURE__ */ new Error(`enumerate: ${badMaxDepthMessage(maxDepth)}`));
|
|
19
|
+
const isPackage = (absolute) => fs.exists(path.join(absolute, "package.json")).pipe(Effect.orElseSucceed(() => false));
|
|
20
|
+
const isDirectory = (absolute) => fs.stat(absolute).pipe(Effect.map((info) => info.type === "Directory"), Effect.orElseSucceed(() => false));
|
|
21
|
+
const included = /* @__PURE__ */ new Map();
|
|
22
|
+
/** A shared-traversal stop, materialized as this module's failure record. */
|
|
23
|
+
const failureOf = (stop, pattern) => ({
|
|
24
|
+
kind: stop.kind,
|
|
25
|
+
pattern,
|
|
26
|
+
detail: stop.detail
|
|
27
|
+
});
|
|
28
|
+
for (const literal of globs.literals) {
|
|
29
|
+
const absolute = path.join(root, literal);
|
|
30
|
+
if (yield* isPackage(absolute)) included.set(literal, absolute);
|
|
31
|
+
}
|
|
32
|
+
for (const wildcard of globs.wildcards) {
|
|
33
|
+
const base = baseOf(wildcard);
|
|
34
|
+
const absoluteBase = path.join(root, base);
|
|
35
|
+
if (!(yield* isDirectory(absoluteBase))) return yield* Effect.fail({
|
|
36
|
+
kind: "missingBaseDir",
|
|
37
|
+
pattern: wildcard.source,
|
|
38
|
+
detail: base === "" ? root : base
|
|
39
|
+
});
|
|
40
|
+
const traversal = new Traversal(base, absoluteBase, maxDepth);
|
|
41
|
+
for (let current = traversal.next(); current !== void 0; current = traversal.next()) {
|
|
42
|
+
const spent = traversal.charge();
|
|
43
|
+
if (spent !== void 0) return yield* Effect.fail(failureOf(spent, wildcard.source));
|
|
44
|
+
const frame = current;
|
|
45
|
+
const entries = yield* fs.readDirectory(frame.absolute).pipe(Effect.catch((error) => error.reason._tag === "NotFound" ? Effect.succeed([]) : Effect.fail({
|
|
46
|
+
kind: "unreadableDirectory",
|
|
47
|
+
pattern: wildcard.source,
|
|
48
|
+
detail: frame.relative === "" ? root : frame.relative
|
|
49
|
+
})));
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
if (isPruned(entry)) continue;
|
|
52
|
+
const relative = joinRelative(frame.relative, entry);
|
|
53
|
+
const absolute = path.join(frame.absolute, entry);
|
|
54
|
+
if (!(yield* isDirectory(absolute))) continue;
|
|
55
|
+
if (wildcard.crossesSegments && !traversal.admits(frame)) return yield* Effect.fail(failureOf(traversal.depthStop(), wildcard.source));
|
|
56
|
+
if (wildcard.matches(relative) && (yield* isPackage(absolute))) included.set(relative, absolute);
|
|
57
|
+
if (!wildcard.crossesSegments) continue;
|
|
58
|
+
traversal.push(frame, relative, absolute);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const results = [];
|
|
63
|
+
for (const [relativePath, absolute] of included) {
|
|
64
|
+
if (globs.excludes.some((exclude) => exclude.matches(relativePath))) continue;
|
|
65
|
+
results.push({
|
|
66
|
+
relativePath,
|
|
67
|
+
path: absolute
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
results.sort((a, b) => a.relativePath < b.relativePath ? -1 : a.relativePath > b.relativePath ? 1 : 0);
|
|
71
|
+
return results;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { enumerate };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/internal/limits.ts
|
|
2
|
+
/**
|
|
3
|
+
* Hard ceiling on directories the enumerator will visit for one pattern set.
|
|
4
|
+
* Guards the pathological case a depth cap alone does not: a wide, shallow
|
|
5
|
+
* tree. Exceeding it fails typed rather than hanging.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
const MAX_ENUMERATION_ENTRIES = 1e5;
|
|
10
|
+
/**
|
|
11
|
+
* Directory names never descended into. pnpm, npm, yarn and bun all ignore
|
|
12
|
+
* `node_modules` when expanding workspace globs; without the prune a
|
|
13
|
+
* `packages/**` in an installed repo would walk the entire store.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { MAX_ENUMERATION_ENTRIES, PRUNED_DIRECTORIES };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Effect, FileSystem, Path } from "effect";
|
|
2
|
+
import { Yaml } from "@effected/yaml";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/patterns.ts
|
|
5
|
+
const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
|
|
6
|
+
/** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
|
|
7
|
+
const pnpmPatternsOf = (document) => {
|
|
8
|
+
if (document === null || typeof document !== "object") return [];
|
|
9
|
+
return stringsOf(document.packages) ?? [];
|
|
10
|
+
};
|
|
11
|
+
/** The `workspaces` field of a root package.json, in either supported shape. */
|
|
12
|
+
const manifestPatternsOf = (manifest) => {
|
|
13
|
+
if (manifest === null || typeof manifest !== "object") return [];
|
|
14
|
+
const workspaces = manifest.workspaces;
|
|
15
|
+
const direct = stringsOf(workspaces);
|
|
16
|
+
if (direct !== void 0) return direct;
|
|
17
|
+
if (workspaces !== null && typeof workspaces === "object" && "packages" in workspaces) return stringsOf(workspaces.packages) ?? [];
|
|
18
|
+
return [];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The workspace `packages:` patterns for `root`: `pnpm-workspace.yaml` first,
|
|
22
|
+
* then the root package.json `workspaces` field. An absent config is a
|
|
23
|
+
* standalone package, not an error — it yields an empty list.
|
|
24
|
+
*/
|
|
25
|
+
const readPatterns = (root) => Effect.gen(function* () {
|
|
26
|
+
const fs = yield* FileSystem.FileSystem;
|
|
27
|
+
const path = yield* Path.Path;
|
|
28
|
+
const pnpmWorkspacePath = path.join(root, "pnpm-workspace.yaml");
|
|
29
|
+
if (yield* fs.exists(pnpmWorkspacePath).pipe(Effect.orElseSucceed(() => false))) {
|
|
30
|
+
const content = yield* fs.readFileString(pnpmWorkspacePath).pipe(Effect.mapError((cause) => ({
|
|
31
|
+
path: pnpmWorkspacePath,
|
|
32
|
+
kind: "read",
|
|
33
|
+
cause
|
|
34
|
+
})));
|
|
35
|
+
const document = yield* Yaml.parse(content).pipe(Effect.mapError((cause) => ({
|
|
36
|
+
path: pnpmWorkspacePath,
|
|
37
|
+
kind: "invalidYaml",
|
|
38
|
+
cause
|
|
39
|
+
})));
|
|
40
|
+
const patterns = pnpmPatternsOf(document);
|
|
41
|
+
if (patterns.length > 0) return patterns;
|
|
42
|
+
}
|
|
43
|
+
const manifestPath = path.join(root, "package.json");
|
|
44
|
+
if (!(yield* fs.exists(manifestPath).pipe(Effect.orElseSucceed(() => false)))) return [];
|
|
45
|
+
const content = yield* fs.readFileString(manifestPath).pipe(Effect.mapError((cause) => ({
|
|
46
|
+
path: manifestPath,
|
|
47
|
+
kind: "read",
|
|
48
|
+
cause
|
|
49
|
+
})));
|
|
50
|
+
const manifest = yield* Effect.try({
|
|
51
|
+
try: () => JSON.parse(content),
|
|
52
|
+
catch: (cause) => ({
|
|
53
|
+
path: manifestPath,
|
|
54
|
+
kind: "invalidJson",
|
|
55
|
+
cause
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
return manifestPatternsOf(manifest);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { manifestPatternsOf, pnpmPatternsOf, readPatterns };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { MAX_ENUMERATION_ENTRIES, PRUNED_DIRECTORIES } from "./limits.js";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/traverse.ts
|
|
4
|
+
/** Directory names never descended into. */
|
|
5
|
+
const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
|
|
6
|
+
/** Join root-relative POSIX segments; `""` is the root itself. */
|
|
7
|
+
const joinRelative = (base, entry) => base === "" ? entry : `${base}/${entry}`;
|
|
8
|
+
/**
|
|
9
|
+
* Whether `maxDepth` is a usable bound.
|
|
10
|
+
*
|
|
11
|
+
* `NaN < 1` is `false` and so is `2.5 < 1` — a bare relational guard admits both,
|
|
12
|
+
* and a `NaN` bound then runs the loop zero times and returns an empty result
|
|
13
|
+
* indistinguishable from a legitimate one. Integrality first. A bad bound is a
|
|
14
|
+
* PROGRAMMER error, not a data condition, so both entry points treat it as a
|
|
15
|
+
* defect (an `Effect.die` / a thrown `RangeError`) rather than a typed failure.
|
|
16
|
+
*/
|
|
17
|
+
const isValidMaxDepth = (maxDepth) => Number.isInteger(maxDepth) && maxDepth >= 1;
|
|
18
|
+
/** The message both entry points use when `maxDepth` is not a positive integer. */
|
|
19
|
+
const badMaxDepthMessage = (maxDepth) => `maxDepth must be a positive integer, received ${String(maxDepth)}`;
|
|
20
|
+
/**
|
|
21
|
+
* The shared worklist for one wildcard's descent.
|
|
22
|
+
*
|
|
23
|
+
* A worklist, not a recursion: it cannot overflow the stack, so there is no cap
|
|
24
|
+
* to get wrong.
|
|
25
|
+
*/
|
|
26
|
+
var Traversal = class {
|
|
27
|
+
#frames = [];
|
|
28
|
+
#head = 0;
|
|
29
|
+
#visited = 0;
|
|
30
|
+
#base;
|
|
31
|
+
#maxDepth;
|
|
32
|
+
#maxEntries;
|
|
33
|
+
constructor(base, absoluteBase, maxDepth, maxEntries = MAX_ENUMERATION_ENTRIES) {
|
|
34
|
+
this.#base = base;
|
|
35
|
+
this.#maxDepth = maxDepth;
|
|
36
|
+
this.#maxEntries = maxEntries;
|
|
37
|
+
this.#frames.push({
|
|
38
|
+
relative: base,
|
|
39
|
+
absolute: absoluteBase,
|
|
40
|
+
depth: 0
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The next directory to read, or `undefined` when the worklist is drained.
|
|
45
|
+
*
|
|
46
|
+
* A head index, never `Array.shift()`. `shift()` re-indexes the whole array on
|
|
47
|
+
* every dequeue, so draining a worklist anywhere near `MAX_ENUMERATION_ENTRIES`
|
|
48
|
+
* (100,000) is quadratic — the very budget that bounds the walk would become
|
|
49
|
+
* the slow path.
|
|
50
|
+
*/
|
|
51
|
+
next() {
|
|
52
|
+
if (this.#head >= this.#frames.length) return void 0;
|
|
53
|
+
const frame = this.#frames[this.#head];
|
|
54
|
+
this.#head += 1;
|
|
55
|
+
return frame;
|
|
56
|
+
}
|
|
57
|
+
/** Charge one directory read against the visit budget. */
|
|
58
|
+
charge() {
|
|
59
|
+
this.#visited += 1;
|
|
60
|
+
if (this.#visited > this.#maxEntries) return {
|
|
61
|
+
kind: "budgetExceeded",
|
|
62
|
+
detail: `visited more than ${this.#maxEntries} directories`
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Whether a child of `parent` lies within the depth cap.
|
|
67
|
+
*
|
|
68
|
+
* Callers must consult this BEFORE accepting a child as a package, not merely
|
|
69
|
+
* before descending into it. The cap bounds what the traversal *enumerates*;
|
|
70
|
+
* a directory beyond it is out of scope entirely, and gating only the descent
|
|
71
|
+
* is what let a package one level past the cap slip into the sync results.
|
|
72
|
+
*/
|
|
73
|
+
admits(parent) {
|
|
74
|
+
return parent.depth + 1 <= this.#maxDepth;
|
|
75
|
+
}
|
|
76
|
+
/** The stop a child beyond the depth cap produces. */
|
|
77
|
+
depthStop() {
|
|
78
|
+
return {
|
|
79
|
+
kind: "depthExceeded",
|
|
80
|
+
detail: `descended past ${this.#maxDepth} levels below "${this.#base}"`
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Queue a child of `parent` for descent. Only call when {@link Traversal.admits} holds. */
|
|
84
|
+
push(parent, relative, absolute) {
|
|
85
|
+
this.#frames.push({
|
|
86
|
+
relative,
|
|
87
|
+
absolute,
|
|
88
|
+
depth: parent.depth + 1
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
export { Traversal, badMaxDepthMessage, isPruned, isValidMaxDepth, joinRelative };
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@effected/workspaces",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Monorepo workspace tooling as Effect services — root discovery, package enumeration, the dependency graph, package-manager detection, pnpm catalog resolution, lockfile IO and git-based change detection.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"monorepo",
|
|
8
|
+
"workspaces",
|
|
9
|
+
"pnpm",
|
|
10
|
+
"npm",
|
|
11
|
+
"yarn",
|
|
12
|
+
"bun",
|
|
13
|
+
"dependency-graph",
|
|
14
|
+
"catalog",
|
|
15
|
+
"effect",
|
|
16
|
+
"effected"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/spencerbeggs/effected/tree/main/packages/workspaces#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/spencerbeggs/effected/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/spencerbeggs/effected.git",
|
|
25
|
+
"directory": "packages/workspaces"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"author": {
|
|
29
|
+
"name": "C. Spencer Beggs",
|
|
30
|
+
"email": "spencer@beggs.codes",
|
|
31
|
+
"url": "https://spencerbeg.gs"
|
|
32
|
+
},
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"type": "module",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./index.d.ts",
|
|
38
|
+
"import": "./index.js"
|
|
39
|
+
},
|
|
40
|
+
"./package.json": "./package.json"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@effected/git": "0.1.0",
|
|
44
|
+
"@effected/glob": "0.1.0",
|
|
45
|
+
"@effected/lockfiles": "0.1.0",
|
|
46
|
+
"@effected/npm": "0.1.0",
|
|
47
|
+
"@effected/package-json": "0.1.0",
|
|
48
|
+
"@effected/walker": "0.1.0",
|
|
49
|
+
"@effected/yaml": "0.1.0",
|
|
50
|
+
"@pnpm/catalogs.config": "^1100.0.0",
|
|
51
|
+
"@pnpm/catalogs.protocol-parser": "^1100.0.0",
|
|
52
|
+
"@pnpm/catalogs.resolver": "^1100.0.0",
|
|
53
|
+
"@pnpm/catalogs.types": "^1100.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"effect": "4.0.0-beta.98"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=24.11.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.58.9"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|