@peers-app/peers-sdk 0.19.10 → 0.19.12
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.
- package/dist/package-installer/index.d.ts +1 -0
- package/dist/package-installer/index.js +1 -0
- package/dist/package-installer/package-seed-installer.d.ts +18 -2
- package/dist/package-installer/package-seed-installer.js +41 -18
- package/dist/package-installer/peers-core-installer.d.ts +49 -0
- package/dist/package-installer/peers-core-installer.js +126 -0
- package/package.json +1 -1
|
@@ -23,4 +23,5 @@ __exportStar(require("./package-publisher"), exports);
|
|
|
23
23
|
__exportStar(require("./package-remote-checker"), exports);
|
|
24
24
|
__exportStar(require("./package-seed-installer"), exports);
|
|
25
25
|
__exportStar(require("./package-tarball"), exports);
|
|
26
|
+
__exportStar(require("./peers-core-installer"), exports);
|
|
26
27
|
__exportStar(require("./types"), exports);
|
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
* Called at group creation time (not on every startup).
|
|
6
6
|
*/
|
|
7
7
|
import type { DataContext } from "../context/data-context";
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import { type IPackage } from "../data/packages";
|
|
9
|
+
/**
|
|
10
|
+
* Metadata needed to create (or backfill) a {@link IPackage} record, without
|
|
11
|
+
* any version/bundle data. Shared by {@link ensurePackageRecord} and
|
|
12
|
+
* {@link seedPackageInContext}.
|
|
13
|
+
*/
|
|
14
|
+
export interface IEnsurePackageRecordOpts {
|
|
10
15
|
packageId: string;
|
|
11
16
|
name: string;
|
|
12
17
|
description?: string;
|
|
@@ -16,6 +21,9 @@ export interface ISeedPackageOpts {
|
|
|
16
21
|
followVersionTags?: string;
|
|
17
22
|
updateUrl?: string;
|
|
18
23
|
remoteRepo?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Options for seeding a package into a data context. */
|
|
26
|
+
export interface ISeedPackageOpts extends IEnsurePackageRecordOpts {
|
|
19
27
|
/** Bundle data for the initial PackageVersion. */
|
|
20
28
|
version: string;
|
|
21
29
|
versionTag: string;
|
|
@@ -43,3 +51,11 @@ export interface ISeedPackageOpts {
|
|
|
43
51
|
* @returns true if seeding occurred, false if package already existed.
|
|
44
52
|
*/
|
|
45
53
|
export declare function seedPackageInContext(dataContext: DataContext, opts: ISeedPackageOpts): Promise<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Ensure a {@link IPackage} record exists in `dataContext`, creating it from
|
|
56
|
+
* `opts` when absent and backfilling any missing metadata defaults when
|
|
57
|
+
* present. Does not create or modify any PackageVersion.
|
|
58
|
+
*
|
|
59
|
+
* @returns The current (created or existing) Package record.
|
|
60
|
+
*/
|
|
61
|
+
export declare function ensurePackageRecord(dataContext: DataContext, opts: IEnsurePackageRecordOpts): Promise<IPackage>;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.seedPackageInContext = seedPackageInContext;
|
|
10
|
+
exports.ensurePackageRecord = ensurePackageRecord;
|
|
10
11
|
const package_versions_1 = require("../data/package-versions");
|
|
11
12
|
const packages_1 = require("../data/packages");
|
|
12
13
|
const utils_1 = require("../utils");
|
|
@@ -21,20 +22,35 @@ const package_installer_1 = require("./package-installer");
|
|
|
21
22
|
* @returns true if seeding occurred, false if package already existed.
|
|
22
23
|
*/
|
|
23
24
|
async function seedPackageInContext(dataContext, opts) {
|
|
24
|
-
const
|
|
25
|
-
const existingPkg = await pkgTable.get(opts.packageId);
|
|
25
|
+
const existingPkg = await (0, packages_1.Packages)(dataContext).get(opts.packageId);
|
|
26
26
|
if (existingPkg) {
|
|
27
27
|
// Package already exists — check if it has any version installed
|
|
28
|
-
const
|
|
29
|
-
const existingPvs = await pvTable.list({ packageId: opts.packageId });
|
|
28
|
+
const existingPvs = await (0, package_versions_1.PackageVersions)(dataContext).list({ packageId: opts.packageId });
|
|
30
29
|
if (existingPvs.length > 0) {
|
|
31
30
|
return false;
|
|
32
31
|
}
|
|
33
|
-
// Package record exists but no versions — install the initial PV
|
|
34
|
-
applyMissingSeedDefaults(existingPkg, opts);
|
|
35
|
-
return await installSeedVersion(dataContext, existingPkg, opts);
|
|
36
32
|
}
|
|
37
|
-
// Create Package record
|
|
33
|
+
// Create the Package record (or backfill missing defaults on an existing one),
|
|
34
|
+
// then install the initial PackageVersion from the bundle.
|
|
35
|
+
const pkg = await ensurePackageRecord(dataContext, opts);
|
|
36
|
+
return await installSeedVersion(dataContext, pkg, opts);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Ensure a {@link IPackage} record exists in `dataContext`, creating it from
|
|
40
|
+
* `opts` when absent and backfilling any missing metadata defaults when
|
|
41
|
+
* present. Does not create or modify any PackageVersion.
|
|
42
|
+
*
|
|
43
|
+
* @returns The current (created or existing) Package record.
|
|
44
|
+
*/
|
|
45
|
+
async function ensurePackageRecord(dataContext, opts) {
|
|
46
|
+
const pkgTable = (0, packages_1.Packages)(dataContext);
|
|
47
|
+
const existing = await pkgTable.get(opts.packageId);
|
|
48
|
+
if (existing) {
|
|
49
|
+
if (applyMissingRecordDefaults(existing, opts)) {
|
|
50
|
+
return await pkgTable.signAndSave(existing, { saveAsSnapshot: true });
|
|
51
|
+
}
|
|
52
|
+
return existing;
|
|
53
|
+
}
|
|
38
54
|
const pkg = {
|
|
39
55
|
packageId: opts.packageId,
|
|
40
56
|
name: opts.name,
|
|
@@ -48,17 +64,24 @@ async function seedPackageInContext(dataContext, opts) {
|
|
|
48
64
|
remoteRepo: opts.remoteRepo,
|
|
49
65
|
signature: "",
|
|
50
66
|
};
|
|
51
|
-
|
|
52
|
-
await installSeedVersion(dataContext, pkg, opts);
|
|
53
|
-
return true;
|
|
67
|
+
return pkgTable.signAndSave(pkg, { saveAsSnapshot: true });
|
|
54
68
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
/** Backfill missing metadata onto an existing record. Returns true if changed. */
|
|
70
|
+
function applyMissingRecordDefaults(pkg, opts) {
|
|
71
|
+
let changed = false;
|
|
72
|
+
const setIfEmpty = (key, value) => {
|
|
73
|
+
if (!pkg[key] && value) {
|
|
74
|
+
pkg[key] = value;
|
|
75
|
+
changed = true;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
setIfEmpty("description", opts.description);
|
|
79
|
+
setIfEmpty("publishPublicKey", opts.publishPublicKey);
|
|
80
|
+
setIfEmpty("versionFollowRange", opts.versionFollowRange);
|
|
81
|
+
setIfEmpty("followVersionTags", opts.followVersionTags);
|
|
82
|
+
setIfEmpty("updateUrl", opts.updateUrl);
|
|
83
|
+
setIfEmpty("remoteRepo", opts.remoteRepo);
|
|
84
|
+
return changed;
|
|
62
85
|
}
|
|
63
86
|
async function installSeedVersion(dataContext, pkg, opts) {
|
|
64
87
|
// Save bundle files (deduped by hash)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* peers-core install orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Ensures the `peers-core` package is installed into a given data context using
|
|
5
|
+
* a layered strategy:
|
|
6
|
+
*
|
|
7
|
+
* 1. No-op if peers-core already has a version in the context.
|
|
8
|
+
* 2. Copy from another context that already has it (used for new groups).
|
|
9
|
+
* 3. Install from the remote S3 `updateUrl` (used for new users; group fallback).
|
|
10
|
+
* 4. Seed the bundled copy shipped with the host app (offline fallback).
|
|
11
|
+
*
|
|
12
|
+
* Callers shape the strategy by what they pass: new users provide no
|
|
13
|
+
* `copyFromContexts` (remote-first), while new groups pass sibling contexts so
|
|
14
|
+
* they copy first and fall back to the remote `updateUrl`.
|
|
15
|
+
*/
|
|
16
|
+
import type { DataContext } from "../context/data-context";
|
|
17
|
+
import type { UserContext } from "../context/user-context";
|
|
18
|
+
import type { IHttpDeps } from "./types";
|
|
19
|
+
/** Bundled peers-core sources shipped with the host app (offline fallback). */
|
|
20
|
+
export interface IPeersCoreBundle {
|
|
21
|
+
version: string;
|
|
22
|
+
versionTag: string;
|
|
23
|
+
packageBundleCode: string;
|
|
24
|
+
routesBundleCode?: string;
|
|
25
|
+
uiBundleCode?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Options controlling {@link ensurePeersCore}'s install strategy. */
|
|
28
|
+
export interface IEnsurePeersCoreOpts {
|
|
29
|
+
/** HTTP interface for remote install. Omit to disable the remote path. */
|
|
30
|
+
http?: IHttpDeps;
|
|
31
|
+
/** S3 `updateUrl` for peers-core. Required for the remote path. */
|
|
32
|
+
updateUrl?: string;
|
|
33
|
+
/** Contexts to copy an already-installed peers-core from (e.g. personal + other groups). */
|
|
34
|
+
copyFromContexts?: DataContext[];
|
|
35
|
+
/** Bundled sources used as the offline fallback. */
|
|
36
|
+
bundle?: IPeersCoreBundle;
|
|
37
|
+
/** When true, try the bundled seed before the remote install (dev electron). */
|
|
38
|
+
preferBundle?: boolean;
|
|
39
|
+
/** Version tag to follow for the remote install. Defaults to `"stable"`. */
|
|
40
|
+
followTag?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Ensure peers-core is installed (with a usable, loaded version) in
|
|
44
|
+
* `dataContext`, applying the layered strategy described in the module docs.
|
|
45
|
+
*
|
|
46
|
+
* @returns true if an install occurred, false if it was already present or no
|
|
47
|
+
* strategy succeeded.
|
|
48
|
+
*/
|
|
49
|
+
export declare function ensurePeersCore(userContext: UserContext, dataContext: DataContext, opts: IEnsurePeersCoreOpts): Promise<boolean>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* peers-core install orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Ensures the `peers-core` package is installed into a given data context using
|
|
6
|
+
* a layered strategy:
|
|
7
|
+
*
|
|
8
|
+
* 1. No-op if peers-core already has a version in the context.
|
|
9
|
+
* 2. Copy from another context that already has it (used for new groups).
|
|
10
|
+
* 3. Install from the remote S3 `updateUrl` (used for new users; group fallback).
|
|
11
|
+
* 4. Seed the bundled copy shipped with the host app (offline fallback).
|
|
12
|
+
*
|
|
13
|
+
* Callers shape the strategy by what they pass: new users provide no
|
|
14
|
+
* `copyFromContexts` (remote-first), while new groups pass sibling contexts so
|
|
15
|
+
* they copy first and fall back to the remote `updateUrl`.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.ensurePeersCore = ensurePeersCore;
|
|
19
|
+
const package_version_resolver_1 = require("../data/package-version-resolver");
|
|
20
|
+
const package_versions_1 = require("../data/package-versions");
|
|
21
|
+
const packages_1 = require("../data/packages");
|
|
22
|
+
const packages_utils_1 = require("../data/packages.utils");
|
|
23
|
+
const system_ids_1 = require("../system-ids");
|
|
24
|
+
const package_remote_checker_1 = require("./package-remote-checker");
|
|
25
|
+
const package_seed_installer_1 = require("./package-seed-installer");
|
|
26
|
+
const PEERS_CORE_NAME = "peers-core";
|
|
27
|
+
const PEERS_CORE_DESCRIPTION = "Core system package for Peers platform";
|
|
28
|
+
/**
|
|
29
|
+
* Ensure peers-core is installed (with a usable, loaded version) in
|
|
30
|
+
* `dataContext`, applying the layered strategy described in the module docs.
|
|
31
|
+
*
|
|
32
|
+
* @returns true if an install occurred, false if it was already present or no
|
|
33
|
+
* strategy succeeded.
|
|
34
|
+
*/
|
|
35
|
+
async function ensurePeersCore(userContext, dataContext, opts) {
|
|
36
|
+
const existingPvs = await (0, package_versions_1.PackageVersions)(dataContext).list({ packageId: system_ids_1.peersCorePackageId });
|
|
37
|
+
if (existingPvs.length > 0)
|
|
38
|
+
return false;
|
|
39
|
+
if (await tryCopyFromContexts(dataContext, opts.copyFromContexts)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
const tryRemote = () => tryRemoteInstall(userContext, dataContext, opts);
|
|
43
|
+
const tryBundle = () => tryBundleSeed(userContext, dataContext, opts);
|
|
44
|
+
const strategies = opts.preferBundle ? [tryBundle, tryRemote] : [tryRemote, tryBundle];
|
|
45
|
+
for (const strategy of strategies) {
|
|
46
|
+
if (await strategy())
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
/** Copy peers-core from the first sibling context that already has it, then load it. */
|
|
52
|
+
async function tryCopyFromContexts(dataContext, copyFromContexts) {
|
|
53
|
+
if (!copyFromContexts?.length)
|
|
54
|
+
return false;
|
|
55
|
+
for (const source of copyFromContexts) {
|
|
56
|
+
if (source.dataContextId === dataContext.dataContextId)
|
|
57
|
+
continue;
|
|
58
|
+
try {
|
|
59
|
+
const sourcePkg = await (0, packages_1.Packages)(source).get(system_ids_1.peersCorePackageId);
|
|
60
|
+
if (!sourcePkg?.activePackageVersionId)
|
|
61
|
+
continue;
|
|
62
|
+
await (0, packages_utils_1.copyPackageToAnotherDataContext)(system_ids_1.peersCorePackageId, source, dataContext);
|
|
63
|
+
const copied = await (0, packages_1.Packages)(dataContext).get(system_ids_1.peersCorePackageId);
|
|
64
|
+
if (copied) {
|
|
65
|
+
await (0, package_version_resolver_1.resolveDevicePackageVersion)(copied, dataContext, { force: true });
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
console.warn(`[peers-core-installer] copy from ${source.dataContextId} failed:`, err);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/** Create the Package record (if needed) and install the latest remote version. */
|
|
76
|
+
async function tryRemoteInstall(userContext, dataContext, opts) {
|
|
77
|
+
if (!opts.http || !opts.updateUrl)
|
|
78
|
+
return false;
|
|
79
|
+
try {
|
|
80
|
+
const pkg = await (0, package_seed_installer_1.ensurePackageRecord)(dataContext, {
|
|
81
|
+
packageId: system_ids_1.peersCorePackageId,
|
|
82
|
+
name: PEERS_CORE_NAME,
|
|
83
|
+
description: PEERS_CORE_DESCRIPTION,
|
|
84
|
+
createdBy: userContext.userId,
|
|
85
|
+
publishPublicKey: system_ids_1.peersCorePublishPublicKey,
|
|
86
|
+
versionFollowRange: "latest",
|
|
87
|
+
followVersionTags: "stable",
|
|
88
|
+
updateUrl: opts.updateUrl,
|
|
89
|
+
remoteRepo: system_ids_1.peersCorePackageRepoUrl,
|
|
90
|
+
});
|
|
91
|
+
const result = await (0, package_remote_checker_1.checkAndInstallPackageRemoteVersion)(dataContext, pkg, opts.followTag ?? "stable", opts.http);
|
|
92
|
+
return !!result;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
console.warn("[peers-core-installer] remote install failed:", err);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Seed the bundled peers-core sources as an offline fallback. */
|
|
100
|
+
async function tryBundleSeed(userContext, dataContext, opts) {
|
|
101
|
+
if (!opts.bundle)
|
|
102
|
+
return false;
|
|
103
|
+
try {
|
|
104
|
+
return await (0, package_seed_installer_1.seedPackageInContext)(dataContext, {
|
|
105
|
+
packageId: system_ids_1.peersCorePackageId,
|
|
106
|
+
name: PEERS_CORE_NAME,
|
|
107
|
+
description: PEERS_CORE_DESCRIPTION,
|
|
108
|
+
createdBy: userContext.userId,
|
|
109
|
+
publishPublicKey: system_ids_1.peersCorePublishPublicKey,
|
|
110
|
+
versionFollowRange: "latest",
|
|
111
|
+
followVersionTags: "stable",
|
|
112
|
+
updateUrl: opts.updateUrl,
|
|
113
|
+
remoteRepo: system_ids_1.peersCorePackageRepoUrl,
|
|
114
|
+
version: opts.bundle.version,
|
|
115
|
+
versionTag: opts.bundle.versionTag,
|
|
116
|
+
packageBundleCode: opts.bundle.packageBundleCode,
|
|
117
|
+
routesBundleCode: opts.bundle.routesBundleCode,
|
|
118
|
+
uiBundleCode: opts.bundle.uiBundleCode,
|
|
119
|
+
loadAfterSeed: true,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
console.warn("[peers-core-installer] bundle seed failed:", err);
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|