@eclipse-docks/core 0.7.133 → 0.7.135

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 (47) hide show
  1. package/dist/api/index.d.ts +3 -1
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +3 -3
  4. package/dist/api/services.d.ts +2 -0
  5. package/dist/api/services.d.ts.map +1 -1
  6. package/dist/api/types.d.ts +3 -1
  7. package/dist/api/types.d.ts.map +1 -1
  8. package/dist/{api-DImisUWV.js → api-DNLFdSfp.js} +128 -24
  9. package/dist/api-DNLFdSfp.js.map +1 -0
  10. package/dist/components/npm-packages.d.ts +5 -1
  11. package/dist/components/npm-packages.d.ts.map +1 -1
  12. package/dist/contributions/default-attributions-contributions.d.ts +2 -0
  13. package/dist/contributions/default-attributions-contributions.d.ts.map +1 -0
  14. package/dist/contributions/index.d.ts.map +1 -1
  15. package/dist/core/apploader.d.ts +11 -5
  16. package/dist/core/apploader.d.ts.map +1 -1
  17. package/dist/core/contribution-names.d.ts +1 -0
  18. package/dist/core/contribution-names.d.ts.map +1 -1
  19. package/dist/core/license-attribution.d.ts +13 -0
  20. package/dist/core/license-attribution.d.ts.map +1 -0
  21. package/dist/core/resolved-package-info.d.ts +10 -0
  22. package/dist/core/resolved-package-info.d.ts.map +1 -0
  23. package/dist/index.js +3 -3
  24. package/dist/parts/index.js +1 -1
  25. package/dist/{parts-DQRktiiR.js → parts-VwCbRGd_.js} +5 -2
  26. package/dist/parts-VwCbRGd_.js.map +1 -0
  27. package/dist/vite-plugin-resolve-deps.d.ts +18 -8
  28. package/dist/vite-plugin-resolve-deps.d.ts.map +1 -1
  29. package/dist/vite-plugin-resolve-deps.js +140 -21
  30. package/dist/vite-plugin-resolve-deps.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/api/index.ts +10 -1
  33. package/src/api/services.ts +2 -0
  34. package/src/api/types.ts +10 -1
  35. package/src/commands/global.ts +1 -1
  36. package/src/components/npm-packages.ts +103 -11
  37. package/src/contributions/default-attributions-contributions.ts +34 -0
  38. package/src/contributions/default-ui-contributions.ts +1 -14
  39. package/src/contributions/index.ts +1 -0
  40. package/src/core/apploader.ts +20 -11
  41. package/src/core/contribution-names.ts +1 -0
  42. package/src/core/license-attribution.ts +45 -0
  43. package/src/core/resolved-package-info.ts +15 -0
  44. package/src/vite-env.d.ts +11 -2
  45. package/src/vite-plugin-resolve-deps.ts +231 -31
  46. package/dist/api-DImisUWV.js.map +0 -1
  47. package/dist/parts-DQRktiiR.js.map +0 -1
@@ -1,17 +1,28 @@
1
1
  import { Plugin } from 'vite';
2
+ import { ResolvedDependencyInfo, ResolvedDependencyMap } from './core/resolved-package-info';
3
+ export type { ResolvedDependencyInfo, ResolvedDependencyMap };
2
4
  export interface ResolvedPackageInfo {
3
5
  name: string;
4
6
  version: string;
5
7
  description?: string;
6
- dependencies: Record<string, string>;
8
+ dependencies: ResolvedDependencyMap;
9
+ /** Direct app `package.json` dependencies, in declaration order. */
10
+ directDependencies: string[];
11
+ /** Third-party runtime packages nested under a direct @eclipse-docks/core or extension-* dependency. */
12
+ nestedDependencies: Record<string, string[]>;
7
13
  marketplaceCatalogUrls?: string[];
8
14
  }
9
- export declare function resolvePackageInfo(appRoot: string, options?: {
15
+ export type ResolvePackageInfoOptions = {
10
16
  includeDevDependencies?: boolean;
11
- }): ResolvedPackageInfo | null;
12
- export declare function resolveDepVersions(appRoot: string, options?: {
13
- includeDevDependencies?: boolean;
14
- }): Record<string, string>;
17
+ /**
18
+ * When true (default), list each direct `@eclipse-docks/core` and `extension-*`
19
+ * dependency's own third-party `package.json` dependencies in the About tree.
20
+ */
21
+ includeExtensionRuntimeDependencies?: boolean;
22
+ };
23
+ export declare function resolveDependencyInfo(appRoot: string, depName: string): ResolvedDependencyInfo;
24
+ export declare function resolvePackageInfo(appRoot: string, options?: ResolvePackageInfoOptions): ResolvedPackageInfo | null;
25
+ export declare function resolveDepVersions(appRoot: string, options?: ResolvePackageInfoOptions): Record<string, string>;
15
26
  /** Virtual module id; prepended to `src/main.ts` when extension side-effects are enabled. */
16
27
  export declare const VIRTUAL_EXTENSION_IMPORTS = "virtual:eclipse-docks-extension-imports";
17
28
  /** Prepends the virtual extension side-effect import when not already present. */
@@ -34,8 +45,7 @@ export interface ExtensionSideEffectsOptions {
34
45
  */
35
46
  packageNamePattern?: RegExp;
36
47
  }
37
- export type ResolveDepVersionsPluginOptions = {
38
- includeDevDependencies?: boolean;
48
+ export type ResolveDepVersionsPluginOptions = ResolvePackageInfoOptions & {
39
49
  /**
40
50
  * By default, registers a virtual module that side-effect-imports every matching direct
41
51
  * `dependencies` entry (see `ExtensionSideEffectsOptions`), and prepends
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin-resolve-deps.d.ts","sourceRoot":"","sources":["../src/vite-plugin-resolve-deps.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AA8DD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,mBAAmB,GAAG,IAAI,CAkB5B;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGxB;AAID,6FAA6F;AAC7F,eAAO,MAAM,yBAAyB,4CAA4C,CAAC;AASnF,kFAAkF;AAClF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrE;AAOD,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,+BAA+B,GAAG;IAC5C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,OAAO,GAAG,2BAA2B,CAAC;CAC9D,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqBF,wBAAgB,+BAA+B,CAC7C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAQV;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAqBV;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAQV;AAED,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,+BAA+B,GACxC,MAAM,CAoER"}
1
+ {"version":3,"file":"vite-plugin-resolve-deps.d.ts","sourceRoot":"","sources":["../src/vite-plugin-resolve-deps.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAElG,YAAY,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;AAE9D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,qBAAqB,CAAC;IACpC,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,wGAAwG;IACxG,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7C,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAkBD,MAAM,MAAM,yBAAyB,GAAG;IACtC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,mCAAmC,CAAC,EAAE,OAAO,CAAC;CAC/C,CAAC;AA4HF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,sBAAsB,CASxB;AA0DD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,yBAAyB,GAClC,mBAAmB,GAAG,IAAI,CA+B5B;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,yBAAyB,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBxB;AAID,6FAA6F;AAC7F,eAAO,MAAM,yBAAyB,4CAA4C,CAAC;AASnF,kFAAkF;AAClF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrE;AAID,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,+BAA+B,GAAG,yBAAyB,GAAG;IACxE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,OAAO,GAAG,2BAA2B,CAAC;CAC9D,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqBF,wBAAgB,+BAA+B,CAC7C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAQV;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAqBV;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,+BAA+B,GAC3C,MAAM,EAAE,CAQV;AAUD,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,+BAA+B,GACxC,MAAM,CAuER"}
@@ -1,6 +1,21 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
2
  import path from "path";
3
3
  //#region src/vite-plugin-resolve-deps.ts
4
+ var RUNTIME_SKIP_PATTERN = /^@types\//;
5
+ var RUNTIME_SKIP_PACKAGES = /* @__PURE__ */ new Set([
6
+ "typescript",
7
+ "vite",
8
+ "vitest",
9
+ "jsdom",
10
+ "playwright",
11
+ "rolldown",
12
+ "fake-indexeddb",
13
+ "@vitest/coverage-v8",
14
+ "vite-plugin-dts",
15
+ "vite-plugin-cross-origin-isolation",
16
+ "vite-plugin-mkcert",
17
+ "vite-plugin-pwa"
18
+ ]);
4
19
  function packageJsonPath(appRoot, packageName) {
5
20
  const segments = packageName.startsWith("@") ? packageName.split("/") : [packageName];
6
21
  const relativePath = path.join("node_modules", ...segments, "package.json");
@@ -14,26 +29,105 @@ function packageJsonPath(appRoot, packageName) {
14
29
  }
15
30
  return null;
16
31
  }
32
+ function readWorkspacePackageJson(appRoot, depName) {
33
+ if (!depName.startsWith("@eclipse-docks/")) return null;
34
+ const folder = depName === "@eclipse-docks/core" ? "core" : depName.slice(15);
35
+ let dir = path.resolve(appRoot);
36
+ const root = path.parse(dir).root;
37
+ while (dir !== root) {
38
+ const workspacePkgPath = path.join(dir, "packages", folder, "package.json");
39
+ if (existsSync(workspacePkgPath)) try {
40
+ return JSON.parse(readFileSync(workspacePkgPath, "utf8"));
41
+ } catch {
42
+ return null;
43
+ }
44
+ dir = path.dirname(dir);
45
+ }
46
+ return null;
47
+ }
17
48
  function readPackageJson(appRoot, packageName) {
18
49
  const pkgPath = packageJsonPath(appRoot, packageName);
19
- if (!pkgPath) return null;
20
- try {
21
- return JSON.parse(readFileSync(pkgPath, "utf8"));
50
+ let pkg = null;
51
+ if (pkgPath) try {
52
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
22
53
  } catch {
23
- return null;
54
+ pkg = null;
24
55
  }
56
+ const workspacePkg = readWorkspacePackageJson(appRoot, packageName);
57
+ if (workspacePkg) pkg = {
58
+ ...workspacePkg,
59
+ ...pkg,
60
+ description: pkg?.description ?? workspacePkg.description,
61
+ license: pkg?.license ?? workspacePkg.license,
62
+ homepage: pkg?.homepage ?? workspacePkg.homepage,
63
+ repository: pkg?.repository ?? workspacePkg.repository
64
+ };
65
+ return pkg;
66
+ }
67
+ function normalizeLicense(license) {
68
+ if (!license) return void 0;
69
+ if (typeof license === "string") return license;
70
+ if (Array.isArray(license)) {
71
+ const parts = license.map((entry) => typeof entry === "string" ? entry : entry.type ?? "").filter(Boolean);
72
+ return parts.length > 0 ? parts.join(" AND ") : void 0;
73
+ }
74
+ return license.type;
75
+ }
76
+ function normalizeRepository(repository) {
77
+ if (!repository) return void 0;
78
+ const raw = typeof repository === "string" ? repository : repository.url;
79
+ if (!raw) return void 0;
80
+ return raw.replace(/^git\+/, "").replace(/^git:\/\//, "https://").replace(/\.git$/, "");
81
+ }
82
+ function shouldSkipRuntimePackage(name) {
83
+ if (RUNTIME_SKIP_PATTERN.test(name)) return true;
84
+ if (RUNTIME_SKIP_PACKAGES.has(name)) return true;
85
+ if (name.startsWith("vite-plugin-")) return true;
86
+ return false;
25
87
  }
26
- function findPackageVersion(appRoot, depName) {
88
+ /** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */
89
+ var DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\/)?extension-/;
90
+ function isEclipseDocksPlatformPackage(name) {
91
+ return name === "@eclipse-docks/core" || DEFAULT_EXTENSION_PATTERN.test(name);
92
+ }
93
+ function resolveDependencyInfo(appRoot, depName) {
27
94
  const pkg = readPackageJson(appRoot, depName);
28
- if (typeof pkg?.version === "string") return pkg.version;
29
- return null;
95
+ return {
96
+ license: normalizeLicense(pkg?.license),
97
+ homepage: typeof pkg?.homepage === "string" ? pkg.homepage : void 0,
98
+ repository: normalizeRepository(pkg?.repository),
99
+ description: typeof pkg?.description === "string" ? pkg.description : void 0
100
+ };
30
101
  }
31
- function resolveDepVersionsFromPkg(appRoot, pkg, options) {
102
+ function collectDirectDependencyEntries(pkg, options) {
32
103
  const deps = { ...pkg.dependencies };
33
104
  if (options?.includeDevDependencies && pkg.devDependencies) Object.assign(deps, pkg.devDependencies);
34
- const result = {};
35
- for (const [name, specifier] of Object.entries(deps)) result[name] = findPackageVersion(appRoot, name) ?? specifier;
36
- return result;
105
+ return Object.entries(deps);
106
+ }
107
+ /** Direct third-party runtime dependencies declared in `seed`'s package.json. */
108
+ function collectDirectThirdPartyDependencies(appRoot, seed) {
109
+ const pkg = readPackageJson(appRoot, seed);
110
+ if (!pkg?.dependencies) return [];
111
+ return Object.keys(pkg.dependencies).filter((dep) => !shouldSkipRuntimePackage(dep)).filter((dep) => !isEclipseDocksPlatformPackage(dep)).sort((a, b) => a.localeCompare(b));
112
+ }
113
+ function resolveDependenciesFromPkg(appRoot, pkg, options) {
114
+ const depEntries = collectDirectDependencyEntries(pkg, options);
115
+ const directDependencies = depEntries.map(([name]) => name);
116
+ const dependencies = {};
117
+ for (const [name] of depEntries) dependencies[name] = resolveDependencyInfo(appRoot, name);
118
+ const nestedDependencies = {};
119
+ if (options?.includeExtensionRuntimeDependencies !== false) for (const name of directDependencies) {
120
+ if (!isEclipseDocksPlatformPackage(name)) continue;
121
+ const thirdParty = collectDirectThirdPartyDependencies(appRoot, name);
122
+ if (thirdParty.length === 0) continue;
123
+ nestedDependencies[name] = thirdParty;
124
+ for (const dep of thirdParty) if (!dependencies[dep]) dependencies[dep] = resolveDependencyInfo(appRoot, dep);
125
+ }
126
+ return {
127
+ dependencies,
128
+ directDependencies,
129
+ nestedDependencies
130
+ };
37
131
  }
38
132
  function resolvePackageInfo(appRoot, options) {
39
133
  const pkgPath = path.join(appRoot, "package.json");
@@ -44,16 +138,36 @@ function resolvePackageInfo(appRoot, options) {
44
138
  } catch {
45
139
  return null;
46
140
  }
141
+ const name = typeof pkg.name === "string" ? pkg.name : "";
142
+ const version = typeof pkg.version === "string" ? pkg.version : "0.0.0";
143
+ const description = typeof pkg.description === "string" ? pkg.description : void 0;
144
+ const { dependencies, directDependencies, nestedDependencies } = resolveDependenciesFromPkg(appRoot, pkg, options);
47
145
  return {
48
- name: typeof pkg.name === "string" ? pkg.name : "",
49
- version: typeof pkg.version === "string" ? pkg.version : "0.0.0",
50
- description: typeof pkg.description === "string" ? pkg.description : void 0,
51
- dependencies: resolveDepVersionsFromPkg(appRoot, pkg, options),
146
+ name,
147
+ version,
148
+ description,
149
+ dependencies,
150
+ directDependencies,
151
+ nestedDependencies,
52
152
  marketplaceCatalogUrls: pkg.marketplace?.catalogUrls
53
153
  };
54
154
  }
55
155
  function resolveDepVersions(appRoot, options) {
56
- return resolvePackageInfo(appRoot, options)?.dependencies ?? {};
156
+ const pkgPath = path.join(appRoot, "package.json");
157
+ if (!existsSync(pkgPath)) return {};
158
+ let pkg;
159
+ try {
160
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
161
+ } catch {
162
+ return {};
163
+ }
164
+ const depEntries = collectDirectDependencyEntries(pkg, options);
165
+ const result = {};
166
+ for (const [name, specifier] of depEntries) {
167
+ const installed = readPackageJson(appRoot, name);
168
+ result[name] = typeof installed?.version === "string" ? installed.version : specifier;
169
+ }
170
+ return result;
57
171
  }
58
172
  var RESOLVED_PACKAGE_INFO_KEY = "__RESOLVED_PACKAGE_INFO__";
59
173
  /** Virtual module id; prepended to `src/main.ts` when extension side-effects are enabled. */
@@ -67,8 +181,6 @@ function prependExtensionSideEffectImport(code) {
67
181
  if (code.includes("virtual:eclipse-docks-extension-imports")) return code;
68
182
  return EXTENSION_IMPORT_STATEMENT + code;
69
183
  }
70
- /** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */
71
- var DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\/)?extension-/;
72
184
  var DEFAULT_PRIORITY_FIRST = ["@eclipse-docks/extension-pwa", "extension-pwa"];
73
185
  function normalizeExtensionSideEffects(opt) {
74
186
  if (opt === false) return null;
@@ -119,6 +231,11 @@ function resolveExtensionSideEffectPackages(appRoot, dependencies, sideEffects)
119
231
  const allNames = [.../* @__PURE__ */ new Set([...direct, ...transitive])];
120
232
  return listExtensionSideEffectPackages(Object.fromEntries(allNames.map((name) => [name, "*"])), sideEffects);
121
233
  }
234
+ function dependencyKeysFromInfo(info) {
235
+ if (!info) return [];
236
+ if (info.directDependencies.length > 0) return info.directDependencies;
237
+ return Object.keys(info.dependencies);
238
+ }
122
239
  function resolveDepVersionsPlugin(options) {
123
240
  let appRoot = process.cwd();
124
241
  let extensionSideEffectsActive = false;
@@ -131,6 +248,8 @@ function resolveDepVersionsPlugin(options) {
131
248
  version: "0.0.0",
132
249
  description: void 0,
133
250
  dependencies: {},
251
+ directDependencies: [],
252
+ nestedDependencies: {},
134
253
  marketplaceCatalogUrls: void 0
135
254
  };
136
255
  return { define: { [RESOLVED_PACKAGE_INFO_KEY]: JSON.stringify(value) } };
@@ -143,8 +262,8 @@ function resolveDepVersionsPlugin(options) {
143
262
  extensionImportPackages = [];
144
263
  return;
145
264
  }
146
- const info = resolvePackageInfo(appRoot, options);
147
- extensionImportPackages = resolveExtensionSideEffectPackages(appRoot, info?.dependencies ?? {}, normalized);
265
+ const depKeys = dependencyKeysFromInfo(resolvePackageInfo(appRoot, options));
266
+ extensionImportPackages = resolveExtensionSideEffectPackages(appRoot, Object.fromEntries(depKeys.map((name) => [name, "*"])), normalized);
148
267
  },
149
268
  resolveId(id) {
150
269
  if (id === "virtual:eclipse-docks-extension-imports") return RESOLVED_VIRTUAL_EXTENSION_IMPORTS;
@@ -164,6 +283,6 @@ function resolveDepVersionsPlugin(options) {
164
283
  };
165
284
  }
166
285
  //#endregion
167
- export { VIRTUAL_EXTENSION_IMPORTS, collectTransitiveExtensionPackages, listExtensionSideEffectPackages, prependExtensionSideEffectImport, resolveDepVersions, resolveDepVersionsPlugin, resolveExtensionSideEffectPackages, resolvePackageInfo };
286
+ export { VIRTUAL_EXTENSION_IMPORTS, collectTransitiveExtensionPackages, listExtensionSideEffectPackages, prependExtensionSideEffectImport, resolveDepVersions, resolveDepVersionsPlugin, resolveDependencyInfo, resolveExtensionSideEffectPackages, resolvePackageInfo };
168
287
 
169
288
  //# sourceMappingURL=vite-plugin-resolve-deps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin-resolve-deps.js","names":[],"sources":["../src/vite-plugin-resolve-deps.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'fs';\nimport path from 'path';\nimport type { Plugin } from 'vite';\n\nexport interface ResolvedPackageInfo {\n name: string;\n version: string;\n description?: string;\n dependencies: Record<string, string>;\n marketplaceCatalogUrls?: string[];\n}\n\ninterface PackageJson {\n name?: string;\n version?: string;\n description?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nfunction packageJsonPath(appRoot: string, packageName: string): string | null {\n const segments = packageName.startsWith('@')\n ? packageName.split('/')\n : [packageName];\n const relativePath = path.join('node_modules', ...segments, 'package.json');\n let dir = path.resolve(appRoot);\n const root = path.parse(dir).root;\n\n while (true) {\n const pkgPath = path.join(dir, relativePath);\n if (existsSync(pkgPath)) {\n return pkgPath;\n }\n if (dir === root) break;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction readPackageJson(appRoot: string, packageName: string): PackageJson | null {\n const pkgPath = packageJsonPath(appRoot, packageName);\n if (!pkgPath) return null;\n try {\n return JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n}\n\nfunction findPackageVersion(appRoot: string, depName: string): string | null {\n const pkg = readPackageJson(appRoot, depName);\n if (typeof pkg?.version === 'string') return pkg.version;\n return null;\n}\n\nfunction resolveDepVersionsFromPkg(\n appRoot: string,\n pkg: PackageJson,\n options?: { includeDevDependencies?: boolean }\n): Record<string, string> {\n const deps = { ...pkg.dependencies };\n if (options?.includeDevDependencies && pkg.devDependencies) {\n Object.assign(deps, pkg.devDependencies);\n }\n const result: Record<string, string> = {};\n for (const [name, specifier] of Object.entries(deps)) {\n const version = findPackageVersion(appRoot, name);\n result[name] = version ?? specifier;\n }\n return result;\n}\n\nexport function resolvePackageInfo(\n appRoot: string,\n options?: { includeDevDependencies?: boolean }\n): ResolvedPackageInfo | null {\n const pkgPath = path.join(appRoot, 'package.json');\n if (!existsSync(pkgPath)) return null;\n\n let pkg: PackageJson;\n try {\n pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n\n const name = typeof pkg.name === 'string' ? pkg.name : '';\n const version = typeof pkg.version === 'string' ? pkg.version : '0.0.0';\n const description = typeof pkg.description === 'string' ? pkg.description : undefined;\n const dependencies = resolveDepVersionsFromPkg(appRoot, pkg, options);\n const marketplaceCatalogUrls = (pkg as { marketplace?: { catalogUrls?: string[] } }).marketplace?.catalogUrls;\n\n return { name, version, description, dependencies, marketplaceCatalogUrls };\n}\n\nexport function resolveDepVersions(\n appRoot: string,\n options?: { includeDevDependencies?: boolean }\n): Record<string, string> {\n const info = resolvePackageInfo(appRoot, options);\n return info?.dependencies ?? {};\n}\n\nconst RESOLVED_PACKAGE_INFO_KEY = '__RESOLVED_PACKAGE_INFO__';\n\n/** Virtual module id; prepended to `src/main.ts` when extension side-effects are enabled. */\nexport const VIRTUAL_EXTENSION_IMPORTS = 'virtual:eclipse-docks-extension-imports';\n\nconst RESOLVED_VIRTUAL_EXTENSION_IMPORTS = `\\0${VIRTUAL_EXTENSION_IMPORTS}`;\n\n/** App entry module transformed by {@link resolveDepVersionsPlugin}. */\nconst MAIN_TS_MODULE_RE = /[/\\\\]src[/\\\\]main\\.ts$/;\n\nconst EXTENSION_IMPORT_STATEMENT = `import ${JSON.stringify(VIRTUAL_EXTENSION_IMPORTS)};\\n`;\n\n/** Prepends the virtual extension side-effect import when not already present. */\nexport function prependExtensionSideEffectImport(code: string): string {\n if (code.includes(VIRTUAL_EXTENSION_IMPORTS)) {\n return code;\n }\n return EXTENSION_IMPORT_STATEMENT + code;\n}\n\n/** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */\nconst DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\\/)?extension-/;\n\nconst DEFAULT_PRIORITY_FIRST = ['@eclipse-docks/extension-pwa', 'extension-pwa'];\n\nexport interface ExtensionSideEffectsOptions {\n /**\n * When false, disables automatic extension side-effect imports. Omitted or true keeps them on.\n */\n enabled?: boolean;\n /** Dependency names to skip (even if they match `packageNamePattern`). */\n exclude?: string[];\n /**\n * Packages to load first, in order (only those present in dependencies are imported).\n * Default includes PWA so `beforeinstallprompt` can register early.\n */\n priorityFirst?: string[];\n /**\n * Which direct `dependencies` keys qualify as Docks-style extensions (`extension-*`, with an optional npm scope).\n * @default /^(?:@[^/]+\\/)?extension-/\n */\n packageNamePattern?: RegExp;\n}\n\nexport type ResolveDepVersionsPluginOptions = {\n includeDevDependencies?: boolean;\n /**\n * By default, registers a virtual module that side-effect-imports every matching direct\n * `dependencies` entry (see `ExtensionSideEffectsOptions`), and prepends\n * `import 'virtual:eclipse-docks-extension-imports'` to `src/main.ts` so extension\n * registration completes before `registerApp({ autoStart: true })`.\n * Pass `false` or `{ enabled: false }` to disable.\n */\n extensionSideEffects?: boolean | ExtensionSideEffectsOptions;\n};\n\n/** Normalized match options for {@link listExtensionSideEffectPackages}. */\nexport type ExtensionSideEffectsListOptions = {\n exclude: Set<string>;\n priorityFirst: string[];\n pattern: RegExp;\n};\n\nfunction normalizeExtensionSideEffects(\n opt: boolean | ExtensionSideEffectsOptions | undefined,\n): ExtensionSideEffectsListOptions | null {\n if (opt === false) return null;\n if (opt === undefined || opt === true) {\n return {\n exclude: new Set(),\n priorityFirst: [...DEFAULT_PRIORITY_FIRST],\n pattern: DEFAULT_EXTENSION_PATTERN,\n };\n }\n if (opt.enabled === false) return null;\n return {\n exclude: new Set(opt.exclude ?? []),\n priorityFirst: opt.priorityFirst ?? [...DEFAULT_PRIORITY_FIRST],\n pattern: opt.packageNamePattern ?? DEFAULT_EXTENSION_PATTERN,\n };\n}\n\nexport function listExtensionSideEffectPackages(\n dependencies: Record<string, string>,\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const names = Object.keys(dependencies).filter(\n (name) => sideEffects.pattern.test(name) && !sideEffects.exclude.has(name),\n );\n const prioritySet = new Set(sideEffects.priorityFirst);\n const first = sideEffects.priorityFirst.filter((p) => names.includes(p));\n const rest = names.filter((n) => !prioritySet.has(n)).sort((a, b) => a.localeCompare(b));\n return [...first, ...rest];\n}\n\n/**\n * Walks extension package.json `dependencies` to collect transitive extension-* packages\n * (e.g. extension-utils → extension-python-runtime → extension-terminal).\n */\nexport function collectTransitiveExtensionPackages(\n appRoot: string,\n seeds: string[],\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const found = new Set<string>();\n const queue = [...seeds];\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (visited.has(name)) continue;\n visited.add(name);\n\n const pkg = readPackageJson(appRoot, name);\n if (!pkg?.dependencies) continue;\n\n for (const dep of Object.keys(pkg.dependencies)) {\n if (!sideEffects.pattern.test(dep) || sideEffects.exclude.has(dep)) continue;\n found.add(dep);\n queue.push(dep);\n }\n }\n\n return [...found];\n}\n\nexport function resolveExtensionSideEffectPackages(\n appRoot: string,\n dependencies: Record<string, string>,\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const direct = listExtensionSideEffectPackages(dependencies, sideEffects);\n const transitive = collectTransitiveExtensionPackages(appRoot, direct, sideEffects);\n const allNames = [...new Set([...direct, ...transitive])];\n return listExtensionSideEffectPackages(\n Object.fromEntries(allNames.map((name) => [name, '*'])),\n sideEffects,\n );\n}\n\nexport function resolveDepVersionsPlugin(\n options?: ResolveDepVersionsPluginOptions,\n): Plugin {\n let appRoot = process.cwd();\n let extensionSideEffectsActive = false;\n let extensionImportPackages: string[] = [];\n\n return {\n name: 'resolve-dep-versions',\n config(config) {\n const root = config.root ? path.resolve(config.root) : process.cwd();\n const info = resolvePackageInfo(root, options);\n const value =\n info ?? {\n name: '',\n version: '0.0.0',\n description: undefined,\n dependencies: {},\n marketplaceCatalogUrls: undefined,\n };\n return {\n define: {\n [RESOLVED_PACKAGE_INFO_KEY]: JSON.stringify(value),\n },\n };\n },\n configResolved(config) {\n appRoot = path.resolve(config.root ?? process.cwd());\n const normalized = normalizeExtensionSideEffects(options?.extensionSideEffects);\n extensionSideEffectsActive = normalized !== null;\n if (!normalized) {\n extensionImportPackages = [];\n return;\n }\n const info = resolvePackageInfo(appRoot, options);\n extensionImportPackages = resolveExtensionSideEffectPackages(\n appRoot,\n info?.dependencies ?? {},\n normalized,\n );\n },\n resolveId(id) {\n if (id === VIRTUAL_EXTENSION_IMPORTS) {\n return RESOLVED_VIRTUAL_EXTENSION_IMPORTS;\n }\n return undefined;\n },\n load(id) {\n if (id !== RESOLVED_VIRTUAL_EXTENSION_IMPORTS) {\n return null;\n }\n if (extensionImportPackages.length === 0) {\n return 'export {};\\n';\n }\n return extensionImportPackages.map((pkg) => `import ${JSON.stringify(pkg)};\\n`).join('');\n },\n transform(code, id) {\n if (!extensionSideEffectsActive || extensionImportPackages.length === 0) {\n return null;\n }\n if (!MAIN_TS_MODULE_RE.test(id)) {\n return null;\n }\n const next = prependExtensionSideEffectImport(code);\n if (next === code) {\n return null;\n }\n return next;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"vite-plugin-resolve-deps.js","names":[],"sources":["../src/vite-plugin-resolve-deps.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'fs';\nimport path from 'path';\nimport type { Plugin } from 'vite';\nimport type { ResolvedDependencyInfo, ResolvedDependencyMap } from './core/resolved-package-info';\n\nexport type { ResolvedDependencyInfo, ResolvedDependencyMap };\n\nexport interface ResolvedPackageInfo {\n name: string;\n version: string;\n description?: string;\n dependencies: ResolvedDependencyMap;\n /** Direct app `package.json` dependencies, in declaration order. */\n directDependencies: string[];\n /** Third-party runtime packages nested under a direct @eclipse-docks/core or extension-* dependency. */\n nestedDependencies: Record<string, string[]>;\n marketplaceCatalogUrls?: string[];\n}\n\ntype LicenseField =\n | string\n | { type?: string; url?: string }\n | Array<string | { type?: string; url?: string }>;\n\ninterface PackageJson {\n name?: string;\n version?: string;\n description?: string;\n license?: LicenseField;\n homepage?: string;\n repository?: string | { type?: string; url?: string };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport type ResolvePackageInfoOptions = {\n includeDevDependencies?: boolean;\n /**\n * When true (default), list each direct `@eclipse-docks/core` and `extension-*`\n * dependency's own third-party `package.json` dependencies in the About tree.\n */\n includeExtensionRuntimeDependencies?: boolean;\n};\n\nconst RUNTIME_SKIP_PATTERN = /^@types\\//;\n\nconst RUNTIME_SKIP_PACKAGES = new Set([\n 'typescript',\n 'vite',\n 'vitest',\n 'jsdom',\n 'playwright',\n 'rolldown',\n 'fake-indexeddb',\n '@vitest/coverage-v8',\n 'vite-plugin-dts',\n 'vite-plugin-cross-origin-isolation',\n 'vite-plugin-mkcert',\n 'vite-plugin-pwa',\n]);\n\nfunction packageJsonPath(appRoot: string, packageName: string): string | null {\n const segments = packageName.startsWith('@')\n ? packageName.split('/')\n : [packageName];\n const relativePath = path.join('node_modules', ...segments, 'package.json');\n let dir = path.resolve(appRoot);\n const root = path.parse(dir).root;\n\n while (true) {\n const pkgPath = path.join(dir, relativePath);\n if (existsSync(pkgPath)) {\n return pkgPath;\n }\n if (dir === root) break;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction readWorkspacePackageJson(appRoot: string, depName: string): PackageJson | null {\n if (!depName.startsWith('@eclipse-docks/')) return null;\n\n const folder = depName === '@eclipse-docks/core' ? 'core' : depName.slice('@eclipse-docks/'.length);\n let dir = path.resolve(appRoot);\n const root = path.parse(dir).root;\n\n while (dir !== root) {\n const workspacePkgPath = path.join(dir, 'packages', folder, 'package.json');\n if (existsSync(workspacePkgPath)) {\n try {\n return JSON.parse(readFileSync(workspacePkgPath, 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n }\n dir = path.dirname(dir);\n }\n\n return null;\n}\n\nfunction readPackageJson(appRoot: string, packageName: string): PackageJson | null {\n const pkgPath = packageJsonPath(appRoot, packageName);\n let pkg: PackageJson | null = null;\n if (pkgPath) {\n try {\n pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;\n } catch {\n pkg = null;\n }\n }\n\n const workspacePkg = readWorkspacePackageJson(appRoot, packageName);\n if (workspacePkg) {\n pkg = {\n ...workspacePkg,\n ...pkg,\n description: pkg?.description ?? workspacePkg.description,\n license: pkg?.license ?? workspacePkg.license,\n homepage: pkg?.homepage ?? workspacePkg.homepage,\n repository: pkg?.repository ?? workspacePkg.repository,\n };\n }\n\n return pkg;\n}\n\nfunction normalizeLicense(license: LicenseField | undefined): string | undefined {\n if (!license) return undefined;\n if (typeof license === 'string') return license;\n if (Array.isArray(license)) {\n const parts = license\n .map((entry) => (typeof entry === 'string' ? entry : entry.type ?? ''))\n .filter(Boolean);\n return parts.length > 0 ? parts.join(' AND ') : undefined;\n }\n return license.type;\n}\n\nfunction normalizeRepository(\n repository: PackageJson['repository'],\n): string | undefined {\n if (!repository) return undefined;\n const raw = typeof repository === 'string' ? repository : repository.url;\n if (!raw) return undefined;\n return raw\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/\\.git$/, '');\n}\n\nfunction shouldSkipRuntimePackage(name: string): boolean {\n if (RUNTIME_SKIP_PATTERN.test(name)) return true;\n if (RUNTIME_SKIP_PACKAGES.has(name)) return true;\n if (name.startsWith('vite-plugin-')) return true;\n return false;\n}\n\n/** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */\nconst DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\\/)?extension-/;\n\nfunction isEclipseDocksPlatformPackage(name: string): boolean {\n return name === '@eclipse-docks/core' || DEFAULT_EXTENSION_PATTERN.test(name);\n}\n\nexport function resolveDependencyInfo(\n appRoot: string,\n depName: string,\n): ResolvedDependencyInfo {\n const pkg = readPackageJson(appRoot, depName);\n\n return {\n license: normalizeLicense(pkg?.license),\n homepage: typeof pkg?.homepage === 'string' ? pkg.homepage : undefined,\n repository: normalizeRepository(pkg?.repository),\n description: typeof pkg?.description === 'string' ? pkg.description : undefined,\n };\n}\n\nfunction collectDirectDependencyEntries(\n pkg: PackageJson,\n options?: ResolvePackageInfoOptions,\n): Array<[string, string]> {\n const deps = { ...pkg.dependencies };\n if (options?.includeDevDependencies && pkg.devDependencies) {\n Object.assign(deps, pkg.devDependencies);\n }\n return Object.entries(deps);\n}\n\n/** Direct third-party runtime dependencies declared in `seed`'s package.json. */\nfunction collectDirectThirdPartyDependencies(appRoot: string, seed: string): string[] {\n const pkg = readPackageJson(appRoot, seed);\n if (!pkg?.dependencies) return [];\n\n return Object.keys(pkg.dependencies)\n .filter((dep) => !shouldSkipRuntimePackage(dep))\n .filter((dep) => !isEclipseDocksPlatformPackage(dep))\n .sort((a, b) => a.localeCompare(b));\n}\n\nfunction resolveDependenciesFromPkg(\n appRoot: string,\n pkg: PackageJson,\n options?: ResolvePackageInfoOptions,\n): Pick<ResolvedPackageInfo, 'dependencies' | 'directDependencies' | 'nestedDependencies'> {\n const depEntries = collectDirectDependencyEntries(pkg, options);\n const directDependencies = depEntries.map(([name]) => name);\n const dependencies: ResolvedDependencyMap = {};\n\n for (const [name] of depEntries) {\n dependencies[name] = resolveDependencyInfo(appRoot, name);\n }\n\n const nestedDependencies: Record<string, string[]> = {};\n\n if (options?.includeExtensionRuntimeDependencies !== false) {\n for (const name of directDependencies) {\n if (!isEclipseDocksPlatformPackage(name)) continue;\n\n const thirdParty = collectDirectThirdPartyDependencies(appRoot, name);\n if (thirdParty.length === 0) continue;\n\n nestedDependencies[name] = thirdParty;\n for (const dep of thirdParty) {\n if (!dependencies[dep]) {\n dependencies[dep] = resolveDependencyInfo(appRoot, dep);\n }\n }\n }\n }\n\n return { dependencies, directDependencies, nestedDependencies };\n}\n\nexport function resolvePackageInfo(\n appRoot: string,\n options?: ResolvePackageInfoOptions,\n): ResolvedPackageInfo | null {\n const pkgPath = path.join(appRoot, 'package.json');\n if (!existsSync(pkgPath)) return null;\n\n let pkg: PackageJson;\n try {\n pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n\n const name = typeof pkg.name === 'string' ? pkg.name : '';\n const version = typeof pkg.version === 'string' ? pkg.version : '0.0.0';\n const description = typeof pkg.description === 'string' ? pkg.description : undefined;\n const { dependencies, directDependencies, nestedDependencies } = resolveDependenciesFromPkg(\n appRoot,\n pkg,\n options,\n );\n const marketplaceCatalogUrls = (pkg as { marketplace?: { catalogUrls?: string[] } }).marketplace\n ?.catalogUrls;\n\n return {\n name,\n version,\n description,\n dependencies,\n directDependencies,\n nestedDependencies,\n marketplaceCatalogUrls,\n };\n}\n\nexport function resolveDepVersions(\n appRoot: string,\n options?: ResolvePackageInfoOptions,\n): Record<string, string> {\n const pkgPath = path.join(appRoot, 'package.json');\n if (!existsSync(pkgPath)) return {};\n\n let pkg: PackageJson;\n try {\n pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;\n } catch {\n return {};\n }\n\n const depEntries = collectDirectDependencyEntries(pkg, options);\n const result: Record<string, string> = {};\n for (const [name, specifier] of depEntries) {\n const installed = readPackageJson(appRoot, name);\n result[name] =\n typeof installed?.version === 'string' ? installed.version : specifier;\n }\n return result;\n}\n\nconst RESOLVED_PACKAGE_INFO_KEY = '__RESOLVED_PACKAGE_INFO__';\n\n/** Virtual module id; prepended to `src/main.ts` when extension side-effects are enabled. */\nexport const VIRTUAL_EXTENSION_IMPORTS = 'virtual:eclipse-docks-extension-imports';\n\nconst RESOLVED_VIRTUAL_EXTENSION_IMPORTS = `\\0${VIRTUAL_EXTENSION_IMPORTS}`;\n\n/** App entry module transformed by {@link resolveDepVersionsPlugin}. */\nconst MAIN_TS_MODULE_RE = /[/\\\\]src[/\\\\]main\\.ts$/;\n\nconst EXTENSION_IMPORT_STATEMENT = `import ${JSON.stringify(VIRTUAL_EXTENSION_IMPORTS)};\\n`;\n\n/** Prepends the virtual extension side-effect import when not already present. */\nexport function prependExtensionSideEffectImport(code: string): string {\n if (code.includes(VIRTUAL_EXTENSION_IMPORTS)) {\n return code;\n }\n return EXTENSION_IMPORT_STATEMENT + code;\n}\n\nconst DEFAULT_PRIORITY_FIRST = ['@eclipse-docks/extension-pwa', 'extension-pwa'];\n\nexport interface ExtensionSideEffectsOptions {\n /**\n * When false, disables automatic extension side-effect imports. Omitted or true keeps them on.\n */\n enabled?: boolean;\n /** Dependency names to skip (even if they match `packageNamePattern`). */\n exclude?: string[];\n /**\n * Packages to load first, in order (only those present in dependencies are imported).\n * Default includes PWA so `beforeinstallprompt` can register early.\n */\n priorityFirst?: string[];\n /**\n * Which direct `dependencies` keys qualify as Docks-style extensions (`extension-*`, with an optional npm scope).\n * @default /^(?:@[^/]+\\/)?extension-/\n */\n packageNamePattern?: RegExp;\n}\n\nexport type ResolveDepVersionsPluginOptions = ResolvePackageInfoOptions & {\n /**\n * By default, registers a virtual module that side-effect-imports every matching direct\n * `dependencies` entry (see `ExtensionSideEffectsOptions`), and prepends\n * `import 'virtual:eclipse-docks-extension-imports'` to `src/main.ts` so extension\n * registration completes before `registerApp({ autoStart: true })`.\n * Pass `false` or `{ enabled: false }` to disable.\n */\n extensionSideEffects?: boolean | ExtensionSideEffectsOptions;\n};\n\n/** Normalized match options for {@link listExtensionSideEffectPackages}. */\nexport type ExtensionSideEffectsListOptions = {\n exclude: Set<string>;\n priorityFirst: string[];\n pattern: RegExp;\n};\n\nfunction normalizeExtensionSideEffects(\n opt: boolean | ExtensionSideEffectsOptions | undefined,\n): ExtensionSideEffectsListOptions | null {\n if (opt === false) return null;\n if (opt === undefined || opt === true) {\n return {\n exclude: new Set(),\n priorityFirst: [...DEFAULT_PRIORITY_FIRST],\n pattern: DEFAULT_EXTENSION_PATTERN,\n };\n }\n if (opt.enabled === false) return null;\n return {\n exclude: new Set(opt.exclude ?? []),\n priorityFirst: opt.priorityFirst ?? [...DEFAULT_PRIORITY_FIRST],\n pattern: opt.packageNamePattern ?? DEFAULT_EXTENSION_PATTERN,\n };\n}\n\nexport function listExtensionSideEffectPackages(\n dependencies: Record<string, string>,\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const names = Object.keys(dependencies).filter(\n (name) => sideEffects.pattern.test(name) && !sideEffects.exclude.has(name),\n );\n const prioritySet = new Set(sideEffects.priorityFirst);\n const first = sideEffects.priorityFirst.filter((p) => names.includes(p));\n const rest = names.filter((n) => !prioritySet.has(n)).sort((a, b) => a.localeCompare(b));\n return [...first, ...rest];\n}\n\n/**\n * Walks extension package.json `dependencies` to collect transitive extension-* packages\n * (e.g. extension-utils → extension-python-runtime → extension-terminal).\n */\nexport function collectTransitiveExtensionPackages(\n appRoot: string,\n seeds: string[],\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const found = new Set<string>();\n const queue = [...seeds];\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const name = queue.shift()!;\n if (visited.has(name)) continue;\n visited.add(name);\n\n const pkg = readPackageJson(appRoot, name);\n if (!pkg?.dependencies) continue;\n\n for (const dep of Object.keys(pkg.dependencies)) {\n if (!sideEffects.pattern.test(dep) || sideEffects.exclude.has(dep)) continue;\n found.add(dep);\n queue.push(dep);\n }\n }\n\n return [...found];\n}\n\nexport function resolveExtensionSideEffectPackages(\n appRoot: string,\n dependencies: Record<string, string>,\n sideEffects: ExtensionSideEffectsListOptions,\n): string[] {\n const direct = listExtensionSideEffectPackages(dependencies, sideEffects);\n const transitive = collectTransitiveExtensionPackages(appRoot, direct, sideEffects);\n const allNames = [...new Set([...direct, ...transitive])];\n return listExtensionSideEffectPackages(\n Object.fromEntries(allNames.map((name) => [name, '*'])),\n sideEffects,\n );\n}\n\nfunction dependencyKeysFromInfo(info: ResolvedPackageInfo | null | undefined): string[] {\n if (!info) return [];\n if (info.directDependencies.length > 0) {\n return info.directDependencies;\n }\n return Object.keys(info.dependencies);\n}\n\nexport function resolveDepVersionsPlugin(\n options?: ResolveDepVersionsPluginOptions,\n): Plugin {\n let appRoot = process.cwd();\n let extensionSideEffectsActive = false;\n let extensionImportPackages: string[] = [];\n\n return {\n name: 'resolve-dep-versions',\n config(config) {\n const root = config.root ? path.resolve(config.root) : process.cwd();\n const info = resolvePackageInfo(root, options);\n const value =\n info ?? {\n name: '',\n version: '0.0.0',\n description: undefined,\n dependencies: {},\n directDependencies: [],\n nestedDependencies: {},\n marketplaceCatalogUrls: undefined,\n };\n return {\n define: {\n [RESOLVED_PACKAGE_INFO_KEY]: JSON.stringify(value),\n },\n };\n },\n configResolved(config) {\n appRoot = path.resolve(config.root ?? process.cwd());\n const normalized = normalizeExtensionSideEffects(options?.extensionSideEffects);\n extensionSideEffectsActive = normalized !== null;\n if (!normalized) {\n extensionImportPackages = [];\n return;\n }\n const info = resolvePackageInfo(appRoot, options);\n const depKeys = dependencyKeysFromInfo(info);\n extensionImportPackages = resolveExtensionSideEffectPackages(\n appRoot,\n Object.fromEntries(depKeys.map((name) => [name, '*'])),\n normalized,\n );\n },\n resolveId(id) {\n if (id === VIRTUAL_EXTENSION_IMPORTS) {\n return RESOLVED_VIRTUAL_EXTENSION_IMPORTS;\n }\n return undefined;\n },\n load(id) {\n if (id !== RESOLVED_VIRTUAL_EXTENSION_IMPORTS) {\n return null;\n }\n if (extensionImportPackages.length === 0) {\n return 'export {};\\n';\n }\n return extensionImportPackages.map((pkg) => `import ${JSON.stringify(pkg)};\\n`).join('');\n },\n transform(code, id) {\n if (!extensionSideEffectsActive || extensionImportPackages.length === 0) {\n return null;\n }\n if (!MAIN_TS_MODULE_RE.test(id)) {\n return null;\n }\n const next = prependExtensionSideEffectImport(code);\n if (next === code) {\n return null;\n }\n return next;\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-docks/core",
3
- "version": "0.7.133",
3
+ "version": "0.7.135",
4
4
  "description": "Eclipse Docks platform core: registries, services, parts, widgets, and API",
5
5
  "type": "module",
6
6
  "license": "EPL-2.0",
package/src/api/index.ts CHANGED
@@ -27,5 +27,14 @@ export * from './constants';
27
27
  export * from './types';
28
28
 
29
29
  // Re-export AppDefinition for convenience
30
- export type { AppDefinition, AppContributions, LayoutDescriptor, ReleaseEntry, ReleaseHistory, RenderDescriptor } from '../core/apploader';
30
+ export type {
31
+ AppDefinition,
32
+ AppContributions,
33
+ LayoutDescriptor,
34
+ ReleaseEntry,
35
+ ReleaseHistory,
36
+ RenderDescriptor,
37
+ } from '../core/apploader';
38
+ export type { ResolvedDependencyInfo, ResolvedDependencyMap } from '../core/resolved-package-info';
39
+ export type { LicenseAttributionOptions } from '../core/license-attribution';
31
40
 
@@ -91,4 +91,6 @@ export {
91
91
  resolveStoredPanelVisibility,
92
92
  } from '../core/layout-panels';
93
93
  export { sanitizeHtml, parseMarkdownHtml } from '../core/markdown-html';
94
+ export { registerLicenseAttribution } from '../core/license-attribution';
95
+ export type { LicenseAttributionOptions } from '../core/license-attribution';
94
96
 
package/src/api/types.ts CHANGED
@@ -1,5 +1,14 @@
1
1
  // Re-export framework types for app usage
2
- export type { AppDefinition, AppContributions, LayoutDescriptor, ReleaseEntry, ReleaseHistory, RenderDescriptor } from '../core/apploader';
2
+ export type {
3
+ AppDefinition,
4
+ AppContributions,
5
+ LayoutDescriptor,
6
+ ReleaseEntry,
7
+ ReleaseHistory,
8
+ RenderDescriptor,
9
+ } from '../core/apploader';
10
+ export type { ResolvedDependencyInfo, ResolvedDependencyMap } from '../core/resolved-package-info';
11
+ export type { LicenseAttributionOptions } from '../core/license-attribution';
3
12
  export type {
4
13
  Command,
5
14
  Parameter,
@@ -124,7 +124,7 @@ registerAll({
124
124
  title: "Extensions",
125
125
  data: {},
126
126
  key: "system.extensions",
127
- icon: "docks extensions",
127
+ icon: "puzzle-piece",
128
128
  state: {},
129
129
  component: (id: string) => html`<docks-extensions id="${id}"></docks-extensions>`,
130
130
  }
@@ -1,7 +1,15 @@
1
- import { html, css } from "lit";
1
+ import { html, css, nothing, type TemplateResult } from "lit";
2
2
  import { customElement } from "lit/decorators.js";
3
3
  import { DocksPart } from "../parts/part";
4
4
  import { appLoaderService } from "../core/apploader";
5
+ import {
6
+ normalizeDependencyInfo,
7
+ type ResolvedDependencyInfo,
8
+ } from "../core/resolved-package-info";
9
+
10
+ function packageLink(info: ResolvedDependencyInfo): string | undefined {
11
+ return info.homepage ?? info.repository;
12
+ }
5
13
 
6
14
  @customElement("docks-npm-packages")
7
15
  export class DocksNpmPackages extends DocksPart {
@@ -14,18 +22,101 @@ export class DocksNpmPackages extends DocksPart {
14
22
  box-sizing: border-box;
15
23
  }
16
24
 
17
- wa-tree-item > span small {
25
+ .pkg-name a {
26
+ color: inherit;
27
+ text-decoration: underline;
28
+ text-underline-offset: 0.12em;
29
+ }
30
+
31
+ .pkg-meta {
18
32
  color: var(--wa-color-neutral-60);
19
33
  font-size: 0.875em;
20
- margin-left: 0.5rem;
34
+ }
35
+
36
+ .pkg-meta-label {
37
+ font-weight: 600;
38
+ color: var(--wa-color-neutral-50);
21
39
  }
22
40
  `,
23
41
  ];
24
42
 
43
+ private renderPackageName(name: string, info: ResolvedDependencyInfo) {
44
+ const link = packageLink(info);
45
+ return html`
46
+ <span class="pkg-name">
47
+ ${link
48
+ ? html`<a href=${link} target="_blank" rel="noopener noreferrer">${name}</a>`
49
+ : name}
50
+ </span>
51
+ `;
52
+ }
53
+
54
+ private renderMetaRows(info: ResolvedDependencyInfo) {
55
+ return html`
56
+ ${info.license
57
+ ? html`
58
+ <wa-tree-item>
59
+ <span class="pkg-meta">
60
+ <span class="pkg-meta-label">License:</span> ${info.license}
61
+ </span>
62
+ </wa-tree-item>
63
+ `
64
+ : nothing}
65
+ ${info.description
66
+ ? html`
67
+ <wa-tree-item>
68
+ <span class="pkg-meta">
69
+ <span class="pkg-meta-label">Description:</span> ${info.description}
70
+ </span>
71
+ </wa-tree-item>
72
+ `
73
+ : nothing}
74
+ `;
75
+ }
76
+
77
+ private renderDependencyNode(
78
+ name: string,
79
+ info: ResolvedDependencyInfo | undefined,
80
+ nested: Record<string, string[]>,
81
+ allDependencies: Record<string, ResolvedDependencyInfo>,
82
+ ): TemplateResult | typeof nothing {
83
+ if (!info) {
84
+ return nothing;
85
+ }
86
+
87
+ const children = nested[name] ?? [];
88
+ const hasChildren = children.length > 0 || info.license || info.description;
89
+
90
+ return html`
91
+ <wa-tree-item ?expanded=${hasChildren}>
92
+ ${this.renderPackageName(name, info)}
93
+ ${this.renderMetaRows(info)}
94
+ ${children.map((childName) => {
95
+ const childInfo = normalizeDependencyInfo(allDependencies[childName]);
96
+ if (!childInfo) {
97
+ return nothing;
98
+ }
99
+ return this.renderDependencyNode(
100
+ childName,
101
+ childInfo,
102
+ nested,
103
+ allDependencies,
104
+ );
105
+ })}
106
+ </wa-tree-item>
107
+ `;
108
+ }
109
+
25
110
  protected renderContent() {
26
111
  const app = appLoaderService.getCurrentApp();
27
- const entries = Object.entries(app?.dependencies ?? {});
28
- if (entries.length === 0) {
112
+ const dependencies = app?.dependencies ?? {};
113
+ const directDependencies =
114
+ app?.directDependencies && app.directDependencies.length > 0
115
+ ? app.directDependencies
116
+ : Object.keys(dependencies);
117
+ const nestedDependencies = app?.nestedDependencies ?? {};
118
+
119
+ if (directDependencies.length === 0) {
29
120
  return html`<div class="packages-panel">No package information available.</div>`;
30
121
  }
31
122
 
@@ -34,12 +125,13 @@ export class DocksNpmPackages extends DocksPart {
34
125
  <wa-tree style="--indent-guide-width: 1px;">
35
126
  <wa-tree-item expanded>
36
127
  <span>${app?.name ?? ""}</span>
37
- ${entries.map(
38
- ([name, version]) => html`
39
- <wa-tree-item>
40
- <span>${name} <small>${version}</small></span>
41
- </wa-tree-item>
42
- `,
128
+ ${directDependencies.map((name) =>
129
+ this.renderDependencyNode(
130
+ name,
131
+ normalizeDependencyInfo(dependencies[name]),
132
+ nestedDependencies,
133
+ dependencies,
134
+ ),
43
135
  )}
44
136
  </wa-tree-item>
45
137
  </wa-tree>
@@ -0,0 +1,34 @@
1
+ import { html } from "lit";
2
+ import { registerLicenseAttribution } from "../core/license-attribution";
3
+ import { ATTRIBUTION_ECLIPSE_DOCKS, ATTRIBUTION_FONT_AWESOME } from "../core/contribution-names";
4
+
5
+ registerLicenseAttribution({
6
+ name: ATTRIBUTION_ECLIPSE_DOCKS,
7
+ label: "Eclipse Docks",
8
+ ranking: 1000,
9
+ component: () => html`
10
+ <p>Copyright (c) 2026 The Eclipse Foundation and others.</p>
11
+ <p>
12
+ Eclipse Docks is made available under the
13
+ <a href="https://www.eclipse.org/legal/epl-2.0" target="_blank" rel="noopener noreferrer"
14
+ >Eclipse Public License 2.0</a
15
+ >.
16
+ </p>
17
+ `,
18
+ });
19
+
20
+ registerLicenseAttribution({
21
+ name: ATTRIBUTION_FONT_AWESOME,
22
+ label: "Font Awesome",
23
+ ranking: 900,
24
+ component: () => html`
25
+ <p>
26
+ Icons by
27
+ <a href="https://fontawesome.com" target="_blank" rel="noopener noreferrer">Font Awesome</a>.
28
+ Font Awesome Free is licensed under
29
+ <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener noreferrer"
30
+ >CC BY 4.0</a
31
+ >.
32
+ </p>
33
+ `,
34
+ });