@quo-systems/quo 0.2.5 → 0.2.7
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/SPEC.md +21 -8
- package/dist/being/being.d.ts +1 -0
- package/dist/being/being.js +5 -1
- package/dist/being/types.d.ts +1 -0
- package/dist/ward/stance.d.ts +1 -0
- package/dist/ward/stance.js +6 -0
- package/dist/ward/ward.js +10 -0
- package/package.json +2 -2
- package/src/being/being.ts +5 -1
- package/src/being/types.ts +4 -0
- package/src/ward/stance.ts +8 -0
- package/src/ward/ward.ts +9 -0
package/SPEC.md
CHANGED
|
@@ -121,8 +121,8 @@ in the stance at birth, once, for life
|
|
|
121
121
|
out her answer(asker, method?, args?) -> object | silence the one method the ward calls
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
The stance is her cells, her standings to ask,
|
|
125
|
-
knock, take and remove. The ward builds it and hands it to the harbor's
|
|
124
|
+
The stance is her cells, her standings to ask, the calls to invite,
|
|
125
|
+
knock, take and remove, and boot. The ward builds it and hands it to the harbor's
|
|
126
126
|
instantiate with a class name, and receives her. No method is the empty ask,
|
|
127
127
|
and what she answers to it is her blueprint.
|
|
128
128
|
|
|
@@ -142,6 +142,8 @@ stance
|
|
|
142
142
|
standings[id].ask(method?, args?, wanted?) -> object | silence | word
|
|
143
143
|
standings.remove(id) -> nothing
|
|
144
144
|
|
|
145
|
+
boot(class, key) -> key | null a new being of her ward, by class name
|
|
146
|
+
|
|
145
147
|
wanted = { time? } what this one ask may spend, in milliseconds. optional,
|
|
146
148
|
and so is saying anything at all
|
|
147
149
|
```
|
|
@@ -164,6 +166,15 @@ Return table.
|
|
|
164
166
|
| ask(m, a, w) | object | she answered |
|
|
165
167
|
| | silence | she chose to say nothing, or bytes came back that are not Quo's |
|
|
166
168
|
| | word | why not: removed, absent, repeated, threw, unreached, late, dropped |
|
|
169
|
+
| boot(class, key) | key | she exists from now, with fresh cells, and a restart finds her |
|
|
170
|
+
| | null | the key is already booted, the harbor holds no such class, or the class threw at birth |
|
|
171
|
+
|
|
172
|
+
A being may make, and only the owner reaches into another. Boot touches
|
|
173
|
+
nobody: the being made has empty cells and no relation, hers included, until
|
|
174
|
+
one is invited and taken like any other. What the owner has that she does
|
|
175
|
+
not is every ask that reaches into a being from outside: public, invite and
|
|
176
|
+
knock for her, remove, unboot. Who may ask her to boot is her gate, as who
|
|
177
|
+
may ask her anything is.
|
|
167
178
|
|
|
168
179
|
Ask, knock, invite and take are awaitable. Async where the language has it,
|
|
169
180
|
blocking where it does not. Every ask she makes is a new call.
|
|
@@ -967,9 +978,10 @@ become one.
|
|
|
967
978
|
The root is not an occupant. It holds no heir, no key, no invitation. The
|
|
968
979
|
ward names every arrival on the ask `{ id: 'OWNER' }`, the third asker of the
|
|
969
980
|
ward-to-being edge, and answers it as such; an owner at the door arrives as
|
|
970
|
-
her id. What an owner can do is
|
|
971
|
-
public being, place a relation into a being of the
|
|
972
|
-
her, and take her out of the ward.
|
|
981
|
+
her id. What an owner can do is reach into a being from outside, which no
|
|
982
|
+
being can: mark the public being, place a relation into a being of the
|
|
983
|
+
ward, take one out of her, and take her out of the ward. Boot it shares
|
|
984
|
+
with every being of the ward. The root's asks carry no allowance of
|
|
973
985
|
their own. The ward is a being to her owner: the empty ask is her describe,
|
|
974
986
|
and each ask in it carries a description and an input naming its fields, as
|
|
975
987
|
a being's asks do, so that a side renders the owner's asks the way it
|
|
@@ -1044,9 +1056,10 @@ The ward:
|
|
|
1044
1056
|
- Derives its pk from its seed and names itself outward by that and nothing
|
|
1045
1057
|
else. Mints every other key from the ground's random, one per side of one
|
|
1046
1058
|
relation.
|
|
1047
|
-
- Instantiates beings when the owner asks, by class
|
|
1048
|
-
stance, names the class, and receives the object from
|
|
1049
|
-
instantiate call. It never sees a class body, its own
|
|
1059
|
+
- Instantiates beings when the owner or a being of the ward asks, by class
|
|
1060
|
+
name. It builds the stance, names the class, and receives the object from
|
|
1061
|
+
the harbor's instantiate call. It never sees a class body, its own
|
|
1062
|
+
included.
|
|
1050
1063
|
- Keeps, per being, the cells, the standings and the occupants, in the
|
|
1051
1064
|
partition, and outside her cells the bind table. Never reads notes.
|
|
1052
1065
|
- Mints a heir for every id a being mints, keeps its pk beside the id, and
|
package/dist/being/being.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class Being {
|
|
|
16
16
|
invite(id: string): Promise<Invitation | null>;
|
|
17
17
|
knock(invitation: Invitation, method?: string, args?: JsonObject, wanted?: Wanted): Promise<Answer>;
|
|
18
18
|
take(id: string, invitation: Invitation): Promise<string | null>;
|
|
19
|
+
boot(className: string, key: string): string | null;
|
|
19
20
|
occupant(asker: Asker): OccupantRecord | undefined;
|
|
20
21
|
describe(asker: Asker): Blueprint;
|
|
21
22
|
answer(asker: Asker, method?: string, args?: JsonObject): Promise<Reply>;
|
package/dist/being/being.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Names a subclass may not use for an ask, because they are the base's own.
|
|
2
|
-
const RESERVED = new Set(['answer', 'describe', 'stance', 'cells', 'standings', 'occupants', 'occupant', 'invite', 'knock', 'take', 'constructor']);
|
|
2
|
+
const RESERVED = new Set(['answer', 'describe', 'stance', 'cells', 'standings', 'occupants', 'occupant', 'invite', 'knock', 'take', 'boot', 'constructor']);
|
|
3
3
|
export class Being {
|
|
4
4
|
// Her cells' defaults. Merged in at birth, only where a key is missing, so
|
|
5
5
|
// a restart keeps what she wrote.
|
|
@@ -38,6 +38,10 @@ export class Being {
|
|
|
38
38
|
take(id, invitation) {
|
|
39
39
|
return this.stance.standings.take(id, invitation);
|
|
40
40
|
}
|
|
41
|
+
// A new being of her ward, by class name, under a key she chooses.
|
|
42
|
+
boot(className, key) {
|
|
43
|
+
return this.stance.boot(className, key);
|
|
44
|
+
}
|
|
41
45
|
// The occupant record for whoever is at the door. Undefined at a public being.
|
|
42
46
|
occupant(asker) {
|
|
43
47
|
return asker.id === undefined ? undefined : this.cells.occupants[asker.id];
|
package/dist/being/types.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export type Stance = {
|
|
|
77
77
|
readonly cells: Cells;
|
|
78
78
|
readonly occupants: Occupants;
|
|
79
79
|
readonly standings: Standings;
|
|
80
|
+
boot(className: string, key: string): string | null;
|
|
80
81
|
};
|
|
81
82
|
export interface BeingLike {
|
|
82
83
|
answer(asker: Asker, method?: string, args?: JsonObject): Reply | Promise<Reply>;
|
package/dist/ward/stance.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type Inside = {
|
|
|
10
10
|
openHeir(heir: string, being: string, id: string): void;
|
|
11
11
|
closeHeir(heir: string): void;
|
|
12
12
|
send(bind: Bind, keys: StandingKeys, announce: boolean, method: string | undefined, args: JsonObject, wanted: Wanted | undefined): Promise<ReplyPayload | Silence | Word>;
|
|
13
|
+
instantiate(key: string, className: string): string | null;
|
|
13
14
|
};
|
|
14
15
|
export type SealedInvitation = {
|
|
15
16
|
ward: string;
|
package/dist/ward/stance.js
CHANGED
|
@@ -234,6 +234,12 @@ export function buildStance(inside, key, cells, bind) {
|
|
|
234
234
|
});
|
|
235
235
|
return {
|
|
236
236
|
cells,
|
|
237
|
+
// A being may make. The ward refuses what it refuses the owner: a key
|
|
238
|
+
// already booted, a class the harbor does not hold, and a throw at birth
|
|
239
|
+
// leaves the partition as it was. Reaching into the being made is not
|
|
240
|
+
// offered here: that is the owner's, and she has no relation to her
|
|
241
|
+
// until one is invited and taken like any other.
|
|
242
|
+
boot: (className, key) => inside.instantiate(key, className),
|
|
237
243
|
occupants: {
|
|
238
244
|
// rotation one: the ward mints the occupant's first key and gives the secret away.
|
|
239
245
|
// it keeps the pk beside the id and nothing else. the invitation IS the key.
|
package/dist/ward/ward.js
CHANGED
|
@@ -135,6 +135,16 @@ class Self {
|
|
|
135
135
|
openHeir: (heir, being, id) => this.heirs.open(heir, being, id),
|
|
136
136
|
closeHeir: (heir) => this.heirs.close(heir),
|
|
137
137
|
send: (b, keys, announce, method, args, wanted) => this.#send(b, keys, announce, method, args, wanted),
|
|
138
|
+
// A throw at birth is null to her, not a throw in her method: she asked
|
|
139
|
+
// for a being and got none, and her own answer is still hers to give.
|
|
140
|
+
instantiate: (k, className) => {
|
|
141
|
+
try {
|
|
142
|
+
return this.#instantiate(k, className)?.key ?? null;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
138
148
|
}, key, cells, bind);
|
|
139
149
|
const being = classNameOrSelf === this ? this : this.g.instantiate(classNameOrSelf, stance);
|
|
140
150
|
if (!being)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quo-systems/quo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Quo: an object asks another object and gets an answer, without knowing where it is. Being, Ward, Harbor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"quo",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
40
40
|
"test": "node --test \"test/*.test.ts\"",
|
|
41
41
|
"check:terrain": "node --test \"test/terrain/*.test.ts\"",
|
|
42
|
-
"prepublishOnly": "
|
|
42
|
+
"prepublishOnly": "test \"$QUO_GATED\" = 1 || { echo 'publish from the root, gated once: npm run release' >&2; exit 1; }"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
package/src/being/being.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type AskSpec = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
// Names a subclass may not use for an ask, because they are the base's own.
|
|
19
|
-
const RESERVED = new Set(['answer', 'describe', 'stance', 'cells', 'standings', 'occupants', 'occupant', 'invite', 'knock', 'take', 'constructor']);
|
|
19
|
+
const RESERVED = new Set(['answer', 'describe', 'stance', 'cells', 'standings', 'occupants', 'occupant', 'invite', 'knock', 'take', 'boot', 'constructor']);
|
|
20
20
|
|
|
21
21
|
export class Being {
|
|
22
22
|
// Her cells' defaults. Merged in at birth, only where a key is missing, so
|
|
@@ -55,6 +55,10 @@ export class Being {
|
|
|
55
55
|
take(id: string, invitation: Invitation): Promise<string | null> {
|
|
56
56
|
return this.stance.standings.take(id, invitation);
|
|
57
57
|
}
|
|
58
|
+
// A new being of her ward, by class name, under a key she chooses.
|
|
59
|
+
boot(className: string, key: string): string | null {
|
|
60
|
+
return this.stance.boot(className, key);
|
|
61
|
+
}
|
|
58
62
|
// The occupant record for whoever is at the door. Undefined at a public being.
|
|
59
63
|
occupant(asker: Asker): OccupantRecord | undefined {
|
|
60
64
|
return asker.id === undefined ? undefined : this.cells.occupants[asker.id];
|
package/src/being/types.ts
CHANGED
|
@@ -89,6 +89,10 @@ export type Stance = {
|
|
|
89
89
|
readonly cells: Cells;
|
|
90
90
|
readonly occupants: Occupants;
|
|
91
91
|
readonly standings: Standings;
|
|
92
|
+
// A new being of her ward, by class name, under a key she chooses. The key
|
|
93
|
+
// back, or null: the key is taken or the harbor holds no such class. A
|
|
94
|
+
// being may make; only the owner reaches into another.
|
|
95
|
+
boot(className: string, key: string): string | null;
|
|
92
96
|
};
|
|
93
97
|
|
|
94
98
|
// The raw shape of a being. Anything with these two is a being.
|
package/src/ward/stance.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type Inside = {
|
|
|
18
18
|
// one send for every destination. the far door's reply, silence, or unreached.
|
|
19
19
|
// signs as keys.current, announces keys.next (minting one if asked), and rotates keys on an answer.
|
|
20
20
|
send(bind: Bind, keys: StandingKeys, announce: boolean, method: string | undefined, args: JsonObject, wanted: Wanted | undefined): Promise<ReplyPayload | Silence | Word>;
|
|
21
|
+
// a new being of this ward, as the owner's boot makes one. the key, or null.
|
|
22
|
+
instantiate(key: string, className: string): string | null;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
// An invitation as it travels: the far ward's pk, the heir pk, the heir's secret seed. Or just the ward, for its public being.
|
|
@@ -247,6 +249,12 @@ export function buildStance(inside: Inside, key: string, cells: Cells, bind: Bin
|
|
|
247
249
|
|
|
248
250
|
return {
|
|
249
251
|
cells,
|
|
252
|
+
// A being may make. The ward refuses what it refuses the owner: a key
|
|
253
|
+
// already booted, a class the harbor does not hold, and a throw at birth
|
|
254
|
+
// leaves the partition as it was. Reaching into the being made is not
|
|
255
|
+
// offered here: that is the owner's, and she has no relation to her
|
|
256
|
+
// until one is invited and taken like any other.
|
|
257
|
+
boot: (className: string, key: string): string | null => inside.instantiate(key, className),
|
|
250
258
|
occupants: {
|
|
251
259
|
// rotation one: the ward mints the occupant's first key and gives the secret away.
|
|
252
260
|
// it keeps the pk beside the id and nothing else. the invitation IS the key.
|
package/src/ward/ward.ts
CHANGED
|
@@ -145,6 +145,15 @@ class Self implements BeingLike {
|
|
|
145
145
|
openHeir: (heir, being, id) => this.heirs.open(heir, being, id),
|
|
146
146
|
closeHeir: (heir) => this.heirs.close(heir),
|
|
147
147
|
send: (b, keys, announce, method, args, wanted) => this.#send(b, keys, announce, method, args, wanted),
|
|
148
|
+
// A throw at birth is null to her, not a throw in her method: she asked
|
|
149
|
+
// for a being and got none, and her own answer is still hers to give.
|
|
150
|
+
instantiate: (k, className) => {
|
|
151
|
+
try {
|
|
152
|
+
return this.#instantiate(k, className)?.key ?? null;
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
},
|
|
148
157
|
},
|
|
149
158
|
key,
|
|
150
159
|
cells,
|