@peers-app/peers-sdk 0.29.0 → 0.29.1
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.
|
@@ -8,7 +8,10 @@ export declare const PACKAGES_CONTRACT_VERSION = 1;
|
|
|
8
8
|
export interface IPackagesHostCapabilities {
|
|
9
9
|
/** The host can read package folders: import, create, clone, and reload from disk. */
|
|
10
10
|
fileSystem: boolean;
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* The host can create and link a remote repository (`linkRemoteRepo` without a URL). Recording
|
|
13
|
+
* a given URL needs no host tooling.
|
|
14
|
+
*/
|
|
12
15
|
linkRemote: boolean;
|
|
13
16
|
/** The host can install the default packages into a context (`installDefaultPackages`). */
|
|
14
17
|
installDefaults: boolean;
|
|
@@ -172,6 +175,14 @@ export declare function packageVersionPromotionTargets(versionTag: string | unde
|
|
|
172
175
|
* @param target - Input as typed.
|
|
173
176
|
*/
|
|
174
177
|
export declare function isPackageRepositoryUrl(target: string): boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Whether a URL may be recorded as a package's source (`Packages.remoteRepo`) by
|
|
180
|
+
* `linkRemoteRepo`: an `https://` or `http://` URL, a `git@host:` remote, or a Git package
|
|
181
|
+
* remote, `peers://<groupId>/<repoId>`. No whitespace; at most 2,048 characters.
|
|
182
|
+
*
|
|
183
|
+
* @param url - The URL to record.
|
|
184
|
+
*/
|
|
185
|
+
export declare function isPackageSourceUrl(url: string): boolean;
|
|
175
186
|
/** Typed consumer proxy for System Packages v1. */
|
|
176
187
|
export interface IPackagesConsumer extends IContractConsumerBase {
|
|
177
188
|
tools: {
|
|
@@ -223,9 +234,14 @@ export interface IPackagesConsumer extends IContractConsumerBase {
|
|
|
223
234
|
}): Promise<IPackageOperationResult>;
|
|
224
235
|
/** Re-read every package folder on this device and reload packages whose bundles changed. */
|
|
225
236
|
reloadAllPackages(): Promise<IReloadAllPackagesResult>;
|
|
226
|
-
/**
|
|
237
|
+
/**
|
|
238
|
+
* Record a package's source repository. With `remoteRepo` (see {@link isPackageSourceUrl}),
|
|
239
|
+
* record that URL; otherwise create a remote repository with the host's tooling and link it.
|
|
240
|
+
* A package that already has a source keeps it and the result carries a warning.
|
|
241
|
+
*/
|
|
227
242
|
linkRemoteRepo(input: {
|
|
228
243
|
packageId: string;
|
|
244
|
+
remoteRepo?: string;
|
|
229
245
|
}): Promise<IPackageOperationResult>;
|
|
230
246
|
/** Remove a package from the group and unload it here. */
|
|
231
247
|
uninstallPackage(input: {
|
|
@@ -4,6 +4,7 @@ exports.PACKAGES_CONTRACT_VERSION = void 0;
|
|
|
4
4
|
exports.packageGroupVersionWarning = packageGroupVersionWarning;
|
|
5
5
|
exports.packageVersionPromotionTargets = packageVersionPromotionTargets;
|
|
6
6
|
exports.isPackageRepositoryUrl = isPackageRepositoryUrl;
|
|
7
|
+
exports.isPackageSourceUrl = isPackageSourceUrl;
|
|
7
8
|
exports.getPackagesContractDefinition = getPackagesContractDefinition;
|
|
8
9
|
const system_ids_1 = require("../../system-ids");
|
|
9
10
|
const field_type_1 = require("../../types/field-type");
|
|
@@ -43,6 +44,29 @@ function packageVersionPromotionTargets(versionTag) {
|
|
|
43
44
|
function isPackageRepositoryUrl(target) {
|
|
44
45
|
return /^(https?:\/\/|git@[^:/\s]+:)/.test(target.trim());
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Whether a URL may be recorded as a package's source (`Packages.remoteRepo`) by
|
|
49
|
+
* `linkRemoteRepo`: an `https://` or `http://` URL, a `git@host:` remote, or a Git package
|
|
50
|
+
* remote, `peers://<groupId>/<repoId>`. No whitespace; at most 2,048 characters.
|
|
51
|
+
*
|
|
52
|
+
* @param url - The URL to record.
|
|
53
|
+
*/
|
|
54
|
+
function isPackageSourceUrl(url) {
|
|
55
|
+
if (url.length > 2048 || /\s|\p{Cc}/u.test(url))
|
|
56
|
+
return false;
|
|
57
|
+
if (/^peers:\/\/[A-Za-z0-9]{25}\/[A-Za-z0-9]{25}$/.test(url))
|
|
58
|
+
return true;
|
|
59
|
+
if (/^git@[^:/\\]+:.+$/.test(url))
|
|
60
|
+
return true;
|
|
61
|
+
if (!/^https?:\/\//.test(url) || url.includes("\\"))
|
|
62
|
+
return false;
|
|
63
|
+
try {
|
|
64
|
+
return !!new URL(url).hostname;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
46
70
|
const field = (name, type, description, opts = {}) => ({ name, type, description, ...opts });
|
|
47
71
|
const packageIdField = field("packageId", field_type_1.FieldType.id, "Package id.");
|
|
48
72
|
const operationResultFields = [
|
|
@@ -162,8 +186,11 @@ function getPackagesContractDefinition() {
|
|
|
162
186
|
},
|
|
163
187
|
{
|
|
164
188
|
name: "linkRemoteRepo",
|
|
165
|
-
usageDescription: "
|
|
166
|
-
inputFields: [
|
|
189
|
+
usageDescription: "Record a package's source repository: the given URL, or one created with the host's tooling. A package that already has a source keeps it.",
|
|
190
|
+
inputFields: [
|
|
191
|
+
packageIdField,
|
|
192
|
+
field("remoteRepo", field_type_1.FieldType.string, "Record this URL (https://, git@host:, or a Git package peers:// URL) instead of creating a repository.", { optional: true }),
|
|
193
|
+
],
|
|
167
194
|
outputFields: operationResultFields,
|
|
168
195
|
},
|
|
169
196
|
{
|
|
@@ -330,11 +330,9 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
330
330
|
}
|
|
331
331
|
// ─── Drain / Backpressure ────────────────────────────────────────
|
|
332
332
|
// Single persistent drain handler to avoid leaking listeners
|
|
333
|
-
|
|
333
|
+
const drainWaiters = new Set();
|
|
334
334
|
peer.on("drain", () => {
|
|
335
|
-
|
|
336
|
-
const resolve = drainResolve;
|
|
337
|
-
drainResolve = null;
|
|
335
|
+
for (const resolve of drainWaiters) {
|
|
338
336
|
resolve();
|
|
339
337
|
}
|
|
340
338
|
});
|
|
@@ -351,15 +349,18 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
351
349
|
// Backpressure: wait for buffer to drain before sending more
|
|
352
350
|
while ((peer.getBufferedAmount?.() ?? 0) > config.highWaterMark) {
|
|
353
351
|
await new Promise((resolve) => {
|
|
354
|
-
|
|
352
|
+
const resume = () => {
|
|
353
|
+
clearInterval(timer);
|
|
354
|
+
drainWaiters.delete(resume);
|
|
355
|
+
resolve();
|
|
356
|
+
};
|
|
355
357
|
// Also poll as fallback (drain event might not fire on all transports)
|
|
356
358
|
const timer = setInterval(() => {
|
|
357
359
|
if ((peer.getBufferedAmount?.() ?? 0) <= config.lowWaterMark) {
|
|
358
|
-
|
|
359
|
-
drainResolve = null;
|
|
360
|
-
resolve();
|
|
360
|
+
resume();
|
|
361
361
|
}
|
|
362
362
|
}, 5);
|
|
363
|
+
drainWaiters.add(resume);
|
|
363
364
|
});
|
|
364
365
|
}
|
|
365
366
|
// A retired cipher must not fall back to a clear frame; the peer would close
|