@jskit-ai/kernel 0.1.147 → 0.1.149

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.
@@ -1,14 +1,17 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { loadInstalledPackageDescriptor } from "../../internal/node/installedPackageDescriptor.js";
3
+ import {
4
+ collectRootDependencySpecifiers,
5
+ discoverInstalledPackages
6
+ } from "../../internal/node/installedPackages.js";
4
7
  import { normalizeObject } from "../../shared/support/normalize.js";
5
8
  import { sortStrings } from "../../shared/support/sorting.js";
6
9
  import {
7
- normalizeDescriptorClientProviders,
8
- normalizeDescriptorClientOptimizeSpecifiers,
9
- normalizeDescriptorUiRoutes,
10
- normalizeClientDescriptorSections
11
- } from "../descriptorSections.js";
10
+ normalizePackageMetadataClientProviders,
11
+ normalizePackageMetadataClientOptimizeSpecifiers,
12
+ normalizePackageMetadataUiRoutes,
13
+ normalizeClientPackageMetadataSections
14
+ } from "../packageMetadataSections.js";
12
15
 
13
16
  const CLIENT_BOOTSTRAP_VIRTUAL_ID = "virtual:jskit-client-bootstrap";
14
17
  const CLIENT_BOOTSTRAP_RESOLVED_ID = `\0${CLIENT_BOOTSTRAP_VIRTUAL_ID}`;
@@ -54,35 +57,23 @@ function isPathInsideRoot(rootPath, candidatePath) {
54
57
  * That hash does not change when local source changes, which lets a browser reuse stale client code
55
58
  * even after Vite restarts.
56
59
  *
57
- * Build this table from every lock-classified local package, not only packages with a ./client export.
60
+ * Build this table from every local package declared by the app, not only packages with a ./client export.
58
61
  * Resolving only the bootstrap entry is insufficient: a local client can use bare imports from another
59
62
  * local package's root, shared entry, or exported subpath and accidentally re-enter node_modules caching.
60
63
  */
61
- async function resolveLocalPackageSources({ appRoot, lockPath }) {
62
- const absoluteLockPath = path.resolve(appRoot, lockPath);
63
- const lockPayload = await readJsonFile(absoluteLockPath, {});
64
- const installedPackages = normalizeObject(lockPayload.installedPackages);
65
- const packages = [];
66
-
67
- for (const packageId of sortStrings(Object.keys(installedPackages))) {
68
- const installedPackageState = normalizeObject(installedPackages[packageId]);
69
- const source = normalizeObject(installedPackageState.source);
70
- const sourceType = String(source.type || "").trim().toLowerCase();
71
- const packagePath = String(source.packagePath || "").trim();
72
- if (!LOCAL_PACKAGE_SOURCE_TYPES.has(sourceType) || !packagePath) {
73
- continue;
74
- }
75
-
76
- packages.push(
77
- Object.freeze({
78
- packageId,
79
- installedPackageRoot: path.resolve(appRoot, "node_modules", ...packageId.split("/")),
80
- sourcePackageRoot: path.resolve(appRoot, packagePath)
81
- })
82
- );
83
- }
84
-
85
- return Object.freeze(packages);
64
+ async function resolveLocalPackageSources({ appRoot }) {
65
+ const installedPackages = await discoverInstalledPackages({ appRoot });
66
+ return Object.freeze(
67
+ installedPackages
68
+ .filter((entry) => LOCAL_PACKAGE_SOURCE_TYPES.has(entry.sourceType))
69
+ .map((entry) =>
70
+ Object.freeze({
71
+ packageId: entry.packageId,
72
+ installedPackageRoot: entry.installedPackageRoot,
73
+ sourcePackageRoot: entry.sourcePackageRoot
74
+ })
75
+ )
76
+ );
86
77
  }
87
78
 
88
79
  function splitSpecifierSuffix(source) {
@@ -126,37 +117,23 @@ function resolveCanonicalLocalPackageId(resolvedId, localPackage) {
126
117
  : "";
127
118
  }
128
119
 
129
- async function resolveInstalledClientModules({ appRoot, lockPath }) {
130
- const absoluteLockPath = path.resolve(appRoot, lockPath);
131
- const lockPayload = await readJsonFile(absoluteLockPath, {});
132
- const installedPackages = normalizeObject(lockPayload.installedPackages);
133
- const packageIds = sortStrings(Object.keys(installedPackages));
134
-
120
+ async function resolveInstalledClientModules({ appRoot }) {
121
+ const installedPackages = await discoverInstalledPackages({ appRoot });
135
122
  const modules = [];
136
- for (const packageId of packageIds) {
137
- const installedPackageState = normalizeObject(installedPackages[packageId]);
138
- const packageJsonPath = path.resolve(appRoot, "node_modules", ...packageId.split("/"), "package.json");
139
- const packageJson = await readJsonFile(packageJsonPath, {});
140
- if (!hasClientExport(packageJson)) {
123
+ for (const installedPackage of installedPackages) {
124
+ if (!hasClientExport(installedPackage.packageJson)) {
141
125
  continue;
142
126
  }
143
-
144
- const descriptorRecord = await loadInstalledPackageDescriptor({
145
- appRoot,
146
- packageId,
147
- installedPackageState,
148
- required: false
149
- });
150
- const descriptorSections = normalizeClientDescriptorSections(descriptorRecord.descriptor);
127
+ const packageMetadataSections = normalizeClientPackageMetadataSections(installedPackage.packageMetadata);
151
128
 
152
129
  modules.push(
153
130
  Object.freeze({
154
- packageId,
155
- sourceType: String(installedPackageState?.source?.type || "").trim().toLowerCase(),
156
- descriptorUiRoutes: descriptorSections.descriptorUiRoutes,
157
- descriptorClientProviders: descriptorSections.descriptorClientProviders,
158
- descriptorClientOptimizeIncludeSpecifiers: descriptorSections.descriptorClientOptimizeIncludeSpecifiers,
159
- descriptorClientOptimizeExcludeSpecifiers: descriptorSections.descriptorClientOptimizeExcludeSpecifiers
131
+ packageId: installedPackage.packageId,
132
+ sourceType: installedPackage.sourceType,
133
+ packageMetadataUiRoutes: packageMetadataSections.packageMetadataUiRoutes,
134
+ packageMetadataClientProviders: packageMetadataSections.packageMetadataClientProviders,
135
+ packageMetadataClientOptimizeIncludeSpecifiers: packageMetadataSections.packageMetadataClientOptimizeIncludeSpecifiers,
136
+ packageMetadataClientOptimizeExcludeSpecifiers: packageMetadataSections.packageMetadataClientOptimizeExcludeSpecifiers
160
137
  })
161
138
  );
162
139
  }
@@ -169,26 +146,20 @@ async function resolveInstalledClientPackageIds(options) {
169
146
  return Object.freeze(modules.map((entry) => entry.packageId));
170
147
  }
171
148
 
172
- async function resolveLocalScopePackageIds({ appRoot, lockPath }) {
173
- const absoluteLockPath = path.resolve(appRoot, lockPath);
174
- const lockPayload = await readJsonFile(absoluteLockPath, {});
175
- const installedPackages = normalizeObject(lockPayload.installedPackages);
176
- const localScopeFromLock = Object.keys(installedPackages).filter((packageId) => isLocalScopePackageId(packageId));
177
-
149
+ async function resolveLocalScopePackageIds({ appRoot }) {
178
150
  const appPackageJson = await readJsonFile(path.resolve(appRoot, "package.json"), {});
179
- const localScopeFromPackageJson = Object.keys({
180
- ...normalizeObject(appPackageJson.dependencies),
181
- ...normalizeObject(appPackageJson.devDependencies),
182
- ...normalizeObject(appPackageJson.optionalDependencies),
183
- ...normalizeObject(appPackageJson.peerDependencies)
184
- }).filter((packageId) => isLocalScopePackageId(packageId));
185
-
186
- return Object.freeze(sortStrings([...localScopeFromLock, ...localScopeFromPackageJson]));
151
+ return Object.freeze(
152
+ sortStrings(
153
+ [...collectRootDependencySpecifiers(appPackageJson).keys()].filter((packageId) =>
154
+ isLocalScopePackageId(packageId)
155
+ )
156
+ )
157
+ );
187
158
  }
188
159
 
189
- function normalizeClientModuleDescriptors(value) {
160
+ function normalizeClientModulePackageMetadataEntries(value) {
190
161
  const items = Array.isArray(value) ? value : [];
191
- const descriptors = [];
162
+ const packageMetadataEntries = [];
192
163
 
193
164
  for (const item of items) {
194
165
  const record = normalizeObject(item);
@@ -197,33 +168,33 @@ function normalizeClientModuleDescriptors(value) {
197
168
  continue;
198
169
  }
199
170
  const sourceType = String(record.sourceType || "").trim().toLowerCase();
200
- descriptors.push({
171
+ packageMetadataEntries.push({
201
172
  packageId,
202
173
  sourceType,
203
- descriptorUiRoutes: normalizeDescriptorUiRoutes(record.descriptorUiRoutes),
204
- descriptorClientProviders: normalizeDescriptorClientProviders(record.descriptorClientProviders),
205
- descriptorClientOptimizeIncludeSpecifiers: normalizeDescriptorClientOptimizeSpecifiers(
206
- record.descriptorClientOptimizeIncludeSpecifiers
174
+ packageMetadataUiRoutes: normalizePackageMetadataUiRoutes(record.packageMetadataUiRoutes),
175
+ packageMetadataClientProviders: normalizePackageMetadataClientProviders(record.packageMetadataClientProviders),
176
+ packageMetadataClientOptimizeIncludeSpecifiers: normalizePackageMetadataClientOptimizeSpecifiers(
177
+ record.packageMetadataClientOptimizeIncludeSpecifiers
207
178
  ),
208
- descriptorClientOptimizeExcludeSpecifiers: normalizeDescriptorClientOptimizeSpecifiers(
209
- record.descriptorClientOptimizeExcludeSpecifiers
179
+ packageMetadataClientOptimizeExcludeSpecifiers: normalizePackageMetadataClientOptimizeSpecifiers(
180
+ record.packageMetadataClientOptimizeExcludeSpecifiers
210
181
  )
211
182
  });
212
183
  }
213
184
 
214
185
  return Object.freeze(
215
- descriptors.sort((left, right) => left.packageId.localeCompare(right.packageId))
186
+ packageMetadataEntries.sort((left, right) => left.packageId.localeCompare(right.packageId))
216
187
  );
217
188
  }
218
189
 
219
190
  function createVirtualModuleSource(clientModules = []) {
220
- const moduleDescriptors = normalizeClientModuleDescriptors(clientModules);
221
- const importLines = moduleDescriptors.map(
191
+ const modulePackageMetadataEntries = normalizeClientModulePackageMetadataEntries(clientModules);
192
+ const importLines = modulePackageMetadataEntries.map(
222
193
  (entry, index) => `import * as clientModule${index} from ${JSON.stringify(`${entry.packageId}/client`)};`
223
194
  );
224
- const moduleEntries = moduleDescriptors.map(
195
+ const moduleEntries = modulePackageMetadataEntries.map(
225
196
  (entry, index) =>
226
- ` { packageId: ${JSON.stringify(entry.packageId)}, module: clientModule${index}, descriptorUiRoutes: ${JSON.stringify(entry.descriptorUiRoutes)}, descriptorClientProviders: ${JSON.stringify(entry.descriptorClientProviders)} }`
197
+ ` { packageId: ${JSON.stringify(entry.packageId)}, module: clientModule${index}, packageMetadataUiRoutes: ${JSON.stringify(entry.packageMetadataUiRoutes)}, packageMetadataClientProviders: ${JSON.stringify(entry.packageMetadataClientProviders)} }`
227
198
  );
228
199
 
229
200
  const entriesSource = moduleEntries.length > 0 ? moduleEntries.join(",\n") : "";
@@ -247,26 +218,26 @@ export { installedClientModules, bootInstalledClientModules };
247
218
 
248
219
  // Vite-only: this Set-based source-type filter exists solely to drive optimizeDeps include/exclude decisions.
249
220
  function resolveClientOptimizeExcludeSpecifiers(clientModules = []) {
250
- const moduleDescriptors = normalizeClientModuleDescriptors(clientModules);
221
+ const modulePackageMetadataEntries = normalizeClientModulePackageMetadataEntries(clientModules);
251
222
  return sortStrings(
252
223
  [
253
- ...moduleDescriptors
224
+ ...modulePackageMetadataEntries
254
225
  .filter((entry) => LOCAL_PACKAGE_SOURCE_TYPES.has(entry.sourceType))
255
226
  .flatMap((entry) => [entry.packageId, `${entry.packageId}/shared`, `${entry.packageId}/client`]),
256
- ...moduleDescriptors.flatMap((entry) => entry.descriptorClientOptimizeExcludeSpecifiers || [])
227
+ ...modulePackageMetadataEntries.flatMap((entry) => entry.packageMetadataClientOptimizeExcludeSpecifiers || [])
257
228
  ]
258
229
  );
259
230
  }
260
231
 
261
232
  function resolveClientOptimizeIncludeSpecifiers(clientModules = [], excludeSpecifiers = []) {
262
- const moduleDescriptors = normalizeClientModuleDescriptors(clientModules);
233
+ const modulePackageMetadataEntries = normalizeClientModulePackageMetadataEntries(clientModules);
263
234
  const excluded = new Set(sortStrings(excludeSpecifiers));
264
235
  return sortStrings(
265
236
  [
266
- ...moduleDescriptors
237
+ ...modulePackageMetadataEntries
267
238
  .filter((entry) => !LOCAL_PACKAGE_SOURCE_TYPES.has(entry.sourceType))
268
239
  .map((entry) => `${entry.packageId}/client`),
269
- ...moduleDescriptors.flatMap((entry) => entry.descriptorClientOptimizeIncludeSpecifiers || [])
240
+ ...modulePackageMetadataEntries.flatMap((entry) => entry.packageMetadataClientOptimizeIncludeSpecifiers || [])
270
241
  ].filter((specifier) => !excluded.has(specifier))
271
242
  );
272
243
  }
@@ -283,7 +254,7 @@ function resolveClientRuntimeDedupeSpecifiers(userResolveConfig = {}) {
283
254
  return sortStrings([...userDedupe, ...CLIENT_RUNTIME_DEDUPE_SPECIFIERS]);
284
255
  }
285
256
 
286
- function createJskitClientBootstrapPlugin({ lockPath = ".jskit/lock.json" } = {}) {
257
+ function createJskitClientBootstrapPlugin() {
287
258
  let appRoot = process.cwd();
288
259
  let localPackages = Object.freeze([]);
289
260
  let resolvePackageSpecifier = null;
@@ -295,17 +266,14 @@ function createJskitClientBootstrapPlugin({ lockPath = ".jskit/lock.json" } = {}
295
266
  async config(userConfig = {}) {
296
267
  appRoot = process.cwd();
297
268
  const clientModules = await resolveInstalledClientModules({
298
- appRoot,
299
- lockPath
269
+ appRoot
300
270
  });
301
271
  const localScopePackageIds = await resolveLocalScopePackageIds({
302
- appRoot,
303
- lockPath
272
+ appRoot
304
273
  });
305
274
  const userResolve = normalizeObject(userConfig.resolve);
306
275
  localPackages = await resolveLocalPackageSources({
307
- appRoot,
308
- lockPath
276
+ appRoot
309
277
  });
310
278
  const clientExcludeSpecifiers = resolveClientOptimizeExcludeSpecifiers(clientModules);
311
279
  const localScopeExcludeSpecifiers = resolveLocalScopeOptimizeExcludeSpecifiers(localScopePackageIds);
@@ -364,8 +332,7 @@ function createJskitClientBootstrapPlugin({ lockPath = ".jskit/lock.json" } = {}
364
332
  }
365
333
 
366
334
  const clientModules = await resolveInstalledClientModules({
367
- appRoot,
368
- lockPath
335
+ appRoot
369
336
  });
370
337
 
371
338
  return createVirtualModuleSource(clientModules);