@peers-app/peers-sdk 0.19.9 → 0.19.10

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.
@@ -136,7 +136,11 @@ async function installAllPackageBundles(dataContext, deps) {
136
136
  if (pkg.disabled)
137
137
  continue;
138
138
  try {
139
- await installPackageFromBundles(dataContext, deps, pkg.packageId);
139
+ const localPath = await getPackageLocalPath(pkg.packageId, dataContext, deps);
140
+ if (!(await hasPackageJson(deps, localPath))) {
141
+ continue;
142
+ }
143
+ await installPackageFromBundles(dataContext, deps, pkg.packageId, { localPath });
140
144
  }
141
145
  catch (err) {
142
146
  console.error(`[package-installer] Failed to install bundles for ${pkg.name} (${pkg.packageId}):`, err);
@@ -210,18 +214,65 @@ async function getPackageInfo(deps, localPath) {
210
214
  }
211
215
  return info;
212
216
  }
213
- /**
214
- * Resolve the local filesystem path for a package based on device vars.
215
- * Awaits the loading promise to ensure the DB-stored value is available
216
- * before reading. Falls back to `{packagesRootDir}`.
217
- */
218
- async function getPackageLocalPath(packageId, dataContext, deps) {
217
+ async function readPackageLocalPathPvar(packageId, dataContext, deps) {
219
218
  const pvar = (0, persistent_vars_1.groupDeviceVar)(`packageLocalPath_${packageId}`, {
220
219
  defaultValue: deps.packagesRootDir,
221
220
  dataContext,
222
221
  });
223
222
  await pvar.loadingPromise;
224
- return deps.resolvePath(pvar() ?? deps.packagesRootDir);
223
+ const value = pvar();
224
+ if (!value || value === deps.packagesRootDir) {
225
+ return undefined;
226
+ }
227
+ return deps.resolvePath(value);
228
+ }
229
+ async function hasPackageJson(deps, localPath) {
230
+ return deps.fs.exists(deps.resolvePath(localPath, "package.json"));
231
+ }
232
+ function packageNameToFolderSlug(name) {
233
+ let slug = name.replace(/[^a-zA-Z0-9]/g, " ");
234
+ slug = slug.replace(/\s+/g, " ").trim();
235
+ return (0, utils_1.camelCaseToHyphens)(slug);
236
+ }
237
+ /**
238
+ * Resolve the local filesystem path for a package based on device vars.
239
+ * Awaits the loading promise to ensure the DB-stored value is available
240
+ * before reading. Falls back to paths from other data contexts on this device,
241
+ * then to `{packagesRootDir}/{name-slug}` when that directory exists.
242
+ */
243
+ async function getPackageLocalPath(packageId, dataContext, deps) {
244
+ const candidates = [];
245
+ const currentPath = await readPackageLocalPathPvar(packageId, dataContext, deps);
246
+ if (currentPath) {
247
+ candidates.push(currentPath);
248
+ }
249
+ const userContext = dataContext.userContext;
250
+ if (userContext && dataContext.dataContextId !== userContext.userId) {
251
+ const personalPath = await readPackageLocalPathPvar(packageId, userContext.userDataContext, deps);
252
+ if (personalPath) {
253
+ candidates.push(personalPath);
254
+ }
255
+ }
256
+ if (userContext) {
257
+ for (const dc of userContext.groupDataContexts.values()) {
258
+ if (dc.dataContextId === dataContext.dataContextId)
259
+ continue;
260
+ const groupPath = await readPackageLocalPathPvar(packageId, dc, deps);
261
+ if (groupPath) {
262
+ candidates.push(groupPath);
263
+ }
264
+ }
265
+ }
266
+ const pkg = await (0, packages_1.Packages)(dataContext).get(packageId);
267
+ if (pkg) {
268
+ candidates.push(deps.resolvePath(deps.packagesRootDir, packageNameToFolderSlug(pkg.name)));
269
+ }
270
+ for (const path of candidates) {
271
+ if (await hasPackageJson(deps, path)) {
272
+ return path;
273
+ }
274
+ }
275
+ return candidates[0] ?? deps.packagesRootDir;
225
276
  }
226
277
  /** Extract the first non-heading paragraph from a README as a description. */
227
278
  function extractReadmeDescription(readme) {
@@ -658,9 +658,46 @@ describe("getPackageLocalPath (via installPackageFromBundles)", () => {
658
658
  const deps = makeMockDeps({});
659
659
  const dc = mockDataContext();
660
660
  mockGroupDeviceVar.mockReturnValue(Object.assign(() => undefined, { loadingPromise: Promise.resolve() }));
661
+ mockGetPkg.mockResolvedValue(undefined);
661
662
  // Since resolvePath just joins, and packagesRootDir = "/packages",
662
663
  // the resolved path will be "/packages" — which won't have bundles.
663
664
  // This should throw "Package directory does not exist"
664
665
  await expect((0, package_installer_1.installPackageFromBundles)(dc, deps, packageId, { skipLoad: true, skipResolve: true })).rejects.toThrow("Package directory does not exist");
665
666
  });
667
+ it("falls back to personal context packageLocalPath in another group context", async () => {
668
+ const packageId = (0, utils_1.newid)();
669
+ const personalPath = `/packages/my-widget`;
670
+ const files = {
671
+ [`${personalPath}/package.json`]: JSON.stringify({ name: "My Widget", version: "1.0.0" }),
672
+ [`${personalPath}/dist/package.bundle.js`]: "code",
673
+ };
674
+ const deps = makeMockDeps(files);
675
+ const personalDc = { dataContextId: "user123" };
676
+ const groupDc = mockDataContext({
677
+ dataContextId: "group456",
678
+ userContext: {
679
+ userId: "user123",
680
+ userDataContext: personalDc,
681
+ groupDataContexts: new Map([["group456", { dataContextId: "group456" }]]),
682
+ },
683
+ });
684
+ mockGroupDeviceVar.mockImplementation((_name, opts) => {
685
+ const path = opts?.dataContext?.dataContextId === "user123" ? personalPath : deps.packagesRootDir;
686
+ return Object.assign(() => path, { loadingPromise: Promise.resolve() });
687
+ });
688
+ mockFindOnePV.mockResolvedValue(undefined);
689
+ mockFindOneFile.mockResolvedValue(undefined);
690
+ mockGetPkg.mockResolvedValue({
691
+ packageId,
692
+ name: "My Widget",
693
+ description: "",
694
+ signature: "",
695
+ createdBy: "u",
696
+ });
697
+ await (0, package_installer_1.installPackageFromBundles)(groupDc, deps, packageId, {
698
+ skipLoad: true,
699
+ skipResolve: true,
700
+ });
701
+ expect(mockSignAndSavePV).toHaveBeenCalled();
702
+ });
666
703
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-sdk",
3
- "version": "0.19.9",
3
+ "version": "0.19.10",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-sdk.git"