@fuman/build 0.0.1

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.
Files changed (105) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +108 -0
  3. package/ci/github-actions.d.ts +3 -0
  4. package/ci/github-actions.js +28 -0
  5. package/ci/index.d.ts +1 -0
  6. package/cli/commands/_utils.d.ts +8 -0
  7. package/cli/commands/_utils.js +18 -0
  8. package/cli/commands/build.d.ts +20 -0
  9. package/cli/commands/build.js +45 -0
  10. package/cli/commands/bump-version.d.ts +18 -0
  11. package/cli/commands/bump-version.js +72 -0
  12. package/cli/commands/cr.d.ts +17 -0
  13. package/cli/commands/cr.js +76 -0
  14. package/cli/commands/find-changed-packages.d.ts +12 -0
  15. package/cli/commands/find-changed-packages.js +44 -0
  16. package/cli/commands/gen-changelog.d.ts +12 -0
  17. package/cli/commands/gen-changelog.js +49 -0
  18. package/cli/commands/gen-deps-graph.d.ts +15 -0
  19. package/cli/commands/gen-deps-graph.js +78 -0
  20. package/cli/commands/jsr.d.ts +6 -0
  21. package/cli/commands/jsr.js +79 -0
  22. package/cli/commands/publish.d.ts +48 -0
  23. package/cli/commands/publish.js +197 -0
  24. package/cli/commands/release.d.ts +34 -0
  25. package/cli/commands/release.js +226 -0
  26. package/cli/commands/validate-workspace-deps.d.ts +38 -0
  27. package/cli/commands/validate-workspace-deps.js +68 -0
  28. package/cli/index.d.ts +3 -0
  29. package/cli/main.d.ts +2 -0
  30. package/config.d.ts +32 -0
  31. package/fuman-build.d.ts +1 -0
  32. package/fuman-build.js +33 -0
  33. package/git/github.d.ts +14 -0
  34. package/git/github.js +48 -0
  35. package/git/index.d.ts +1 -0
  36. package/git/utils.d.ts +38 -0
  37. package/git/utils.js +110 -0
  38. package/index.d.ts +7 -0
  39. package/index.js +46 -0
  40. package/jsr/build-jsr.d.ts +7 -0
  41. package/jsr/build-jsr.js +145 -0
  42. package/jsr/config.d.ts +48 -0
  43. package/jsr/create-packages.d.ts +8 -0
  44. package/jsr/create-packages.js +46 -0
  45. package/jsr/deno-json.d.ts +19 -0
  46. package/jsr/deno-json.js +80 -0
  47. package/jsr/generate-workspace.d.ts +9 -0
  48. package/jsr/generate-workspace.js +174 -0
  49. package/jsr/index.d.ts +5 -0
  50. package/jsr/populate.d.ts +45 -0
  51. package/jsr/populate.js +132 -0
  52. package/jsr/utils/external-libs.d.ts +8 -0
  53. package/jsr/utils/external-libs.js +46 -0
  54. package/jsr/utils/index.d.ts +4 -0
  55. package/jsr/utils/jsr-api.d.ts +23 -0
  56. package/jsr/utils/jsr-api.js +115 -0
  57. package/jsr/utils/jsr-json.d.ts +10 -0
  58. package/jsr/utils/jsr-json.js +80 -0
  59. package/jsr/utils/jsr.d.ts +11 -0
  60. package/jsr/utils/jsr.js +74 -0
  61. package/jsr.d.ts +1 -0
  62. package/jsr.js +23 -0
  63. package/misc/_config.d.ts +1 -0
  64. package/misc/_config.js +18 -0
  65. package/misc/exec.d.ts +9 -0
  66. package/misc/exec.js +40 -0
  67. package/misc/fs.d.ts +4 -0
  68. package/misc/fs.js +32 -0
  69. package/misc/index.d.ts +4 -0
  70. package/misc/path.d.ts +1 -0
  71. package/misc/path.js +12 -0
  72. package/misc/publish-order.d.ts +3 -0
  73. package/misc/publish-order.js +56 -0
  74. package/misc/tsconfig.d.ts +2 -0
  75. package/misc/tsconfig.js +28 -0
  76. package/npm/index.d.ts +1 -0
  77. package/npm/npm-api.d.ts +7 -0
  78. package/npm/npm-api.js +18 -0
  79. package/package-json/collect-package-jsons.d.ts +8 -0
  80. package/package-json/collect-package-jsons.js +61 -0
  81. package/package-json/find-package-json.d.ts +7 -0
  82. package/package-json/find-package-json.js +28 -0
  83. package/package-json/index.d.ts +5 -0
  84. package/package-json/parse.d.ts +4 -0
  85. package/package-json/parse.js +40 -0
  86. package/package-json/process-package-json.d.ts +13 -0
  87. package/package-json/process-package-json.js +132 -0
  88. package/package-json/types.d.ts +56 -0
  89. package/package-json/types.js +57 -0
  90. package/package-json/utils.d.ts +4 -0
  91. package/package-json/utils.js +27 -0
  92. package/package.json +67 -0
  93. package/versioning/bump-version.d.ts +48 -0
  94. package/versioning/bump-version.js +129 -0
  95. package/versioning/collect-files.d.ts +22 -0
  96. package/versioning/collect-files.js +66 -0
  97. package/versioning/generate-changelog.d.ts +13 -0
  98. package/versioning/generate-changelog.js +81 -0
  99. package/versioning/types.d.ts +32 -0
  100. package/vite/build-plugin.d.ts +73 -0
  101. package/vite/build-plugin.js +170 -0
  102. package/vite/config.d.ts +34 -0
  103. package/vite/index.d.ts +2 -0
  104. package/vite.d.ts +1 -0
  105. package/vite.js +4 -0
@@ -0,0 +1,80 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { parseConfigFileTextToJson } from "typescript";
4
+ import { parseImportSpecifier } from "./external-libs.js";
5
+ function parseJsrJson(json) {
6
+ const res = parseConfigFileTextToJson("jsr.json", json);
7
+ if (res.error) {
8
+ throw new Error(res.error.messageText.toString());
9
+ }
10
+ const obj = res.config;
11
+ if (typeof obj !== "object" || obj === null) {
12
+ throw new Error("Expected object");
13
+ }
14
+ if (typeof obj.name !== "string") {
15
+ throw new TypeError('Expected "name" to be a string');
16
+ }
17
+ if (typeof obj.version !== "string") {
18
+ throw new TypeError('Expected "version" to be a string');
19
+ }
20
+ if (typeof obj.exports !== "string" && (typeof obj.exports !== "object" || obj.exports === null)) {
21
+ throw new TypeError('Expected "exports" to be a string or an object');
22
+ }
23
+ if (typeof obj.exports !== "string") {
24
+ for (const key in obj.exports) {
25
+ if (typeof key !== "string") {
26
+ throw new TypeError("exports: Expected key to be a string");
27
+ }
28
+ if (typeof obj.exports[key] !== "string") {
29
+ throw new TypeError("exports: Expected value to be a string");
30
+ }
31
+ }
32
+ }
33
+ if (obj.imports !== void 0) {
34
+ if (typeof obj.imports !== "object" || obj.imports === null) {
35
+ throw new TypeError('Expected "imports" to be an object');
36
+ }
37
+ for (const key in obj.imports) {
38
+ if (typeof key !== "string") {
39
+ throw new TypeError("imports: Expected key to be a string");
40
+ }
41
+ if (typeof obj.imports[key] !== "string") {
42
+ throw new TypeError("imports: Expected value to be a string");
43
+ }
44
+ obj.imports[key] = parseImportSpecifier(obj.imports[key]);
45
+ }
46
+ }
47
+ if (obj.compilerOptions !== void 0) {
48
+ if (typeof obj.compilerOptions !== "object" || obj.compilerOptions === null) {
49
+ throw new TypeError('Expected "compilerOptions" to be an object');
50
+ }
51
+ }
52
+ return obj;
53
+ }
54
+ const _findClosestJsrJsonCache = /* @__PURE__ */ new Map();
55
+ function findClosestJsrJson(path) {
56
+ while (true) {
57
+ if (_findClosestJsrJsonCache.has(path)) {
58
+ return _findClosestJsrJsonCache.get(path);
59
+ }
60
+ for (const file of ["jsr.json", "deno.json", "jsr.jsonc", "deno.jsonc"]) {
61
+ if (existsSync(join(path, file))) {
62
+ _findClosestJsrJsonCache.set(path, join(path, file));
63
+ return join(path, file);
64
+ }
65
+ }
66
+ if (existsSync(join(path, "package.json"))) {
67
+ _findClosestJsrJsonCache.set(path, null);
68
+ return null;
69
+ }
70
+ const parent = join(path, "..");
71
+ if (parent === path) {
72
+ return null;
73
+ }
74
+ path = parent;
75
+ }
76
+ }
77
+ export {
78
+ findClosestJsrJson,
79
+ parseJsrJson
80
+ };
@@ -0,0 +1,11 @@
1
+ import { ImportSpecifier } from './external-libs.js';
2
+ /** check if a specific version (or a package at all) is available in the jsr registry */
3
+ export declare function jsrCheckVersion(params: {
4
+ registry?: string;
5
+ package: string;
6
+ version?: string;
7
+ }): Promise<boolean>;
8
+ export declare function downloadJsrPackage(specifier: ImportSpecifier, params?: {
9
+ registry?: string;
10
+ force?: boolean;
11
+ }): Promise<string>;
@@ -0,0 +1,74 @@
1
+ import * as fs from "node:fs";
2
+ import * as fsp from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import process from "node:process";
5
+ import { ffetchBase, ffetchAddons } from "@fuman/fetch";
6
+ import { ffetchZodAdapter } from "@fuman/fetch/zod";
7
+ import { write, webReadableToFuman } from "@fuman/io";
8
+ import { nodeWritableToFuman } from "@fuman/node";
9
+ import { asyncPool } from "@fuman/utils";
10
+ import semver from "semver";
11
+ import { z } from "zod";
12
+ import { directoryExists } from "../../misc/fs.js";
13
+ import { getModuleCacheDirectory } from "./external-libs.js";
14
+ const DEFAULT_REGISTRY = process.env.JSR_URL ?? "https://jsr.io";
15
+ async function jsrCheckVersion(params) {
16
+ const {
17
+ registry = DEFAULT_REGISTRY,
18
+ package: packageName,
19
+ version
20
+ } = params;
21
+ const res = await ffetchBase(`/${packageName}/meta${version != null ? `_${version}` : ""}.json`, {
22
+ baseUrl: registry,
23
+ validateResponse: false
24
+ });
25
+ return res.status === 200;
26
+ }
27
+ async function downloadJsrPackage(specifier, params) {
28
+ if (specifier.registry !== "jsr") {
29
+ throw new Error("Invalid registry");
30
+ }
31
+ const registry = params?.registry ?? DEFAULT_REGISTRY;
32
+ const ffetch = ffetchBase.extend({
33
+ baseUrl: registry,
34
+ addons: [
35
+ ffetchAddons.parser(ffetchZodAdapter())
36
+ ]
37
+ });
38
+ const targetDir = `${specifier.packageName.replace(/\//g, "+")}@${specifier.version}`;
39
+ const registryHost = new URL(registry).host;
40
+ const cacheDir = join(getModuleCacheDirectory(), "jsr", registryHost, targetDir);
41
+ if (await directoryExists(cacheDir)) {
42
+ if (params?.force) {
43
+ await fsp.rm(cacheDir, { recursive: true });
44
+ } else {
45
+ return cacheDir;
46
+ }
47
+ }
48
+ const meta = await ffetch(`${specifier.packageName}/meta.json`).parsedJson(z.object({
49
+ versions: z.record(z.unknown())
50
+ }));
51
+ const availableVersions = Object.keys(meta.versions);
52
+ const version = semver.maxSatisfying(availableVersions, specifier.version);
53
+ if (version == null) {
54
+ throw new Error(`No matching version for ${specifier.packageName}@${specifier.version}`);
55
+ }
56
+ await fsp.mkdir(cacheDir, { recursive: true });
57
+ const versionMeta = await ffetch(`${specifier.packageName}/${version}_meta.json`).parsedJson(z.object({
58
+ manifest: z.record(z.unknown())
59
+ }));
60
+ const fetchFile = async (file) => {
61
+ file = file.replace(/^\//, "");
62
+ const filePath = join(cacheDir, file);
63
+ await fsp.mkdir(join(filePath, ".."), { recursive: true });
64
+ const from = await ffetch(`${specifier.packageName}/${version}/${file}`).stream();
65
+ const into = nodeWritableToFuman(fs.createWriteStream(filePath));
66
+ await write.pipe(into, webReadableToFuman(from));
67
+ };
68
+ await asyncPool(Object.keys(versionMeta.manifest), fetchFile, { limit: 16 });
69
+ return cacheDir;
70
+ }
71
+ export {
72
+ downloadJsrPackage,
73
+ jsrCheckVersion
74
+ };
package/jsr.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./jsr/index.js"
package/jsr.js ADDED
@@ -0,0 +1,23 @@
1
+ import { runJsrBuild } from "./jsr/build-jsr.js";
2
+ import { packageJsonToDeno } from "./jsr/deno-json.js";
3
+ import { populateFromUpstream } from "./jsr/populate.js";
4
+ import { getModuleCacheDirectory, parseImportSpecifier, splitImportRequest } from "./jsr/utils/external-libs.js";
5
+ import { jsrCreateScope, jsrGetScopeInfo, jsrMaybeCreatePackage, jsrSetGithubRepo } from "./jsr/utils/jsr-api.js";
6
+ import { findClosestJsrJson, parseJsrJson } from "./jsr/utils/jsr-json.js";
7
+ import { downloadJsrPackage, jsrCheckVersion } from "./jsr/utils/jsr.js";
8
+ export {
9
+ downloadJsrPackage,
10
+ findClosestJsrJson,
11
+ getModuleCacheDirectory,
12
+ jsrCheckVersion,
13
+ jsrCreateScope,
14
+ jsrGetScopeInfo,
15
+ jsrMaybeCreatePackage,
16
+ jsrSetGithubRepo,
17
+ packageJsonToDeno,
18
+ parseImportSpecifier,
19
+ parseJsrJson,
20
+ populateFromUpstream,
21
+ runJsrBuild,
22
+ splitImportRequest
23
+ };
@@ -0,0 +1 @@
1
+ export declare function loadBuildConfig<T>(packageRoot: string, configName?: string): Promise<T | undefined>;
@@ -0,0 +1,18 @@
1
+ import { join } from "node:path";
2
+ async function loadBuildConfig(packageRoot, configName = "build.config.js") {
3
+ try {
4
+ const mod = (await import(join(packageRoot, configName))).default;
5
+ if (typeof mod === "function") {
6
+ return mod();
7
+ } else {
8
+ return mod;
9
+ }
10
+ } catch (e) {
11
+ if (!(e instanceof Error && e.code === "ERR_MODULE_NOT_FOUND")) {
12
+ throw new Error(`Could not load ${configName}`, { cause: e });
13
+ }
14
+ }
15
+ }
16
+ export {
17
+ loadBuildConfig
18
+ };
package/misc/exec.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { SpawnOptions } from 'node:child_process';
2
+ export interface ExecResult {
3
+ stdout: string;
4
+ stderr: string;
5
+ exitCode: number;
6
+ }
7
+ export declare function exec(cmd: string[], options?: SpawnOptions & {
8
+ throwOnError?: boolean;
9
+ }): Promise<ExecResult>;
package/misc/exec.js ADDED
@@ -0,0 +1,40 @@
1
+ import { spawn } from "node:child_process";
2
+ function exec(cmd, options) {
3
+ return new Promise((resolve, reject) => {
4
+ if (options?.stdio === "inherit") {
5
+ console.log("\x1B[;34m$\x1B[;0m", cmd.map((it) => it.includes(" ") ? `"${it.replace(/"/g, '\\"')}"` : it).join(" "));
6
+ }
7
+ const proc = spawn(cmd[0], cmd.slice(1), {
8
+ stdio: "pipe",
9
+ ...options
10
+ });
11
+ const stdout = [];
12
+ const stderr = [];
13
+ proc.stdout?.on("data", (data) => {
14
+ stdout.push(data);
15
+ });
16
+ proc.stderr?.on("data", (data) => {
17
+ stderr.push(data);
18
+ });
19
+ proc.on("error", reject);
20
+ proc.on("close", (code) => {
21
+ if (code !== 0 && options?.throwOnError) {
22
+ reject(new Error(`Command exited with code ${code}`, {
23
+ cause: {
24
+ stderr: Buffer.concat(stderr).toString(),
25
+ exitCode: code,
26
+ cmd
27
+ }
28
+ }));
29
+ }
30
+ resolve({
31
+ stdout: Buffer.concat(stdout).toString(),
32
+ stderr: Buffer.concat(stderr).toString(),
33
+ exitCode: code ?? -1
34
+ });
35
+ });
36
+ });
37
+ }
38
+ export {
39
+ exec
40
+ };
package/misc/fs.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { CopyOptions } from 'node:fs';
2
+ export declare function fileExists(path: string): Promise<boolean>;
3
+ export declare function directoryExists(path: string): Promise<boolean>;
4
+ export declare function tryCopy(src: string, dest: string, options?: CopyOptions): Promise<void>;
package/misc/fs.js ADDED
@@ -0,0 +1,32 @@
1
+ import * as fsp from "node:fs/promises";
2
+ async function fileExists(path) {
3
+ try {
4
+ const stat = await fsp.stat(path);
5
+ return stat.isFile();
6
+ } catch {
7
+ return false;
8
+ }
9
+ }
10
+ async function directoryExists(path) {
11
+ try {
12
+ const stat = await fsp.stat(path);
13
+ return stat.isDirectory();
14
+ } catch {
15
+ return false;
16
+ }
17
+ }
18
+ async function tryCopy(src, dest, options) {
19
+ try {
20
+ await fsp.cp(src, dest, options);
21
+ } catch (err) {
22
+ if (err.code === "ENOENT") ;
23
+ else {
24
+ throw err;
25
+ }
26
+ }
27
+ }
28
+ export {
29
+ directoryExists,
30
+ fileExists,
31
+ tryCopy
32
+ };
@@ -0,0 +1,4 @@
1
+ export * from './exec.js';
2
+ export * from './path.js';
3
+ export * from './publish-order.js';
4
+ export * from './tsconfig.js';
package/misc/path.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function normalizeFilePath(filePath: string | URL): string;
package/misc/path.js ADDED
@@ -0,0 +1,12 @@
1
+ import { fileURLToPath } from "node:url";
2
+ function normalizeFilePath(filePath) {
3
+ if (filePath instanceof URL) {
4
+ return fileURLToPath(filePath);
5
+ } else if (filePath.startsWith("file://")) {
6
+ return fileURLToPath(new URL(filePath));
7
+ }
8
+ return filePath;
9
+ }
10
+ export {
11
+ normalizeFilePath
12
+ };
@@ -0,0 +1,3 @@
1
+ import { WorkspacePackage } from '../package-json/collect-package-jsons.js';
2
+ export declare function sortWorkspaceByPublishOrder(packages: WorkspacePackage[]): WorkspacePackage[];
3
+ export declare function determinePublishOrder(dependencies: Record<string, string[]>): string[];
@@ -0,0 +1,56 @@
1
+ import { asNonNull } from "@fuman/utils";
2
+ function sortWorkspaceByPublishOrder(packages) {
3
+ const workspacePackages = /* @__PURE__ */ new Map();
4
+ for (const pkg of packages) {
5
+ workspacePackages.set(asNonNull(pkg.json.name), pkg);
6
+ }
7
+ const dependencies = {};
8
+ for (const pkg of packages) {
9
+ if (pkg.json.name == null) continue;
10
+ const list = [];
11
+ for (const key of ["dependencies", "peerDependencies"]) {
12
+ const deps = pkg.json[key];
13
+ if (!deps) continue;
14
+ for (const name in deps) {
15
+ if (workspacePackages.has(name)) {
16
+ list.push(name);
17
+ }
18
+ }
19
+ }
20
+ dependencies[pkg.json.name] = list;
21
+ }
22
+ const order = determinePublishOrder(dependencies);
23
+ const res = [];
24
+ for (const name of order) {
25
+ res.push(asNonNull(workspacePackages.get(name)));
26
+ }
27
+ return res;
28
+ }
29
+ function determinePublishOrder(dependencies) {
30
+ const result = [];
31
+ const visited = /* @__PURE__ */ new Set();
32
+ const visiting = /* @__PURE__ */ new Set();
33
+ function visit(name) {
34
+ if (visited.has(name)) {
35
+ return;
36
+ }
37
+ if (visiting.has(name)) {
38
+ throw new Error(`Circular dependency detected: ${name}`);
39
+ }
40
+ visiting.add(name);
41
+ for (const dep of dependencies[name] ?? []) {
42
+ visit(dep);
43
+ }
44
+ visiting.delete(name);
45
+ visited.add(name);
46
+ result.push(name);
47
+ }
48
+ for (const name in dependencies) {
49
+ visit(name);
50
+ }
51
+ return result;
52
+ }
53
+ export {
54
+ determinePublishOrder,
55
+ sortWorkspaceByPublishOrder
56
+ };
@@ -0,0 +1,2 @@
1
+ export declare function getTsconfigFor(cwd: string): Promise<unknown>;
2
+ export declare function getTsconfigFiles(cwd: string): Promise<string[]>;
@@ -0,0 +1,28 @@
1
+ import { LruMap } from "@fuman/utils";
2
+ import { exec } from "./exec.js";
3
+ async function getTsconfigFor(cwd) {
4
+ const res = await exec(["npx", "tsc", "--showConfig"], {
5
+ cwd,
6
+ throwOnError: true
7
+ });
8
+ return JSON.parse(res.stdout);
9
+ }
10
+ const _tsconfigFilesCache = new LruMap(32);
11
+ async function getTsconfigFiles(cwd) {
12
+ const cached = _tsconfigFilesCache.get(cwd);
13
+ if (cached) return cached;
14
+ const config = await getTsconfigFor(cwd);
15
+ if (typeof config !== "object" || config === null) {
16
+ throw new Error("tsconfig.json is not an object");
17
+ }
18
+ if (!("files" in config) || !Array.isArray(config.files)) {
19
+ throw new Error("tsconfig.json > .files is not an array");
20
+ }
21
+ const files = config.files.map((file) => file.replace(/^\.\//, ""));
22
+ _tsconfigFilesCache.set(cwd, files);
23
+ return files;
24
+ }
25
+ export {
26
+ getTsconfigFiles,
27
+ getTsconfigFor
28
+ };
package/npm/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './npm-api.js';
@@ -0,0 +1,7 @@
1
+ export declare const NPM_PACKAGE_NAME_REGEX: RegExp;
2
+ /** check if a specific version is available in the jsr registry */
3
+ export declare function npmCheckVersion(params: {
4
+ registry?: string;
5
+ package: string;
6
+ version: string;
7
+ }): Promise<boolean>;
package/npm/npm-api.js ADDED
@@ -0,0 +1,18 @@
1
+ import { ffetchBase } from "@fuman/fetch";
2
+ const NPM_PACKAGE_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
3
+ async function npmCheckVersion(params) {
4
+ const {
5
+ registry = "https://registry.npmjs.org",
6
+ package: packageName,
7
+ version
8
+ } = params;
9
+ const res = await ffetchBase(`/${packageName}/${version}`, {
10
+ baseUrl: registry,
11
+ validateResponse: false
12
+ });
13
+ return res.status === 200;
14
+ }
15
+ export {
16
+ NPM_PACKAGE_NAME_REGEX,
17
+ npmCheckVersion
18
+ };
@@ -0,0 +1,8 @@
1
+ import { PackageJson } from './types.js';
2
+ export interface WorkspacePackage {
3
+ path: string;
4
+ root: boolean;
5
+ json: PackageJson;
6
+ }
7
+ export declare function collectPackageJsons(workspaceRoot: string | URL, includeRoot?: boolean): Promise<WorkspacePackage[]>;
8
+ export declare function filterPackageJsonsForPublish(packages: WorkspacePackage[], registry: 'jsr' | 'npm'): WorkspacePackage[];
@@ -0,0 +1,61 @@
1
+ import * as path from "node:path";
2
+ import process from "node:process";
3
+ import { glob } from "tinyglobby";
4
+ import { normalizeFilePath } from "../misc/path.js";
5
+ import { parseWorkspaceRootPackageJson, parsePackageJsonFile } from "./parse.js";
6
+ const maxDepth = process.env.FUMAN_BUILD_MAX_DEPTH !== void 0 ? Number(process.env.FUMAN_BUILD_MAX_DEPTH) : 5;
7
+ async function collectPackageJsons(workspaceRoot, includeRoot = false) {
8
+ workspaceRoot = normalizeFilePath(workspaceRoot);
9
+ const packageJsons = [];
10
+ const rootPackageJson = await parseWorkspaceRootPackageJson(workspaceRoot);
11
+ if (!rootPackageJson.workspaces) {
12
+ throw new Error("No workspaces found in package.json");
13
+ }
14
+ if (includeRoot) {
15
+ packageJsons.push({
16
+ path: workspaceRoot,
17
+ root: true,
18
+ json: rootPackageJson
19
+ });
20
+ }
21
+ for (const dir of await glob({
22
+ patterns: rootPackageJson.workspaces,
23
+ cwd: workspaceRoot,
24
+ onlyDirectories: true,
25
+ followSymbolicLinks: true,
26
+ deep: maxDepth
27
+ })) {
28
+ try {
29
+ const packageJson = await parsePackageJsonFile(path.join(workspaceRoot, dir, "package.json"));
30
+ packageJsons.push({
31
+ path: path.join(workspaceRoot, dir),
32
+ root: false,
33
+ json: packageJson
34
+ });
35
+ } catch (err) {
36
+ if (err.code === "ENOENT") ;
37
+ else {
38
+ throw err;
39
+ }
40
+ }
41
+ }
42
+ return packageJsons;
43
+ }
44
+ function filterPackageJsonsForPublish(packages, registry) {
45
+ const otherRegistry = registry === "npm" ? "jsr" : "npm";
46
+ return packages.filter((pkg) => {
47
+ if (pkg.root) {
48
+ return false;
49
+ }
50
+ const fumanConfig = pkg.json.fuman;
51
+ if (!fumanConfig) return true;
52
+ if (fumanConfig.private) return false;
53
+ if (fumanConfig[registry] === "skip") return false;
54
+ if (fumanConfig[otherRegistry] === "only") return false;
55
+ return true;
56
+ });
57
+ }
58
+ export {
59
+ collectPackageJsons,
60
+ filterPackageJsonsForPublish
61
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Find the closest package.json file
3
+ *
4
+ * @param from The directory (or file) to start searching from
5
+ * @example `findPackageJson(import.meta.url)` // returns the package.json file of this package
6
+ */
7
+ export declare function findPackageJson(from: string | URL): Promise<string | null>;
@@ -0,0 +1,28 @@
1
+ import * as path from "node:path";
2
+ import { LruMap } from "@fuman/utils";
3
+ import { fileExists } from "../misc/fs.js";
4
+ import { normalizeFilePath } from "../misc/path.js";
5
+ const _findPackageJsonCache = new LruMap(32);
6
+ async function findPackageJson(from) {
7
+ from = normalizeFilePath(from);
8
+ const cached = _findPackageJsonCache.get(from);
9
+ if (cached != null) return cached;
10
+ let current = from;
11
+ while (true) {
12
+ if (current === "/") return null;
13
+ const file = path.join(current, "package.json");
14
+ if (await fileExists(file)) {
15
+ _findPackageJsonCache.set(from, file);
16
+ return file;
17
+ }
18
+ const parent = path.join(current, "..");
19
+ if (parent === current) {
20
+ _findPackageJsonCache.set(from, null);
21
+ return null;
22
+ }
23
+ current = parent;
24
+ }
25
+ }
26
+ export {
27
+ findPackageJson
28
+ };
@@ -0,0 +1,5 @@
1
+ export * from './collect-package-jsons.js';
2
+ export * from './find-package-json.js';
3
+ export * from './parse.js';
4
+ export * from './process-package-json.js';
5
+ export * from './types.js';
@@ -0,0 +1,4 @@
1
+ import { PackageJson } from './types.js';
2
+ export declare function parsePackageJson(packageJson: string): PackageJson;
3
+ export declare function parsePackageJsonFile(packageJsonPath: string | URL): Promise<PackageJson>;
4
+ export declare function parseWorkspaceRootPackageJson(workspaceRoot: string | URL): Promise<PackageJson>;
@@ -0,0 +1,40 @@
1
+ import * as fsp from "node:fs/promises";
2
+ import path__default from "node:path";
3
+ import * as jsyaml from "js-yaml";
4
+ import { normalizeFilePath } from "../misc/path.js";
5
+ import { PackageJsonSchema } from "./types.js";
6
+ function parsePackageJson(packageJson) {
7
+ return PackageJsonSchema.parse(JSON.parse(packageJson));
8
+ }
9
+ async function parsePackageJsonFile(packageJsonPath) {
10
+ return parsePackageJson(await fsp.readFile(normalizeFilePath(packageJsonPath), "utf8"));
11
+ }
12
+ async function parseWorkspaceRootPackageJson(workspaceRoot) {
13
+ workspaceRoot = normalizeFilePath(workspaceRoot);
14
+ const packageJsonPath = path__default.join(workspaceRoot, "package.json");
15
+ const parsed = await parsePackageJsonFile(packageJsonPath);
16
+ if (!parsed.workspaces) {
17
+ const pnpmWorkspacePath = path__default.join(workspaceRoot, "pnpm-workspace.yaml");
18
+ let yaml;
19
+ try {
20
+ yaml = await fsp.readFile(pnpmWorkspacePath, "utf8");
21
+ } catch (e) {
22
+ if (e.code !== "ENOENT") throw e;
23
+ return parsed;
24
+ }
25
+ const workspace = jsyaml.load(yaml);
26
+ if (!workspace.packages) {
27
+ throw new Error("No packages found in pnpm-workspace.yaml");
28
+ }
29
+ return {
30
+ ...parsed,
31
+ workspaces: workspace.packages
32
+ };
33
+ }
34
+ return parsed;
35
+ }
36
+ export {
37
+ parsePackageJson,
38
+ parsePackageJsonFile,
39
+ parseWorkspaceRootPackageJson
40
+ };
@@ -0,0 +1,13 @@
1
+ import { PackageJson } from './types.js';
2
+ export declare function processPackageJson(params: {
3
+ packageJson: PackageJson;
4
+ workspaceVersions?: Record<string, string>;
5
+ bundledWorkspaceDeps?: RegExp[];
6
+ rootPackageJson?: PackageJson;
7
+ rootFieldsToCopy?: string[];
8
+ fixedVersion?: string;
9
+ }): {
10
+ packageJson: PackageJson;
11
+ packageJsonOrig: PackageJson;
12
+ entrypoints: Record<string, string>;
13
+ };