@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
@@ -5,7 +5,6 @@ import {
5
5
  PANEL_BOTTOM,
6
6
  SIDEBAR_MAIN,
7
7
  SIDEBAR_MAIN_TOOLBAR,
8
- SYSTEM_ATTRIBUTIONS,
9
8
  TOOLBAR_BOTTOM_END,
10
9
  TOOLBAR_MAIN_RIGHT
11
10
  } from "../core/contribution-targets";
@@ -13,7 +12,6 @@ import {
13
12
  ABOUT_TAB_ATTRIBUTIONS,
14
13
  ABOUT_TAB_PACKAGES,
15
14
  ABOUT_TAB_RELEASE,
16
- ATTRIBUTION_ECLIPSE_DOCKS,
17
15
  VIEW_FILEBROWSER,
18
16
  VIEW_LOG_TERMINAL,
19
17
  TOOLBAR_LAYOUT_SWITCHER,
@@ -67,17 +65,6 @@ contributionRegistry.registerContribution(ABOUT_TABS, {
67
65
  component: (id: string) => html`<docks-npm-packages id="${id}" embedded></docks-npm-packages>`
68
66
  });
69
67
 
70
- contributionRegistry.registerContribution(SYSTEM_ATTRIBUTIONS, {
71
- name: ATTRIBUTION_ECLIPSE_DOCKS,
72
- label: "Eclipse Docks",
73
- component: () => html`
74
- <p>
75
- Eclipse Docks is made available under the
76
- <a href="https://www.eclipse.org/legal/epl-2.0" target="_blank" rel="noopener noreferrer">Eclipse Public License 2.0</a>.
77
- </p>
78
- `
79
- } as HTMLContribution);
80
-
81
68
  contributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {
82
69
  name: TOOLBAR_INFO,
83
70
  label: "Info",
@@ -107,6 +94,6 @@ contributionRegistry.registerContribution(TOOLBAR_MAIN_RIGHT, {
107
94
  contributionRegistry.registerContribution(SIDEBAR_MAIN_TOOLBAR, {
108
95
  name: SIDEBAR_TOOLBAR_EXTENSIONS,
109
96
  command: "open_extensions",
110
- icon: "docks extensions",
97
+ icon: "puzzle-piece",
111
98
  label: "Extensions",
112
99
  });
@@ -1,4 +1,5 @@
1
1
  import "./default-ui-contributions";
2
+ import "./default-attributions-contributions";
2
3
  import "./default-layout-contributions";
3
4
  import "./marketplace-catalog-contributions";
4
5
 
@@ -12,17 +12,17 @@
12
12
  * - App Loader: Bridge between framework and application
13
13
  */
14
14
 
15
- import { render, TemplateResult, html } from "lit";
15
+ import { render } from "lit";
16
+ import { contributionTargetMappingRegistry, type ContributionNameRemap } from "./contribution-mapping";
17
+ import { SYSTEM_LAYOUTS } from "./contribution-targets";
18
+ import { Contribution, LayoutContribution, TOPIC_CONTRIBUTEIONS_CHANGED, contributionRegistry } from "./contributionregistry";
16
19
  import { rootContext } from "./di";
20
+ import { publish } from "./events";
21
+ import { Extension, extensionRegistry } from "./extensionregistry";
17
22
  import { createLogger } from "./logger";
18
- import { extensionRegistry, Extension } from "./extensionregistry";
19
- import { contributionRegistry, Contribution, LayoutContribution, TOPIC_CONTRIBUTEIONS_CHANGED } from "./contributionregistry";
20
- import { SYSTEM_LAYOUTS } from "./contribution-targets";
21
- import { appSettings } from "./settingsservice";
22
23
  import { marketplaceRegistry } from "./marketplaceregistry";
23
- import { contributionTargetMappingRegistry, type ContributionNameRemap } from "./contribution-mapping";
24
- import { publish } from "./events";
25
-
24
+ import type { ResolvedDependencyMap } from "./resolved-package-info";
25
+ import { appSettings } from "./settingsservice";
26
26
 
27
27
  const logger = createLogger('AppLoader');
28
28
 
@@ -179,8 +179,14 @@ export interface AppDefinition {
179
179
  */
180
180
  dispose?: () => void | Promise<void>;
181
181
 
182
- /** Resolved dependency versions (e.g. from build plugin). Shown in About / version info. */
183
- dependencies?: Record<string, string>;
182
+ /** Resolved dependency metadata (from build plugin). Shown in About / NPM Packages. */
183
+ dependencies?: ResolvedDependencyMap;
184
+
185
+ /** Direct app package.json dependencies, in declaration order. */
186
+ directDependencies?: string[];
187
+
188
+ /** Third-party packages nested under a direct core/extension dependency in the About tree. */
189
+ nestedDependencies?: Record<string, string[]>;
184
190
 
185
191
  /** Marketplace catalog URLs for this app. Registered when the app is registered. */
186
192
  marketplaceCatalogUrls?: string[];
@@ -213,7 +219,8 @@ export interface RegisterAppOptions {
213
219
  container?: HTMLElement;
214
220
 
215
221
  /**
216
- * When true, fill name, version, description, dependencies, marketplaceCatalogUrls from __RESOLVED_PACKAGE_INFO__ only when not already set on the app.
222
+ * When true, fill name, version, description, dependencies, directDependencies,
223
+ * nestedDependencies, and marketplaceCatalogUrls from __RESOLVED_PACKAGE_INFO__ only when not already set on the app.
217
224
  */
218
225
  hostConfig?: boolean;
219
226
  }
@@ -250,6 +257,8 @@ class AppLoaderService {
250
257
  if (app.version === undefined) app.version = resolved.version;
251
258
  if (app.description === undefined) app.description = resolved.description;
252
259
  if (app.dependencies === undefined) app.dependencies = resolved.dependencies;
260
+ if (app.directDependencies === undefined) app.directDependencies = resolved.directDependencies;
261
+ if (app.nestedDependencies === undefined) app.nestedDependencies = resolved.nestedDependencies;
253
262
  if (app.marketplaceCatalogUrls === undefined) app.marketplaceCatalogUrls = resolved.marketplaceCatalogUrls;
254
263
  }
255
264
  app.name = app.name ?? 'app';
@@ -26,6 +26,7 @@ export const ABOUT_TAB_PACKAGES = "about.tab.packages";
26
26
  export const ABOUT_TAB_ATTRIBUTIONS = "about.tab.attributions";
27
27
 
28
28
  export const ATTRIBUTION_ECLIPSE_DOCKS = "attribution.eclipse-docks";
29
+ export const ATTRIBUTION_FONT_AWESOME = "attribution.font-awesome";
29
30
 
30
31
  export const CTXMENU_FILEBROWSER_RENAME = "contextmenu.filebrowser.rename";
31
32
  export const CTXMENU_FILEBROWSER_DELETE = "contextmenu.filebrowser.delete";
@@ -0,0 +1,45 @@
1
+ import { html, nothing, type TemplateResult } from "lit";
2
+ import { contributionRegistry, type HTMLContribution } from "./contributionregistry";
3
+ import { SYSTEM_ATTRIBUTIONS } from "./contribution-targets";
4
+
5
+ export type LicenseAttributionOptions = {
6
+ name: string;
7
+ label: string;
8
+ ranking?: number;
9
+ component?: () => TemplateResult;
10
+ license?: string;
11
+ licenseUrl?: string;
12
+ projectUrl?: string;
13
+ projectLabel?: string;
14
+ };
15
+
16
+ export function registerLicenseAttribution(options: LicenseAttributionOptions): void {
17
+ const component =
18
+ options.component ??
19
+ (() => {
20
+ if (!options.license || !options.licenseUrl) {
21
+ return html`<p>${options.label}</p>`;
22
+ }
23
+ return html`
24
+ <p>
25
+ ${options.label} is used under the
26
+ <a href=${options.licenseUrl} target="_blank" rel="noopener noreferrer">${options.license}</a>.
27
+ ${options.projectUrl
28
+ ? html`
29
+ See
30
+ <a href=${options.projectUrl} target="_blank" rel="noopener noreferrer"
31
+ >${options.projectLabel ?? options.projectUrl}</a
32
+ >.
33
+ `
34
+ : nothing}
35
+ </p>
36
+ `;
37
+ });
38
+
39
+ contributionRegistry.registerContribution(SYSTEM_ATTRIBUTIONS, {
40
+ name: options.name,
41
+ label: options.label,
42
+ ranking: options.ranking ?? 0,
43
+ component,
44
+ } as HTMLContribution);
45
+ }
@@ -0,0 +1,15 @@
1
+ /** Metadata for one npm package resolved at build time from its installed package.json. */
2
+ export interface ResolvedDependencyInfo {
3
+ license?: string;
4
+ homepage?: string;
5
+ repository?: string;
6
+ description?: string;
7
+ }
8
+
9
+ export type ResolvedDependencyMap = Record<string, ResolvedDependencyInfo>;
10
+
11
+ export function normalizeDependencyInfo(
12
+ value: ResolvedDependencyInfo | undefined,
13
+ ): ResolvedDependencyInfo | undefined {
14
+ return value;
15
+ }
package/src/vite-env.d.ts CHANGED
@@ -14,7 +14,16 @@ declare const __RESOLVED_PACKAGE_INFO__: {
14
14
  name: string;
15
15
  version: string;
16
16
  description?: string;
17
- dependencies: Record<string, string>;
17
+ dependencies: Record<
18
+ string,
19
+ {
20
+ license?: string;
21
+ homepage?: string;
22
+ repository?: string;
23
+ description?: string;
24
+ }
25
+ >;
26
+ directDependencies: string[];
27
+ nestedDependencies: Record<string, string[]>;
18
28
  marketplaceCatalogUrls?: string[];
19
29
  } | undefined;
20
-
@@ -1,23 +1,64 @@
1
1
  import { readFileSync, existsSync } from 'fs';
2
2
  import path from 'path';
3
3
  import type { Plugin } from 'vite';
4
+ import type { ResolvedDependencyInfo, ResolvedDependencyMap } from './core/resolved-package-info';
5
+
6
+ export type { ResolvedDependencyInfo, ResolvedDependencyMap };
4
7
 
5
8
  export interface ResolvedPackageInfo {
6
9
  name: string;
7
10
  version: string;
8
11
  description?: string;
9
- dependencies: Record<string, string>;
12
+ dependencies: ResolvedDependencyMap;
13
+ /** Direct app `package.json` dependencies, in declaration order. */
14
+ directDependencies: string[];
15
+ /** Third-party runtime packages nested under a direct @eclipse-docks/core or extension-* dependency. */
16
+ nestedDependencies: Record<string, string[]>;
10
17
  marketplaceCatalogUrls?: string[];
11
18
  }
12
19
 
20
+ type LicenseField =
21
+ | string
22
+ | { type?: string; url?: string }
23
+ | Array<string | { type?: string; url?: string }>;
24
+
13
25
  interface PackageJson {
14
26
  name?: string;
15
27
  version?: string;
16
28
  description?: string;
29
+ license?: LicenseField;
30
+ homepage?: string;
31
+ repository?: string | { type?: string; url?: string };
17
32
  dependencies?: Record<string, string>;
18
33
  devDependencies?: Record<string, string>;
19
34
  }
20
35
 
36
+ export type ResolvePackageInfoOptions = {
37
+ includeDevDependencies?: boolean;
38
+ /**
39
+ * When true (default), list each direct `@eclipse-docks/core` and `extension-*`
40
+ * dependency's own third-party `package.json` dependencies in the About tree.
41
+ */
42
+ includeExtensionRuntimeDependencies?: boolean;
43
+ };
44
+
45
+ const RUNTIME_SKIP_PATTERN = /^@types\//;
46
+
47
+ const RUNTIME_SKIP_PACKAGES = new Set([
48
+ 'typescript',
49
+ 'vite',
50
+ 'vitest',
51
+ 'jsdom',
52
+ 'playwright',
53
+ 'rolldown',
54
+ 'fake-indexeddb',
55
+ '@vitest/coverage-v8',
56
+ 'vite-plugin-dts',
57
+ 'vite-plugin-cross-origin-isolation',
58
+ 'vite-plugin-mkcert',
59
+ 'vite-plugin-pwa',
60
+ ]);
61
+
21
62
  function packageJsonPath(appRoot: string, packageName: string): string | null {
22
63
  const segments = packageName.startsWith('@')
23
64
  ? packageName.split('/')
@@ -37,42 +78,165 @@ function packageJsonPath(appRoot: string, packageName: string): string | null {
37
78
  return null;
38
79
  }
39
80
 
81
+ function readWorkspacePackageJson(appRoot: string, depName: string): PackageJson | null {
82
+ if (!depName.startsWith('@eclipse-docks/')) return null;
83
+
84
+ const folder = depName === '@eclipse-docks/core' ? 'core' : depName.slice('@eclipse-docks/'.length);
85
+ let dir = path.resolve(appRoot);
86
+ const root = path.parse(dir).root;
87
+
88
+ while (dir !== root) {
89
+ const workspacePkgPath = path.join(dir, 'packages', folder, 'package.json');
90
+ if (existsSync(workspacePkgPath)) {
91
+ try {
92
+ return JSON.parse(readFileSync(workspacePkgPath, 'utf8')) as PackageJson;
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+ dir = path.dirname(dir);
98
+ }
99
+
100
+ return null;
101
+ }
102
+
40
103
  function readPackageJson(appRoot: string, packageName: string): PackageJson | null {
41
104
  const pkgPath = packageJsonPath(appRoot, packageName);
42
- if (!pkgPath) return null;
43
- try {
44
- return JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;
45
- } catch {
46
- return null;
105
+ let pkg: PackageJson | null = null;
106
+ if (pkgPath) {
107
+ try {
108
+ pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;
109
+ } catch {
110
+ pkg = null;
111
+ }
112
+ }
113
+
114
+ const workspacePkg = readWorkspacePackageJson(appRoot, packageName);
115
+ if (workspacePkg) {
116
+ pkg = {
117
+ ...workspacePkg,
118
+ ...pkg,
119
+ description: pkg?.description ?? workspacePkg.description,
120
+ license: pkg?.license ?? workspacePkg.license,
121
+ homepage: pkg?.homepage ?? workspacePkg.homepage,
122
+ repository: pkg?.repository ?? workspacePkg.repository,
123
+ };
47
124
  }
125
+
126
+ return pkg;
48
127
  }
49
128
 
50
- function findPackageVersion(appRoot: string, depName: string): string | null {
51
- const pkg = readPackageJson(appRoot, depName);
52
- if (typeof pkg?.version === 'string') return pkg.version;
53
- return null;
129
+ function normalizeLicense(license: LicenseField | undefined): string | undefined {
130
+ if (!license) return undefined;
131
+ if (typeof license === 'string') return license;
132
+ if (Array.isArray(license)) {
133
+ const parts = license
134
+ .map((entry) => (typeof entry === 'string' ? entry : entry.type ?? ''))
135
+ .filter(Boolean);
136
+ return parts.length > 0 ? parts.join(' AND ') : undefined;
137
+ }
138
+ return license.type;
54
139
  }
55
140
 
56
- function resolveDepVersionsFromPkg(
141
+ function normalizeRepository(
142
+ repository: PackageJson['repository'],
143
+ ): string | undefined {
144
+ if (!repository) return undefined;
145
+ const raw = typeof repository === 'string' ? repository : repository.url;
146
+ if (!raw) return undefined;
147
+ return raw
148
+ .replace(/^git\+/, '')
149
+ .replace(/^git:\/\//, 'https://')
150
+ .replace(/\.git$/, '');
151
+ }
152
+
153
+ function shouldSkipRuntimePackage(name: string): boolean {
154
+ if (RUNTIME_SKIP_PATTERN.test(name)) return true;
155
+ if (RUNTIME_SKIP_PACKAGES.has(name)) return true;
156
+ if (name.startsWith('vite-plugin-')) return true;
157
+ return false;
158
+ }
159
+
160
+ /** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */
161
+ const DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\/)?extension-/;
162
+
163
+ function isEclipseDocksPlatformPackage(name: string): boolean {
164
+ return name === '@eclipse-docks/core' || DEFAULT_EXTENSION_PATTERN.test(name);
165
+ }
166
+
167
+ export function resolveDependencyInfo(
57
168
  appRoot: string,
169
+ depName: string,
170
+ ): ResolvedDependencyInfo {
171
+ const pkg = readPackageJson(appRoot, depName);
172
+
173
+ return {
174
+ license: normalizeLicense(pkg?.license),
175
+ homepage: typeof pkg?.homepage === 'string' ? pkg.homepage : undefined,
176
+ repository: normalizeRepository(pkg?.repository),
177
+ description: typeof pkg?.description === 'string' ? pkg.description : undefined,
178
+ };
179
+ }
180
+
181
+ function collectDirectDependencyEntries(
58
182
  pkg: PackageJson,
59
- options?: { includeDevDependencies?: boolean }
60
- ): Record<string, string> {
183
+ options?: ResolvePackageInfoOptions,
184
+ ): Array<[string, string]> {
61
185
  const deps = { ...pkg.dependencies };
62
186
  if (options?.includeDevDependencies && pkg.devDependencies) {
63
187
  Object.assign(deps, pkg.devDependencies);
64
188
  }
65
- const result: Record<string, string> = {};
66
- for (const [name, specifier] of Object.entries(deps)) {
67
- const version = findPackageVersion(appRoot, name);
68
- result[name] = version ?? specifier;
189
+ return Object.entries(deps);
190
+ }
191
+
192
+ /** Direct third-party runtime dependencies declared in `seed`'s package.json. */
193
+ function collectDirectThirdPartyDependencies(appRoot: string, seed: string): string[] {
194
+ const pkg = readPackageJson(appRoot, seed);
195
+ if (!pkg?.dependencies) return [];
196
+
197
+ return Object.keys(pkg.dependencies)
198
+ .filter((dep) => !shouldSkipRuntimePackage(dep))
199
+ .filter((dep) => !isEclipseDocksPlatformPackage(dep))
200
+ .sort((a, b) => a.localeCompare(b));
201
+ }
202
+
203
+ function resolveDependenciesFromPkg(
204
+ appRoot: string,
205
+ pkg: PackageJson,
206
+ options?: ResolvePackageInfoOptions,
207
+ ): Pick<ResolvedPackageInfo, 'dependencies' | 'directDependencies' | 'nestedDependencies'> {
208
+ const depEntries = collectDirectDependencyEntries(pkg, options);
209
+ const directDependencies = depEntries.map(([name]) => name);
210
+ const dependencies: ResolvedDependencyMap = {};
211
+
212
+ for (const [name] of depEntries) {
213
+ dependencies[name] = resolveDependencyInfo(appRoot, name);
69
214
  }
70
- return result;
215
+
216
+ const nestedDependencies: Record<string, string[]> = {};
217
+
218
+ if (options?.includeExtensionRuntimeDependencies !== false) {
219
+ for (const name of directDependencies) {
220
+ if (!isEclipseDocksPlatformPackage(name)) continue;
221
+
222
+ const thirdParty = collectDirectThirdPartyDependencies(appRoot, name);
223
+ if (thirdParty.length === 0) continue;
224
+
225
+ nestedDependencies[name] = thirdParty;
226
+ for (const dep of thirdParty) {
227
+ if (!dependencies[dep]) {
228
+ dependencies[dep] = resolveDependencyInfo(appRoot, dep);
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ return { dependencies, directDependencies, nestedDependencies };
71
235
  }
72
236
 
73
237
  export function resolvePackageInfo(
74
238
  appRoot: string,
75
- options?: { includeDevDependencies?: boolean }
239
+ options?: ResolvePackageInfoOptions,
76
240
  ): ResolvedPackageInfo | null {
77
241
  const pkgPath = path.join(appRoot, 'package.json');
78
242
  if (!existsSync(pkgPath)) return null;
@@ -87,18 +251,47 @@ export function resolvePackageInfo(
87
251
  const name = typeof pkg.name === 'string' ? pkg.name : '';
88
252
  const version = typeof pkg.version === 'string' ? pkg.version : '0.0.0';
89
253
  const description = typeof pkg.description === 'string' ? pkg.description : undefined;
90
- const dependencies = resolveDepVersionsFromPkg(appRoot, pkg, options);
91
- const marketplaceCatalogUrls = (pkg as { marketplace?: { catalogUrls?: string[] } }).marketplace?.catalogUrls;
254
+ const { dependencies, directDependencies, nestedDependencies } = resolveDependenciesFromPkg(
255
+ appRoot,
256
+ pkg,
257
+ options,
258
+ );
259
+ const marketplaceCatalogUrls = (pkg as { marketplace?: { catalogUrls?: string[] } }).marketplace
260
+ ?.catalogUrls;
92
261
 
93
- return { name, version, description, dependencies, marketplaceCatalogUrls };
262
+ return {
263
+ name,
264
+ version,
265
+ description,
266
+ dependencies,
267
+ directDependencies,
268
+ nestedDependencies,
269
+ marketplaceCatalogUrls,
270
+ };
94
271
  }
95
272
 
96
273
  export function resolveDepVersions(
97
274
  appRoot: string,
98
- options?: { includeDevDependencies?: boolean }
275
+ options?: ResolvePackageInfoOptions,
99
276
  ): Record<string, string> {
100
- const info = resolvePackageInfo(appRoot, options);
101
- return info?.dependencies ?? {};
277
+ const pkgPath = path.join(appRoot, 'package.json');
278
+ if (!existsSync(pkgPath)) return {};
279
+
280
+ let pkg: PackageJson;
281
+ try {
282
+ pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;
283
+ } catch {
284
+ return {};
285
+ }
286
+
287
+ const depEntries = collectDirectDependencyEntries(pkg, options);
288
+ const result: Record<string, string> = {};
289
+ for (const [name, specifier] of depEntries) {
290
+ const installed = readPackageJson(appRoot, name);
291
+ result[name] =
292
+ typeof installed?.version === 'string' ? installed.version : specifier;
293
+ }
294
+ return result;
102
295
  }
103
296
 
104
297
  const RESOLVED_PACKAGE_INFO_KEY = '__RESOLVED_PACKAGE_INFO__';
@@ -121,9 +314,6 @@ export function prependExtensionSideEffectImport(code: string): string {
121
314
  return EXTENSION_IMPORT_STATEMENT + code;
122
315
  }
123
316
 
124
- /** Unscoped `extension-*` or scoped `@namespace/extension-*` (any npm scope). */
125
- const DEFAULT_EXTENSION_PATTERN = /^(?:@[^/]+\/)?extension-/;
126
-
127
317
  const DEFAULT_PRIORITY_FIRST = ['@eclipse-docks/extension-pwa', 'extension-pwa'];
128
318
 
129
319
  export interface ExtensionSideEffectsOptions {
@@ -145,8 +335,7 @@ export interface ExtensionSideEffectsOptions {
145
335
  packageNamePattern?: RegExp;
146
336
  }
147
337
 
148
- export type ResolveDepVersionsPluginOptions = {
149
- includeDevDependencies?: boolean;
338
+ export type ResolveDepVersionsPluginOptions = ResolvePackageInfoOptions & {
150
339
  /**
151
340
  * By default, registers a virtual module that side-effect-imports every matching direct
152
341
  * `dependencies` entry (see `ExtensionSideEffectsOptions`), and prepends
@@ -241,6 +430,14 @@ export function resolveExtensionSideEffectPackages(
241
430
  );
242
431
  }
243
432
 
433
+ function dependencyKeysFromInfo(info: ResolvedPackageInfo | null | undefined): string[] {
434
+ if (!info) return [];
435
+ if (info.directDependencies.length > 0) {
436
+ return info.directDependencies;
437
+ }
438
+ return Object.keys(info.dependencies);
439
+ }
440
+
244
441
  export function resolveDepVersionsPlugin(
245
442
  options?: ResolveDepVersionsPluginOptions,
246
443
  ): Plugin {
@@ -259,6 +456,8 @@ export function resolveDepVersionsPlugin(
259
456
  version: '0.0.0',
260
457
  description: undefined,
261
458
  dependencies: {},
459
+ directDependencies: [],
460
+ nestedDependencies: {},
262
461
  marketplaceCatalogUrls: undefined,
263
462
  };
264
463
  return {
@@ -276,9 +475,10 @@ export function resolveDepVersionsPlugin(
276
475
  return;
277
476
  }
278
477
  const info = resolvePackageInfo(appRoot, options);
478
+ const depKeys = dependencyKeysFromInfo(info);
279
479
  extensionImportPackages = resolveExtensionSideEffectPackages(
280
480
  appRoot,
281
- info?.dependencies ?? {},
481
+ Object.fromEntries(depKeys.map((name) => [name, '*'])),
282
482
  normalized,
283
483
  );
284
484
  },