poe-code 12.0.2 → 12.0.3
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 +24 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +2 -2
- package/dist/metafile.json +1 -1
- package/package.json +8 -2
- package/packages/package-lint/dist/bundle-policy.d.ts +45 -0
- package/packages/package-lint/dist/bundle-policy.js +169 -0
- package/packages/package-lint/dist/model.d.ts +4 -10
- package/packages/package-lint/dist/model.js +4 -2
- package/packages/package-lint/dist/packlist.js +5 -1
- package/packages/package-lint/dist/rules/bundle-self-contained.js +11 -25
- package/packages/safe-fs/dist/contracts/abort.d.ts +5 -0
- package/packages/safe-fs/dist/contracts/cleanup.d.ts +1 -0
- package/packages/safe-fs/dist/contracts/errors.d.ts +49 -0
- package/packages/safe-fs/dist/contracts/filesystem.d.ts +96 -0
- package/packages/safe-fs/dist/contracts/index.d.ts +4 -0
- package/packages/safe-fs/dist/contracts/io.d.ts +8 -0
- package/packages/safe-fs/dist/contracts/path.d.ts +13 -0
- package/packages/safe-fs/dist/fs/memory/index.d.ts +58 -0
- package/packages/safe-fs/dist/fs/mount/comparison.d.ts +18 -0
- package/packages/safe-fs/dist/fs/mount/identity.d.ts +2 -0
- package/packages/safe-fs/dist/fs/mount/index.d.ts +44 -0
- package/packages/safe-fs/dist/fs/overlay/index.d.ts +72 -0
- package/packages/safe-fs/dist/fs/readonly/index.d.ts +30 -0
- package/packages/safe-fs/dist/fs/real/allocation.d.ts +1 -0
- package/packages/safe-fs/dist/fs/real/index.d.ts +76 -0
- package/packages/safe-fs/dist/fs/s3/authority.d.ts +13 -0
- package/packages/safe-fs/dist/fs/s3/filesystem.d.ts +93 -0
- package/packages/safe-fs/dist/fs/s3/http/index.d.ts +2 -0
- package/packages/safe-fs/dist/fs/s3/http/request.d.ts +16 -0
- package/packages/safe-fs/dist/fs/s3/http/signature.d.ts +20 -0
- package/packages/safe-fs/dist/fs/s3/http/transport.d.ts +3 -0
- package/packages/safe-fs/dist/fs/s3/http/types.d.ts +30 -0
- package/packages/safe-fs/dist/fs/s3/http/xml.d.ts +11 -0
- package/packages/safe-fs/dist/fs/s3/index.d.ts +6 -0
- package/packages/safe-fs/dist/fs/s3/mock.d.ts +48 -0
- package/packages/safe-fs/dist/fs/s3/transport.d.ts +103 -0
- package/packages/safe-fs/dist/fs/webdav/index.d.ts +2 -0
- package/packages/safe-fs/dist/fs/webdav/resource-id.d.ts +18 -0
- package/packages/safe-fs/dist/fs/webdav/webdav.d.ts +98 -0
- package/packages/safe-fs/dist/fs/webdav/xml.d.ts +15 -0
- package/packages/safe-fs/dist/index.d.ts +11 -0
- package/packages/safe-fs/dist/node/filesystem.d.ts +11 -0
- package/packages/safe-fs/dist/node/index.d.ts +2 -0
- package/packages/safe-fs/dist/node/stats.d.ts +4 -0
- package/packages/safe-fs/dist/node/values.d.ts +6 -0
- package/packages/safejs/dist/safe-fs.js +6476 -0
- package/packages/safejs/dist/safe-fs.js.map +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poe-code",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.3",
|
|
4
4
|
"description": "CLI tool to configure Poe API for developer workflows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"./skills": {
|
|
47
47
|
"types": "./dist/skills.d.ts",
|
|
48
48
|
"import": "./dist/skills.js"
|
|
49
|
+
},
|
|
50
|
+
"./safe-fs": {
|
|
51
|
+
"types": "./packages/safe-fs/dist/index.d.ts",
|
|
52
|
+
"import": "./packages/safejs/dist/safe-fs.js"
|
|
49
53
|
}
|
|
50
54
|
},
|
|
51
55
|
"workspaces": [
|
|
@@ -194,7 +198,8 @@
|
|
|
194
198
|
"packages/toolcraft-openapi/dist",
|
|
195
199
|
"packages/toolcraft-schema/dist",
|
|
196
200
|
"packages/workspace-resolver/dist",
|
|
197
|
-
"packages/worktree/dist"
|
|
201
|
+
"packages/worktree/dist",
|
|
202
|
+
"packages/safe-fs/dist/**/*.d.ts"
|
|
198
203
|
],
|
|
199
204
|
"engines": {
|
|
200
205
|
"node": ">=18.18"
|
|
@@ -270,6 +275,7 @@
|
|
|
270
275
|
"@poe-code/providers": "*",
|
|
271
276
|
"@poe-code/py-poe-spawn": "*",
|
|
272
277
|
"@poe-code/ralph": "*",
|
|
278
|
+
"@poe-code/safe-fs": "*",
|
|
273
279
|
"@poe-code/safejs": "*",
|
|
274
280
|
"@poe-code/superintendent": "*",
|
|
275
281
|
"@poe-code/task-list": "*",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const canonicalFs: {
|
|
2
|
+
readonly workspace: "../../safe-fs/dist/index.js";
|
|
3
|
+
readonly specifier: "poe-code/safe-fs";
|
|
4
|
+
readonly source: "packages/safe-fs/src/index.ts";
|
|
5
|
+
readonly runtime: "packages/safejs/dist/safe-fs.js";
|
|
6
|
+
readonly types: "packages/safe-fs/dist/index.d.ts";
|
|
7
|
+
};
|
|
8
|
+
export interface BundleMetafile {
|
|
9
|
+
inputs?: Record<string, unknown>;
|
|
10
|
+
outputs?: Record<string, {
|
|
11
|
+
entryPoint?: string;
|
|
12
|
+
imports?: {
|
|
13
|
+
path?: string;
|
|
14
|
+
external?: boolean;
|
|
15
|
+
kind?: string;
|
|
16
|
+
}[];
|
|
17
|
+
inputs?: Record<string, unknown>;
|
|
18
|
+
cssBundle?: string;
|
|
19
|
+
}>;
|
|
20
|
+
canonicalBundle?: {
|
|
21
|
+
entryPoints: string[];
|
|
22
|
+
metafile: BundleMetafile;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface BundleIssue {
|
|
26
|
+
external: string;
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
interface PackageManifest {
|
|
30
|
+
name: string;
|
|
31
|
+
exports?: unknown;
|
|
32
|
+
dependencies?: Record<string, string>;
|
|
33
|
+
optionalDependencies?: Record<string, string>;
|
|
34
|
+
}
|
|
35
|
+
export declare function findBundleIssues(manifest: PackageManifest, workspaceNames: ReadonlySet<string>, metafile: BundleMetafile, packedFiles: ReadonlySet<string>): BundleIssue[];
|
|
36
|
+
export declare function collectPackageFiles(rootDir: string, entries: readonly string[], files: {
|
|
37
|
+
readdir(filename: string): Promise<{
|
|
38
|
+
name: string;
|
|
39
|
+
isDirectory(): boolean;
|
|
40
|
+
}[]>;
|
|
41
|
+
stat?(filename: string): Promise<{
|
|
42
|
+
isFile(): boolean;
|
|
43
|
+
}>;
|
|
44
|
+
}): Promise<Set<string>>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { isBuiltin } from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const canonicalFs = {
|
|
4
|
+
workspace: "@poe-code/safe-fs",
|
|
5
|
+
specifier: "poe-code/safe-fs",
|
|
6
|
+
source: "packages/safe-fs/src/index.ts",
|
|
7
|
+
runtime: "packages/safejs/dist/safe-fs.js",
|
|
8
|
+
types: "packages/safe-fs/dist/index.d.ts"
|
|
9
|
+
};
|
|
10
|
+
function record(value) {
|
|
11
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
12
|
+
? value
|
|
13
|
+
: {};
|
|
14
|
+
}
|
|
15
|
+
function packageName(specifier) {
|
|
16
|
+
if (!specifier ||
|
|
17
|
+
specifier.startsWith(".") ||
|
|
18
|
+
specifier.startsWith("/") ||
|
|
19
|
+
[...specifier].some((character) => character.charCodeAt(0) <= 32) ||
|
|
20
|
+
[":", "\\", "?", "#", "%"].some((character) => specifier.includes(character)))
|
|
21
|
+
return undefined;
|
|
22
|
+
const parts = specifier.split("/");
|
|
23
|
+
if (parts.some((part) => !part || part === "." || part === ".."))
|
|
24
|
+
return undefined;
|
|
25
|
+
if (specifier.startsWith("@")) {
|
|
26
|
+
if (parts.length < 2 || parts[0].length === 1)
|
|
27
|
+
return undefined;
|
|
28
|
+
return `${parts[0]}/${parts[1]}`;
|
|
29
|
+
}
|
|
30
|
+
return parts[0];
|
|
31
|
+
}
|
|
32
|
+
export function findBundleIssues(manifest, workspaceNames, metafile, packedFiles) {
|
|
33
|
+
const issues = [];
|
|
34
|
+
const exported = record(record(manifest.exports)["./safe-fs"]);
|
|
35
|
+
const imports = new Set(Object.values(metafile.outputs ?? {}).flatMap((output) => (output.imports ?? [])
|
|
36
|
+
.filter((dependency) => dependency.external)
|
|
37
|
+
.map((dependency) => dependency.path ?? "")));
|
|
38
|
+
const runtimeDependencies = new Set([
|
|
39
|
+
...Object.keys(manifest.dependencies ?? {}),
|
|
40
|
+
...Object.keys(manifest.optionalDependencies ?? {})
|
|
41
|
+
]);
|
|
42
|
+
for (const specifier of [...imports].sort()) {
|
|
43
|
+
if (isBuiltin(specifier))
|
|
44
|
+
continue;
|
|
45
|
+
if (specifier === canonicalFs.specifier && manifest.name === "poe-code")
|
|
46
|
+
continue;
|
|
47
|
+
const dependency = packageName(specifier);
|
|
48
|
+
const reason = !dependency
|
|
49
|
+
? "invalid-external"
|
|
50
|
+
: dependency === manifest.name || workspaceNames.has(dependency)
|
|
51
|
+
? "workspace-not-inlined"
|
|
52
|
+
: !runtimeDependencies.has(dependency)
|
|
53
|
+
? "undeclared-dependency"
|
|
54
|
+
: undefined;
|
|
55
|
+
if (reason)
|
|
56
|
+
issues.push({ external: specifier, reason });
|
|
57
|
+
}
|
|
58
|
+
if (!metafile.canonicalBundle &&
|
|
59
|
+
!imports.has(canonicalFs.specifier) &&
|
|
60
|
+
!Object.keys(exported).length)
|
|
61
|
+
return issues;
|
|
62
|
+
const fail = (reason) => issues.push({ external: canonicalFs.specifier, reason });
|
|
63
|
+
if (manifest.name !== "poe-code" ||
|
|
64
|
+
exported.import !== `./${canonicalFs.runtime}` ||
|
|
65
|
+
exported.types !== `./${canonicalFs.types}` ||
|
|
66
|
+
Object.keys(exported).some((condition) => condition !== "import" && condition !== "types")) {
|
|
67
|
+
fail("invalid-canonical-export");
|
|
68
|
+
}
|
|
69
|
+
if (!packedFiles.has(canonicalFs.types))
|
|
70
|
+
fail("unpacked-canonical-types");
|
|
71
|
+
if ([...packedFiles].some((filename) => filename.startsWith("packages/safe-fs/dist/") &&
|
|
72
|
+
[".js", ".mjs", ".cjs"].some((extension) => filename.endsWith(extension))))
|
|
73
|
+
fail("duplicate-packed-runtime");
|
|
74
|
+
if (Object.keys(metafile.inputs ?? {}).some((input) => input.startsWith("packages/safe-fs/src/"))) {
|
|
75
|
+
fail("duplicate-canonical-runtime");
|
|
76
|
+
}
|
|
77
|
+
const canonical = metafile.canonicalBundle;
|
|
78
|
+
if (!canonical ||
|
|
79
|
+
!Array.isArray(canonical.entryPoints) ||
|
|
80
|
+
!canonical.entryPoints.includes(canonicalFs.source)) {
|
|
81
|
+
fail("missing-canonical-root");
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
84
|
+
const outputs = canonical.metafile.outputs ?? {};
|
|
85
|
+
if (!Object.hasOwn(canonical.metafile.inputs ?? {}, canonicalFs.source))
|
|
86
|
+
fail("missing-canonical-source");
|
|
87
|
+
if (outputs[canonicalFs.runtime]?.entryPoint !== canonicalFs.source)
|
|
88
|
+
fail("invalid-canonical-root");
|
|
89
|
+
for (const entry of canonical.entryPoints) {
|
|
90
|
+
if (!Object.values(outputs).some((output) => output.entryPoint === entry))
|
|
91
|
+
fail("missing-declared-root");
|
|
92
|
+
}
|
|
93
|
+
const pending = [canonicalFs.runtime];
|
|
94
|
+
const visited = new Set();
|
|
95
|
+
while (pending.length) {
|
|
96
|
+
const filename = pending.pop();
|
|
97
|
+
if (visited.has(filename))
|
|
98
|
+
continue;
|
|
99
|
+
visited.add(filename);
|
|
100
|
+
if (!filename.startsWith("packages/safejs/dist/") ||
|
|
101
|
+
path.posix.normalize(filename) !== filename) {
|
|
102
|
+
fail("invalid-canonical-path");
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const output = outputs[filename];
|
|
106
|
+
if (!output) {
|
|
107
|
+
fail("missing-canonical-output");
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (!packedFiles.has(filename))
|
|
111
|
+
fail("unpacked-canonical-output");
|
|
112
|
+
if (filename.endsWith(".js"))
|
|
113
|
+
pending.push(`${filename}.map`);
|
|
114
|
+
if (Object.keys(output.inputs ?? {}).some((input) => !input.startsWith("packages/safe-fs/src/")))
|
|
115
|
+
fail("foreign-canonical-input");
|
|
116
|
+
if (output.cssBundle)
|
|
117
|
+
pending.push(output.cssBundle);
|
|
118
|
+
for (const dependency of output.imports ?? []) {
|
|
119
|
+
if (dependency.external) {
|
|
120
|
+
if (!dependency.path || !isBuiltin(dependency.path))
|
|
121
|
+
fail("external-canonical-dependency");
|
|
122
|
+
}
|
|
123
|
+
else if (dependency.path)
|
|
124
|
+
pending.push(dependency.path);
|
|
125
|
+
else
|
|
126
|
+
fail("missing-canonical-edge");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return issues;
|
|
130
|
+
}
|
|
131
|
+
export async function collectPackageFiles(rootDir, entries, files) {
|
|
132
|
+
const packed = new Set();
|
|
133
|
+
async function visit(filename, declarationsOnly) {
|
|
134
|
+
const absolute = path.join(rootDir, filename);
|
|
135
|
+
let children;
|
|
136
|
+
try {
|
|
137
|
+
children = await files.readdir(absolute);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
const code = error.code;
|
|
141
|
+
if (code === "ENOENT")
|
|
142
|
+
return;
|
|
143
|
+
if (code !== "ENOTDIR")
|
|
144
|
+
throw error;
|
|
145
|
+
if ((!declarationsOnly || filename.endsWith(".d.ts")) &&
|
|
146
|
+
(!files.stat || (await files.stat(absolute)).isFile()))
|
|
147
|
+
packed.add(filename);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
for (const child of children) {
|
|
151
|
+
const relative = path.posix.join(filename, child.name);
|
|
152
|
+
if (child.isDirectory())
|
|
153
|
+
await visit(relative, declarationsOnly);
|
|
154
|
+
else if (!declarationsOnly || child.name.endsWith(".d.ts"))
|
|
155
|
+
packed.add(relative);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const entry of entries) {
|
|
159
|
+
const declarationsOnly = entry.endsWith("/**/*.d.ts");
|
|
160
|
+
const directory = declarationsOnly ? entry.slice(0, -"/**/*.d.ts".length) : entry;
|
|
161
|
+
if (directory.includes("*") ||
|
|
162
|
+
directory.startsWith("/") ||
|
|
163
|
+
directory.split("/").includes("..")) {
|
|
164
|
+
throw new Error(`Unsupported package files entry: ${entry}`);
|
|
165
|
+
}
|
|
166
|
+
await visit(directory, declarationsOnly);
|
|
167
|
+
}
|
|
168
|
+
return packed;
|
|
169
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BundleMetafile } from "./bundle-policy.js";
|
|
1
2
|
import { type PackageFileView, type PacklistProvider } from "./packlist.js";
|
|
2
3
|
import { type RuntimeAssetDeclaration, type RuntimeFileAssetView } from "./runtime-files.js";
|
|
3
4
|
import { type SourceImportView } from "./source-imports.js";
|
|
@@ -97,6 +98,8 @@ export interface BuildView {
|
|
|
97
98
|
inlinedDirs: Set<string>;
|
|
98
99
|
/** Bare specifiers left external by the bundle, reduced to package names. */
|
|
99
100
|
externals: Set<string>;
|
|
101
|
+
externalImports: Set<string>;
|
|
102
|
+
metafile: BundleMetafile;
|
|
100
103
|
}
|
|
101
104
|
export interface Violation {
|
|
102
105
|
rule: string;
|
|
@@ -133,16 +136,7 @@ export declare function loadWorkspace(fs: LintFs, rootDir: string, options?: {
|
|
|
133
136
|
export declare function releaseTargetDirs(model: WorkspaceModel): Set<string>;
|
|
134
137
|
/** A package genuinely reaches npm: it is a public npm package a release workflow publishes. */
|
|
135
138
|
export declare function isGenuinelyPublished(model: WorkspaceModel, pkg: PackageInfo): boolean;
|
|
136
|
-
export declare function parseMetafile(meta:
|
|
137
|
-
inputs?: Record<string, unknown>;
|
|
138
|
-
outputs?: Record<string, {
|
|
139
|
-
imports?: {
|
|
140
|
-
path?: string;
|
|
141
|
-
external?: boolean;
|
|
142
|
-
kind?: string;
|
|
143
|
-
}[];
|
|
144
|
-
}>;
|
|
145
|
-
}): BuildView;
|
|
139
|
+
export declare function parseMetafile(meta: BundleMetafile): BuildView;
|
|
146
140
|
export declare function loadBuildView(fs: LintFs, rootDir: string): Promise<BuildView | undefined>;
|
|
147
141
|
/** All workspace packages plus the root package. */
|
|
148
142
|
export declare function allPackages(model: WorkspaceModel): PackageInfo[];
|
|
@@ -427,16 +427,18 @@ export function parseMetafile(meta) {
|
|
|
427
427
|
inlinedDirs.add(dir);
|
|
428
428
|
}
|
|
429
429
|
const externals = new Set();
|
|
430
|
+
const externalImports = new Set();
|
|
430
431
|
for (const output of Object.values(meta.outputs ?? {})) {
|
|
431
432
|
for (const imp of output.imports ?? []) {
|
|
432
|
-
if (imp.external &&
|
|
433
|
+
if (imp.external && typeof imp.path === "string") {
|
|
434
|
+
externalImports.add(imp.path);
|
|
433
435
|
const name = toPackageName(imp.path);
|
|
434
436
|
if (name)
|
|
435
437
|
externals.add(name);
|
|
436
438
|
}
|
|
437
439
|
}
|
|
438
440
|
}
|
|
439
|
-
return { inlinedDirs, externals };
|
|
441
|
+
return { inlinedDirs, externals, externalImports, metafile: meta };
|
|
440
442
|
}
|
|
441
443
|
export async function loadBuildView(fs, rootDir) {
|
|
442
444
|
let raw;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { collectPackageFiles } from "./bundle-policy.js";
|
|
2
3
|
function toPosix(p) {
|
|
3
4
|
return p.replaceAll("\\", "/");
|
|
4
5
|
}
|
|
@@ -66,7 +67,10 @@ async function listFallbackPackFiles(fs, packageRoot) {
|
|
|
66
67
|
return listAllFiles(fs, packageRoot);
|
|
67
68
|
const files = new Set();
|
|
68
69
|
for (const entry of allowlist) {
|
|
69
|
-
|
|
70
|
+
const listedFiles = entry.endsWith("/**/*.d.ts")
|
|
71
|
+
? await collectPackageFiles(packageRoot, [entry], fs)
|
|
72
|
+
: await listFilesEntry(fs, packageRoot, entry);
|
|
73
|
+
for (const listed of listedFiles)
|
|
70
74
|
files.add(listed);
|
|
71
75
|
}
|
|
72
76
|
return files;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { findBundleIssues } from "../bundle-policy.js";
|
|
2
2
|
const id = "bundle-self-contained";
|
|
3
3
|
function workspaceNames(model) {
|
|
4
4
|
const names = new Set(model.packages.map((p) => p.name));
|
|
@@ -18,30 +18,16 @@ export const bundleSelfContained = {
|
|
|
18
18
|
return [];
|
|
19
19
|
const violations = [];
|
|
20
20
|
const workspace = workspaceNames(model);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
fix: `Add a source alias for ${external} so the bundle inlines it.`
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
else if (!rootDeps.has(external) && !isBuiltin(external)) {
|
|
35
|
-
violations.push({
|
|
36
|
-
rule: id,
|
|
37
|
-
package: model.root.name,
|
|
38
|
-
severity: "error",
|
|
39
|
-
via: "bundle",
|
|
40
|
-
detail: { external, reason: "undeclared-dependency" },
|
|
41
|
-
message: `bundle externalizes ${external}, which is not declared in root dependencies`,
|
|
42
|
-
fix: `Add ${external} to root "dependencies".`
|
|
43
|
-
});
|
|
44
|
-
}
|
|
21
|
+
for (const issue of findBundleIssues(model.root, workspace, build.metafile, model.packageFiles.get(".")?.files ?? new Set())) {
|
|
22
|
+
violations.push({
|
|
23
|
+
rule: id,
|
|
24
|
+
package: workspace.has(issue.external) ? issue.external : model.root.name,
|
|
25
|
+
severity: "error",
|
|
26
|
+
via: "bundle",
|
|
27
|
+
detail: { ...issue },
|
|
28
|
+
message: `bundle import ${issue.external} violates publication policy: ${issue.reason}`,
|
|
29
|
+
fix: "Inline private workspace code or supply the exact declared and packed canonical artifact; declare ordinary runtime dependencies."
|
|
30
|
+
});
|
|
45
31
|
}
|
|
46
32
|
return violations;
|
|
47
33
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function finishCleanup(cleanup: () => unknown, failed: boolean): Promise<void>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
declare const descriptions: {
|
|
2
|
+
readonly EACCES: "permission denied";
|
|
3
|
+
readonly EAGAIN: "resource temporarily unavailable";
|
|
4
|
+
readonly EBADF: "bad file descriptor";
|
|
5
|
+
readonly EBUSY: "resource busy or locked";
|
|
6
|
+
readonly ECANCELED: "operation canceled";
|
|
7
|
+
readonly EEXIST: "file already exists";
|
|
8
|
+
readonly EFBIG: "file too large";
|
|
9
|
+
readonly EINTR: "interrupted system call";
|
|
10
|
+
readonly EINVAL: "invalid argument";
|
|
11
|
+
readonly EIO: "input/output error";
|
|
12
|
+
readonly EISDIR: "illegal operation on a directory";
|
|
13
|
+
readonly ELOOP: "too many symbolic links encountered";
|
|
14
|
+
readonly EMFILE: "too many open files";
|
|
15
|
+
readonly ENAMETOOLONG: "name too long";
|
|
16
|
+
readonly ENFILE: "file table overflow";
|
|
17
|
+
readonly ENOENT: "no such file or directory";
|
|
18
|
+
readonly ENOMEM: "not enough memory";
|
|
19
|
+
readonly ENOSPC: "no space left on device";
|
|
20
|
+
readonly ENOSYS: "function not implemented";
|
|
21
|
+
readonly ENOTDIR: "not a directory";
|
|
22
|
+
readonly ENOTEMPTY: "directory not empty";
|
|
23
|
+
readonly ENOTSUP: "operation not supported";
|
|
24
|
+
readonly EOPNOTSUPP: "operation not supported";
|
|
25
|
+
readonly EPERM: "operation not permitted";
|
|
26
|
+
readonly EPIPE: "broken pipe";
|
|
27
|
+
readonly EROFS: "read-only file system";
|
|
28
|
+
readonly ETIMEDOUT: "operation timed out";
|
|
29
|
+
readonly EXDEV: "cross-device link not permitted";
|
|
30
|
+
};
|
|
31
|
+
export type ErrnoCode = keyof typeof descriptions;
|
|
32
|
+
export interface FsErrorOptions extends ErrorOptions {
|
|
33
|
+
readonly syscall?: string;
|
|
34
|
+
readonly path?: string;
|
|
35
|
+
readonly dest?: string;
|
|
36
|
+
readonly message?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare class FsError extends Error {
|
|
39
|
+
readonly code: ErrnoCode;
|
|
40
|
+
readonly errno: number;
|
|
41
|
+
readonly syscall?: string;
|
|
42
|
+
readonly path?: string;
|
|
43
|
+
readonly dest?: string;
|
|
44
|
+
constructor(code: ErrnoCode, options?: FsErrorOptions);
|
|
45
|
+
}
|
|
46
|
+
export declare function isErrnoCode(code: unknown): code is ErrnoCode;
|
|
47
|
+
export declare function isFsError(error: unknown, code?: ErrnoCode): error is FsError;
|
|
48
|
+
export declare function toFsError(error: unknown, options?: FsErrorOptions): FsError;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ByteSource } from "./io.js";
|
|
2
|
+
export type FileType = "file" | "directory" | "symlink";
|
|
3
|
+
export type EntryComparison = "same" | "distinct" | "unknown";
|
|
4
|
+
export interface FileStat {
|
|
5
|
+
readonly type: FileType;
|
|
6
|
+
readonly size: number;
|
|
7
|
+
readonly allocatedBytes?: number;
|
|
8
|
+
readonly mode: number;
|
|
9
|
+
readonly mtimeMs: number;
|
|
10
|
+
readonly atimeMs: number;
|
|
11
|
+
readonly ctimeMs: number;
|
|
12
|
+
readonly birthtimeMs?: number;
|
|
13
|
+
readonly identityScope?: object | symbol;
|
|
14
|
+
readonly ino?: number;
|
|
15
|
+
readonly dev?: number;
|
|
16
|
+
readonly nlink?: number;
|
|
17
|
+
readonly uid?: number;
|
|
18
|
+
readonly gid?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface DirectoryEntry {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly type: FileType;
|
|
23
|
+
}
|
|
24
|
+
export interface FileSystemCapabilities {
|
|
25
|
+
readonly readOnly?: boolean;
|
|
26
|
+
readonly symlinks?: boolean;
|
|
27
|
+
readonly hardlinks?: boolean;
|
|
28
|
+
readonly permissions?: boolean;
|
|
29
|
+
readonly timestamps?: boolean;
|
|
30
|
+
readonly atomicRename?: boolean;
|
|
31
|
+
readonly snapshotRmdir?: boolean;
|
|
32
|
+
readonly streamingRead?: boolean;
|
|
33
|
+
readonly streamingWrite?: boolean;
|
|
34
|
+
readonly [capability: string]: boolean | undefined;
|
|
35
|
+
}
|
|
36
|
+
export interface FsOptions {
|
|
37
|
+
readonly signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
export interface ReadFileOptions extends FsOptions {
|
|
40
|
+
readonly maxBytes?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface WriteFileOptions extends FsOptions {
|
|
43
|
+
readonly flag?: "w" | "wx" | "a" | "ax";
|
|
44
|
+
readonly mode?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface AppendFileOptions extends FsOptions {
|
|
47
|
+
readonly mode?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface MkdirOptions extends FsOptions {
|
|
50
|
+
readonly recursive?: boolean;
|
|
51
|
+
readonly mode?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface RemoveOptions extends FsOptions {
|
|
54
|
+
readonly recursive?: boolean;
|
|
55
|
+
readonly force?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface CopyFileOptions extends FsOptions {
|
|
58
|
+
readonly exclusive?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface ReadStreamOptions extends FsOptions {
|
|
61
|
+
readonly start?: number;
|
|
62
|
+
readonly endExclusive?: number;
|
|
63
|
+
readonly chunkSize?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface FileSystem {
|
|
66
|
+
readonly capabilities: FileSystemCapabilities;
|
|
67
|
+
readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
|
|
68
|
+
writeFile(path: string, data: Uint8Array, options?: WriteFileOptions): Promise<void>;
|
|
69
|
+
appendFile(path: string, data: Uint8Array, options?: AppendFileOptions): Promise<void>;
|
|
70
|
+
stat(path: string, options?: FsOptions): Promise<FileStat>;
|
|
71
|
+
lstat(path: string, options?: FsOptions): Promise<FileStat>;
|
|
72
|
+
compareEntry?(path: string, peer: FileSystem, peerPath: string, options?: FsOptions): Promise<EntryComparison>;
|
|
73
|
+
readdir(path: string, options?: FsOptions): Promise<DirectoryEntry[]>;
|
|
74
|
+
mkdir(path: string, options?: MkdirOptions): Promise<void>;
|
|
75
|
+
rm(path: string, options?: RemoveOptions): Promise<void>;
|
|
76
|
+
rmdir?(path: string, options?: FsOptions): Promise<void>;
|
|
77
|
+
rename(source: string, destination: string, options?: FsOptions): Promise<void>;
|
|
78
|
+
copyFile(source: string, destination: string, options?: CopyFileOptions): Promise<void>;
|
|
79
|
+
realpath(path: string, options?: FsOptions): Promise<string>;
|
|
80
|
+
access(path: string, mode?: number, options?: FsOptions): Promise<void>;
|
|
81
|
+
readlink?(path: string, options?: FsOptions): Promise<string>;
|
|
82
|
+
symlink?(target: string, path: string, options?: FsOptions): Promise<void>;
|
|
83
|
+
link?(existingPath: string, newPath: string, options?: FsOptions): Promise<void>;
|
|
84
|
+
chmod?(path: string, mode: number, options?: FsOptions): Promise<void>;
|
|
85
|
+
utimes?(path: string, atimeMs: number, mtimeMs: number, options?: FsOptions): Promise<void>;
|
|
86
|
+
truncate?(path: string, length?: number, options?: FsOptions): Promise<void>;
|
|
87
|
+
readStream?(path: string, options?: ReadStreamOptions): ByteSource;
|
|
88
|
+
writeStream?(path: string, source: ByteSource, options?: WriteFileOptions): Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
export type FileSystemFactory = (options: Readonly<Record<string, unknown>>) => FileSystem | Promise<FileSystem>;
|
|
91
|
+
export declare const ACCESS_MODES: Readonly<{
|
|
92
|
+
F_OK: 0;
|
|
93
|
+
R_OK: 4;
|
|
94
|
+
W_OK: 2;
|
|
95
|
+
X_OK: 1;
|
|
96
|
+
}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ByteSource = AsyncIterable<Uint8Array>;
|
|
2
|
+
export interface CollectOptions {
|
|
3
|
+
readonly maxBytes: number;
|
|
4
|
+
readonly signal?: AbortSignal;
|
|
5
|
+
}
|
|
6
|
+
export declare function toByteSource(input: string | Uint8Array): ByteSource;
|
|
7
|
+
export declare function collectBytes(source: ByteSource, options: CollectOptions): Promise<Uint8Array>;
|
|
8
|
+
export declare function readBytes(source: ByteSource, signal?: AbortSignal): AsyncGenerator<Uint8Array>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
export declare const posixPath: typeof posix;
|
|
3
|
+
export declare const basename: typeof posix.basename;
|
|
4
|
+
export declare const dirname: typeof posix.dirname;
|
|
5
|
+
export declare const extname: typeof posix.extname;
|
|
6
|
+
export declare const joinPath: typeof posix.join;
|
|
7
|
+
export declare const isAbsolutePath: typeof posix.isAbsolute;
|
|
8
|
+
export declare function validatePath(path: string): void;
|
|
9
|
+
export declare function resolvePath(cwd: string, ...paths: string[]): string;
|
|
10
|
+
export declare function normalizePath(path: string, cwd?: string): string;
|
|
11
|
+
export declare function relativePath(from: string, to: string): string;
|
|
12
|
+
export declare function isPathWithin(root: string, path: string): boolean;
|
|
13
|
+
export declare function assertPathWithin(root: string, path: string): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { AppendFileOptions, CopyFileOptions, DirectoryEntry, EntryComparison, FileStat, FileSystem, FsOptions, MkdirOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions } from "../../contracts/filesystem.js";
|
|
2
|
+
import type { ByteSource } from "../../contracts/io.js";
|
|
3
|
+
export declare class MemoryFileSystem implements FileSystem {
|
|
4
|
+
readonly capabilities: Readonly<{
|
|
5
|
+
readOnly: false;
|
|
6
|
+
symlinks: true;
|
|
7
|
+
hardlinks: true;
|
|
8
|
+
permissions: true;
|
|
9
|
+
timestamps: true;
|
|
10
|
+
atomicRename: true;
|
|
11
|
+
streamingRead: true;
|
|
12
|
+
streamingWrite: true;
|
|
13
|
+
}>;
|
|
14
|
+
private readonly identityScope;
|
|
15
|
+
private nextInode;
|
|
16
|
+
private readonly root;
|
|
17
|
+
constructor();
|
|
18
|
+
compareEntry(path: string, peer: FileSystem, peerPath: string, options?: FsOptions): Promise<EntryComparison>;
|
|
19
|
+
private metadata;
|
|
20
|
+
private directory;
|
|
21
|
+
private fail;
|
|
22
|
+
private validatePath;
|
|
23
|
+
private permission;
|
|
24
|
+
private mode;
|
|
25
|
+
private integer;
|
|
26
|
+
private changed;
|
|
27
|
+
private resolve;
|
|
28
|
+
private file;
|
|
29
|
+
private entry;
|
|
30
|
+
private terminalDot;
|
|
31
|
+
private snapshot;
|
|
32
|
+
private bytes;
|
|
33
|
+
private allocate;
|
|
34
|
+
private openWrite;
|
|
35
|
+
private append;
|
|
36
|
+
readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
|
|
37
|
+
writeFile(path: string, data: Uint8Array, options?: WriteFileOptions): Promise<void>;
|
|
38
|
+
appendFile(path: string, data: Uint8Array, options?: AppendFileOptions): Promise<void>;
|
|
39
|
+
stat(path: string, options?: FsOptions): Promise<FileStat>;
|
|
40
|
+
lstat(path: string, options?: FsOptions): Promise<FileStat>;
|
|
41
|
+
readdir(path: string, options?: FsOptions): Promise<DirectoryEntry[]>;
|
|
42
|
+
mkdir(path: string, options?: MkdirOptions): Promise<void>;
|
|
43
|
+
rmdir(path: string, options?: FsOptions): Promise<void>;
|
|
44
|
+
rm(path: string, options?: RemoveOptions): Promise<void>;
|
|
45
|
+
rename(source: string, destination: string, options?: FsOptions): Promise<void>;
|
|
46
|
+
copyFile(source: string, destination: string, options?: CopyFileOptions): Promise<void>;
|
|
47
|
+
realpath(path: string, options?: FsOptions): Promise<string>;
|
|
48
|
+
access(path: string, mode?: number, options?: FsOptions): Promise<void>;
|
|
49
|
+
readlink(path: string, options?: FsOptions): Promise<string>;
|
|
50
|
+
symlink(target: string, path: string, options?: FsOptions): Promise<void>;
|
|
51
|
+
link(existingPath: string, newPath: string, options?: FsOptions): Promise<void>;
|
|
52
|
+
chmod(path: string, mode: number, options?: FsOptions): Promise<void>;
|
|
53
|
+
utimes(path: string, atimeMs: number, mtimeMs: number, options?: FsOptions): Promise<void>;
|
|
54
|
+
truncate(path: string, length?: number, options?: FsOptions): Promise<void>;
|
|
55
|
+
readStream(path: string, options?: ReadStreamOptions): ByteSource;
|
|
56
|
+
writeStream(path: string, source: ByteSource, options?: WriteFileOptions): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
export declare function createMemoryFileSystem(): MemoryFileSystem;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EntryComparison, FileStat, FileSystem, FsOptions } from "../../contracts/filesystem.js";
|
|
2
|
+
export interface EntryLocation {
|
|
3
|
+
readonly filesystem: FileSystem;
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly readOnly?: boolean;
|
|
6
|
+
readonly stat?: FileStat;
|
|
7
|
+
}
|
|
8
|
+
export interface EntryView extends EntryLocation {
|
|
9
|
+
readonly stat: FileStat;
|
|
10
|
+
readonly readOnly: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type EntryViewResolver = (path: string, options: FsOptions) => Promise<EntryLocation>;
|
|
13
|
+
export type EntryAuthority = (own: EntryView, peer: EntryView, options: FsOptions) => Promise<EntryComparison>;
|
|
14
|
+
export declare function registerEntryView(filesystem: FileSystem, resolver: EntryViewResolver): void;
|
|
15
|
+
export declare function registerEntryAuthority(filesystem: FileSystem, authority: EntryAuthority): void;
|
|
16
|
+
export declare function resolveEntryView(filesystem: FileSystem, path: string, options?: FsOptions): Promise<EntryView>;
|
|
17
|
+
export declare function compareResolvedEntries(own: EntryView, peer: EntryView, options?: FsOptions): Promise<EntryComparison>;
|
|
18
|
+
export declare function compareEntries(filesystem: FileSystem, path: string, peer: FileSystem, peerPath: string, options?: FsOptions): Promise<EntryComparison>;
|