@git.zone/tspack 1.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/.smartconfig.json +26 -0
- package/cli.js +3 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/archive.d.ts +3 -0
- package/dist_ts/archive.js +60 -0
- package/dist_ts/classes.tspack.d.ts +11 -0
- package/dist_ts/classes.tspack.js +181 -0
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +4 -0
- package/dist_ts/interfaces.d.ts +60 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +13 -0
- package/dist_ts/plugins.js +16 -0
- package/dist_ts/tspack.cli.d.ts +1 -0
- package/dist_ts/tspack.cli.js +53 -0
- package/dist_ts/validation.d.ts +32 -0
- package/dist_ts/validation.js +132 -0
- package/license.md +21 -0
- package/package.json +49 -0
- package/readme.md +181 -0
- package/readme.plan.md +26 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/archive.ts +60 -0
- package/ts/classes.tspack.ts +170 -0
- package/ts/index.ts +3 -0
- package/ts/interfaces.ts +68 -0
- package/ts/plugins.ts +16 -0
- package/ts/tspack.cli.ts +44 -0
- package/ts/validation.ts +136 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@git.zone/cli": {
|
|
3
|
+
"schemaVersion": 2,
|
|
4
|
+
"projectType": "npm",
|
|
5
|
+
"module": {
|
|
6
|
+
"githost": "code.foss.global",
|
|
7
|
+
"gitscope": "git.zone",
|
|
8
|
+
"gitrepo": "tspack",
|
|
9
|
+
"description": "Verified executable and asset bundles for GitZone projects.",
|
|
10
|
+
"npmPackagename": "@git.zone/tspack",
|
|
11
|
+
"license": "MIT"
|
|
12
|
+
},
|
|
13
|
+
"release": {
|
|
14
|
+
"preflight": { "test": true, "build": true },
|
|
15
|
+
"targets": {
|
|
16
|
+
"git": { "enabled": true, "remote": "origin", "pushBranch": true, "pushTags": true },
|
|
17
|
+
"npm": {
|
|
18
|
+
"enabled": true,
|
|
19
|
+
"registries": ["https://verdaccio.lossless.digital", "https://registry.npmjs.org"],
|
|
20
|
+
"accessLevel": "public",
|
|
21
|
+
"alreadyPublished": "success"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/cli.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@git.zone/tspack',
|
|
6
|
+
version: '1.1.0',
|
|
7
|
+
description: 'Verified executable and asset bundles for GitZone projects.'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDZEQUE2RDtDQUMzRSxDQUFBIn0=
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ITsPackArtifact, ITsPackFileRecord } from './interfaces.js';
|
|
2
|
+
export declare function packArchive(directory: string, output: string, files: Record<string, ITsPackFileRecord>): Promise<void>;
|
|
3
|
+
export declare function verifyArchive(file: string, artifact: ITsPackArtifact, expectedMetadata: unknown): Promise<void>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { limits, requireValue, TsPackError, sha256, jsonBytes } from './validation.js';
|
|
3
|
+
export async function packArchive(directory, output, files) {
|
|
4
|
+
const tar = new plugins.smartarchive.TarTools().getPackStream();
|
|
5
|
+
const written = plugins.streamPromises.pipeline(tar, plugins.zlib.createGzip({ level: 6 }), plugins.nodeFs.createWriteStream(output, { flags: 'wx', mode: 0o644 }));
|
|
6
|
+
void written.catch(() => undefined);
|
|
7
|
+
try {
|
|
8
|
+
for (const name of Object.keys(files).sort()) {
|
|
9
|
+
const file = files[name];
|
|
10
|
+
const entry = tar.entry({ name, size: file.size, mode: file.mode, mtime: new Date(0), uid: 0, gid: 0, uname: '', gname: '' });
|
|
11
|
+
await plugins.streamPromises.pipeline(plugins.nodeFs.createReadStream(plugins.path.join(directory, name)), entry);
|
|
12
|
+
}
|
|
13
|
+
tar.finalize();
|
|
14
|
+
await written;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
tar.destroy(error instanceof Error ? error : new Error('Archive creation failed.'));
|
|
18
|
+
await written.catch(() => undefined);
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function verifyArchive(file, artifact, expectedMetadata) {
|
|
23
|
+
const extract = new plugins.smartarchive.TarTools().getExtractStream();
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
extract.on('entry', (header, entry, next) => {
|
|
26
|
+
void (async () => {
|
|
27
|
+
const expected = Object.hasOwn(artifact.files, header.name) ? artifact.files[header.name] : undefined;
|
|
28
|
+
requireValue(header.type === 'file' && expected && !seen.has(header.name) && header.size === expected.size &&
|
|
29
|
+
header.mode === expected.mode, 'archive', 'Unexpected, duplicate or changed archive member.');
|
|
30
|
+
seen.add(header.name);
|
|
31
|
+
const hash = plugins.crypto.createHash('sha256');
|
|
32
|
+
const chunks = [];
|
|
33
|
+
let bytes = 0;
|
|
34
|
+
for await (const chunk of entry) {
|
|
35
|
+
requireValue(Buffer.isBuffer(chunk), 'archive', 'Expected binary archive content.');
|
|
36
|
+
bytes += chunk.length;
|
|
37
|
+
requireValue(bytes <= expected.size, 'archive', 'Archive member exceeds its declared size.');
|
|
38
|
+
hash.update(chunk);
|
|
39
|
+
if (header.name === 'tspack.json') {
|
|
40
|
+
requireValue(bytes <= limits.json, 'archive', 'Bundle metadata exceeds its limit.');
|
|
41
|
+
chunks.push(chunk);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
requireValue(bytes === expected.size && hash.digest('hex') === expected.sha256, 'integrity', 'Archive member integrity mismatch.');
|
|
45
|
+
if (header.name === 'tspack.json') {
|
|
46
|
+
requireValue(sha256(Buffer.concat(chunks)) === sha256(jsonBytes(expectedMetadata)), 'integrity', 'Bundle and artifact-set metadata disagree.');
|
|
47
|
+
}
|
|
48
|
+
})().then(() => next(), (error) => extract.destroy(error instanceof Error ? error : new Error('Archive verification failed.')));
|
|
49
|
+
});
|
|
50
|
+
try {
|
|
51
|
+
await plugins.streamPromises.pipeline(plugins.nodeFs.createReadStream(file), plugins.zlib.createGunzip(), extract);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof TsPackError)
|
|
55
|
+
throw error;
|
|
56
|
+
throw new TsPackError('archive', 'Invalid or incomplete archive.');
|
|
57
|
+
}
|
|
58
|
+
requireValue(seen.size === Object.keys(artifact.files).length, 'archive', 'Archive members are missing.');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2FyY2hpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFFeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV2RixNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVcsQ0FBQyxTQUFpQixFQUFFLE1BQWMsRUFBRSxLQUF3QztJQUMzRyxNQUFNLEdBQUcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDaEUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQ3hGLE9BQU8sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFFLEtBQUssT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUM7UUFDSCxLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM3QyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFFLENBQUM7WUFDMUIsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElB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
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ITsPackConfig, ITsPackOptions, ITsPackResult, ITsPackVerifyOptions } from './interfaces.js';
|
|
2
|
+
export { TsPackError } from './validation.js';
|
|
3
|
+
/** Packages explicit code/assets. Compilation, publishing and runtime installation have separate owners. */
|
|
4
|
+
export declare class TsPack {
|
|
5
|
+
private readonly cwd;
|
|
6
|
+
constructor(cwd?: string);
|
|
7
|
+
private source;
|
|
8
|
+
pack(configArg?: ITsPackConfig, optionsArg?: ITsPackOptions): Promise<ITsPackResult>;
|
|
9
|
+
private checksums;
|
|
10
|
+
verify(directoryArg: string, optionsArg?: ITsPackVerifyOptions): Promise<ITsPackResult>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { packArchive, verifyArchive } from './archive.js';
|
|
3
|
+
import { digestFile, isCommit, isDigest, isPath, isVersion, jsonBytes, limits, noSymlinks, normalizeConfig, object, readJson, requireValue, sha256, validateManifest } from './validation.js';
|
|
4
|
+
export { TsPackError } from './validation.js';
|
|
5
|
+
const exec = plugins.util.promisify(plugins.childProcess.execFile);
|
|
6
|
+
const bundleMetadata = (manifest, id, files) => ({
|
|
7
|
+
format: 'tspack.bundle.v1', packageName: manifest.packageName, version: manifest.version,
|
|
8
|
+
id, sourceCommit: manifest.sourceCommit, sourceDirty: manifest.sourceDirty,
|
|
9
|
+
publishable: manifest.publishable, configurationSha256: manifest.configurationSha256, files,
|
|
10
|
+
});
|
|
11
|
+
/** Packages explicit code/assets. Compilation, publishing and runtime installation have separate owners. */
|
|
12
|
+
export class TsPack {
|
|
13
|
+
cwd;
|
|
14
|
+
constructor(cwd = process.cwd()) {
|
|
15
|
+
this.cwd = cwd;
|
|
16
|
+
}
|
|
17
|
+
async source(root, version, release) {
|
|
18
|
+
const run = async (...args) => (await exec('git', args, { cwd: root, maxBuffer: 4 * 1024 ** 2 })).stdout.trim();
|
|
19
|
+
const commit = await run('rev-parse', 'HEAD');
|
|
20
|
+
requireValue(isCommit(commit), 'source_state', 'A committed Git source identity is required.');
|
|
21
|
+
const dirty = (await run('status', '--porcelain')).length !== 0;
|
|
22
|
+
if (release) {
|
|
23
|
+
requireValue(!dirty && await run('rev-parse', `refs/tags/v${version}^{commit}`) === commit, 'source_state', 'Release packaging requires clean source at its matching version tag.');
|
|
24
|
+
}
|
|
25
|
+
return { commit, dirty };
|
|
26
|
+
}
|
|
27
|
+
async pack(configArg, optionsArg = {}) {
|
|
28
|
+
object(optionsArg, ['release', 'reuse']);
|
|
29
|
+
requireValue((optionsArg.release === undefined || typeof optionsArg.release === 'boolean') &&
|
|
30
|
+
(optionsArg.reuse === undefined || typeof optionsArg.reuse === 'boolean') &&
|
|
31
|
+
(!optionsArg.reuse || optionsArg.release), 'invalid_config', 'Reuse requires release mode.');
|
|
32
|
+
const root = await plugins.fs.realpath(this.cwd);
|
|
33
|
+
const { value: packageJson } = await readJson(plugins.path.join(root, 'package.json'));
|
|
34
|
+
object(packageJson);
|
|
35
|
+
requireValue(typeof packageJson.name === 'string' && packageJson.name.length <= 214 && isVersion(packageJson.version), 'invalid_config', 'Package metadata requires a name and version.');
|
|
36
|
+
const config = normalizeConfig(configArg ?? new plugins.smartconfig.Smartconfig(root).dataFor('@git.zone/tspack', {}), packageJson.name);
|
|
37
|
+
requireValue(config.bundles.every((bundle) => isPath(`${config.name}-${packageJson.version}-${bundle.id}.tar.gz`)), 'invalid_config', 'Archive names exceed the portable path limit.');
|
|
38
|
+
const configurationSha256 = sha256(jsonBytes(config));
|
|
39
|
+
const source = await this.source(root, packageJson.version, optionsArg.release === true);
|
|
40
|
+
const outputRoot = await noSymlinks(root, config.outputDirectory, true);
|
|
41
|
+
const releaseName = `${config.name}-${packageJson.version}-${source.commit.slice(0, 12)}`;
|
|
42
|
+
if (optionsArg.reuse) {
|
|
43
|
+
const directory = plugins.path.join(outputRoot, releaseName);
|
|
44
|
+
let exists = true;
|
|
45
|
+
try {
|
|
46
|
+
await plugins.fs.lstat(directory);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code === 'ENOENT')
|
|
50
|
+
exists = false;
|
|
51
|
+
else
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
if (exists) {
|
|
55
|
+
const result = await this.verify(directory, { requireRelease: true, expectedSourceCommit: source.commit });
|
|
56
|
+
requireValue(result.manifest.configurationSha256 === configurationSha256 && result.manifest.packageName === packageJson.name &&
|
|
57
|
+
result.manifest.version === packageJson.version, 'integrity', 'Retained release set belongs to another configuration.');
|
|
58
|
+
return { ...result, reused: true };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
await plugins.fs.mkdir(outputRoot, { recursive: true });
|
|
62
|
+
const stage = await plugins.fs.mkdtemp(plugins.path.join(outputRoot, '.tspack-'));
|
|
63
|
+
const assets = plugins.path.join(stage, 'assets');
|
|
64
|
+
await plugins.fs.mkdir(assets);
|
|
65
|
+
await plugins.fs.mkdir(plugins.path.join(stage, 'bundles'));
|
|
66
|
+
try {
|
|
67
|
+
const manifest = {
|
|
68
|
+
format: 'tspack.release.v1', packageName: packageJson.name, name: config.name, version: packageJson.version,
|
|
69
|
+
sourceCommit: source.commit, sourceDirty: source.dirty, publishable: optionsArg.release === true,
|
|
70
|
+
configurationSha256, artifacts: [],
|
|
71
|
+
};
|
|
72
|
+
let total = 0;
|
|
73
|
+
for (const bundle of config.bundles) {
|
|
74
|
+
const directory = plugins.path.join(stage, 'bundles', bundle.id);
|
|
75
|
+
await plugins.fs.mkdir(directory);
|
|
76
|
+
const files = Object.create(null);
|
|
77
|
+
for (const file of bundle.files) {
|
|
78
|
+
const input = await noSymlinks(root, file.source);
|
|
79
|
+
const handle = await plugins.fs.open(input, plugins.nodeFs.constants.O_RDONLY | plugins.nodeFs.constants.O_NOFOLLOW);
|
|
80
|
+
try {
|
|
81
|
+
const before = await handle.stat({ bigint: true });
|
|
82
|
+
requireValue(before.isFile() && before.size <= BigInt(limits.file), 'unsafe_input', 'Expected a bounded regular input file.');
|
|
83
|
+
total += Number(before.size);
|
|
84
|
+
requireValue(total <= limits.total, 'unsafe_input', 'Package inputs exceed the total byte limit.');
|
|
85
|
+
const destination = plugins.path.join(directory, file.path);
|
|
86
|
+
await plugins.fs.mkdir(plugins.path.dirname(destination), { recursive: true });
|
|
87
|
+
const hash = plugins.crypto.createHash('sha256');
|
|
88
|
+
let size = 0;
|
|
89
|
+
const meter = new plugins.stream.Transform({ transform(chunk, _encoding, callback) {
|
|
90
|
+
size += chunk.length;
|
|
91
|
+
if (size > Number(before.size)) {
|
|
92
|
+
callback(new Error('Input changed while copying.'));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
hash.update(chunk);
|
|
96
|
+
callback(null, chunk);
|
|
97
|
+
} });
|
|
98
|
+
await plugins.streamPromises.pipeline(handle.createReadStream({ autoClose: false }), meter, plugins.nodeFs.createWriteStream(destination, { flags: 'wx', mode: 0o600 }));
|
|
99
|
+
const after = await handle.stat({ bigint: true });
|
|
100
|
+
const current = await plugins.fs.lstat(input, { bigint: true });
|
|
101
|
+
requireValue(size === Number(before.size) && ['dev', 'ino', 'size', 'mtimeNs', 'ctimeNs'].every((key) => before[key] === after[key] &&
|
|
102
|
+
before[key] === current[key]), 'integrity', 'Input changed while copying.');
|
|
103
|
+
const record = { sha256: hash.digest('hex'), size, mode: (file.executable ? 0o755 : 0o644) };
|
|
104
|
+
requireValue(!file.sha256 || file.sha256 === record.sha256, 'integrity', 'Input does not match its pinned digest.');
|
|
105
|
+
files[file.path] = record;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await handle.close();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const metadata = jsonBytes(bundleMetadata(manifest, bundle.id, files));
|
|
112
|
+
requireValue(metadata.length <= limits.json, 'invalid_config', 'Bundle metadata exceeds its limit.');
|
|
113
|
+
await plugins.fs.writeFile(plugins.path.join(directory, 'tspack.json'), metadata, { flag: 'wx' });
|
|
114
|
+
files['tspack.json'] = { sha256: sha256(metadata), size: metadata.length, mode: 0o644 };
|
|
115
|
+
const name = `${config.name}-${packageJson.version}-${bundle.id}.tar.gz`;
|
|
116
|
+
await packArchive(directory, plugins.path.join(assets, name), files);
|
|
117
|
+
manifest.artifacts.push({ id: bundle.id, name, ...await digestFile(plugins.path.join(assets, name)), files });
|
|
118
|
+
}
|
|
119
|
+
const finalSource = await this.source(root, packageJson.version, optionsArg.release === true);
|
|
120
|
+
requireValue(finalSource.commit === source.commit && finalSource.dirty === source.dirty, 'source_state', 'Source identity changed while packaging.');
|
|
121
|
+
validateManifest(manifest);
|
|
122
|
+
const metadata = jsonBytes(manifest);
|
|
123
|
+
const manifestSha256 = sha256(metadata);
|
|
124
|
+
await plugins.fs.writeFile(plugins.path.join(assets, 'tspack-manifest.json'), metadata, { flag: 'wx' });
|
|
125
|
+
await plugins.fs.writeFile(plugins.path.join(assets, 'SHA256SUMS.txt'), this.checksums(manifest, manifestSha256), { flag: 'wx' });
|
|
126
|
+
await this.verify(assets, { expectedManifestSha256: manifestSha256 });
|
|
127
|
+
const name = optionsArg.release ? releaseName : `${releaseName}-qualification-${manifestSha256.slice(0, 16)}`;
|
|
128
|
+
const output = plugins.path.join(outputRoot, name);
|
|
129
|
+
let exists = true;
|
|
130
|
+
try {
|
|
131
|
+
await plugins.fs.lstat(output);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (error.code === 'ENOENT')
|
|
135
|
+
exists = false;
|
|
136
|
+
else
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
requireValue(!exists, 'exists', 'A sealed set already occupies this output; use verified release reuse or a separate output directory.');
|
|
140
|
+
await plugins.fs.rename(assets, output);
|
|
141
|
+
return { directory: output, manifest, manifestSha256, reused: false };
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await plugins.fs.rm(stage, { recursive: true, force: true });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
checksums(manifest, manifestSha256) {
|
|
148
|
+
return [...manifest.artifacts.map((artifact) => [artifact.name, artifact.sha256]), ['tspack-manifest.json', manifestSha256]]
|
|
149
|
+
.sort(([a], [b]) => a.localeCompare(b, 'en')).map(([name, hash]) => `${hash} ${name}`).join('\n') + '\n';
|
|
150
|
+
}
|
|
151
|
+
async verify(directoryArg, optionsArg = {}) {
|
|
152
|
+
object(optionsArg, ['expectedManifestSha256', 'expectedSourceCommit', 'requireRelease']);
|
|
153
|
+
requireValue((optionsArg.expectedManifestSha256 === undefined || isDigest(optionsArg.expectedManifestSha256)) &&
|
|
154
|
+
(optionsArg.expectedSourceCommit === undefined || isCommit(optionsArg.expectedSourceCommit)) &&
|
|
155
|
+
(optionsArg.requireRelease === undefined || typeof optionsArg.requireRelease === 'boolean'), 'invalid_config', 'Invalid verification identity.');
|
|
156
|
+
const directory = plugins.path.resolve(this.cwd, directoryArg);
|
|
157
|
+
requireValue((await plugins.fs.lstat(directory)).isDirectory() && await plugins.fs.realpath(directory) === directory, 'unsafe_input', 'A canonical regular artifact directory is required.');
|
|
158
|
+
const { value, bytes } = await readJson(plugins.path.join(directory, 'tspack-manifest.json'));
|
|
159
|
+
const manifestSha256 = sha256(bytes);
|
|
160
|
+
validateManifest(value);
|
|
161
|
+
const manifest = value;
|
|
162
|
+
requireValue((!optionsArg.expectedManifestSha256 || optionsArg.expectedManifestSha256 === manifestSha256) &&
|
|
163
|
+
(!optionsArg.expectedSourceCommit || optionsArg.expectedSourceCommit === manifest.sourceCommit) &&
|
|
164
|
+
(!optionsArg.requireRelease || manifest.publishable), 'integrity', 'Artifact set does not match its required identity.');
|
|
165
|
+
const names = (await plugins.fs.readdir(directory)).sort();
|
|
166
|
+
requireValue(names.join('\n') === [...manifest.artifacts.map((artifact) => artifact.name), 'tspack-manifest.json', 'SHA256SUMS.txt'].sort().join('\n'), 'integrity', 'Artifact directory has an unexpected file set.');
|
|
167
|
+
const checksumPath = plugins.path.join(directory, 'SHA256SUMS.txt');
|
|
168
|
+
const checksumStat = await plugins.fs.lstat(checksumPath);
|
|
169
|
+
requireValue(checksumStat.isFile() && checksumStat.size <= 32 * 1024 &&
|
|
170
|
+
await plugins.fs.readFile(checksumPath, 'utf8') === this.checksums(manifest, manifestSha256), 'integrity', 'Artifact-set checksums disagree.');
|
|
171
|
+
for (const artifact of manifest.artifacts) {
|
|
172
|
+
const file = plugins.path.join(directory, artifact.name);
|
|
173
|
+
const actual = await digestFile(file);
|
|
174
|
+
requireValue(actual.size === artifact.size && actual.sha256 === artifact.sha256, 'integrity', 'Archive integrity mismatch.');
|
|
175
|
+
const { ['tspack.json']: _metadata, ...files } = artifact.files;
|
|
176
|
+
await verifyArchive(file, artifact, bundleMetadata(manifest, artifact.id, files));
|
|
177
|
+
}
|
|
178
|
+
return { directory, manifest, manifestSha256, reused: false };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50c3BhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnRzcGFjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMxRCxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQUUsTUFBTSxFQUNoSCxRQUFRLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU5QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ25FLE1BQU0sY0FBYyxHQUFHLENBQUMsUUFBNEMsRUFBRSxFQUFVLEVBQUUsS0FBd0MsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM5SCxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO0lBQ3hGLEVBQUUsRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsUUFBUSxDQUFDLFdBQVc7SUFDMUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEtBQUs7Q0FDNUYsQ0FBQyxDQUFDO0FBRUgsNEdBQTRHO0FBQzVHLE1BQU0sT0FBTyxNQUFNO0lBQ1k7SUFBN0IsWUFBNkIsTUFBTSxPQUFPLENBQUMsR0FBRyxFQUFF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
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from './interfaces.js';
|
|
2
|
+
export * from './classes.tspack.js';
|
|
3
|
+
export { runCli } from './tspack.cli.js';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDIn0=
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface ITsPackFile {
|
|
2
|
+
/** Project-relative regular input file. Ancestor symlinks are rejected. */
|
|
3
|
+
source: string;
|
|
4
|
+
/** Portable relative name inside the bundle. */
|
|
5
|
+
path: string;
|
|
6
|
+
executable?: boolean;
|
|
7
|
+
/** Optional upstream identity, verified before assembly. */
|
|
8
|
+
sha256?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ITsPackBundle {
|
|
11
|
+
id: string;
|
|
12
|
+
files: ITsPackFile[];
|
|
13
|
+
}
|
|
14
|
+
export interface ITsPackConfig {
|
|
15
|
+
schemaVersion: 1;
|
|
16
|
+
/** Defaults to the package name with its scope separator replaced by a hyphen. */
|
|
17
|
+
name?: string;
|
|
18
|
+
outputDirectory?: string;
|
|
19
|
+
bundles: ITsPackBundle[];
|
|
20
|
+
}
|
|
21
|
+
export interface ITsPackOptions {
|
|
22
|
+
/** Requires clean source at the package's vVERSION tag. */
|
|
23
|
+
release?: boolean;
|
|
24
|
+
/** Reuse a verified existing sealed set for this exact tagged source/configuration. */
|
|
25
|
+
reuse?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface ITsPackFileRecord {
|
|
28
|
+
sha256: string;
|
|
29
|
+
size: number;
|
|
30
|
+
mode: 420 | 493;
|
|
31
|
+
}
|
|
32
|
+
export interface ITsPackArtifact {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
sha256: string;
|
|
36
|
+
size: number;
|
|
37
|
+
files: Record<string, ITsPackFileRecord>;
|
|
38
|
+
}
|
|
39
|
+
export interface ITsPackManifest {
|
|
40
|
+
format: 'tspack.release.v1';
|
|
41
|
+
packageName: string;
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
sourceCommit: string;
|
|
45
|
+
sourceDirty: boolean;
|
|
46
|
+
publishable: boolean;
|
|
47
|
+
configurationSha256: string;
|
|
48
|
+
artifacts: ITsPackArtifact[];
|
|
49
|
+
}
|
|
50
|
+
export interface ITsPackResult {
|
|
51
|
+
directory: string;
|
|
52
|
+
manifest: ITsPackManifest;
|
|
53
|
+
manifestSha256: string;
|
|
54
|
+
reused: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface ITsPackVerifyOptions {
|
|
57
|
+
expectedManifestSha256?: string;
|
|
58
|
+
expectedSourceCommit?: string;
|
|
59
|
+
requireRelease?: boolean;
|
|
60
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as nodeFs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import * as crypto from 'node:crypto';
|
|
5
|
+
import * as stream from 'node:stream';
|
|
6
|
+
import * as streamPromises from 'node:stream/promises';
|
|
7
|
+
import * as zlib from 'node:zlib';
|
|
8
|
+
import * as childProcess from 'node:child_process';
|
|
9
|
+
import * as util from 'node:util';
|
|
10
|
+
export { fs, nodeFs, path, crypto, stream, streamPromises, zlib, childProcess, util };
|
|
11
|
+
import * as smartarchive from '@push.rocks/smartarchive';
|
|
12
|
+
import * as smartconfig from '@push.rocks/smartconfig';
|
|
13
|
+
export { smartarchive, smartconfig };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Node native modules
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as nodeFs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import * as crypto from 'node:crypto';
|
|
6
|
+
import * as stream from 'node:stream';
|
|
7
|
+
import * as streamPromises from 'node:stream/promises';
|
|
8
|
+
import * as zlib from 'node:zlib';
|
|
9
|
+
import * as childProcess from 'node:child_process';
|
|
10
|
+
import * as util from 'node:util';
|
|
11
|
+
export { fs, nodeFs, path, crypto, stream, streamPromises, zlib, childProcess, util };
|
|
12
|
+
// @push.rocks modules
|
|
13
|
+
import * as smartarchive from '@push.rocks/smartarchive';
|
|
14
|
+
import * as smartconfig from '@push.rocks/smartconfig';
|
|
15
|
+
export { smartarchive, smartconfig };
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0JBQXNCO0FBQ3RCLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLE1BQU0sTUFBTSxTQUFTLENBQUM7QUFDbEMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxLQUFLLGNBQWMsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEtBQUssWUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBQ25ELE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDO0FBRXRGLHNCQUFzQjtBQUN0QixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQyJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runCli(args?: string[]): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TsPack, TsPackError } from './classes.tspack.js';
|
|
2
|
+
import * as plugins from './plugins.js';
|
|
3
|
+
import { readJson } from './validation.js';
|
|
4
|
+
export async function runCli(args = process.argv.slice(2)) {
|
|
5
|
+
try {
|
|
6
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === 'help') {
|
|
7
|
+
console.log('tspack pack [--release] [--reuse] [--config <json-file>]\ntspack verify <artifact-directory> [--release] [--sha256 <manifest-digest>]');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const command = args[0];
|
|
11
|
+
const values = args.slice(1);
|
|
12
|
+
const directory = command === 'verify' ? values.shift() : undefined;
|
|
13
|
+
let release = false;
|
|
14
|
+
let reuse = false;
|
|
15
|
+
let configFile;
|
|
16
|
+
let expectedManifestSha256;
|
|
17
|
+
const used = new Set();
|
|
18
|
+
while (values.length) {
|
|
19
|
+
const option = values.shift();
|
|
20
|
+
if (used.has(option))
|
|
21
|
+
throw new TsPackError('arguments', 'Duplicate command option.');
|
|
22
|
+
used.add(option);
|
|
23
|
+
if (option === '--release')
|
|
24
|
+
release = true;
|
|
25
|
+
else if (option === '--reuse' && command === 'pack')
|
|
26
|
+
reuse = true;
|
|
27
|
+
else if ((option === '--config' && command === 'pack') || (option === '--sha256' && command === 'verify')) {
|
|
28
|
+
const value = values.shift();
|
|
29
|
+
if (!value || value.startsWith('--'))
|
|
30
|
+
throw new TsPackError('arguments', 'Command option requires a value.');
|
|
31
|
+
if (option === '--config')
|
|
32
|
+
configFile = value;
|
|
33
|
+
else
|
|
34
|
+
expectedManifestSha256 = value;
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
throw new TsPackError('arguments', 'Unknown command option.');
|
|
38
|
+
}
|
|
39
|
+
const pack = new TsPack();
|
|
40
|
+
const result = command === 'pack'
|
|
41
|
+
? await pack.pack(configFile ? (await readJson(plugins.path.resolve(configFile))).value : undefined, { release, reuse })
|
|
42
|
+
: command === 'verify' && directory && !directory.startsWith('--')
|
|
43
|
+
? await pack.verify(directory, { requireRelease: release, expectedManifestSha256 })
|
|
44
|
+
: (() => { throw new TsPackError('arguments', 'Expected pack or verify with its required arguments.'); })();
|
|
45
|
+
console.log(JSON.stringify({ directory: result.directory, manifestSha256: result.manifestSha256,
|
|
46
|
+
publishable: result.manifest.publishable, reused: result.reused, bundles: result.manifest.artifacts.length }));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error(error instanceof TsPackError ? `tspack: ${error.code}: ${error.message}` : 'tspack: operation failed.');
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHNwYWNrLmNsaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3RzcGFjay5jbGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRCxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0MsTUFBTSxDQUFDLEtBQUssVUFBVSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN2RCxJQUFJLENBQUM7UUFDSCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3BFLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUlBQXVJLENBQUMsQ0FBQztZQUNySixPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLE1BQU0sU0FBUyxHQUFHLE9BQU8sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3BFLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbEIsSUFBSSxVQUE4QixDQUFDO1FBQ25DLElBQUksc0JBQTBDLENBQUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN2QixPQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FB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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ITsPackConfig, ITsPackFileRecord, ITsPackManifest } from './interfaces.js';
|
|
2
|
+
export declare const limits: {
|
|
3
|
+
file: number;
|
|
4
|
+
total: number;
|
|
5
|
+
files: number;
|
|
6
|
+
json: number;
|
|
7
|
+
};
|
|
8
|
+
export declare class TsPackError extends Error {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
constructor(code: string, message: string);
|
|
11
|
+
}
|
|
12
|
+
export declare function requireValue(value: unknown, code: string, message: string): asserts value;
|
|
13
|
+
export declare const sha256: (value: string | Buffer) => string;
|
|
14
|
+
export declare const isDigest: (value: unknown) => value is string;
|
|
15
|
+
export declare const isCommit: (value: unknown) => value is string;
|
|
16
|
+
export declare const isName: (value: unknown) => value is string;
|
|
17
|
+
export declare const isVersion: (value: unknown) => value is string;
|
|
18
|
+
export declare const isPath: (value: unknown) => value is string;
|
|
19
|
+
export declare const jsonBytes: (value: unknown) => Buffer<ArrayBuffer>;
|
|
20
|
+
export declare function object(value: unknown, allowed?: readonly string[]): asserts value is Record<string, unknown>;
|
|
21
|
+
export declare function normalizeConfig(value: unknown, packageName: string): Required<ITsPackConfig>;
|
|
22
|
+
export declare function validateFileRecord(value: unknown): asserts value is ITsPackFileRecord;
|
|
23
|
+
export declare function validateManifest(value: unknown): asserts value is ITsPackManifest;
|
|
24
|
+
export declare function noSymlinks(root: string, relative: string, allowMissing?: boolean): Promise<string>;
|
|
25
|
+
export declare function readJson(file: string): Promise<{
|
|
26
|
+
value: unknown;
|
|
27
|
+
bytes: Buffer;
|
|
28
|
+
}>;
|
|
29
|
+
export declare function digestFile(file: string): Promise<{
|
|
30
|
+
sha256: string;
|
|
31
|
+
size: number;
|
|
32
|
+
}>;
|