nerdsystem 0.0.11 → 0.0.12
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 +13 -2
- package/dist/api.d.ts +39 -0
- package/dist/api.js +54 -12
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +21 -9
- package/dist/commands/admin.js +1 -1
- package/dist/commands/deploy.d.ts +58 -5
- package/dist/commands/deploy.js +122 -30
- package/dist/commands/dev.js +4 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +5 -4
- package/dist/commands/ops.d.ts +15 -0
- package/dist/commands/ops.js +7 -0
- package/dist/commands/pull.d.ts +31 -0
- package/dist/commands/pull.js +137 -0
- package/dist/commands/save.d.ts +27 -0
- package/dist/commands/save.js +67 -0
- package/dist/commands/source.d.ts +38 -0
- package/dist/commands/source.js +145 -0
- package/dist/commands/trash.d.ts +1 -1
- package/dist/commands/trash.js +2 -3
- package/dist/gates/text.d.ts +65 -0
- package/dist/gates/text.js +108 -0
- package/dist/snapshot.d.ts +161 -0
- package/dist/snapshot.js +896 -0
- package/package.json +2 -1
- package/template/.claude/skills/nerdsystem/SKILL.md +10 -2
- package/template/.cursor/rules/nerdsystem.mdc +11 -3
- package/template/.github/copilot-instructions.md +11 -3
- package/template/AGENTS.md +11 -3
- package/template/CLAUDE.md +2 -1
- package/template/GEMINI.md +11 -3
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type SnapshotManifest } from "./gates/text.js";
|
|
2
|
+
export { MAX_SNAPSHOT_FILE_BYTES, MAX_SOURCE_BYTES, MAX_SOURCE_FILES, MAX_SOURCE_UNPACKED, SNAPSHOT_MANIFEST, validateSnapshotEntry, type SnapshotFile, type SnapshotManifest } from "./gates/text.js";
|
|
3
|
+
export type SnapshotErrorCode = "invalid_snapshot" | "not_empty" | "changed" | "too_large";
|
|
4
|
+
export declare class SnapshotError extends Error {
|
|
5
|
+
readonly code: SnapshotErrorCode;
|
|
6
|
+
constructor(message: string, code: SnapshotErrorCode);
|
|
7
|
+
}
|
|
8
|
+
export declare function formatMb(bytes: number): string;
|
|
9
|
+
export interface SnapshotCandidate {
|
|
10
|
+
/** Posix path relative to the root. */
|
|
11
|
+
path: string;
|
|
12
|
+
abs: string;
|
|
13
|
+
size: number;
|
|
14
|
+
/** 0o644 or 0o755. */
|
|
15
|
+
mode: number;
|
|
16
|
+
}
|
|
17
|
+
export interface SkippedFile {
|
|
18
|
+
path: string;
|
|
19
|
+
size: number;
|
|
20
|
+
reason: string;
|
|
21
|
+
}
|
|
22
|
+
export interface SnapshotSelection {
|
|
23
|
+
files: SnapshotCandidate[];
|
|
24
|
+
warnings: string[];
|
|
25
|
+
skipped: SkippedFile[];
|
|
26
|
+
/** Ignored files a rebuild needs that were kept anyway (every one; `warnings` folds past 20). */
|
|
27
|
+
forced: string[];
|
|
28
|
+
/** Where the candidate list came from. */
|
|
29
|
+
listedBy: "git" | "walk";
|
|
30
|
+
}
|
|
31
|
+
export interface ListOptions {
|
|
32
|
+
/** Set false to skip git and use the filesystem walker (tests). Default true. */
|
|
33
|
+
useGit?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** `{ sha, branch }` of the checkout at `root`, or null when there is no git, no repo, or no commit yet. */
|
|
36
|
+
export declare function gitInfo(root: string): {
|
|
37
|
+
sha: string;
|
|
38
|
+
branch: string;
|
|
39
|
+
} | null;
|
|
40
|
+
interface IgnoreRule {
|
|
41
|
+
re: RegExp;
|
|
42
|
+
dirOnly: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare function parseGitignore(text: string, baseRel: string): IgnoreRule[];
|
|
45
|
+
/**
|
|
46
|
+
* The files a snapshot of `root` holds, sorted by path in byte order. Uses git when `.git` exists and
|
|
47
|
+
* git runs, else walks the folder. Every candidate is stat'ed; missing and non-regular paths are
|
|
48
|
+
* dropped, the hard exclude list is applied last, and a file over 50 MB is left out with a warning.
|
|
49
|
+
*/
|
|
50
|
+
export declare function listSnapshotFiles(root: string, opts?: ListOptions): SnapshotSelection;
|
|
51
|
+
export interface RawTarEntry {
|
|
52
|
+
name: string;
|
|
53
|
+
type: string;
|
|
54
|
+
data?: Buffer;
|
|
55
|
+
mode?: number;
|
|
56
|
+
linkname?: string;
|
|
57
|
+
/** Written into the ustar prefix field (tests only). */
|
|
58
|
+
prefix?: string;
|
|
59
|
+
}
|
|
60
|
+
/** The bytes of one entry: an optional PAX header for a long path, the ustar header, data, padding. */
|
|
61
|
+
export declare function tarEntryBytes(e: RawTarEntry): Buffer[];
|
|
62
|
+
/** A whole tar from raw entries, in the given order, with the two end blocks. Tests build hostile tars with it. */
|
|
63
|
+
export declare function buildTar(entries: RawTarEntry[]): Buffer;
|
|
64
|
+
/** gzip level 6 with a fixed header (mtime 0, OS byte 3) so the same tar always gives the same bytes. */
|
|
65
|
+
export declare function gzipDeterministic(chunks: AsyncIterable<Buffer> | Iterable<Buffer>, maxBytes?: number): Promise<Buffer>;
|
|
66
|
+
export interface PackOptions extends ListOptions {
|
|
67
|
+
/** CLI version written into the manifest. */
|
|
68
|
+
cli?: string;
|
|
69
|
+
/** Git provenance for the manifest; omitted means "detect from root", null means none. */
|
|
70
|
+
git?: {
|
|
71
|
+
sha: string;
|
|
72
|
+
branch: string;
|
|
73
|
+
} | null;
|
|
74
|
+
/** Manifest timestamp; defaults to now. Tests pin it so two packs give the same bytes. */
|
|
75
|
+
createdAt?: string;
|
|
76
|
+
node?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface TooLarge {
|
|
79
|
+
/** Which cap was hit. */
|
|
80
|
+
reason: "files" | "unpacked" | "compressed";
|
|
81
|
+
/** Size of the selected files on disk. */
|
|
82
|
+
bytes: number;
|
|
83
|
+
fileCount: number;
|
|
84
|
+
/** The five largest selected files, biggest first. */
|
|
85
|
+
largest: {
|
|
86
|
+
path: string;
|
|
87
|
+
size: number;
|
|
88
|
+
}[];
|
|
89
|
+
/** The sentence the CLI prints. */
|
|
90
|
+
message: string;
|
|
91
|
+
}
|
|
92
|
+
export interface PackBase {
|
|
93
|
+
fileCount: number;
|
|
94
|
+
manifest: SnapshotManifest;
|
|
95
|
+
warnings: string[];
|
|
96
|
+
skipped: SkippedFile[];
|
|
97
|
+
forced: string[];
|
|
98
|
+
listedBy: "git" | "walk";
|
|
99
|
+
}
|
|
100
|
+
export interface PackOk extends PackBase {
|
|
101
|
+
gz: Buffer;
|
|
102
|
+
/** Hex sha256 of `gz`, what the API stores and verifies. */
|
|
103
|
+
sha256: string;
|
|
104
|
+
/** Hex sha256 of the uncompressed tar minus the manifest entry: the dedup key. */
|
|
105
|
+
treeHash: string;
|
|
106
|
+
/** Compressed size. */
|
|
107
|
+
bytes: number;
|
|
108
|
+
/** Uncompressed tar size. */
|
|
109
|
+
tarBytes: number;
|
|
110
|
+
tooLarge?: undefined;
|
|
111
|
+
}
|
|
112
|
+
export interface PackTooLarge extends PackBase {
|
|
113
|
+
gz?: undefined;
|
|
114
|
+
sha256?: undefined;
|
|
115
|
+
treeHash?: undefined;
|
|
116
|
+
/** Size of the selected files on disk. */
|
|
117
|
+
bytes: number;
|
|
118
|
+
tarBytes: number;
|
|
119
|
+
tooLarge: TooLarge;
|
|
120
|
+
}
|
|
121
|
+
export type PackResult = PackOk | PackTooLarge;
|
|
122
|
+
/**
|
|
123
|
+
* Packs the app at `root` into a deterministic tar.gz. Returns `tooLarge` instead of `gz` when a
|
|
124
|
+
* cap is hit (a user-caused skip: the deploy proceeds without a snapshot). Throws `SnapshotError`
|
|
125
|
+
* with code `changed` when a file changed under it; the caller should try once more.
|
|
126
|
+
*/
|
|
127
|
+
export declare function packSnapshot(root: string, opts?: PackOptions): Promise<PackResult>;
|
|
128
|
+
interface ParsedEntry {
|
|
129
|
+
name: string;
|
|
130
|
+
type: string;
|
|
131
|
+
size: number;
|
|
132
|
+
mode: number;
|
|
133
|
+
data: Buffer;
|
|
134
|
+
}
|
|
135
|
+
/** Raw entries in order; PAX and long-name headers are yielded as entries and resolved by the caller. */
|
|
136
|
+
export declare function parseTar(tar: Buffer): Generator<ParsedEntry>;
|
|
137
|
+
/** Uncompresses a snapshot with the unpacked cap enforced. */
|
|
138
|
+
export declare function gunzipSnapshot(gz: Buffer): Buffer;
|
|
139
|
+
/** The manifest alone, for callers that only need the file list. */
|
|
140
|
+
export declare function readSnapshotManifest(gz: Buffer): SnapshotManifest;
|
|
141
|
+
export interface ExtractOptions {
|
|
142
|
+
/** Write into a directory that already has files in it. */
|
|
143
|
+
force?: boolean;
|
|
144
|
+
}
|
|
145
|
+
export interface ExtractResult {
|
|
146
|
+
/** Regular files written. */
|
|
147
|
+
files: number;
|
|
148
|
+
manifest: SnapshotManifest;
|
|
149
|
+
dir: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Extracts a snapshot into `targetDir` with every hardening rule from the spec: only regular files,
|
|
153
|
+
* directories, PAX and long-name headers; relative names with no `..`, backslash, or `.git`; nothing
|
|
154
|
+
* outside the target after resolution (symlinked parents included); every file listed in the
|
|
155
|
+
* manifest with the listed size and sha256, and every listed file present. The whole archive and the
|
|
156
|
+
* whole target are checked before the first write, so a refused archive changes nothing on the disk,
|
|
157
|
+
* the files already in a `force` target included. A non-empty target needs `force`.
|
|
158
|
+
*/
|
|
159
|
+
export declare function extractSnapshot(gz: Buffer, targetDir: string, opts?: ExtractOptions): ExtractResult;
|
|
160
|
+
/** The size on disk of a folder's selected files, for messages. */
|
|
161
|
+
export declare function selectionBytes(selection: SnapshotSelection): number;
|