@peers-app/peers-sdk 0.28.4 → 0.28.6

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.
@@ -10,7 +10,6 @@ export declare class UserContext {
10
10
  readonly ephemeral?: boolean | undefined;
11
11
  readonly deviceId: Observable<string>;
12
12
  readonly currentlyActiveGroupId: Observable<string | undefined>;
13
- readonly reloadPackagesOnPageRefresh: Observable<boolean>;
14
13
  readonly groupIds: Observable<string[]>;
15
14
  readonly userDataContext: DataContext;
16
15
  readonly groupDataContexts: Map<string, DataContext>;
@@ -15,7 +15,6 @@ class UserContext {
15
15
  ephemeral;
16
16
  deviceId = (0, observable_1.observable)("");
17
17
  currentlyActiveGroupId = (0, observable_1.observable)();
18
- reloadPackagesOnPageRefresh = (0, observable_1.observable)(false);
19
18
  groupIds = (0, observable_1.observable)([]);
20
19
  userDataContext;
21
20
  groupDataContexts = new Map();
@@ -167,7 +166,7 @@ class UserContext {
167
166
  // const persistentVars: PersistentVarsTable = await this.userDataContext.tableContainer.getTableByName(persistentVarsMetaData.name) as PersistentVarsTable;
168
167
  const persistentVars = (0, data_1.PersistentVars)(this.userDataContext);
169
168
  const vars = await persistentVars.list({
170
- name: { $in: ["thisDeviceId", "currentlyActiveGroupId", "reloadPackagesOnPageRefresh"] },
169
+ name: { $in: ["thisDeviceId", "currentlyActiveGroupId"] },
171
170
  });
172
171
  if (this.disposed) {
173
172
  return;
@@ -192,18 +191,7 @@ class UserContext {
192
191
  this._currentlyActiveGroupIdPVar = currentlyActiveGroupIdPVar;
193
192
  this.currentlyActiveGroupId(currentlyActiveGroupIdPVar());
194
193
  this.observableSubscriptions.push((0, observable_1.linkObservables)(currentlyActiveGroupIdPVar, this.currentlyActiveGroupId));
195
- const reloadPackagesOnPageRefreshPVar = (0, data_1.deviceVar)("reloadPackagesOnPageRefresh", {
196
- defaultValue: false,
197
- dbValue: varDbValues.reloadPackagesOnPageRefresh,
198
- userContext: this,
199
- });
200
- this.reloadPackagesOnPageRefresh(reloadPackagesOnPageRefreshPVar());
201
- this.observableSubscriptions.push((0, observable_1.linkObservables)(reloadPackagesOnPageRefreshPVar, this.reloadPackagesOnPageRefresh));
202
- await Promise.all([
203
- deviceIdPVar.loadingPromise,
204
- currentlyActiveGroupIdPVar.loadingPromise,
205
- reloadPackagesOnPageRefreshPVar.loadingPromise,
206
- ]);
194
+ await Promise.all([deviceIdPVar.loadingPromise, currentlyActiveGroupIdPVar.loadingPromise]);
207
195
  }
208
196
  /**
209
197
  * Load the signed-in user's `Users` row from the personal data context.
@@ -143,8 +143,6 @@ export declare class ContractRegistry {
143
143
  } | undefined;
144
144
  /** Get the stored contract definition (regardless of active provider). */
145
145
  getDefinition(contractId: string, version: number): IContractDefinition | undefined;
146
- /** Replace the stored definition for a contract (e.g. to freeze a dev contract). */
147
- updateDefinition(contractId: string, version: number, definition: IContractDefinition): void;
148
146
  /** Get all contract keys provided by a package. */
149
147
  getContractKeysForPackage(packageId: string): string[];
150
148
  /**
@@ -349,18 +349,6 @@ class ContractRegistry {
349
349
  getDefinition(contractId, version) {
350
350
  return this.definitions.get((0, types_1.contractKey)(contractId, version));
351
351
  }
352
- /** Replace the stored definition for a contract (e.g. to freeze a dev contract). */
353
- updateDefinition(contractId, version, definition) {
354
- const key = (0, types_1.contractKey)(contractId, version);
355
- this.definitions.set(key, definition);
356
- // Also update any active/all providers that reference this definition
357
- const providers = this.allProviders.get(key);
358
- if (providers) {
359
- for (const p of providers) {
360
- p.definition = definition;
361
- }
362
- }
363
- }
364
352
  /** Get all contract keys provided by a package. */
365
353
  getContractKeysForPackage(packageId) {
366
354
  return this.packageContracts.get(packageId) ?? [];
@@ -238,7 +238,5 @@ export declare function Devices(dataContext?: DataContext): import("..").Table<{
238
238
  serverUrl?: string | undefined;
239
239
  ownerSignature?: string | undefined;
240
240
  }>;
241
- /** Relay server URLs trusted by the active group. */
242
- export declare const trustedServers: import("./persistent-vars").PersistentVar<string[]>;
243
241
  /** Persistent identifier for the current physical/runtime device. */
244
242
  export declare const thisDeviceId: import("./persistent-vars").PersistentVar<string | undefined>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.thisDeviceId = exports.trustedServers = exports.deviceHandshakeSchema = exports.handshakeFrameCryptoSchema = exports.deviceInfoSchema = exports.deviceSchema = exports.displayNameSchema = exports.DISPLAY_NAME_MAX_LENGTH = void 0;
3
+ exports.thisDeviceId = exports.deviceHandshakeSchema = exports.handshakeFrameCryptoSchema = exports.deviceInfoSchema = exports.deviceSchema = exports.displayNameSchema = exports.DISPLAY_NAME_MAX_LENGTH = void 0;
4
4
  exports.deviceOwnerStatement = deviceOwnerStatement;
5
5
  exports.isDeviceOwnerSigned = isDeviceOwnerSigned;
6
6
  exports.Devices = Devices;
@@ -99,9 +99,5 @@ const metaData = {
99
99
  function Devices(dataContext) {
100
100
  return (0, user_context_singleton_1.getTableContainer)(dataContext).getTable(metaData, exports.deviceSchema);
101
101
  }
102
- /** Relay server URLs trusted by the active group. */
103
- exports.trustedServers = (0, persistent_vars_1.groupVar)("trustedServers", {
104
- defaultValue: ["https://peers.app"],
105
- });
106
102
  /** Persistent identifier for the current physical/runtime device. */
107
103
  exports.thisDeviceId = (0, persistent_vars_1.deviceVar)("thisDeviceId");
@@ -66,6 +66,4 @@ export declare function Packages(dataContext?: DataContext): PackagesTable;
66
66
  export declare const packagesRootDir = "~/peers/packages";
67
67
  /** Device preference controlling package reloads when the UI refreshes. */
68
68
  export declare const reloadPackagesOnPageRefresh: import("./persistent-vars").PersistentVar<boolean>;
69
- /** Device preference enabling automatic peers-core updates. */
70
- export declare const autoUpdatePeersCore: import("./persistent-vars").PersistentVar<boolean>;
71
69
  export {};
@@ -34,7 +34,7 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
34
34
  done = true;
35
35
  };
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.autoUpdatePeersCore = exports.reloadPackagesOnPageRefresh = exports.packagesRootDir = exports.PackagesTable = void 0;
37
+ exports.reloadPackagesOnPageRefresh = exports.packagesRootDir = exports.PackagesTable = void 0;
38
38
  exports.Packages = Packages;
39
39
  const zod_1 = require("zod");
40
40
  const context_1 = require("../context");
@@ -152,5 +152,3 @@ exports.packagesRootDir = "~/peers/packages";
152
152
  exports.reloadPackagesOnPageRefresh = (0, persistent_vars_1.deviceVar)("reloadPackagesOnPageRefresh", {
153
153
  defaultValue: true,
154
154
  });
155
- /** Device preference enabling automatic peers-core updates. */
156
- exports.autoUpdatePeersCore = (0, persistent_vars_1.deviceVar)("autoUpdatePeersCore", { defaultValue: true });
@@ -141,7 +141,11 @@ export declare class Connection {
141
141
  /** Round-trip time in milliseconds. @throws if the connection is not verified */
142
142
  ping(): Promise<number>;
143
143
  private closed;
144
- /** Notifies the peer (best effort, 100 ms) then tears down the local side. */
144
+ /**
145
+ * Notifies the peer (best effort, 100 ms) then tears down the local side. A socket that has
146
+ * already disconnected skips the courtesy: the peer can't receive it and its reply never
147
+ * comes, so waiting would only hold the teardown for the full 100 ms.
148
+ */
145
149
  close(): Promise<void>;
146
150
  }
147
151
  /** Normalizes a peer address for transport and security comparisons. */
@@ -560,18 +560,24 @@ class Connection {
560
560
  return Date.now() - startTime;
561
561
  }
562
562
  closed = false;
563
- /** Notifies the peer (best effort, 100 ms) then tears down the local side. */
563
+ /**
564
+ * Notifies the peer (best effort, 100 ms) then tears down the local side. A socket that has
565
+ * already disconnected skips the courtesy: the peer can't receive it and its reply never
566
+ * comes, so waiting would only hold the teardown for the full 100 ms.
567
+ */
564
568
  async close() {
565
569
  if (this.closed)
566
570
  return;
567
571
  this.closed = true;
568
- await Promise.race([
569
- this.emit("close").catch((_err) => {
570
- // swallow error
571
- // console.error('Error sending close event to remote device', err);
572
- }),
573
- (0, utils_1.sleep)(100),
574
- ]);
572
+ if (this.socket.connected !== false) {
573
+ await Promise.race([
574
+ this.emit("close").catch((_err) => {
575
+ // swallow error
576
+ // console.error('Error sending close event to remote device', err);
577
+ }),
578
+ (0, utils_1.sleep)(100),
579
+ ]);
580
+ }
575
581
  this.closeLocal();
576
582
  }
577
583
  }
@@ -46,6 +46,7 @@ export declare function generatePackageManifest(buildOptions?: IPackageBuildOpti
46
46
  export declare function packageManifest(buildOptions?: IPackageBuildOptions): Promise<IIsolatedPackageManifest>;
47
47
  /**
48
48
  * Generate the manifest, bundle the provider for the sandbox, and write `dist/package.bundle.js`.
49
+ * Packages with only screens have an empty provider source and run no worker.
49
50
  *
50
51
  * @param buildOptions - Package root, declaration entry, and output directory.
51
52
  */
@@ -129,23 +129,25 @@ async function loadModule(options, entry) {
129
129
  function validateManifest(manifest, providerSource = "void 0;") {
130
130
  (0, isolated_artifact_1.validateIsolatedPackageArtifact)({ manifest: structuredClone(manifest), providerSource }, { strict: true });
131
131
  }
132
- /** The package's manifest from its declarations, validated. */
133
- async function validManifest(options) {
132
+ /** The package's definition and manifest, validated together. */
133
+ async function validPackage(options) {
134
134
  // frozen-contracts.json gives the shapes of older versions a contract also implements.
135
- const manifest = (0, manifest_1.buildPackageManifest)(await loadDefinition(options), {
135
+ const definition = await loadDefinition(options);
136
+ const manifest = (0, manifest_1.buildPackageManifest)(definition, {
136
137
  frozen: await (0, freeze_contracts_1.readFrozenContracts)(options.root),
137
138
  });
138
139
  validateManifest(manifest);
139
- return manifest;
140
+ return { definition, manifest };
140
141
  }
141
142
  /** The package's manifest, validated and checked against the contracts it froze. */
142
- async function checkedManifest(options) {
143
- const manifest = await validManifest(options);
144
- await (0, freeze_contracts_1.assertFrozenContracts)(options.root, manifest);
145
- return manifest;
143
+ async function checkedPackage(options) {
144
+ const result = await validPackage(options);
145
+ await (0, freeze_contracts_1.assertFrozenContracts)(options.root, result.manifest);
146
+ return result;
146
147
  }
147
148
  async function writeManifest(options) {
148
- return saveManifest(options, await checkedManifest(options));
149
+ const { manifest } = await checkedPackage(options);
150
+ return saveManifest(options, manifest);
149
151
  }
150
152
  async function saveManifest(options, manifest) {
151
153
  const manifestPath = path.join(options.outDir, "manifest.json");
@@ -229,18 +231,25 @@ async function generatePackageManifest(buildOptions = {}) {
229
231
  * @param buildOptions - Package root and declaration entry.
230
232
  */
231
233
  async function packageManifest(buildOptions = {}) {
232
- return validManifest(resolveOptions(buildOptions));
234
+ return (await validPackage(resolveOptions(buildOptions))).manifest;
233
235
  }
234
236
  /**
235
237
  * Generate the manifest, bundle the provider for the sandbox, and write `dist/package.bundle.js`.
238
+ * Packages with only screens have an empty provider source and run no worker.
236
239
  *
237
240
  * @param buildOptions - Package root, declaration entry, and output directory.
238
241
  */
239
242
  async function buildPackage(buildOptions = {}) {
240
243
  const options = resolveOptions(buildOptions);
241
- const manifest = await checkedManifest(options);
242
- const output = await options.esbuild.build(providerBuildOptions(options, manifest));
243
- const providerSource = output.outputFiles?.[0]?.text ?? "";
244
+ const { definition, manifest } = await checkedPackage(options);
245
+ const hasProvider = definition.provides.length > 0 ||
246
+ definition.tables.length > 0 ||
247
+ definition.startHooks.length > 0 ||
248
+ definition.stopHooks.length > 0;
249
+ const output = hasProvider
250
+ ? await options.esbuild.build(providerBuildOptions(options, manifest))
251
+ : undefined;
252
+ const providerSource = output?.outputFiles?.[0]?.text ?? "";
244
253
  const artifactPath = await writeArtifact(options, manifest, providerSource);
245
254
  const { manifestPath } = await saveManifest(options, manifest);
246
255
  return { manifest, manifestPath, artifactPath, providerChars: providerSource.length };
@@ -254,7 +263,7 @@ async function buildPackage(buildOptions = {}) {
254
263
  */
255
264
  async function watchPackage(buildOptions = {}, onBuild = () => undefined) {
256
265
  const options = resolveOptions(buildOptions);
257
- const manifest = await validManifest(options);
266
+ const { manifest } = await validPackage(options);
258
267
  let mode = manifest.executionMode ?? "sandbox";
259
268
  let disposed = false;
260
269
  let restart = Promise.resolve();
@@ -10,7 +10,7 @@ export declare function deriveRepoSlug(url: string): string;
10
10
  * build it, and register the dev bundle in the database.
11
11
  *
12
12
  * Prerequisites (git, and Node.js/npm unless `skipBuild`) are validated up front.
13
- * If the target directory already exists and contains a valid package, delegates
14
- * to {@link installPackageFromBundles} instead of re-cloning.
13
+ * If the target directory already exists and contains a valid package, registers
14
+ * its signing identity and installs its bundles without re-cloning or building.
15
15
  */
16
16
  export declare function clonePackage(dataContext: DataContext, deps: IPackageInstallerDeps, opts: IClonePackageOpts): Promise<IClonePackageResult>;
@@ -6,6 +6,7 @@ const packages_1 = require("../data/packages");
6
6
  const persistent_vars_1 = require("../data/persistent-vars");
7
7
  const system_ids_1 = require("../system-ids");
8
8
  const utils_1 = require("../utils");
9
+ const package_creator_1 = require("./package-creator");
9
10
  const package_dev_tools_1 = require("./package-dev-tools");
10
11
  const package_installer_1 = require("./package-installer");
11
12
  /**
@@ -28,8 +29,8 @@ function autoDetectDisabled(remoteRepo) {
28
29
  * build it, and register the dev bundle in the database.
29
30
  *
30
31
  * Prerequisites (git, and Node.js/npm unless `skipBuild`) are validated up front.
31
- * If the target directory already exists and contains a valid package, delegates
32
- * to {@link installPackageFromBundles} instead of re-cloning.
32
+ * If the target directory already exists and contains a valid package, registers
33
+ * its signing identity and installs its bundles without re-cloning or building.
33
34
  */
34
35
  async function clonePackage(dataContext, deps, opts) {
35
36
  // 1. Validate prerequisites before cloning so a missing toolchain does not leave a partial repo.
@@ -37,25 +38,19 @@ async function clonePackage(dataContext, deps, opts) {
37
38
  // 2. Resolve location
38
39
  const location = opts.location ?? deps.resolvePath(deps.packagesRootDir, deriveRepoSlug(opts.remoteRepo));
39
40
  // 3. Check if directory already exists
40
- if (await deps.fs.exists(location)) {
41
+ const directoryExists = await deps.fs.exists(location);
42
+ if (directoryExists) {
41
43
  const info = await (0, package_installer_1.getPackageInfo)(deps, location);
42
- if (info.packageId && (0, utils_1.isid)(info.packageId)) {
43
- const result = await (0, package_installer_1.installPackageFromBundles)(dataContext, deps, info.packageId, {
44
- localPath: location,
45
- });
46
- return {
47
- packageId: info.packageId,
48
- localPath: location,
49
- remoteRepo: opts.remoteRepo,
50
- packageVersion: result.packageVersion,
51
- };
44
+ if (!info.packageId || !(0, utils_1.isid)(info.packageId)) {
45
+ throw new Error(`Directory already exists at ${location} but does not contain a valid Peers package (missing peers.packageId)`);
52
46
  }
53
- throw new Error(`Directory already exists at ${location} but does not contain a valid Peers package (missing peers.packageId)`);
54
47
  }
55
48
  // 4. Clone
56
- await deps.shell.exec(`git clone ${opts.remoteRepo} ${location}`);
49
+ if (!directoryExists) {
50
+ await deps.shell.exec(`git clone ${opts.remoteRepo} ${location}`);
51
+ }
57
52
  // 5. Install + build (unless skipBuild)
58
- if (!opts.skipBuild) {
53
+ if (!directoryExists && !opts.skipBuild) {
59
54
  try {
60
55
  await deps.shell.exec("npm install", { cwd: location });
61
56
  await deps.shell.exec("npm run build", { cwd: location });
@@ -80,17 +75,42 @@ async function clonePackage(dataContext, deps, opts) {
80
75
  await deps.fs.writeFile(packageJsonPath, JSON.stringify(packageObj, null, 2));
81
76
  }
82
77
  // 7. Register package record
83
- const disabled = opts.disabled ?? autoDetectDisabled(opts.remoteRepo);
84
- await (0, packages_1.Packages)(dataContext).signAndSave({
78
+ const existing = await (0, packages_1.Packages)(dataContext).get(packageId);
79
+ const userContext = dataContext.userContext;
80
+ let existingPublishPublicKey = existing?.publishPublicKey;
81
+ if (!existingPublishPublicKey) {
82
+ for (const sourceContext of [
83
+ userContext.userDataContext,
84
+ ...userContext.groupDataContexts.values(),
85
+ ]) {
86
+ if (sourceContext.dataContextId === dataContext.dataContextId)
87
+ continue;
88
+ const sourcePackage = await (0, packages_1.Packages)(sourceContext).get(packageId);
89
+ if (sourcePackage?.publishPublicKey?.trim()) {
90
+ existingPublishPublicKey = sourcePackage.publishPublicKey;
91
+ break;
92
+ }
93
+ }
94
+ }
95
+ const publishPublicKey = await (0, package_creator_1.ensurePackageSigningKey)({
96
+ personalContext: userContext.userDataContext,
85
97
  packageId,
86
- name: info.name,
87
- description: info.description ?? "",
88
- createdBy: system_ids_1.peersRootUserId,
89
- disabled,
90
- remoteRepo: opts.remoteRepo,
91
- publishPublicKey: "",
92
- signature: "",
93
- }, { restoreIfDeleted: true, saveAsSnapshot: true });
98
+ packageName: info.name,
99
+ existingPublishPublicKey,
100
+ resolveSigningPublicKey: opts.resolveSigningPublicKey,
101
+ });
102
+ await (0, packages_1.Packages)(dataContext).signAndSave(existing
103
+ ? { ...existing, publishPublicKey }
104
+ : {
105
+ packageId,
106
+ name: info.name,
107
+ description: info.description ?? "",
108
+ createdBy: system_ids_1.peersRootUserId,
109
+ disabled: opts.disabled ?? autoDetectDisabled(opts.remoteRepo),
110
+ remoteRepo: opts.remoteRepo,
111
+ publishPublicKey,
112
+ signature: "",
113
+ }, { restoreIfDeleted: true, saveAsSnapshot: true });
94
114
  // Set the packageLocalPath device var
95
115
  const pvar = (0, persistent_vars_1.groupDeviceVar)(`packageLocalPath_${packageId}`, {
96
116
  defaultValue: deps.packagesRootDir,
@@ -84,7 +84,7 @@ export interface ICreatePackageOpts {
84
84
  /**
85
85
  * The user's personal DataContext for storing the signing key as a secret `userVar`.
86
86
  * If omitted, keypair generation is skipped (useful for tests or contexts where
87
- * personal storage isn't available). The migration script backfills these.
87
+ * personal storage isn't available).
88
88
  */
89
89
  personalContext?: import("../context/data-context").DataContext;
90
90
  /**
@@ -131,6 +131,8 @@ export interface IClonePackageOpts {
131
131
  disabled?: boolean;
132
132
  /** Skip `npm install` + `npm run build` (useful if pre-built). */
133
133
  skipBuild?: boolean;
134
+ /** Host-only recovery of an encrypted personal signing secret's public key. */
135
+ resolveSigningPublicKey?: ICreatePackageOpts["resolveSigningPublicKey"];
134
136
  }
135
137
  /** Result of {@link clonePackage}. */
136
138
  export interface IClonePackageResult {
@@ -31,14 +31,3 @@ export declare function installContractPackage(dataContext: DataContext, package
31
31
  * including UI-only packages with zero contracts.
32
32
  */
33
33
  export declare function extractPackageDefinition(bundleExports: Record<string, unknown>): IPackageDefinitionResult | undefined;
34
- /**
35
- * Determines whether a bundle exports a contract-based package definition,
36
- * indicating it should be installed via the new contract-aware path.
37
- */
38
- export declare function hasPackageDefinition(bundleExports: Record<string, unknown>): boolean;
39
- /**
40
- * Finalize all dev contracts for a package when promoting to stable.
41
- * Removes `devTag` from each contract in the registry, freezing their shapes.
42
- * Returns the list of contract keys that were finalized.
43
- */
44
- export declare function finalizeContractsForPromotion(registry: ContractRegistry, packageId: string): string[];
@@ -2,8 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.installContractPackage = installContractPackage;
4
4
  exports.extractPackageDefinition = extractPackageDefinition;
5
- exports.hasPackageDefinition = hasPackageDefinition;
6
- exports.finalizeContractsForPromotion = finalizeContractsForPromotion;
7
5
  const registry_1 = require("../contracts/registry");
8
6
  const tool_catalog_1 = require("../contracts/tool-catalog");
9
7
  /**
@@ -90,30 +88,3 @@ function extractPackageDefinition(bundleExports) {
90
88
  }
91
89
  return undefined;
92
90
  }
93
- /**
94
- * Determines whether a bundle exports a contract-based package definition,
95
- * indicating it should be installed via the new contract-aware path.
96
- */
97
- function hasPackageDefinition(bundleExports) {
98
- return extractPackageDefinition(bundleExports) !== undefined;
99
- }
100
- /**
101
- * Finalize all dev contracts for a package when promoting to stable.
102
- * Removes `devTag` from each contract in the registry, freezing their shapes.
103
- * Returns the list of contract keys that were finalized.
104
- */
105
- function finalizeContractsForPromotion(registry, packageId) {
106
- const finalized = [];
107
- const contractKeys = registry.getContractKeysForPackage(packageId);
108
- for (const key of contractKeys) {
109
- const [contractId, versionStr] = key.split("@");
110
- const version = Number(versionStr);
111
- const def = registry.getDefinition(contractId, version);
112
- if (def?.devTag === "dev") {
113
- const frozenDef = { ...def, devTag: undefined };
114
- registry.updateDefinition(contractId, version, frozenDef);
115
- finalized.push(key);
116
- }
117
- }
118
- return finalized;
119
- }
@@ -236,6 +236,7 @@ export interface IIsolatedPackageManifest {
236
236
  */
237
237
  export interface IIsolatedPackageArtifact {
238
238
  manifest: IIsolatedPackageManifest;
239
+ /** Empty for a guest API 3 package with no provided contracts, tables, or worker hooks. */
239
240
  providerSource: string;
240
241
  }
241
242
  /** Outcome of installing one isolated artifact into a host runtime. */
@@ -788,7 +788,13 @@ function validateIsolatedPackageArtifact(artifact, options = {}) {
788
788
  "executionMode",
789
789
  "guestApi",
790
790
  ], "manifest");
791
- if (typeof providerSource !== "string" || providerSource.trim() === "") {
791
+ if (typeof providerSource !== "string" ||
792
+ (providerSource.trim() === "" &&
793
+ !(manifest.guestApi === 3 &&
794
+ Array.isArray(manifest.provides) &&
795
+ manifest.provides.length === 0 &&
796
+ (manifest.tables === undefined ||
797
+ (Array.isArray(manifest.tables) && manifest.tables.length === 0))))) {
792
798
  throw new Error("Package artifact.providerSource must be a non-empty string");
793
799
  }
794
800
  if (manifest.executionMode !== undefined &&
@@ -803,7 +809,8 @@ function validateIsolatedPackageArtifact(artifact, options = {}) {
803
809
  if (typeof manifest.version !== "string" || manifest.version.trim() === "") {
804
810
  throw new Error("package version is required");
805
811
  }
806
- if (!Array.isArray(manifest.provides) || manifest.provides.length === 0) {
812
+ if (!Array.isArray(manifest.provides) ||
813
+ (manifest.provides.length === 0 && manifest.guestApi !== 3)) {
807
814
  throw new Error("package must provide at least one contract");
808
815
  }
809
816
  if (!Array.isArray(manifest.consumes)) {
@@ -27,7 +27,6 @@ export interface IRemoteLogsQueryInput {
27
27
  }
28
28
  /** RPC methods implemented by the trusted local server/main process. */
29
29
  export declare const rpcServerCalls: {
30
- ping: (msg: string) => Promise<string>;
31
30
  encryptData: (value: string, groupId?: string) => Promise<string>;
32
31
  tableMethodCall: (dataContextId: string, tableName: string, methodName: string, ...args: any[]) => Promise<any>;
33
32
  getFileContents: (fileId: string, encoding?: BufferEncoding) => Promise<string>;
@@ -74,7 +73,6 @@ export declare const rpcServerCalls: {
74
73
  };
75
74
  /** RPC methods implemented by renderer/frontend clients. */
76
75
  export declare const rpcClientCalls: {
77
- ping: (msg: string) => Promise<string>;
78
76
  emitEvent: (event: IEventData) => Promise<boolean>;
79
77
  };
80
78
  /** Name of a server/main-process RPC method. */
package/dist/rpc-types.js CHANGED
@@ -12,7 +12,6 @@ function rpcStub(rpcName) {
12
12
  }
13
13
  /** RPC methods implemented by the trusted local server/main process. */
14
14
  exports.rpcServerCalls = {
15
- ping: async (msg) => `pong: ${msg}`,
16
15
  encryptData: rpcStub("encryptData"),
17
16
  tableMethodCall: rpcStub("tableMethodCall"),
18
17
  // TODO lock this down so not all code can get any file contents
@@ -49,7 +48,6 @@ exports.rpcServerCalls = {
49
48
  };
50
49
  /** RPC methods implemented by renderer/frontend clients. */
51
50
  exports.rpcClientCalls = {
52
- ping: async (msg) => `pong: ${msg}`,
53
51
  // emitEvent: rpcStub('emitEvent') as ((event: IEventData) => Promise<boolean>),
54
52
  emitEvent: ((..._args) => Promise.resolve(false)),
55
53
  };
@@ -70,8 +68,3 @@ function setSingleProcessClient(value) {
70
68
  function isSingleProcessClient() {
71
69
  return _singleProcessClient;
72
70
  }
73
- if (exports.isClient) {
74
- if (typeof window !== "undefined") {
75
- window.rpc = exports.rpcServerCalls;
76
- }
77
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-sdk",
3
- "version": "0.28.4",
3
+ "version": "0.28.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-sdk.git"