nervur 0.21.0 → 0.21.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.
- package/README.md +7 -1
- package/dist/contract/index.js +2 -1
- package/dist/harbor/catalogue.js +11 -3
- package/dist/harbor/dock.js +6 -2
- package/dist/node/index.js +12 -4
- package/dist/proof/law.js +1 -1
- package/package.json +1 -1
- package/src/contract/index.ts +2 -1
- package/src/harbor/catalogue.ts +11 -4
- package/src/harbor/dock.ts +3 -1
- package/src/node/index.ts +11 -4
- package/src/proof/law.ts +1 -1
package/README.md
CHANGED
|
@@ -218,7 +218,11 @@ stands a ward under a seed you name, or a drawn one.
|
|
|
218
218
|
and every class between it and `Faculty`.
|
|
219
219
|
- **Entropy, Clock, Custody, Memory, Carrier, Loader.** The contracts a
|
|
220
220
|
terrain fulfils. Each has one suite, and every body that fulfils it
|
|
221
|
-
passes it.
|
|
221
|
+
passes it. `nervur/proof` hands you those suites and the unpacking
|
|
222
|
+
law's as scenes, a title and a function each, so a body of your own,
|
|
223
|
+
a store in a cloud or a secret of your platform's, runs them under
|
|
224
|
+
your own runner: `for (const [title, scene] of memoryScenes('Mine',
|
|
225
|
+
make, expect)) test(title, scene)`. `@nervur-org/s3` is one such body.
|
|
222
226
|
- **Harbor, Terrain, Dock, Catalogue, Registry, WardBeing.** The onion.
|
|
223
227
|
- **World, PointerTerrain** and the pointer bodies, `HeldLoader` among
|
|
224
228
|
them. A whole world with this package alone.
|
|
@@ -240,6 +244,8 @@ stands a ward under a seed you name, or a drawn one.
|
|
|
240
244
|
- **WebDialer, webFaculty**: Quo over the web, a post to `https://` or a
|
|
241
245
|
held line to `wss://`, in any engine with `fetch` and WebSocket.
|
|
242
246
|
`webServe` and `webGround`, from `nervur/http`, listen for it on Node.
|
|
247
|
+
`answerPost(harbor, listen, request)` answers one post and nothing
|
|
248
|
+
more, for a function that opens a harbor per request and closes it.
|
|
243
249
|
|
|
244
250
|
- **The relay**, `org.nervur.relay` and `org.nervur.relay-client`, in
|
|
245
251
|
every harbor: a harbor nobody can dial is reached through one that
|
package/dist/contract/index.js
CHANGED
|
@@ -18,7 +18,8 @@ export class Memory {
|
|
|
18
18
|
export class Custody {
|
|
19
19
|
}
|
|
20
20
|
// Code, by the name a harbor keeps for it, or null where this loader has
|
|
21
|
-
// none. Code
|
|
21
|
+
// none. Code it has that does not load throws, saying why. Code never
|
|
22
|
+
// crosses a door and never lives in a cell, so it is the
|
|
22
23
|
// one thing beside the seed a terrain hands in: a map, an import, a bundle.
|
|
23
24
|
export class Loader {
|
|
24
25
|
}
|
package/dist/harbor/catalogue.js
CHANGED
|
@@ -42,8 +42,14 @@ export class Catalogue extends Faculty {
|
|
|
42
42
|
// it. The rest stay out, each with its reason.
|
|
43
43
|
async wake() {
|
|
44
44
|
for (const [module, row] of Object.entries(this.#rows)) {
|
|
45
|
-
const loaded = await this.#harbor.load(row.from).catch(() =>
|
|
46
|
-
const refused = loaded
|
|
45
|
+
const loaded = await this.#harbor.load(row.from).catch((e) => e);
|
|
46
|
+
const refused = loaded instanceof Error
|
|
47
|
+
? loaded.message
|
|
48
|
+
: loaded === null
|
|
49
|
+
? `not found at ${row.from}`
|
|
50
|
+
: loaded.module !== module
|
|
51
|
+
? `${row.from} is module ${loaded.module}`
|
|
52
|
+
: this.#harbor.check([...this.#running.values(), loaded]);
|
|
47
53
|
if (refused === null)
|
|
48
54
|
this.#running.set(module, loaded);
|
|
49
55
|
else
|
|
@@ -54,7 +60,9 @@ export class Catalogue extends Faculty {
|
|
|
54
60
|
async add(args) {
|
|
55
61
|
if (!text(args.from))
|
|
56
62
|
return { error: 'from is text' };
|
|
57
|
-
const loaded = await this.#harbor.load(args.from);
|
|
63
|
+
const loaded = await this.#harbor.load(args.from).catch((e) => e);
|
|
64
|
+
if (loaded instanceof Error)
|
|
65
|
+
return { error: loaded.message };
|
|
58
66
|
if (loaded === null)
|
|
59
67
|
return { error: 'no such module' };
|
|
60
68
|
const running = new Map(this.#running);
|
package/dist/harbor/dock.js
CHANGED
|
@@ -126,8 +126,12 @@ export class Dock extends WardBeing {
|
|
|
126
126
|
}
|
|
127
127
|
async host(args) {
|
|
128
128
|
const name = args.ward;
|
|
129
|
-
if (!text(name)
|
|
130
|
-
return { error: '
|
|
129
|
+
if (!text(name))
|
|
130
|
+
return { error: 'ward is text' };
|
|
131
|
+
if (name === BOX)
|
|
132
|
+
return { error: 'box is the box ward' };
|
|
133
|
+
if (this.hosted.some((h) => h.ward === name))
|
|
134
|
+
return { error: `${name} is hosted already` };
|
|
131
135
|
if (args.seed !== undefined && !text(args.seed))
|
|
132
136
|
return { error: 'seed is text' };
|
|
133
137
|
const invitation = await this.stance.occupants.invite(name, { hosted: true });
|
package/dist/node/index.js
CHANGED
|
@@ -53,8 +53,10 @@ export const isFile = (from) => /^(\.{1,2}[\\/]|[\\/]|[A-Za-z]:[\\/])/.test(from
|
|
|
53
53
|
// Code from a file or an installed package: a module that exports
|
|
54
54
|
// `module`, `version` and `classes`, found again by where it was found, a
|
|
55
55
|
// file by its absolute path and a package by its name, resolved from each
|
|
56
|
-
// folder of `bases` in order. What
|
|
57
|
-
//
|
|
56
|
+
// folder of `bases` in order. What is not there, or exports no module, is
|
|
57
|
+
// none. Code that is there and does not import throws Node's reason, so
|
|
58
|
+
// whoever added it learns why; an ES module read as CommonJS says which
|
|
59
|
+
// field its package.json lacks.
|
|
58
60
|
export class ImportLoader extends Loader {
|
|
59
61
|
#bases;
|
|
60
62
|
constructor(bases = [process.cwd()]) {
|
|
@@ -69,8 +71,14 @@ export class ImportLoader extends Loader {
|
|
|
69
71
|
try {
|
|
70
72
|
exported = (await import(__rewriteRelativeImportExtension(pathToFileURL(found).href)));
|
|
71
73
|
}
|
|
72
|
-
catch {
|
|
73
|
-
|
|
74
|
+
catch (e) {
|
|
75
|
+
const said = e.message;
|
|
76
|
+
// The name itself is nowhere, as against code there that needs
|
|
77
|
+
// something that is not.
|
|
78
|
+
if (e.code === 'ERR_MODULE_NOT_FOUND' && said.includes(`'${found}'`))
|
|
79
|
+
return null;
|
|
80
|
+
const commonjs = e instanceof SyntaxError && /\b(export|import)\b/.test(said);
|
|
81
|
+
throw new Error(`${found} did not load: ${said}${commonjs ? '; it is an ES module read as CommonJS, so set "type": "module" in its package.json' : ''}`, { cause: e });
|
|
74
82
|
}
|
|
75
83
|
const { module, version, classes } = exported;
|
|
76
84
|
if (typeof module !== 'string' || typeof version !== 'string' || !Array.isArray(classes))
|
package/dist/proof/law.js
CHANGED
|
@@ -210,7 +210,7 @@ export const lawScenes = (t, expect) => [
|
|
|
210
210
|
expect.same(again.names, ['good']);
|
|
211
211
|
expect.same((await census(again)).failed, { wards: { bad: 'an entry the package did not seal' }, routes: {} });
|
|
212
212
|
expect.same(await rootLine(again, { ward: 'bad' }), { error: 'the ward did not stand', reason: 'an entry the package did not seal' });
|
|
213
|
-
expect.same(await again.root('host', { ward: 'bad' }), { error: '
|
|
213
|
+
expect.same(await again.root('host', { ward: 'bad' }), { error: 'bad is hosted already' }, 'its name and seed stay kept');
|
|
214
214
|
await spoil(places[1]);
|
|
215
215
|
let refused = '';
|
|
216
216
|
await world.restart('h', t.again(bodies)).catch((e) => (refused = e.message));
|
package/package.json
CHANGED
package/src/contract/index.ts
CHANGED
|
@@ -62,7 +62,8 @@ export type Module = { readonly module: string; readonly version: string; readon
|
|
|
62
62
|
export type Loaded = Module & { readonly from: string };
|
|
63
63
|
|
|
64
64
|
// Code, by the name a harbor keeps for it, or null where this loader has
|
|
65
|
-
// none. Code
|
|
65
|
+
// none. Code it has that does not load throws, saying why. Code never
|
|
66
|
+
// crosses a door and never lives in a cell, so it is the
|
|
66
67
|
// one thing beside the seed a terrain hands in: a map, an import, a bundle.
|
|
67
68
|
export abstract class Loader {
|
|
68
69
|
abstract load(from: string): Promise<Loaded | null>;
|
package/src/harbor/catalogue.ts
CHANGED
|
@@ -67,10 +67,16 @@ export class Catalogue extends Faculty {
|
|
|
67
67
|
// it. The rest stay out, each with its reason.
|
|
68
68
|
async wake(): Promise<void> {
|
|
69
69
|
for (const [module, row] of Object.entries(this.#rows)) {
|
|
70
|
-
const loaded = await this.#harbor.load(row.from).catch(() =>
|
|
70
|
+
const loaded = await this.#harbor.load(row.from).catch((e: Error) => e);
|
|
71
71
|
const refused =
|
|
72
|
-
loaded
|
|
73
|
-
|
|
72
|
+
loaded instanceof Error
|
|
73
|
+
? loaded.message
|
|
74
|
+
: loaded === null
|
|
75
|
+
? `not found at ${row.from}`
|
|
76
|
+
: loaded.module !== module
|
|
77
|
+
? `${row.from} is module ${loaded.module}`
|
|
78
|
+
: this.#harbor.check([...this.#running.values(), loaded]);
|
|
79
|
+
if (refused === null) this.#running.set(module, loaded as Loaded);
|
|
74
80
|
else this.#failed.set(module, refused);
|
|
75
81
|
}
|
|
76
82
|
this.#harbor.run([...this.#running.values()]);
|
|
@@ -78,7 +84,8 @@ export class Catalogue extends Faculty {
|
|
|
78
84
|
|
|
79
85
|
async add(args: JsonObject): Promise<JsonObject> {
|
|
80
86
|
if (!text(args.from)) return { error: 'from is text' };
|
|
81
|
-
const loaded = await this.#harbor.load(args.from);
|
|
87
|
+
const loaded = await this.#harbor.load(args.from).catch((e: Error) => e);
|
|
88
|
+
if (loaded instanceof Error) return { error: loaded.message };
|
|
82
89
|
if (loaded === null) return { error: 'no such module' };
|
|
83
90
|
const running = new Map(this.#running);
|
|
84
91
|
running.set(loaded.module, loaded);
|
package/src/harbor/dock.ts
CHANGED
|
@@ -158,7 +158,9 @@ export class Dock extends WardBeing implements Lender {
|
|
|
158
158
|
|
|
159
159
|
async host(args: JsonObject): Promise<JsonObject> {
|
|
160
160
|
const name = args.ward;
|
|
161
|
-
if (!text(name)
|
|
161
|
+
if (!text(name)) return { error: 'ward is text' };
|
|
162
|
+
if (name === BOX) return { error: 'box is the box ward' };
|
|
163
|
+
if (this.hosted.some((h) => h.ward === name)) return { error: `${name} is hosted already` };
|
|
162
164
|
if (args.seed !== undefined && !text(args.seed)) return { error: 'seed is text' };
|
|
163
165
|
const invitation = await this.stance.occupants.invite(name, { hosted: true });
|
|
164
166
|
if (invitation === null) return { error: 'not hosted' };
|
package/src/node/index.ts
CHANGED
|
@@ -50,8 +50,10 @@ export const isFile = (from: string): boolean => /^(\.{1,2}[\\/]|[\\/]|[A-Za-z]:
|
|
|
50
50
|
// Code from a file or an installed package: a module that exports
|
|
51
51
|
// `module`, `version` and `classes`, found again by where it was found, a
|
|
52
52
|
// file by its absolute path and a package by its name, resolved from each
|
|
53
|
-
// folder of `bases` in order. What
|
|
54
|
-
//
|
|
53
|
+
// folder of `bases` in order. What is not there, or exports no module, is
|
|
54
|
+
// none. Code that is there and does not import throws Node's reason, so
|
|
55
|
+
// whoever added it learns why; an ES module read as CommonJS says which
|
|
56
|
+
// field its package.json lacks.
|
|
55
57
|
export class ImportLoader extends Loader {
|
|
56
58
|
readonly #bases: readonly string[];
|
|
57
59
|
constructor(bases: readonly string[] = [process.cwd()]) {
|
|
@@ -65,8 +67,13 @@ export class ImportLoader extends Loader {
|
|
|
65
67
|
let exported: { module?: unknown; version?: unknown; classes?: unknown };
|
|
66
68
|
try {
|
|
67
69
|
exported = (await import(pathToFileURL(found).href)) as typeof exported;
|
|
68
|
-
} catch {
|
|
69
|
-
|
|
70
|
+
} catch (e) {
|
|
71
|
+
const said = (e as Error).message;
|
|
72
|
+
// The name itself is nowhere, as against code there that needs
|
|
73
|
+
// something that is not.
|
|
74
|
+
if ((e as { code?: string }).code === 'ERR_MODULE_NOT_FOUND' && said.includes(`'${found}'`)) return null;
|
|
75
|
+
const commonjs = e instanceof SyntaxError && /\b(export|import)\b/.test(said);
|
|
76
|
+
throw new Error(`${found} did not load: ${said}${commonjs ? '; it is an ES module read as CommonJS, so set "type": "module" in its package.json' : ''}`, { cause: e });
|
|
70
77
|
}
|
|
71
78
|
const { module, version, classes } = exported;
|
|
72
79
|
if (typeof module !== 'string' || typeof version !== 'string' || !Array.isArray(classes)) return null;
|
package/src/proof/law.ts
CHANGED
|
@@ -220,7 +220,7 @@ export const lawScenes = (t: Terrain, expect: Expect): [string, () => Promise<vo
|
|
|
220
220
|
expect.same(again.names, ['good']);
|
|
221
221
|
expect.same(((await census(again)) as { failed: unknown }).failed, { wards: { bad: 'an entry the package did not seal' }, routes: {} });
|
|
222
222
|
expect.same(await rootLine(again, { ward: 'bad' }), { error: 'the ward did not stand', reason: 'an entry the package did not seal' });
|
|
223
|
-
expect.same(await again.root('host', { ward: 'bad' }), { error: '
|
|
223
|
+
expect.same(await again.root('host', { ward: 'bad' }), { error: 'bad is hosted already' }, 'its name and seed stay kept');
|
|
224
224
|
await spoil(places[1]!);
|
|
225
225
|
let refused = '';
|
|
226
226
|
await world.restart('h', t.again(bodies)).catch((e: Error) => (refused = e.message));
|