@shazhou/proman-core 0.9.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/CHANGELOG.md +26 -0
- package/LICENSE +18 -0
- package/dist/commands/bump.d.ts +13 -0
- package/dist/commands/bump.d.ts.map +1 -0
- package/dist/commands/bump.js +115 -0
- package/dist/commands/deploy.d.ts +9 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +42 -0
- package/dist/commands/dev.d.ts +15 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +175 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +262 -0
- package/dist/commands/link.d.ts +19 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +155 -0
- package/dist/commands/publish.d.ts +18 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +125 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/load-config.d.ts +6 -0
- package/dist/config/load-config.d.ts.map +1 -0
- package/dist/config/load-config.js +29 -0
- package/dist/config/types.d.ts +17 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +1 -0
- package/dist/config/validate-config.d.ts +7 -0
- package/dist/config/validate-config.d.ts.map +1 -0
- package/dist/config/validate-config.js +72 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/utils/changeset.d.ts +16 -0
- package/dist/utils/changeset.d.ts.map +1 -0
- package/dist/utils/changeset.js +80 -0
- package/dist/utils/fingerprint.d.ts +38 -0
- package/dist/utils/fingerprint.d.ts.map +1 -0
- package/dist/utils/fingerprint.js +182 -0
- package/dist/utils/git.d.ts +23 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +105 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/npm.d.ts +30 -0
- package/dist/utils/npm.d.ts.map +1 -0
- package/dist/utils/npm.js +85 -0
- package/dist/utils/smoke-test.d.ts +7 -0
- package/dist/utils/smoke-test.d.ts.map +1 -0
- package/dist/utils/smoke-test.js +59 -0
- package/dist/utils/version.d.ts +5 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +36 -0
- package/dist/utils/workspace.d.ts +21 -0
- package/dist/utils/workspace.d.ts.map +1 -0
- package/dist/utils/workspace.js +73 -0
- package/package.json +45 -0
- package/src/commands/bump.ts +131 -0
- package/src/commands/deploy.ts +52 -0
- package/src/commands/dev.ts +214 -0
- package/src/commands/index.ts +7 -0
- package/src/commands/init.integration.test.ts +59 -0
- package/src/commands/init.test.ts +179 -0
- package/src/commands/init.ts +290 -0
- package/src/commands/link.ts +195 -0
- package/src/commands/publish.ts +168 -0
- package/src/config/index.ts +8 -0
- package/src/config/load-config.ts +33 -0
- package/src/config/types.ts +19 -0
- package/src/config/validate-config.ts +81 -0
- package/src/index.ts +29 -0
- package/src/utils/changeset.ts +98 -0
- package/src/utils/fingerprint.ts +199 -0
- package/src/utils/git.ts +119 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/npm.ts +110 -0
- package/src/utils/smoke-test.ts +79 -0
- package/src/utils/version.ts +41 -0
- package/src/utils/workspace.ts +94 -0
- package/tests/build-fingerprint-integration.test.ts +403 -0
- package/tests/bump.test.ts +261 -0
- package/tests/changeset.test.ts +147 -0
- package/tests/deploy.test.ts +98 -0
- package/tests/dev.test.ts +756 -0
- package/tests/fingerprint.test.ts +316 -0
- package/tests/fixtures/api-only/packages/api/.gitkeep +0 -0
- package/tests/fixtures/api-only/proman.yaml +4 -0
- package/tests/fixtures/bad-packages/proman.yaml +1 -0
- package/tests/fixtures/bun-project/packages/a/.gitkeep +0 -0
- package/tests/fixtures/bun-project/proman.yaml +4 -0
- package/tests/fixtures/defaults/proman.yaml +3 -0
- package/tests/fixtures/no-deployable/packages/core/.gitkeep +0 -0
- package/tests/fixtures/no-deployable/packages/mycli/.gitkeep +0 -0
- package/tests/fixtures/no-deployable/proman.yaml +7 -0
- package/tests/fixtures/node-runtime/packages/a/package.json +5 -0
- package/tests/fixtures/node-runtime/proman.yaml +3 -0
- package/tests/fixtures/pnpm-project/packages/a/package.json +1 -0
- package/tests/fixtures/pnpm-project/pnpm-lock.yaml +0 -0
- package/tests/fixtures/pnpm-project/proman.yaml +3 -0
- package/tests/fixtures/typed/packages/api/.gitkeep +0 -0
- package/tests/fixtures/typed/packages/core/.gitkeep +0 -0
- package/tests/fixtures/typed/packages/dashboard/.gitkeep +0 -0
- package/tests/fixtures/typed/packages/mycli/.gitkeep +0 -0
- package/tests/fixtures/typed/proman.yaml +13 -0
- package/tests/fixtures/valid/packages/cli/package.json +5 -0
- package/tests/fixtures/valid/packages/core/package.json +5 -0
- package/tests/fixtures/valid/packages/fs/package.json +5 -0
- package/tests/fixtures/valid/proman.yaml +13 -0
- package/tests/fixtures/webui-only/packages/dashboard/.gitkeep +0 -0
- package/tests/fixtures/webui-only/proman.yaml +4 -0
- package/tests/link.test.ts +419 -0
- package/tests/load-config.test.ts +44 -0
- package/tests/npm.test.ts +199 -0
- package/tests/publish.test.ts +599 -0
- package/tests/smoke-test.test.ts +211 -0
- package/tests/validate-config.test.ts +67 -0
- package/tests/version.test.ts +86 -0
- package/tests/workflow-schema.test.ts +72 -0
- package/tests/workspace.test.ts +160 -0
- package/tsconfig.build.json +14 -0
- package/tsconfig.json +8 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../../src/config/validate-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,YAAY,CAAA;AAqCzE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAuC3D"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const ERR_PREFIX = 'Invalid proman config:';
|
|
2
|
+
const VALID_TYPES = ['lib', 'cli', 'webui', 'api'];
|
|
3
|
+
function isPlainObject(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function validatePackageEntry(entry, index) {
|
|
7
|
+
if (!isPlainObject(entry)) {
|
|
8
|
+
throw new Error(`${ERR_PREFIX} packages[${index}] must be an object`);
|
|
9
|
+
}
|
|
10
|
+
const { name, path, type, private: isPrivate } = entry;
|
|
11
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
12
|
+
throw new Error(`${ERR_PREFIX} packages[${index}].name must be a non-empty string`);
|
|
13
|
+
}
|
|
14
|
+
if (typeof path !== 'string' || path.length === 0) {
|
|
15
|
+
throw new Error(`${ERR_PREFIX} packages[${index}].path must be a non-empty string`);
|
|
16
|
+
}
|
|
17
|
+
let resolvedType = 'lib';
|
|
18
|
+
if (type !== undefined) {
|
|
19
|
+
if (typeof type !== 'string' || !VALID_TYPES.includes(type)) {
|
|
20
|
+
throw new Error(`${ERR_PREFIX} packages[${index}].type must be one of 'lib' | 'cli' | 'webui' | 'api'`);
|
|
21
|
+
}
|
|
22
|
+
resolvedType = type;
|
|
23
|
+
}
|
|
24
|
+
if (isPrivate !== undefined && typeof isPrivate !== 'boolean') {
|
|
25
|
+
throw new Error(`${ERR_PREFIX} packages[${index}].private must be a boolean`);
|
|
26
|
+
}
|
|
27
|
+
const result = { name, path, type: resolvedType };
|
|
28
|
+
if (isPrivate === true)
|
|
29
|
+
result.private = true;
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pure validator. Throws Error with descriptive message on failure.
|
|
34
|
+
* Returns a typed PromanConfig (does not mutate input, does not apply defaults).
|
|
35
|
+
*/
|
|
36
|
+
export function validateConfig(value) {
|
|
37
|
+
if (!isPlainObject(value)) {
|
|
38
|
+
throw new Error(`${ERR_PREFIX} config must be an object`);
|
|
39
|
+
}
|
|
40
|
+
const { packages, release } = value;
|
|
41
|
+
if (!Array.isArray(packages) || packages.length === 0) {
|
|
42
|
+
throw new Error(`${ERR_PREFIX} packages must be a non-empty array`);
|
|
43
|
+
}
|
|
44
|
+
const validatedPackages = packages.map((p, i) => validatePackageEntry(p, i));
|
|
45
|
+
let validatedRelease;
|
|
46
|
+
if (release !== undefined) {
|
|
47
|
+
if (!isPlainObject(release)) {
|
|
48
|
+
throw new Error(`${ERR_PREFIX} release must be an object`);
|
|
49
|
+
}
|
|
50
|
+
const { registry, access, gitTagPrefix } = release;
|
|
51
|
+
if (registry !== undefined && (typeof registry !== 'string' || registry.length === 0)) {
|
|
52
|
+
throw new Error(`${ERR_PREFIX} release.registry must be a non-empty string`);
|
|
53
|
+
}
|
|
54
|
+
if (access !== undefined && access !== 'public' && access !== 'restricted') {
|
|
55
|
+
throw new Error(`${ERR_PREFIX} release.access must be 'public' or 'restricted'`);
|
|
56
|
+
}
|
|
57
|
+
if (gitTagPrefix !== undefined && typeof gitTagPrefix !== 'string') {
|
|
58
|
+
throw new Error(`${ERR_PREFIX} release.gitTagPrefix must be a string`);
|
|
59
|
+
}
|
|
60
|
+
validatedRelease = {
|
|
61
|
+
registry: registry,
|
|
62
|
+
access: access,
|
|
63
|
+
gitTagPrefix: gitTagPrefix,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const result = {
|
|
67
|
+
packages: validatedPackages,
|
|
68
|
+
};
|
|
69
|
+
if (validatedRelease !== undefined)
|
|
70
|
+
result.release = validatedRelease;
|
|
71
|
+
return result;
|
|
72
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { BumpOptions, DeployCommandOptions, DevCommandOptions, InitOptions, LinkCommandOptions, PublishOptions, } from './commands/index.js';
|
|
2
|
+
export { build, bump, check, deploy, format, init, link, linkStatus, publish, runTests, unlink, } from './commands/index.js';
|
|
3
|
+
export type { PackageEntry, PackageType, PromanConfig, ReleaseConfig } from './config/index.js';
|
|
4
|
+
export { loadConfig, validateConfig } from './config/index.js';
|
|
5
|
+
export * from './utils/index.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,cAAc,GACf,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,KAAK,EACL,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,OAAO,EACP,QAAQ,EACR,MAAM,GACP,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC/F,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAG9D,cAAc,kBAAkB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Re-export config utilities
|
|
2
|
+
// Re-export all command functions
|
|
3
|
+
export { build, bump, check, deploy, format, init, link, linkStatus, publish, runTests, unlink, } from './commands/index.js';
|
|
4
|
+
export { loadConfig, validateConfig } from './config/index.js';
|
|
5
|
+
// Re-export utility functions
|
|
6
|
+
export * from './utils/index.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Bump = 'major' | 'minor' | 'patch';
|
|
2
|
+
export type Changeset = {
|
|
3
|
+
file: string;
|
|
4
|
+
packages: Record<string, Bump>;
|
|
5
|
+
body: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseChangeset(raw: string, file: string): Changeset;
|
|
8
|
+
export declare function readChangesets(rootDir: string): Promise<Changeset[]>;
|
|
9
|
+
export type ChangelogEntryInput = {
|
|
10
|
+
version: string;
|
|
11
|
+
date: string;
|
|
12
|
+
bodies: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare function buildChangelogEntry(input: ChangelogEntryInput): string;
|
|
15
|
+
export declare function prependChangelog(existing: string | null, entry: string): string;
|
|
16
|
+
//# sourceMappingURL=changeset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changeset.d.ts","sourceRoot":"","sources":["../../src/utils/changeset.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;AAE9C,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAYD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAwBnE;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAgB1E;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAatE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAW/E"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const VALID_BUMPS = new Set(['major', 'minor', 'patch']);
|
|
4
|
+
function stripQuotes(s) {
|
|
5
|
+
const t = s.trim();
|
|
6
|
+
if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) {
|
|
7
|
+
return t.slice(1, -1);
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
}
|
|
11
|
+
export function parseChangeset(raw, file) {
|
|
12
|
+
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
13
|
+
if (!fmMatch) {
|
|
14
|
+
throw new Error(`missing frontmatter in changeset: ${file}`);
|
|
15
|
+
}
|
|
16
|
+
const fmBlock = fmMatch[1];
|
|
17
|
+
const body = fmMatch[2].replace(/^\s+|\s+$/g, '');
|
|
18
|
+
const packages = {};
|
|
19
|
+
const lines = fmBlock.split(/\r?\n/);
|
|
20
|
+
for (const line of lines) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
continue;
|
|
24
|
+
const colonIdx = trimmed.indexOf(':');
|
|
25
|
+
if (colonIdx < 0) {
|
|
26
|
+
throw new Error(`invalid frontmatter line in ${file}: ${line}`);
|
|
27
|
+
}
|
|
28
|
+
const key = stripQuotes(trimmed.slice(0, colonIdx));
|
|
29
|
+
const value = stripQuotes(trimmed.slice(colonIdx + 1));
|
|
30
|
+
if (!VALID_BUMPS.has(value)) {
|
|
31
|
+
throw new Error(`invalid bump '${value}' for package '${key}' in ${file}`);
|
|
32
|
+
}
|
|
33
|
+
packages[key] = value;
|
|
34
|
+
}
|
|
35
|
+
return { file, packages, body };
|
|
36
|
+
}
|
|
37
|
+
export async function readChangesets(rootDir) {
|
|
38
|
+
const dir = join(rootDir, '.changeset');
|
|
39
|
+
let entries;
|
|
40
|
+
try {
|
|
41
|
+
entries = await readdir(dir);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
const mdFiles = entries.filter((n) => n.endsWith('.md') && n.toLowerCase() !== 'readme.md').sort();
|
|
47
|
+
const out = [];
|
|
48
|
+
for (const name of mdFiles) {
|
|
49
|
+
const file = join(dir, name);
|
|
50
|
+
const raw = await readFile(file, 'utf8');
|
|
51
|
+
out.push(parseChangeset(raw, file));
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
export function buildChangelogEntry(input) {
|
|
56
|
+
const { version, date, bodies } = input;
|
|
57
|
+
const lines = [`## ${version} — ${date}`, ''];
|
|
58
|
+
for (const body of bodies) {
|
|
59
|
+
const parts = body.split(/\r?\n/);
|
|
60
|
+
const first = parts[0] ?? '';
|
|
61
|
+
lines.push(`- ${first}`);
|
|
62
|
+
for (let i = 1; i < parts.length; i++) {
|
|
63
|
+
lines.push(` ${parts[i]}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
lines.push('');
|
|
67
|
+
return `${lines.join('\n')}\n`;
|
|
68
|
+
}
|
|
69
|
+
export function prependChangelog(existing, entry) {
|
|
70
|
+
if (!existing || existing.trim() === '') {
|
|
71
|
+
return `# Changelog\n\n${entry}`;
|
|
72
|
+
}
|
|
73
|
+
const headingMatch = existing.match(/^(#\s+[^\n]*\n)(\n*)([\s\S]*)$/);
|
|
74
|
+
if (headingMatch) {
|
|
75
|
+
const heading = headingMatch[1];
|
|
76
|
+
const rest = headingMatch[3];
|
|
77
|
+
return `${heading}\n${entry}${rest}`;
|
|
78
|
+
}
|
|
79
|
+
return `${entry}\n${existing}`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PackageEntry } from '../config/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Hash file contents for a set of glob patterns under a directory.
|
|
4
|
+
* Returns a hex sha256 hash string.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hashFiles(dir: string, patterns: string[]): string;
|
|
7
|
+
/** Read a stored fingerprint. Returns null if file does not exist. */
|
|
8
|
+
export declare function readFingerprint(path: string): string | null;
|
|
9
|
+
/** Write a fingerprint, creating parent dirs as needed. */
|
|
10
|
+
export declare function writeFingerprint(path: string, hash: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Compute per-package build fingerprints with dependency propagation.
|
|
13
|
+
* Processes packages in order (assumed topo-sorted in proman.yaml).
|
|
14
|
+
* Each package's fingerprint = hash(own src/** + package.json + tsconfig.json + dep fingerprints).
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeBuildFingerprints(cwd: string, packages: readonly Pick<PackageEntry, 'name' | 'path'>[]): Map<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Compute a root-level fingerprint for test or check commands.
|
|
19
|
+
* - test: all .ts files + package.json (covers src, tests, vitest.config.ts)
|
|
20
|
+
* - check: all .ts files + package.json + biome.json
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeRootFingerprint(cwd: string, command: 'test' | 'check'): string;
|
|
23
|
+
/** Convert a package name to a safe filename: @scope/name → @scope-name */
|
|
24
|
+
export declare function pkgNameToFilename(name: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Get the path where a fingerprint file should be stored.
|
|
27
|
+
*
|
|
28
|
+
* Storage strategy differs by command type:
|
|
29
|
+
* - **build**: stores fingerprint at `<pkg>/dist/.build-fingerprint` so that
|
|
30
|
+
* deleting `dist/` (clean build) automatically invalidates the cache.
|
|
31
|
+
* - **test / check**: stores in `.proman/<command>/` directory, which is
|
|
32
|
+
* independent of build artifacts and survives `dist/` cleanup.
|
|
33
|
+
*
|
|
34
|
+
* This separation ensures `rm -rf dist` forces a rebuild without
|
|
35
|
+
* accidentally invalidating test/check caches (and vice-versa).
|
|
36
|
+
*/
|
|
37
|
+
export declare function fingerprintPath(cwd: string, command: string, pkgName?: string): string;
|
|
38
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/utils/fingerprint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAsEtD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAWjE;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAGjE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,GACvD,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6CrB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAKrF;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAStF"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Recursively collect files matching glob-like patterns.
|
|
6
|
+
* Supports `**\/*.ext`, `dir/**\/*.ext`, and literal filenames.
|
|
7
|
+
*/
|
|
8
|
+
function collectFiles(baseDir, patterns) {
|
|
9
|
+
const results = [];
|
|
10
|
+
function walk(dir) {
|
|
11
|
+
let entries;
|
|
12
|
+
try {
|
|
13
|
+
entries = readdirSync(dir);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
for (const name of entries) {
|
|
19
|
+
if (name === 'node_modules' || name === '.git' || name === 'dist')
|
|
20
|
+
continue;
|
|
21
|
+
if (name === '.proman')
|
|
22
|
+
continue;
|
|
23
|
+
const full = join(dir, name);
|
|
24
|
+
let st;
|
|
25
|
+
try {
|
|
26
|
+
st = statSync(full);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (st.isDirectory()) {
|
|
32
|
+
walk(full);
|
|
33
|
+
}
|
|
34
|
+
else if (st.isFile()) {
|
|
35
|
+
const rel = relative(baseDir, full);
|
|
36
|
+
if (matchesAny(rel, patterns)) {
|
|
37
|
+
results.push(rel);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
walk(baseDir);
|
|
43
|
+
return results.sort();
|
|
44
|
+
}
|
|
45
|
+
function matchesAny(relPath, patterns) {
|
|
46
|
+
for (const p of patterns) {
|
|
47
|
+
// Handle patterns with **/ anywhere (e.g. "**/*.ts", "src/**/*.ts")
|
|
48
|
+
const dstarIdx = p.indexOf('**/');
|
|
49
|
+
if (dstarIdx >= 0) {
|
|
50
|
+
const prefix = p.slice(0, dstarIdx); // e.g. "" or "src/"
|
|
51
|
+
const suffix = p.slice(dstarIdx + 3); // e.g. "*.ts"
|
|
52
|
+
// Check prefix: relPath must start with the prefix (if any)
|
|
53
|
+
if (prefix && !relPath.startsWith(prefix))
|
|
54
|
+
continue;
|
|
55
|
+
// Check suffix: get the part after the prefix match
|
|
56
|
+
const rest = prefix ? relPath.slice(prefix.length) : relPath;
|
|
57
|
+
if (suffix.startsWith('*')) {
|
|
58
|
+
// *.ext pattern
|
|
59
|
+
const ext = suffix.slice(1); // e.g. ".ts"
|
|
60
|
+
if (rest.endsWith(ext))
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
else if (rest.endsWith(suffix)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Exact filename match (e.g. "package.json", "biome.json")
|
|
69
|
+
const base = relPath.split('/').pop() ?? relPath;
|
|
70
|
+
if (base === p || relPath === p)
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Hash file contents for a set of glob patterns under a directory.
|
|
78
|
+
* Returns a hex sha256 hash string.
|
|
79
|
+
*/
|
|
80
|
+
export function hashFiles(dir, patterns) {
|
|
81
|
+
const files = collectFiles(dir, patterns);
|
|
82
|
+
const hash = createHash('sha256');
|
|
83
|
+
for (const rel of files) {
|
|
84
|
+
hash.update(rel);
|
|
85
|
+
hash.update('\0');
|
|
86
|
+
const content = readFileSync(join(dir, rel));
|
|
87
|
+
hash.update(content);
|
|
88
|
+
hash.update('\0');
|
|
89
|
+
}
|
|
90
|
+
return hash.digest('hex');
|
|
91
|
+
}
|
|
92
|
+
/** Read a stored fingerprint. Returns null if file does not exist. */
|
|
93
|
+
export function readFingerprint(path) {
|
|
94
|
+
try {
|
|
95
|
+
return readFileSync(path, 'utf-8').trim();
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Write a fingerprint, creating parent dirs as needed. */
|
|
102
|
+
export function writeFingerprint(path, hash) {
|
|
103
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
104
|
+
writeFileSync(path, hash);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compute per-package build fingerprints with dependency propagation.
|
|
108
|
+
* Processes packages in order (assumed topo-sorted in proman.yaml).
|
|
109
|
+
* Each package's fingerprint = hash(own src/** + package.json + tsconfig.json + dep fingerprints).
|
|
110
|
+
*/
|
|
111
|
+
export function computeBuildFingerprints(cwd, packages) {
|
|
112
|
+
// Build dependency map from package.json files
|
|
113
|
+
const depMap = new Map();
|
|
114
|
+
const pkgNames = new Set(packages.map((p) => p.name));
|
|
115
|
+
for (const pkg of packages) {
|
|
116
|
+
const pkgJsonPath = join(resolve(cwd, pkg.path), 'package.json');
|
|
117
|
+
let deps = [];
|
|
118
|
+
try {
|
|
119
|
+
const json = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
120
|
+
if (json.dependencies) {
|
|
121
|
+
deps = Object.keys(json.dependencies).filter((d) => pkgNames.has(d));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// no package.json or parse error — no deps
|
|
126
|
+
}
|
|
127
|
+
depMap.set(pkg.name, deps);
|
|
128
|
+
}
|
|
129
|
+
const fingerprints = new Map();
|
|
130
|
+
for (const pkg of packages) {
|
|
131
|
+
const pkgDir = resolve(cwd, pkg.path);
|
|
132
|
+
// Own file hash
|
|
133
|
+
const ownHash = hashFiles(pkgDir, ['src/**/*.ts', 'package.json', 'tsconfig.json']);
|
|
134
|
+
// Combine with dependency fingerprints
|
|
135
|
+
const hash = createHash('sha256');
|
|
136
|
+
hash.update(ownHash);
|
|
137
|
+
const deps = depMap.get(pkg.name) ?? [];
|
|
138
|
+
for (const dep of deps.sort()) {
|
|
139
|
+
const depFp = fingerprints.get(dep) ?? '';
|
|
140
|
+
hash.update(dep);
|
|
141
|
+
hash.update('\0');
|
|
142
|
+
hash.update(depFp);
|
|
143
|
+
hash.update('\0');
|
|
144
|
+
}
|
|
145
|
+
fingerprints.set(pkg.name, hash.digest('hex'));
|
|
146
|
+
}
|
|
147
|
+
return fingerprints;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Compute a root-level fingerprint for test or check commands.
|
|
151
|
+
* - test: all .ts files + package.json (covers src, tests, vitest.config.ts)
|
|
152
|
+
* - check: all .ts files + package.json + biome.json
|
|
153
|
+
*/
|
|
154
|
+
export function computeRootFingerprint(cwd, command) {
|
|
155
|
+
const patterns = command === 'test' ? ['**/*.ts', 'package.json'] : ['**/*.ts', 'package.json', 'biome.json'];
|
|
156
|
+
return hashFiles(cwd, patterns);
|
|
157
|
+
}
|
|
158
|
+
/** Convert a package name to a safe filename: @scope/name → @scope-name */
|
|
159
|
+
export function pkgNameToFilename(name) {
|
|
160
|
+
return name.replace(/\//g, '-');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get the path where a fingerprint file should be stored.
|
|
164
|
+
*
|
|
165
|
+
* Storage strategy differs by command type:
|
|
166
|
+
* - **build**: stores fingerprint at `<pkg>/dist/.build-fingerprint` so that
|
|
167
|
+
* deleting `dist/` (clean build) automatically invalidates the cache.
|
|
168
|
+
* - **test / check**: stores in `.proman/<command>/` directory, which is
|
|
169
|
+
* independent of build artifacts and survives `dist/` cleanup.
|
|
170
|
+
*
|
|
171
|
+
* This separation ensures `rm -rf dist` forces a rebuild without
|
|
172
|
+
* accidentally invalidating test/check caches (and vice-versa).
|
|
173
|
+
*/
|
|
174
|
+
export function fingerprintPath(cwd, command, pkgName) {
|
|
175
|
+
if (command === 'build' && pkgName) {
|
|
176
|
+
// For build command, store fingerprint inside package's dist folder
|
|
177
|
+
return join(cwd, 'dist/.build-fingerprint');
|
|
178
|
+
}
|
|
179
|
+
// For test/check commands or when no package name, use .proman directory
|
|
180
|
+
const filename = pkgName ? `${pkgNameToFilename(pkgName)}.fingerprint` : 'root.fingerprint';
|
|
181
|
+
return join(cwd, '.proman', command, filename);
|
|
182
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type GitOps = {
|
|
2
|
+
getCurrentBranch: () => Promise<string>;
|
|
3
|
+
isCleanTree: () => Promise<boolean>;
|
|
4
|
+
branchExists: (name: string) => Promise<boolean>;
|
|
5
|
+
checkoutNewBranch: (name: string) => Promise<void>;
|
|
6
|
+
checkoutNewBranchFrom: (name: string, ref: string) => Promise<void>;
|
|
7
|
+
tagExists: (tag: string) => Promise<boolean>;
|
|
8
|
+
addAll: () => Promise<void>;
|
|
9
|
+
commit: (msg: string, author?: string) => Promise<void>;
|
|
10
|
+
push: (branch: string) => Promise<void>;
|
|
11
|
+
log: (range?: string) => Promise<string>;
|
|
12
|
+
tag: (name: string, message?: string) => Promise<void>;
|
|
13
|
+
pushTags: () => Promise<void>;
|
|
14
|
+
checkout: (branch: string) => Promise<void>;
|
|
15
|
+
merge: (branch: string, opts?: {
|
|
16
|
+
noFf?: boolean;
|
|
17
|
+
message?: string;
|
|
18
|
+
}) => Promise<void>;
|
|
19
|
+
deleteBranchLocal: (name: string) => Promise<void>;
|
|
20
|
+
deleteBranchRemote: (name: string) => Promise<void>;
|
|
21
|
+
};
|
|
22
|
+
export declare function createGitOps(cwd?: string): GitOps;
|
|
23
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG;IACnB,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC,WAAW,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACnC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACxC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrF,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD,CAAA;AAuBD,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CA8EhE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
async function run(args, cwd = process.cwd()) {
|
|
2
|
+
const { execFileSync } = await import('node:child_process');
|
|
3
|
+
try {
|
|
4
|
+
return execFileSync('git', args, {
|
|
5
|
+
cwd,
|
|
6
|
+
encoding: 'utf-8',
|
|
7
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
8
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
const e = err;
|
|
13
|
+
throw new Error(`git ${args.join(' ')} failed: ${(e.stderr ?? e.stdout ?? '').trim()}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function parseAuthor(author) {
|
|
17
|
+
const m = author.match(/^(.+?)\s*<(.+)>\s*$/);
|
|
18
|
+
if (!m)
|
|
19
|
+
throw new Error(`invalid author string: ${author}`);
|
|
20
|
+
return { name: m[1].trim(), email: m[2].trim() };
|
|
21
|
+
}
|
|
22
|
+
export function createGitOps(cwd = process.cwd()) {
|
|
23
|
+
return {
|
|
24
|
+
getCurrentBranch: async () => (await run(['branch', '--show-current'], cwd)).trim(),
|
|
25
|
+
isCleanTree: async () => (await run(['status', '--porcelain'], cwd)).trim() === '',
|
|
26
|
+
branchExists: async (name) => {
|
|
27
|
+
const { execFileSync } = await import('node:child_process');
|
|
28
|
+
try {
|
|
29
|
+
execFileSync('git', ['show-ref', '--verify', '--quiet', `refs/heads/${name}`], {
|
|
30
|
+
cwd,
|
|
31
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
32
|
+
});
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
checkoutNewBranch: async (name) => {
|
|
40
|
+
await run(['checkout', '-b', name], cwd);
|
|
41
|
+
},
|
|
42
|
+
checkoutNewBranchFrom: async (name, ref) => {
|
|
43
|
+
await run(['checkout', '-b', name, ref], cwd);
|
|
44
|
+
},
|
|
45
|
+
tagExists: async (tag) => {
|
|
46
|
+
const { execFileSync } = await import('node:child_process');
|
|
47
|
+
try {
|
|
48
|
+
execFileSync('git', ['rev-parse', '--verify', '-q', `refs/tags/${tag}`], {
|
|
49
|
+
cwd,
|
|
50
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
51
|
+
});
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
addAll: async () => {
|
|
59
|
+
await run(['add', '-A'], cwd);
|
|
60
|
+
},
|
|
61
|
+
commit: async (msg, author) => {
|
|
62
|
+
const args = ['commit', '-m', msg];
|
|
63
|
+
if (author) {
|
|
64
|
+
const { name, email } = parseAuthor(author);
|
|
65
|
+
args.unshift('-c', `user.name=${name}`, '-c', `user.email=${email}`);
|
|
66
|
+
args.push(`--author=${author}`);
|
|
67
|
+
}
|
|
68
|
+
await run(args, cwd);
|
|
69
|
+
},
|
|
70
|
+
push: async (branch) => {
|
|
71
|
+
await run(['push', '-u', 'origin', branch], cwd);
|
|
72
|
+
},
|
|
73
|
+
log: async (range) => {
|
|
74
|
+
const args = ['log', '--pretty=%s'];
|
|
75
|
+
if (range)
|
|
76
|
+
args.push(range);
|
|
77
|
+
return await run(args, cwd);
|
|
78
|
+
},
|
|
79
|
+
tag: async (name, message) => {
|
|
80
|
+
const args = message ? ['tag', '-a', name, '-m', message] : ['tag', name];
|
|
81
|
+
await run(args, cwd);
|
|
82
|
+
},
|
|
83
|
+
pushTags: async () => {
|
|
84
|
+
await run(['push', '--tags'], cwd);
|
|
85
|
+
},
|
|
86
|
+
checkout: async (branch) => {
|
|
87
|
+
await run(['checkout', branch], cwd);
|
|
88
|
+
},
|
|
89
|
+
merge: async (branch, opts) => {
|
|
90
|
+
const args = ['merge'];
|
|
91
|
+
if (opts?.noFf)
|
|
92
|
+
args.push('--no-ff');
|
|
93
|
+
if (opts?.message)
|
|
94
|
+
args.push('-m', opts.message);
|
|
95
|
+
args.push(branch);
|
|
96
|
+
await run(args, cwd);
|
|
97
|
+
},
|
|
98
|
+
deleteBranchLocal: async (name) => {
|
|
99
|
+
await run(['branch', '-d', name], cwd);
|
|
100
|
+
},
|
|
101
|
+
deleteBranchRemote: async (name) => {
|
|
102
|
+
await run(['push', 'origin', '--delete', name], cwd);
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type NpmRegistryFetch = (pkg: string) => Promise<string[]>;
|
|
2
|
+
export type PublishOptions = {
|
|
3
|
+
tag: string;
|
|
4
|
+
access?: 'public' | 'restricted';
|
|
5
|
+
};
|
|
6
|
+
export type NpmRunner = {
|
|
7
|
+
install: () => Promise<void>;
|
|
8
|
+
build: () => Promise<void>;
|
|
9
|
+
test: () => Promise<void>;
|
|
10
|
+
check: () => Promise<void>;
|
|
11
|
+
format: () => Promise<void>;
|
|
12
|
+
publish: (pkgDir: string, opts: PublishOptions) => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export type NextRcOptions = {
|
|
15
|
+
baseVersion: string;
|
|
16
|
+
existing: string[];
|
|
17
|
+
};
|
|
18
|
+
export declare function parseReleaseBranch(branch: string): string;
|
|
19
|
+
export declare function nextRcNumber(opts: NextRcOptions): number;
|
|
20
|
+
export declare function formatRcVersion(baseVersion: string, n: number): string;
|
|
21
|
+
export declare const defaultRegistryFetch: NpmRegistryFetch;
|
|
22
|
+
export type SpawnFn = (argv: string[], cwd: string) => Promise<{
|
|
23
|
+
code: number;
|
|
24
|
+
stdout: string;
|
|
25
|
+
stderr: string;
|
|
26
|
+
}>;
|
|
27
|
+
export declare const defaultSpawn: SpawnFn;
|
|
28
|
+
export declare function runOrThrow(spawn: SpawnFn, argv: string[], cwd: string): Promise<void>;
|
|
29
|
+
export declare function createNpmRunner(cwd: string, spawn?: SpawnFn): NpmRunner;
|
|
30
|
+
//# sourceMappingURL=npm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/utils/npm.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAEjE,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAID,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAWxD;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAQlC,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,KACR,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE9D,eAAO,MAAM,YAAY,EAAE,OAgB1B,CAAA;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3F;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,OAAsB,GAAG,SAAS,CAoBrF"}
|