swarm-deploy 0.0.0 → 0.2.0

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.
Files changed (148) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/LICENSE.md +201 -0
  3. package/NOTICE.md +13 -0
  4. package/README.md +1283 -0
  5. package/RELEASING.md +71 -0
  6. package/SECURITY.md +40 -0
  7. package/dist/abort.d.ts +16 -0
  8. package/dist/abort.js +52 -0
  9. package/dist/abort.js.map +1 -0
  10. package/dist/allowlist.d.ts +2 -0
  11. package/dist/allowlist.js +21 -0
  12. package/dist/allowlist.js.map +1 -0
  13. package/dist/bin/swarm-deploy.d.ts +2 -0
  14. package/dist/bin/swarm-deploy.js +41 -0
  15. package/dist/bin/swarm-deploy.js.map +1 -0
  16. package/dist/cli.d.ts +27 -0
  17. package/dist/cli.js +751 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/client.d.ts +111 -0
  20. package/dist/client.js +276 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/direct-dht.d.ts +81 -0
  23. package/dist/direct-dht.js +254 -0
  24. package/dist/direct-dht.js.map +1 -0
  25. package/dist/error-code.d.ts +15 -0
  26. package/dist/error-code.js +30 -0
  27. package/dist/error-code.js.map +1 -0
  28. package/dist/errors.d.ts +31 -0
  29. package/dist/errors.js +37 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/events-node.d.ts +2 -0
  32. package/dist/events-node.js +7 -0
  33. package/dist/events-node.js.map +1 -0
  34. package/dist/files.d.ts +32 -0
  35. package/dist/files.js +85 -0
  36. package/dist/files.js.map +1 -0
  37. package/dist/fs-node.d.ts +2 -0
  38. package/dist/fs-node.js +7 -0
  39. package/dist/fs-node.js.map +1 -0
  40. package/dist/hooks-module.d.ts +9 -0
  41. package/dist/hooks-module.js +118 -0
  42. package/dist/hooks-module.js.map +1 -0
  43. package/dist/hooks.d.ts +69 -0
  44. package/dist/hooks.js +88 -0
  45. package/dist/hooks.js.map +1 -0
  46. package/dist/identity.d.ts +7 -0
  47. package/dist/identity.js +50 -0
  48. package/dist/identity.js.map +1 -0
  49. package/dist/index.d.ts +12 -0
  50. package/dist/index.js +21 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/os-node.d.ts +2 -0
  53. package/dist/os-node.js +7 -0
  54. package/dist/os-node.js.map +1 -0
  55. package/dist/path-node.d.ts +2 -0
  56. package/dist/path-node.js +7 -0
  57. package/dist/path-node.js.map +1 -0
  58. package/dist/process-node.d.ts +2 -0
  59. package/dist/process-node.js +7 -0
  60. package/dist/process-node.js.map +1 -0
  61. package/dist/release.d.ts +26 -0
  62. package/dist/release.js +419 -0
  63. package/dist/release.js.map +1 -0
  64. package/dist/server.d.ts +239 -0
  65. package/dist/server.js +928 -0
  66. package/dist/server.js.map +1 -0
  67. package/dist/storage/atomic-file.d.ts +15 -0
  68. package/dist/storage/atomic-file.js +172 -0
  69. package/dist/storage/atomic-file.js.map +1 -0
  70. package/dist/storage/commit-journal.d.ts +120 -0
  71. package/dist/storage/commit-journal.js +417 -0
  72. package/dist/storage/commit-journal.js.map +1 -0
  73. package/dist/storage/commit-store.d.ts +307 -0
  74. package/dist/storage/commit-store.js +1691 -0
  75. package/dist/storage/commit-store.js.map +1 -0
  76. package/dist/storage/layout.d.ts +16 -0
  77. package/dist/storage/layout.js +409 -0
  78. package/dist/storage/layout.js.map +1 -0
  79. package/dist/storage/link-store.d.ts +70 -0
  80. package/dist/storage/link-store.js +363 -0
  81. package/dist/storage/link-store.js.map +1 -0
  82. package/dist/storage/recovery.d.ts +100 -0
  83. package/dist/storage/recovery.js +260 -0
  84. package/dist/storage/recovery.js.map +1 -0
  85. package/dist/storage/retention.d.ts +183 -0
  86. package/dist/storage/retention.js +619 -0
  87. package/dist/storage/retention.js.map +1 -0
  88. package/dist/storage/root-coordinator.d.ts +7 -0
  89. package/dist/storage/root-coordinator.js +27 -0
  90. package/dist/storage/root-coordinator.js.map +1 -0
  91. package/dist/storage/session-store.d.ts +2 -0
  92. package/dist/storage/session-store.js +7 -0
  93. package/dist/storage/session-store.js.map +1 -0
  94. package/dist/storage/tar-session-store.d.ts +147 -0
  95. package/dist/storage/tar-session-store.js +1044 -0
  96. package/dist/storage/tar-session-store.js.map +1 -0
  97. package/dist/storage/tree-fs.d.ts +44 -0
  98. package/dist/storage/tree-fs.js +580 -0
  99. package/dist/storage/tree-fs.js.map +1 -0
  100. package/dist/storage/tree-staging.d.ts +9 -0
  101. package/dist/storage/tree-staging.js +64 -0
  102. package/dist/storage/tree-staging.js.map +1 -0
  103. package/dist/storage/types.d.ts +77 -0
  104. package/dist/storage/types.js +3 -0
  105. package/dist/storage/types.js.map +1 -0
  106. package/dist/symlinks.d.ts +36 -0
  107. package/dist/symlinks.js +128 -0
  108. package/dist/symlinks.js.map +1 -0
  109. package/dist/tar-protocol/controls.d.ts +73 -0
  110. package/dist/tar-protocol/controls.js +291 -0
  111. package/dist/tar-protocol/controls.js.map +1 -0
  112. package/dist/tar-protocol/direct-wire.d.ts +43 -0
  113. package/dist/tar-protocol/direct-wire.js +194 -0
  114. package/dist/tar-protocol/direct-wire.js.map +1 -0
  115. package/dist/tar-protocol/extract.d.ts +18 -0
  116. package/dist/tar-protocol/extract.js +124 -0
  117. package/dist/tar-protocol/extract.js.map +1 -0
  118. package/dist/tar-protocol/hash.d.ts +10 -0
  119. package/dist/tar-protocol/hash.js +44 -0
  120. package/dist/tar-protocol/hash.js.map +1 -0
  121. package/dist/tar-protocol/lifecycle.d.ts +13 -0
  122. package/dist/tar-protocol/lifecycle.js +90 -0
  123. package/dist/tar-protocol/lifecycle.js.map +1 -0
  124. package/dist/tar-protocol/manifest.d.ts +58 -0
  125. package/dist/tar-protocol/manifest.js +312 -0
  126. package/dist/tar-protocol/manifest.js.map +1 -0
  127. package/dist/tar-protocol/tree-extract.d.ts +37 -0
  128. package/dist/tar-protocol/tree-extract.js +240 -0
  129. package/dist/tar-protocol/tree-extract.js.map +1 -0
  130. package/dist/tar-protocol/tree-manifest.d.ts +45 -0
  131. package/dist/tar-protocol/tree-manifest.js +277 -0
  132. package/dist/tar-protocol/tree-manifest.js.map +1 -0
  133. package/dist/tar-protocol/tree-path.d.ts +15 -0
  134. package/dist/tar-protocol/tree-path.js +68 -0
  135. package/dist/tar-protocol/tree-path.js.map +1 -0
  136. package/dist/tar-protocol/tree.d.ts +68 -0
  137. package/dist/tar-protocol/tree.js +269 -0
  138. package/dist/tar-protocol/tree.js.map +1 -0
  139. package/dist/tar-protocol/ustar.d.ts +36 -0
  140. package/dist/tar-protocol/ustar.js +167 -0
  141. package/dist/tar-protocol/ustar.js.map +1 -0
  142. package/dist/types.d.ts +61 -0
  143. package/dist/types.js +3 -0
  144. package/dist/types.js.map +1 -0
  145. package/dist/validation.d.ts +4 -0
  146. package/dist/validation.js +26 -0
  147. package/dist/validation.js.map +1 -0
  148. package/package.json +103 -1
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadHooksModule = loadHooksModule;
7
+ const _path_1 = __importDefault(require("#path"));
8
+ const errors_js_1 = require("./errors.js");
9
+ const hooks_js_1 = require("./hooks.js");
10
+ const HOOK_NAMES = ['beforeCommit', 'afterCommit', 'onFailure'];
11
+ const HOOK_EXTENSIONS = ['.js', '.mjs', '.cjs'];
12
+ function rejected(modulePath, reason) {
13
+ // Only the basename and a fixed reason: module text, stack traces, causes and
14
+ // directory names can carry secrets and must never reach the operator log.
15
+ return new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, `Unable to load hooks module ${_path_1.default.basename(modulePath)}: ${reason}`);
16
+ }
17
+ function fileUrl(file) {
18
+ if (/^[A-Za-z]:[\\/]/.test(file)) {
19
+ return `file:///${encodeURI(file.replace(/\\/g, '/')).replace(/[?#]/g, encodeURIComponent)}`;
20
+ }
21
+ return `file://${encodeURI(file).replace(/[?#]/g, encodeURIComponent)}`;
22
+ }
23
+ function isRecord(value) {
24
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
25
+ }
26
+ function hasOwn(value, name) {
27
+ return Object.prototype.hasOwnProperty.call(value, name);
28
+ }
29
+ /** Reads an error's string `code` without ever letting a hostile getter or proxy throw. */
30
+ function errorCode(error) {
31
+ try {
32
+ if ((typeof error !== 'object' && typeof error !== 'function') || error === null) {
33
+ return undefined;
34
+ }
35
+ const code = error.code;
36
+ return typeof code === 'string' ? code : undefined;
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ /**
43
+ * The default export's hook object, or `undefined` when the default is absent or not
44
+ * a plain object (function, primitive, null, array). Unwraps exactly one explicit
45
+ * `__esModule` interop level (TypeScript-compiled CommonJS).
46
+ */
47
+ function defaultHooks(namespace) {
48
+ if (!hasOwn(namespace, 'default'))
49
+ return undefined;
50
+ const fallback = namespace.default;
51
+ if (fallback === undefined)
52
+ return undefined;
53
+ if (!isRecord(fallback))
54
+ return undefined;
55
+ if (hasOwn(fallback, '__esModule') &&
56
+ fallback.__esModule === true &&
57
+ hasOwn(fallback, 'default')) {
58
+ const inner = fallback.default;
59
+ return isRecord(inner) ? inner : undefined;
60
+ }
61
+ return fallback;
62
+ }
63
+ /**
64
+ * Loads a JavaScript hooks module (`.js`, `.mjs` or `.cjs`) and returns the
65
+ * validated, frozen hook snapshot. Only `beforeCommit`, `afterCommit` and
66
+ * `onFailure` are picked, by own property name; other exports are ignored.
67
+ * Defined named exports take precedence over the default export's callbacks. Every failure is a fixed-message configuration
68
+ * error that never includes module content.
69
+ */
70
+ async function loadHooksModule(modulePath, cwd) {
71
+ if (typeof modulePath !== 'string' || modulePath.length === 0) {
72
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Invalid hooks module path');
73
+ }
74
+ if (typeof cwd !== 'string' || cwd.length === 0) {
75
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Invalid working directory');
76
+ }
77
+ const resolved = _path_1.default.resolve(cwd, modulePath);
78
+ // Checked before the import so an unsupported extension gives a precise
79
+ // startup error instead of whatever the runtime's loader happens to say.
80
+ if (!HOOK_EXTENSIONS.includes(_path_1.default.extname(resolved))) {
81
+ throw rejected(modulePath, 'unsupported module extension');
82
+ }
83
+ let namespace;
84
+ try {
85
+ namespace = (await import(fileUrl(resolved)));
86
+ }
87
+ catch (error) {
88
+ const code = errorCode(error);
89
+ if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {
90
+ throw rejected(modulePath, 'module not found');
91
+ }
92
+ throw rejected(modulePath, 'module failed to load');
93
+ }
94
+ try {
95
+ const merged = Object.create(null);
96
+ const fallback = defaultHooks(namespace);
97
+ for (const name of HOOK_NAMES) {
98
+ if (fallback !== undefined && hasOwn(fallback, name)) {
99
+ const value = fallback[name];
100
+ if (value !== undefined)
101
+ merged[name] = value;
102
+ }
103
+ if (hasOwn(namespace, name)) {
104
+ const value = namespace[name];
105
+ if (value !== undefined)
106
+ merged[name] = value;
107
+ }
108
+ }
109
+ const snapshot = (0, hooks_js_1.snapshotHooks)(merged);
110
+ if (Reflect.ownKeys(snapshot).length === 0)
111
+ throw new Error('empty');
112
+ return snapshot;
113
+ }
114
+ catch {
115
+ throw rejected(modulePath, 'invalid hooks exports');
116
+ }
117
+ }
118
+ //# sourceMappingURL=hooks-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-module.js","sourceRoot":"","sources":["../src/hooks-module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { type AbortSignalLike } from './abort.js';
2
+ import { SwarmDeployError } from './errors.js';
3
+ import type { ReleaseCoordinates } from './release.js';
4
+ import type { ArtifactKind } from './types.js';
5
+ export type HookFailurePhase = 'offer' | 'transfer' | 'verification' | 'beforeCommit' | 'commit' | 'afterCommit';
6
+ /** Immutable, secret-free description of the artifact a hook is observing. */
7
+ export interface HookArtifact {
8
+ name: string;
9
+ kind: ArtifactKind;
10
+ size: number;
11
+ /** The file digest, or the canonical tree digest. */
12
+ sha256: string;
13
+ transferId: string;
14
+ /** Present only for a directory artifact. */
15
+ entryCount?: number;
16
+ sourceParent?: string;
17
+ release?: ReleaseCoordinates;
18
+ }
19
+ export interface BeforeCommitContext {
20
+ artifact: HookArtifact;
21
+ /** Absolute path of the verified staging file. */
22
+ path: string;
23
+ resumed: boolean;
24
+ alreadyCommitted: false;
25
+ }
26
+ export interface AfterCommitContext {
27
+ artifact: HookArtifact;
28
+ /** Absolute path of the durably committed artifact. */
29
+ path: string;
30
+ resumed: boolean;
31
+ alreadyCommitted: boolean;
32
+ }
33
+ export interface HookFailureContext {
34
+ artifact: HookArtifact;
35
+ /** The best known absolute path, or `null` before one exists. */
36
+ path: string | null;
37
+ phase: HookFailurePhase;
38
+ resumed: boolean;
39
+ alreadyCommitted: boolean;
40
+ error: unknown;
41
+ }
42
+ export interface ServerHooks {
43
+ beforeCommit?(context: BeforeCommitContext): void | Promise<void>;
44
+ afterCommit?(context: AfterCommitContext): void | Promise<void>;
45
+ onFailure?(context: HookFailureContext): void | Promise<void>;
46
+ }
47
+ /**
48
+ * Validates and freezes caller hooks. Each property is read exactly once and no
49
+ * receiver is bound, so later mutation of the caller's object cannot change the
50
+ * callbacks a running server invokes.
51
+ */
52
+ export declare function snapshotHooks(hooks: ServerHooks | null | undefined): Readonly<ServerHooks>;
53
+ /**
54
+ * Wraps a failed callback. The message is fixed so callback text (which may
55
+ * carry secrets) never reaches the wire; the original error stays on `cause`.
56
+ */
57
+ export declare function hookError(phase: HookFailurePhase, cause: unknown): SwarmDeployError;
58
+ /**
59
+ * The error an `onFailure` hook should see: the raw exception for failures this
60
+ * module wrapped, otherwise the error unchanged. Only identity-tracked wrappers
61
+ * unwrap, so a forged `HOOK_FAILED` error cannot masquerade as one.
62
+ */
63
+ export declare function callbackError(error: unknown): unknown;
64
+ /**
65
+ * Calls a callback with no receiver and settles when it does or when the
66
+ * server aborts, whichever is first. A callback that outlives an abort keeps
67
+ * running detached; its later rejection is swallowed.
68
+ */
69
+ export declare function invokeHook<Context>(callback: (context: Context) => void | Promise<void>, context: Context, signal: AbortSignalLike): Promise<'completed' | 'aborted'>;
package/dist/hooks.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.snapshotHooks = snapshotHooks;
4
+ exports.hookError = hookError;
5
+ exports.callbackError = callbackError;
6
+ exports.invokeHook = invokeHook;
7
+ const abort_js_1 = require("./abort.js");
8
+ const errors_js_1 = require("./errors.js");
9
+ const WRAPPED_CALLBACK_ERRORS = new WeakMap();
10
+ const HOOK_NAMES = ['beforeCommit', 'afterCommit', 'onFailure'];
11
+ /**
12
+ * Validates and freezes caller hooks. Each property is read exactly once and no
13
+ * receiver is bound, so later mutation of the caller's object cannot change the
14
+ * callbacks a running server invokes.
15
+ */
16
+ function snapshotHooks(hooks) {
17
+ if (hooks === null || hooks === undefined)
18
+ return Object.freeze({});
19
+ if (typeof hooks !== 'object') {
20
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Invalid hooks');
21
+ }
22
+ for (const name of Reflect.ownKeys(hooks)) {
23
+ if (!HOOK_NAMES.includes(name)) {
24
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unknown hook');
25
+ }
26
+ }
27
+ const snapshot = {};
28
+ for (const name of HOOK_NAMES) {
29
+ const callback = hooks[name];
30
+ if (callback === undefined)
31
+ continue;
32
+ if (typeof callback !== 'function') {
33
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.PROTOCOL_INVALID, `Invalid ${name} hook`);
34
+ }
35
+ Object.defineProperty(snapshot, name, {
36
+ value: callback,
37
+ enumerable: true,
38
+ writable: false,
39
+ configurable: false
40
+ });
41
+ }
42
+ return Object.freeze(snapshot);
43
+ }
44
+ /**
45
+ * Wraps a failed callback. The message is fixed so callback text (which may
46
+ * carry secrets) never reaches the wire; the original error stays on `cause`.
47
+ */
48
+ function hookError(phase, cause) {
49
+ const error = new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.HOOK_FAILED, `Deployment hook failed during ${phase}`, cause);
50
+ WRAPPED_CALLBACK_ERRORS.set(error, cause);
51
+ return error;
52
+ }
53
+ /**
54
+ * The error an `onFailure` hook should see: the raw exception for failures this
55
+ * module wrapped, otherwise the error unchanged. Only identity-tracked wrappers
56
+ * unwrap, so a forged `HOOK_FAILED` error cannot masquerade as one.
57
+ */
58
+ function callbackError(error) {
59
+ return error instanceof errors_js_1.SwarmDeployError && WRAPPED_CALLBACK_ERRORS.has(error)
60
+ ? WRAPPED_CALLBACK_ERRORS.get(error)
61
+ : error;
62
+ }
63
+ /**
64
+ * Calls a callback with no receiver and settles when it does or when the
65
+ * server aborts, whichever is first. A callback that outlives an abort keeps
66
+ * running detached; its later rejection is swallowed.
67
+ */
68
+ async function invokeHook(callback, context, signal) {
69
+ let pending;
70
+ try {
71
+ pending = Promise.resolve(callback(context));
72
+ }
73
+ catch (cause) {
74
+ pending = Promise.reject(cause);
75
+ }
76
+ pending.catch(() => { });
77
+ let release = () => { };
78
+ const aborted = new Promise((resolve) => {
79
+ release = (0, abort_js_1.onAbort)(signal, () => resolve('aborted'));
80
+ });
81
+ try {
82
+ return await Promise.race([pending.then(() => 'completed'), aborted]);
83
+ }
84
+ finally {
85
+ release();
86
+ }
87
+ }
88
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { BinaryInput, KeyPair, PublicKey, Seed, SeedInput } from './types.js';
2
+ export type { BinaryInput, KeyPair };
3
+ export declare function parseSeed(value: string): Seed;
4
+ export declare function parsePublicKey(value: string): PublicKey;
5
+ export declare function generateSeed(): Seed;
6
+ export declare function keyPairFromSeed(seed: SeedInput): KeyPair;
7
+ export declare function publicKeyFromSeed(seed: SeedInput): PublicKey;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseSeed = parseSeed;
7
+ exports.parsePublicKey = parsePublicKey;
8
+ exports.generateSeed = generateSeed;
9
+ exports.keyPairFromSeed = keyPairFromSeed;
10
+ exports.publicKeyFromSeed = publicKeyFromSeed;
11
+ const b4a_1 = __importDefault(require("b4a"));
12
+ const sodium_native_1 = __importDefault(require("sodium-native"));
13
+ const errors_js_1 = require("./errors.js");
14
+ const CANONICAL_HEX64 = /^[0-9a-f]{64}$/;
15
+ function parseCanonicalHex(value, code) {
16
+ if (typeof value !== 'string' || !CANONICAL_HEX64.test(value)) {
17
+ throw new errors_js_1.SwarmDeployError(code, `Expected lowercase 64-character hex string`);
18
+ }
19
+ return b4a_1.default.from(value, 'hex');
20
+ }
21
+ function parseSeed(value) {
22
+ return parseCanonicalHex(value, errors_js_1.ERRORS.INVALID_SEED);
23
+ }
24
+ function parsePublicKey(value) {
25
+ return parseCanonicalHex(value, errors_js_1.ERRORS.INVALID_PUBLIC_KEY);
26
+ }
27
+ function generateSeed() {
28
+ const seed = b4a_1.default.allocUnsafe(32);
29
+ sodium_native_1.default.randombytes_buf(seed);
30
+ return seed;
31
+ }
32
+ function normalizeSeed(seed) {
33
+ if (typeof seed === 'string')
34
+ return parseSeed(seed);
35
+ if (!b4a_1.default.isBuffer(seed) || seed.byteLength !== 32) {
36
+ throw new errors_js_1.SwarmDeployError(errors_js_1.ERRORS.INVALID_SEED, 'Expected 32-byte seed');
37
+ }
38
+ return b4a_1.default.from(seed);
39
+ }
40
+ function keyPairFromSeed(seed) {
41
+ const normalized = normalizeSeed(seed);
42
+ const publicKey = b4a_1.default.alloc(32);
43
+ const secretKey = b4a_1.default.alloc(64);
44
+ sodium_native_1.default.crypto_sign_seed_keypair(publicKey, secretKey, normalized);
45
+ return { publicKey, secretKey };
46
+ }
47
+ function publicKeyFromSeed(seed) {
48
+ return keyPairFromSeed(seed).publicKey;
49
+ }
50
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,8CAAqB;AACrB,kEAAkC;AAClC,2CAAsD;AAKtD,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAExC,SAAS,iBAAiB,CACxB,KAAa,EACb,IAAmE;IAEnE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,4BAAgB,CAAC,IAAI,EAAE,4CAA4C,CAAC,CAAA;IAChF,CAAC;IACD,OAAO,aAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC/B,CAAC;AAED,mBAA0B,KAAa;IACrC,OAAO,iBAAiB,CAAC,KAAK,EAAE,kBAAM,CAAC,YAAY,CAAC,CAAA;AACtD,CAAC;AAED,wBAA+B,KAAa;IAC1C,OAAO,iBAAiB,CAAC,KAAK,EAAE,kBAAM,CAAC,kBAAkB,CAAC,CAAA;AAC5D,CAAC;AAED;IACE,MAAM,IAAI,GAAG,aAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IAChC,uBAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,aAAa,CAAC,IAAe;IACpC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;IACpD,IAAI,CAAC,aAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;QAClD,MAAM,IAAI,4BAAgB,CAAC,kBAAM,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAA;IAC1E,CAAC;IACD,OAAO,aAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACvB,CAAC;AAED,yBAAgC,IAAe;IAC7C,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,SAAS,GAAG,aAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC/B,MAAM,SAAS,GAAG,aAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC/B,uBAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IACjE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAA;AACjC,CAAC;AAED,2BAAkC,IAAe;IAC/C,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,CAAA;AACxC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { ERRORS, SwarmDeployError, type ErrorCode } from './errors.js';
2
+ export type { Binary, BinaryInput, Digest, FingerprintEvent, KeyPair, Logger, PublicKey, PublicKeyInput, Seed, SeedInput, ServerScheduler } from './types.js';
3
+ export { parseSeed, parsePublicKey, generateSeed, keyPairFromSeed, publicKeyFromSeed } from './identity.js';
4
+ export type { AfterCommitContext, BeforeCommitContext, HookArtifact, HookFailureContext, HookFailurePhase, ServerHooks } from './hooks.js';
5
+ export { fixedSeriesKey, type ReleaseCoordinates, type VersionGranularity } from './release.js';
6
+ export { parseAllowlist } from './allowlist.js';
7
+ export type { ArtifactKind } from './types.js';
8
+ export type { UploadTarget } from './files.js';
9
+ export type { SymlinkRule } from './symlinks.js';
10
+ export { Server, type AllowlistKey, type RecoveryEvent, type RetentionEvent, type ServerCloseEvent, type ServerConnectionEvent, type ServerEvent, type ServerEventName, type ServerEventMap, type ServerListeningEvent, type ServerOfferEvent, type ServerOptions, type ServerProgressEvent, type ServerTransferLifecycleEvent } from './server.js';
11
+ export { Client, type ClientEvent, type ClientEventMap, type ClientEventName, type ClientOfferEvent, type ClientOptions, type ClientProgressEvent, type ClientResultEvent, type ClientUploadResult, type UploadResult, type UploadStatus } from './client.js';
12
+ export type { StorageAdapter, StorageFileHandle, StorageMkdirOptions, StorageReadResult, StorageRmOptions, StorageStatFs, StorageStats, StorageWriteResult, SymlinkCapableStorage } from './storage/types.js';
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Client = exports.Server = exports.parseAllowlist = exports.fixedSeriesKey = exports.publicKeyFromSeed = exports.keyPairFromSeed = exports.generateSeed = exports.parsePublicKey = exports.parseSeed = exports.SwarmDeployError = exports.ERRORS = void 0;
4
+ var errors_js_1 = require("./errors.js");
5
+ Object.defineProperty(exports, "ERRORS", { enumerable: true, get: function () { return errors_js_1.ERRORS; } });
6
+ Object.defineProperty(exports, "SwarmDeployError", { enumerable: true, get: function () { return errors_js_1.SwarmDeployError; } });
7
+ var identity_js_1 = require("./identity.js");
8
+ Object.defineProperty(exports, "parseSeed", { enumerable: true, get: function () { return identity_js_1.parseSeed; } });
9
+ Object.defineProperty(exports, "parsePublicKey", { enumerable: true, get: function () { return identity_js_1.parsePublicKey; } });
10
+ Object.defineProperty(exports, "generateSeed", { enumerable: true, get: function () { return identity_js_1.generateSeed; } });
11
+ Object.defineProperty(exports, "keyPairFromSeed", { enumerable: true, get: function () { return identity_js_1.keyPairFromSeed; } });
12
+ Object.defineProperty(exports, "publicKeyFromSeed", { enumerable: true, get: function () { return identity_js_1.publicKeyFromSeed; } });
13
+ var release_js_1 = require("./release.js");
14
+ Object.defineProperty(exports, "fixedSeriesKey", { enumerable: true, get: function () { return release_js_1.fixedSeriesKey; } });
15
+ var allowlist_js_1 = require("./allowlist.js");
16
+ Object.defineProperty(exports, "parseAllowlist", { enumerable: true, get: function () { return allowlist_js_1.parseAllowlist; } });
17
+ var server_js_1 = require("./server.js");
18
+ Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return server_js_1.Server; } });
19
+ var client_js_1 = require("./client.js");
20
+ Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_js_1.Client; } });
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAsE;AAA7D,mGAAA,MAAM,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAcjC,6CAMsB;AALpB,wGAAA,SAAS,OAAA;AACT,6GAAA,cAAc,OAAA;AACd,2GAAA,YAAY,OAAA;AACZ,8GAAA,eAAe,OAAA;AACf,gHAAA,iBAAiB,OAAA;AAUnB,2CAA+F;AAAtF,4GAAA,cAAc,OAAA;AACvB,+CAA+C;AAAtC,8GAAA,cAAc,OAAA;AAIvB,yCAeoB;AAdlB,mGAAA,MAAM,OAAA;AAeR,yCAYoB;AAXlB,mGAAA,MAAM,OAAA"}
@@ -0,0 +1,2 @@
1
+ import os from 'node:os';
2
+ export = os;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const node_os_1 = __importDefault(require("node:os"));
6
+ module.exports = node_os_1.default;
7
+ //# sourceMappingURL=os-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"os-node.js","sourceRoot":"","sources":["../src/os-node.ts"],"names":[],"mappings":";;;;AAAA,sDAAwB;AAExB,iBAAS,iBAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ import path from 'node:path';
2
+ export = path;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const node_path_1 = __importDefault(require("node:path"));
6
+ module.exports = node_path_1.default;
7
+ //# sourceMappingURL=path-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-node.js","sourceRoot":"","sources":["../src/path-node.ts"],"names":[],"mappings":";;;;AAAA,0DAA4B;AAE5B,iBAAS,mBAAI,CAAA"}
@@ -0,0 +1,2 @@
1
+ import process from 'node:process';
2
+ export = process;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const node_process_1 = __importDefault(require("node:process"));
6
+ module.exports = node_process_1.default;
7
+ //# sourceMappingURL=process-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-node.js","sourceRoot":"","sources":["../src/process-node.ts"],"names":[],"mappings":";;;;AAAA,gEAAkC;AAElC,iBAAS,sBAAO,CAAA"}
@@ -0,0 +1,26 @@
1
+ export type VersionGranularity = 'major' | 'minor';
2
+ export interface ReleaseCoordinates {
3
+ series: string;
4
+ version?: string;
5
+ }
6
+ /** Protocol: artifact basenames are one safe path component, max 100 UTF-8 bytes (`+` disallowed). */
7
+ export declare const MAX_RELEASE_COMPONENT_BYTES = 100;
8
+ /**
9
+ * The persisted series of a template that captures no `{series}`.
10
+ *
11
+ * The template text itself cannot be the key: braces and slashes fail the
12
+ * commit-record basename rules, so every version-only pattern would reject at
13
+ * commit time. Hashing gives a safe 70-byte basename that is stable across
14
+ * restarts and identical on Node and Bare, and distinct templates that happen
15
+ * to describe the same literals stay distinct releases.
16
+ */
17
+ export declare function fixedSeriesKey(template: string): string;
18
+ export declare class ReleaseMatcher {
19
+ #private;
20
+ constructor(patterns: Iterable<string>);
21
+ get size(): number;
22
+ get hasVersionPattern(): boolean;
23
+ match(name: string, sourceParent?: string): ReleaseCoordinates | null;
24
+ }
25
+ export declare function compareReleaseVersions(left: string, right: string): number;
26
+ export declare function releaseVersionGroup(version: string, granularity: VersionGranularity): string;