@decohere/workspace 0.0.1-dev.125 → 0.0.1-dev.5

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 (75) hide show
  1. package/package.json +3 -13
  2. package/src/const.ts +19 -0
  3. package/src/errors.ts +1 -0
  4. package/src/factories/config.factory.ts +21 -0
  5. package/src/factories/find-workspace-root.ts +32 -0
  6. package/src/factories/project.factory.ts +75 -0
  7. package/src/factories/workspace.factory.ts +44 -0
  8. package/{types/src/index.d.ts → src/index.ts} +7 -1
  9. package/src/models/has-package-json.mixin.ts +30 -0
  10. package/src/models/has-tsconfig.mixin.ts +48 -0
  11. package/src/models/package-aliases.ts +130 -0
  12. package/src/models/package-json.model.ts +231 -0
  13. package/src/models/project-file-event.ts +9 -0
  14. package/src/models/project.model.ts +340 -0
  15. package/src/models/source-extensions.ts +59 -0
  16. package/src/models/tsconfig.model.ts +81 -0
  17. package/src/models/workspace-config.type.ts +57 -0
  18. package/src/models/workspace.model.ts +178 -0
  19. package/tests/find-workspace-root.spec.ts +30 -0
  20. package/tests/package-aliases.spec.ts +160 -0
  21. package/tests/package-json.model.spec.ts +78 -0
  22. package/tests/project.factory.spec.ts +100 -0
  23. package/tests/source-extensions.spec.ts +33 -0
  24. package/tests/workspace.factory.spec.ts +147 -0
  25. package/LICENSE +0 -15
  26. package/commonjs/src/const.js +0 -69
  27. package/commonjs/src/errors.js +0 -12
  28. package/commonjs/src/factories/config.factory.js +0 -90
  29. package/commonjs/src/factories/find-workspace-root.js +0 -37
  30. package/commonjs/src/factories/project.factory.js +0 -73
  31. package/commonjs/src/factories/workspace.factory.js +0 -50
  32. package/commonjs/src/index.js +0 -74
  33. package/commonjs/src/models/has-package-json.mixin.js +0 -50
  34. package/commonjs/src/models/has-tsconfig.mixin.js +0 -75
  35. package/commonjs/src/models/package-aliases.js +0 -112
  36. package/commonjs/src/models/package-json.model.js +0 -202
  37. package/commonjs/src/models/project-file-event.js +0 -4
  38. package/commonjs/src/models/project.model.js +0 -316
  39. package/commonjs/src/models/source-extensions.js +0 -81
  40. package/commonjs/src/models/tsconfig.model.js +0 -97
  41. package/commonjs/src/models/workspace-config.type.js +0 -7
  42. package/commonjs/src/models/workspace.model.js +0 -153
  43. package/es6/src/const.js +0 -36
  44. package/es6/src/errors.js +0 -2
  45. package/es6/src/factories/config.factory.js +0 -34
  46. package/es6/src/factories/find-workspace-root.js +0 -26
  47. package/es6/src/factories/project.factory.js +0 -58
  48. package/es6/src/factories/workspace.factory.js +0 -35
  49. package/es6/src/index.js +0 -14
  50. package/es6/src/models/has-package-json.mixin.js +0 -35
  51. package/es6/src/models/has-tsconfig.mixin.js +0 -60
  52. package/es6/src/models/package-aliases.js +0 -97
  53. package/es6/src/models/package-json.model.js +0 -192
  54. package/es6/src/models/project-file-event.js +0 -1
  55. package/es6/src/models/project.model.js +0 -301
  56. package/es6/src/models/source-extensions.js +0 -66
  57. package/es6/src/models/tsconfig.model.js +0 -74
  58. package/es6/src/models/workspace-config.type.js +0 -4
  59. package/es6/src/models/workspace.model.js +0 -143
  60. package/types/src/const.d.ts +0 -8
  61. package/types/src/errors.d.ts +0 -2
  62. package/types/src/factories/config.factory.d.ts +0 -6
  63. package/types/src/factories/find-workspace-root.d.ts +0 -6
  64. package/types/src/factories/project.factory.d.ts +0 -8
  65. package/types/src/factories/workspace.factory.d.ts +0 -9
  66. package/types/src/models/has-package-json.mixin.d.ts +0 -9
  67. package/types/src/models/has-tsconfig.mixin.d.ts +0 -11
  68. package/types/src/models/package-aliases.d.ts +0 -28
  69. package/types/src/models/package-json.model.d.ts +0 -40
  70. package/types/src/models/project-file-event.d.ts +0 -9
  71. package/types/src/models/project.model.d.ts +0 -64
  72. package/types/src/models/source-extensions.d.ts +0 -22
  73. package/types/src/models/tsconfig.model.d.ts +0 -11
  74. package/types/src/models/workspace-config.type.d.ts +0 -52
  75. package/types/src/models/workspace.model.d.ts +0 -40
@@ -1,34 +0,0 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- }
7
- function _ts_metadata(k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- }
10
- import path from "node:path";
11
- import { pathToFileURL } from "node:url";
12
- import { cache } from "@decohere/core/caching";
13
- import { io } from "@decohere/core/io";
14
- import { WORKSPACE_CONFIG } from "../const.js";
15
- class ConfigFactory {
16
- async getUserConfig(configFile) {
17
- const file = configFile ?? WORKSPACE_CONFIG;
18
- if (!file || !await io.fileExists(file)) {
19
- return {};
20
- }
21
- const fileUrl = pathToFileURL(path.resolve(file)).href;
22
- const conf = (await import(fileUrl)).default;
23
- return conf;
24
- }
25
- }
26
- _ts_decorate([
27
- cache(),
28
- _ts_metadata("design:type", Function),
29
- _ts_metadata("design:paramtypes", [
30
- String
31
- ]),
32
- _ts_metadata("design:returntype", Promise)
33
- ], ConfigFactory.prototype, "getUserConfig", null);
34
- export const UserConfigFactory = new ConfigFactory();
@@ -1,26 +0,0 @@
1
- import { existsSync, statSync } from "node:fs";
2
- import path from "node:path";
3
- import { PACKAGE_JSON, PROJECTS_DIR } from "../const.js";
4
- /**
5
- * The workspace root for a command run from `startDir`: the nearest directory at or above
6
- * it with a `package.json` and a `projects/` folder. Falls back to `startDir`, so running
7
- * from a package directory (`projects/api`) still sees the whole workspace.
8
- */ export function findWorkspaceRoot(startDir) {
9
- const start = path.resolve(startDir);
10
- let dir = start;
11
- for(;;){
12
- if (existsSync(path.join(dir, PACKAGE_JSON)) && isDirectory(path.join(dir, PROJECTS_DIR))) {
13
- return dir;
14
- }
15
- const parent = path.dirname(dir);
16
- if (parent === dir) return start;
17
- dir = parent;
18
- }
19
- }
20
- function isDirectory(fullPath) {
21
- try {
22
- return statSync(fullPath).isDirectory();
23
- } catch {
24
- return false;
25
- }
26
- }
@@ -1,58 +0,0 @@
1
- import path from "node:path";
2
- import { io } from "@decohere/core/io";
3
- import { findFiles } from "@decohere/devkit/io";
4
- import { merge } from "@decohere/core/objects";
5
- import { WorkspaceConfigurationError } from "../errors.js";
6
- import { PackageJson } from "../models/package-json.model.js";
7
- import { Project } from "../models/project.model.js";
8
- export class ProjectFactory {
9
- static async getProjectSeeds(config) {
10
- const { includeProjects, ignoreProjects, rootDir } = config;
11
- const cwd = rootDir ?? "./";
12
- const discoveredPackageJsonFiles = await findFiles(includeProjects, {
13
- cwd,
14
- ignore: ignoreProjects
15
- });
16
- const packageJsonFiles = ProjectFactory.filterNestedPackageJsonFiles(discoveredPackageJsonFiles);
17
- const projects = await Promise.all(packageJsonFiles.map((file)=>ProjectFactory.projectFrom(file, config)));
18
- return projects.sort((a, b)=>a.name.localeCompare(b.name));
19
- }
20
- static filterNestedPackageJsonFiles(files) {
21
- const normalize = (filePath)=>filePath.replaceAll("\\", "/");
22
- const packageJsonSet = new Set(files.map((file)=>normalize(file.relativePath)));
23
- return files.filter((file)=>{
24
- const relativePath = normalize(file.relativePath);
25
- const projectDir = path.posix.dirname(relativePath);
26
- let dir = path.posix.dirname(projectDir);
27
- while(dir !== "." && dir !== "/"){
28
- if (packageJsonSet.has(`${dir}/package.json`)) {
29
- return false;
30
- }
31
- dir = path.posix.dirname(dir);
32
- }
33
- return true;
34
- });
35
- }
36
- static async getProjects(config, configuration) {
37
- const seeds = await ProjectFactory.getProjectSeeds(config);
38
- return seeds.map((seed)=>new Project(seed.name, seed.config, configuration));
39
- }
40
- static async projectFrom(file, config) {
41
- const packageJsonData = await io.readJsonFile(file.fullPath).catch((error)=>{
42
- throw new WorkspaceConfigurationError(`Error reading package.json ${file.fullPath}`, error);
43
- });
44
- const name = packageJsonData.name;
45
- const packageJson = new PackageJson(packageJsonData);
46
- const projectDir = path.dirname(file.relativePath);
47
- const mergedConfig = merge.withOptions({
48
- mergeArrays: false
49
- }, config, config?.projects?.[name] ?? {}, {
50
- projectDir,
51
- packageJson
52
- });
53
- return {
54
- name,
55
- config: mergedConfig
56
- };
57
- }
58
- }
@@ -1,35 +0,0 @@
1
- import path from "node:path";
2
- import { io } from "@decohere/core/io";
3
- import { merge } from "@decohere/core/objects";
4
- import { PACKAGE_JSON, WorkspaceDefaults } from "../const.js";
5
- import { PackageJson } from "../models/package-json.model.js";
6
- import { Workspace } from "../models/workspace.model.js";
7
- import { UserConfigFactory } from "./config.factory.js";
8
- import { ProjectFactory } from "./project.factory.js";
9
- class Factory {
10
- async create(options = {}) {
11
- const config = await this.getMergedConfig(options);
12
- const projectSeeds = await ProjectFactory.getProjectSeeds(config);
13
- const packageJson = await this.getPackageJson(config.rootDir ?? "./");
14
- const workspace = new Workspace({
15
- packageJson,
16
- config,
17
- projects: projectSeeds
18
- });
19
- return workspace;
20
- }
21
- async getMergedConfig(options) {
22
- const { configFile, ...rest } = options;
23
- const userConfig = await UserConfigFactory.getUserConfig(configFile);
24
- return merge.withOptions({
25
- mergeArrays: false
26
- }, WorkspaceDefaults, userConfig, rest);
27
- }
28
- async getPackageJson(rootDir) {
29
- const packageJsonPath = path.join(rootDir, PACKAGE_JSON);
30
- if (!await io.fileExists(packageJsonPath)) return;
31
- const data = await io.readJsonFile(packageJsonPath);
32
- return new PackageJson(data);
33
- }
34
- }
35
- export const WorkspaceFactory = new Factory();
package/es6/src/index.js DELETED
@@ -1,14 +0,0 @@
1
- export { WORKSPACE_CONFIG, WorkspaceDefaults } from "./const.js";
2
- export { WorkspaceConfigurationError } from "./errors.js";
3
- export { UserConfigFactory } from "./factories/config.factory.js";
4
- export { findWorkspaceRoot } from "./factories/find-workspace-root.js";
5
- export { ProjectFactory } from "./factories/project.factory.js";
6
- export { WorkspaceFactory } from "./factories/workspace.factory.js";
7
- export { HasPackageJson } from "./models/has-package-json.mixin.js";
8
- export { HasTsConfig } from "./models/has-tsconfig.mixin.js";
9
- export { packageAliases } from "./models/package-aliases.js";
10
- export { PackageJson } from "./models/package-json.model.js";
11
- export { Project } from "./models/project.model.js";
12
- export { sourceExtensions } from "./models/source-extensions.js";
13
- export { DEFAULT_COMPILER_OPTIONS, Tsconfig } from "./models/tsconfig.model.js";
14
- export { Workspace } from "./models/workspace.model.js";
@@ -1,35 +0,0 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- }
7
- function _ts_metadata(k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- }
10
- import path from "node:path";
11
- import { invalidateMemoize, memoize } from "@decohere/core/caching";
12
- import { io } from "@decohere/core/io";
13
- import { PACKAGE_JSON } from "../const.js";
14
- import { PackageJson } from "./package-json.model.js";
15
- export class HasPackageJson {
16
- async getPackageJson() {
17
- return new PackageJson(await io.readJsonFile(path.join(this.packageJsonDirectory, PACKAGE_JSON)));
18
- }
19
- get packageJsonPath() {
20
- return path.join(this.packageJsonDirectory, PACKAGE_JSON);
21
- }
22
- async getVersion() {
23
- return (await this.getPackageJson()).version;
24
- }
25
- async persistPackageJson(packageJson) {
26
- await io.writeFile(this.packageJsonPath, packageJson.toJSON());
27
- invalidateMemoize.evict(this, HasPackageJson.prototype.getPackageJson);
28
- }
29
- }
30
- _ts_decorate([
31
- memoize(),
32
- _ts_metadata("design:type", Function),
33
- _ts_metadata("design:paramtypes", []),
34
- _ts_metadata("design:returntype", Promise)
35
- ], HasPackageJson.prototype, "getPackageJson", null);
@@ -1,60 +0,0 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- }
7
- function _ts_metadata(k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- }
10
- import fs from "node:fs";
11
- import path from "node:path";
12
- import { memoize } from "@decohere/core/caching";
13
- import { io } from "@decohere/core/io";
14
- import { TS_CONFIG } from "../const.js";
15
- import { Tsconfig } from "./tsconfig.model.js";
16
- export class HasTsConfig {
17
- async getTsConfig() {
18
- for (const configPath of this.tsConfigPaths){
19
- if (await io.fileExists(configPath)) return Tsconfig.parse(configPath);
20
- }
21
- return Tsconfig.default();
22
- }
23
- getTsConfigSync() {
24
- const configPath = this.findTsConfigPath();
25
- if (configPath != null) return Tsconfig.parseSync(configPath);
26
- return Tsconfig.default();
27
- }
28
- /** First existing `tsconfig.json` on this object, if any. */ findTsConfigPath() {
29
- return this.tsConfigPaths.find((configPath)=>HasTsConfig.fileExistsSync(configPath));
30
- }
31
- get tsConfigPaths() {
32
- const paths = [
33
- path.join(this.tsConfigDirectory, TS_CONFIG)
34
- ];
35
- const fallback = this.fallbackTsConfigDirectory;
36
- if (fallback != null) {
37
- paths.push(path.join(fallback, TS_CONFIG));
38
- }
39
- return paths;
40
- }
41
- static fileExistsSync(filePath) {
42
- try {
43
- return fs.statSync(filePath).isFile();
44
- } catch {
45
- return false;
46
- }
47
- }
48
- }
49
- _ts_decorate([
50
- memoize(),
51
- _ts_metadata("design:type", Function),
52
- _ts_metadata("design:paramtypes", []),
53
- _ts_metadata("design:returntype", Promise)
54
- ], HasTsConfig.prototype, "getTsConfig", null);
55
- _ts_decorate([
56
- memoize(),
57
- _ts_metadata("design:type", Function),
58
- _ts_metadata("design:paramtypes", []),
59
- _ts_metadata("design:returntype", void 0)
60
- ], HasTsConfig.prototype, "getTsConfigSync", null);
@@ -1,97 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import path from "node:path";
3
- import { sourceExtensions } from "./source-extensions.js";
4
- /**
5
- * Convention aliases from workspace packages, then tsconfig `paths` for the same keys.
6
- * Prefer `Workspace.getPackageAliases` when a workspace is available.
7
- */ function build(projects, options) {
8
- const baseUrl = path.resolve(options.baseUrl);
9
- const paths = {
10
- ...conventionAliasPaths(projects, baseUrl),
11
- ...options.tsconfigPaths
12
- };
13
- return {
14
- baseUrl,
15
- paths
16
- };
17
- }
18
- /** Bare import specifier that is not relative, absolute, or a node/file URL. */ function isBareSpecifier(specifier) {
19
- return specifier.length > 0 && !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("node:") && !specifier.startsWith("file:") && !specifier.startsWith("data:") && !specifier.startsWith("#");
20
- }
21
- /**
22
- * Resolve a bare specifier through package aliases (SWC-style `paths`
23
- * relative to `baseUrl`) to an absolute `.ts` path. Longest key wins.
24
- */ function resolvePath(specifier, paths, baseUrl) {
25
- if (!isBareSpecifier(specifier)) return null;
26
- const resolvedBase = path.resolve(baseUrl);
27
- const keys = Object.keys(paths).sort((a, b)=>b.length - a.length);
28
- for (const key of keys){
29
- const target = paths[key]?.[0];
30
- if (target == null) continue;
31
- if (key.endsWith("/*")) {
32
- const prefix = key.slice(0, -1);
33
- if (!specifier.startsWith(prefix)) continue;
34
- const mappedRoot = target.endsWith("/*") ? target.slice(0, -2) : target;
35
- const subpath = specifier.slice(prefix.length);
36
- return subpathSource(path.resolve(resolvedBase, mappedRoot, subpath));
37
- }
38
- if (specifier === key) {
39
- return toTsSourcePath(path.resolve(resolvedBase, target.replace(/\*$/, "")));
40
- }
41
- }
42
- return null;
43
- }
44
- function conventionAliasPaths(projects, baseUrl) {
45
- const aliases = {};
46
- for (const project of projects){
47
- const name = project.name;
48
- if (name.length === 0) continue;
49
- const entry = path.resolve(project.getSourceEntryPath());
50
- // A package with no root entry (only subpaths, like core) gets no bare alias, and its
51
- // subpaths resolve under `src/`.
52
- const hasEntry = existsSync(entry);
53
- if (hasEntry) aliases[name] = [
54
- toPosixRelative(baseUrl, entry)
55
- ];
56
- const subpathRoot = hasEntry ? path.dirname(entry) : path.resolve(project.rootDir, project.projectDirectory, "src");
57
- if (existsSync(subpathRoot)) {
58
- aliases[`${name}/*`] = [
59
- `${toPosixRelative(baseUrl, subpathRoot)}/*`
60
- ];
61
- }
62
- // Subpaths the package exports, mapped to their sources (#518): these can name any file,
63
- // not just `<sub>.ts` or `<sub>/index.ts` under the entry's directory.
64
- for (const [subpath, source] of Object.entries(project.getSourceExports())){
65
- aliases[`${name}/${subpath.slice(2)}`] = [
66
- toPosixRelative(baseUrl, source)
67
- ];
68
- }
69
- }
70
- return aliases;
71
- }
72
- function toPosixRelative(from, to) {
73
- const relative = path.relative(from, to);
74
- if (relative === "") return ".";
75
- return relative.split(path.sep).join("/");
76
- }
77
- /**
78
- * The source file a wildcard subpath names: `<sub>` with a source extension (`.ts`, `.tsx`, or
79
- * `.mts`/`.cts` for `.mjs`/`.cjs`), else the `index` source of the directory it names (as
80
- * `@pkg/models` is `src/models/index.ts`), else `<sub>.ts` for the caller to report missing.
81
- */ function subpathSource(candidate) {
82
- const files = sourceExtensions.candidates(candidate);
83
- const directory = candidate.replace(/\.([mc]?[jt]sx?)$/, "");
84
- const indexes = sourceExtensions.candidates(path.join(directory, "index"));
85
- return [
86
- ...files,
87
- ...indexes
88
- ].find((file)=>existsSync(file)) ?? toTsSourcePath(candidate);
89
- }
90
- /** A target as a source path: itself when it is one, else its first source candidate. */ function toTsSourcePath(candidate) {
91
- return sourceExtensions.candidates(candidate)[0] ?? `${candidate}.ts`;
92
- }
93
- export const packageAliases = {
94
- build,
95
- isBareSpecifier,
96
- resolvePath
97
- };
@@ -1,192 +0,0 @@
1
- export class PackageJson {
2
- static PACKAGE_JSON_KEY_ORDER = [
3
- "$schema",
4
- "name",
5
- "displayName",
6
- "version",
7
- "description",
8
- "keywords",
9
- "homepage",
10
- "bugs",
11
- "repository",
12
- "license",
13
- "author",
14
- "contributors",
15
- "funding",
16
- "type",
17
- "main",
18
- "module",
19
- "types",
20
- "exports",
21
- "files",
22
- "bin",
23
- "man",
24
- "directories",
25
- "scripts",
26
- "dependencies",
27
- "devDependencies",
28
- "peerDependencies",
29
- "peerDependenciesMeta",
30
- "optionalDependencies",
31
- "bundledDependencies",
32
- "engines",
33
- "os",
34
- "cpu",
35
- "private",
36
- "publishConfig",
37
- "workspaces",
38
- "packageManager",
39
- "forge"
40
- ];
41
- constructor(data){
42
- Object.assign(this, data);
43
- this.dependencies = this.dependencies ?? {};
44
- this.devDependencies = this.devDependencies ?? {};
45
- }
46
- sort() {
47
- const sorted = this.toSortedPackageJsonRecord();
48
- Object.assign(this, sorted);
49
- return this;
50
- }
51
- withVersion(version) {
52
- return new PackageJson({
53
- ...this,
54
- version
55
- });
56
- }
57
- withDependencies(dependencies) {
58
- return new PackageJson({
59
- ...this,
60
- dependencies
61
- });
62
- }
63
- withDevDependencies(devDependencies) {
64
- return new PackageJson({
65
- ...this,
66
- devDependencies
67
- });
68
- }
69
- withPeerDependencies(peerDependencies) {
70
- return new PackageJson({
71
- ...this,
72
- peerDependencies
73
- });
74
- }
75
- toJSON() {
76
- return `${JSON.stringify(this.toSortedPackageJsonRecord(), null, 2)}\n`;
77
- }
78
- getRepositoryOwner() {
79
- return this.parseRepository()?.owner;
80
- }
81
- getRepositoryName() {
82
- return this.parseRepository()?.name;
83
- }
84
- getRepositoryFullName() {
85
- const parsed = this.parseRepository();
86
- if (parsed == null) {
87
- return undefined;
88
- }
89
- return `${parsed.owner}/${parsed.name}`;
90
- }
91
- sortDependencyMap(input) {
92
- return Object.fromEntries(Object.entries(input).sort(([left], [right])=>left.localeCompare(right, "en")));
93
- }
94
- sortPackageJsonKeys(source) {
95
- const sorted = Object.create(null);
96
- for (const key of PackageJson.PACKAGE_JSON_KEY_ORDER){
97
- if (key in source) {
98
- sorted[key] = source[key];
99
- }
100
- }
101
- const remainingKeys = Object.keys(source).filter((key)=>!PackageJson.PACKAGE_JSON_KEY_ORDER.includes(key)).sort();
102
- for (const key of remainingKeys){
103
- sorted[key] = source[key];
104
- }
105
- return sorted;
106
- }
107
- toSortedPackageJsonRecord() {
108
- const clone = {
109
- ...this
110
- };
111
- if (clone.dependencies) {
112
- clone.dependencies = this.sortDependencyMap(clone.dependencies);
113
- }
114
- if (clone.devDependencies) {
115
- clone.devDependencies = this.sortDependencyMap(clone.devDependencies);
116
- }
117
- return this.sortPackageJsonKeys(clone);
118
- }
119
- repositoryReferenceToString(repository) {
120
- if (typeof repository === "string") {
121
- return repository;
122
- }
123
- if (repository == null) {
124
- return "";
125
- }
126
- return String(repository.url ?? "");
127
- }
128
- parseRepository() {
129
- const repositoryValue = this.repositoryReferenceToString(this.repository);
130
- if (repositoryValue === "") {
131
- return undefined;
132
- }
133
- const trimmed = repositoryValue.trim();
134
- if (!trimmed.includes("://") && !trimmed.startsWith("git@")) {
135
- const shorthand = /^(?:[a-z0-9-]+:)?([^/\s]+)\/([^\s]+)$/i.exec(trimmed);
136
- if (shorthand) {
137
- return {
138
- owner: shorthand[1].toLowerCase(),
139
- name: this.sanitizeRepositoryName(shorthand[2])
140
- };
141
- }
142
- }
143
- const ssh = /^git@[^:]+:([^/\s]+)\/([^\s]+)$/i.exec(trimmed);
144
- if (ssh) {
145
- return {
146
- owner: ssh[1].toLowerCase(),
147
- name: this.sanitizeRepositoryName(ssh[2])
148
- };
149
- }
150
- const urlRepository = this.parseRepositoryFromUrl(trimmed);
151
- if (urlRepository != null) {
152
- return urlRepository;
153
- }
154
- return undefined;
155
- }
156
- parseRepositoryFromUrl(repository) {
157
- const normalized = repository.replace(/^git\+/, "");
158
- let url;
159
- try {
160
- url = new URL(normalized);
161
- } catch {
162
- return undefined;
163
- }
164
- const segments = url.pathname.split("/").filter(Boolean);
165
- if (segments.length < 2) {
166
- return undefined;
167
- }
168
- const owner = segments[0]?.toLowerCase();
169
- const name = this.sanitizeRepositoryName(segments[1] ?? "");
170
- if (owner == null || owner === "" || name === "") {
171
- return undefined;
172
- }
173
- return {
174
- owner,
175
- name
176
- };
177
- }
178
- sanitizeRepositoryName(name) {
179
- return name.replace(/\.git$/i, "").toLowerCase();
180
- }
181
- name;
182
- version;
183
- repository;
184
- main;
185
- /** `exports` as written in package.json: a path, or a map of subpaths (values may be condition maps). */ exports;
186
- peerDependencies;
187
- optionalDependencies;
188
- scripts;
189
- dependencies = {};
190
- devDependencies = {};
191
- private;
192
- }
@@ -1 +0,0 @@
1
- export { };