toolaby 1.8.1 → 1.8.2
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/bin.mjs +1 -1
- package/lib/manifest.js +21 -3
- package/lib/test-address.js +43 -0
- package/package.json +1 -1
package/bin.mjs
CHANGED
|
@@ -44,7 +44,7 @@ import { runMcp } from './lib/mcp.js';
|
|
|
44
44
|
import { runCheck } from './lib/check.js';
|
|
45
45
|
import { inside, signInPage, devicePolling, opener, privateKind, privateContent, privateCopies, googleKey, projectRoot, gitDirectory, gitObject, gitObjects, gitFile, notAnImage, unpacked, COMPRESSED, publicLinks, privateLinks, oneLine, fetchBounded, fetchHere, readBounded, readText, SCAFFOLD_FILES } from './lib/safe.js';
|
|
46
46
|
|
|
47
|
-
const VERSION = '1.8.
|
|
47
|
+
const VERSION = '1.8.2';
|
|
48
48
|
const CLIENT_ID = 'toolaby-cli';
|
|
49
49
|
const argv = process.argv.slice(2);
|
|
50
50
|
// `--version` and `--help` are commands of their own; every other command is the first bare word.
|
package/lib/manifest.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated from wall/src/packages/wiring/manifest.ts by wall/scripts/pack-create.mjs — edit there.
|
|
2
|
+
import { isTestAddress } from './test-address.js';
|
|
2
3
|
/**
|
|
3
4
|
* What wiring an extension does to its manifest — the same in the browser
|
|
4
5
|
* (Wire my extension, from the tool's page) and in the terminal
|
|
@@ -70,9 +71,9 @@ export const loadableName = (file) => {
|
|
|
70
71
|
/** The background the manifest names, as the folder spells it: "./background.js" is background.js. */
|
|
71
72
|
export const namedWorker = (manifest) => typeof manifest?.background?.service_worker === 'string' ? manifest.background.service_worker.trim().replace(/^(\.\/)+/, '') || null : null;
|
|
72
73
|
/**
|
|
73
|
-
* The match pattern a manifest names the Wall by: the origin of the key's site, whatever path follows it
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* The match pattern a manifest names the Wall by: the origin of the key's site, whatever path follows it —
|
|
75
|
+
* `https://northwind.toolaby.app/*` on Live; on Test, the address the Wall made for the workspace
|
|
76
|
+
* (`https://quiet-otter-4172.toolaby.app/*`, ./test-address). A wiring to one side takes the other's Test address out.
|
|
76
77
|
*/
|
|
77
78
|
export function sitePattern(site) {
|
|
78
79
|
try {
|
|
@@ -124,6 +125,23 @@ export function wireManifest(input, o) {
|
|
|
124
125
|
added.push('storage');
|
|
125
126
|
}
|
|
126
127
|
const pattern = sitePattern(o.site);
|
|
128
|
+
// A Test address of the Wall's that is not this key's (./test-address): left by an earlier wiring to the other side.
|
|
129
|
+
// Test's workspaces have hosts of their own, and a build wired for Test and then for Live went on asking its buyers,
|
|
130
|
+
// at install, for access to Test's host too (29 Sep 2026).
|
|
131
|
+
const stale = (p) => typeof p === 'string' && p !== pattern && isTestAddress(/^https:\/\/([a-z0-9-]+)\.[^/]+\/\*$/.exec(p)?.[1]);
|
|
132
|
+
for (const field of ['host_permissions', 'externally_connectable']) {
|
|
133
|
+
const list = field === 'host_permissions' ? manifest.host_permissions : manifest.externally_connectable?.matches;
|
|
134
|
+
const gone = Array.isArray(list) ? list.filter(stale) : [];
|
|
135
|
+
if (!gone.length)
|
|
136
|
+
continue;
|
|
137
|
+
const kept = list.filter((p) => !stale(p));
|
|
138
|
+
if (field === 'host_permissions')
|
|
139
|
+
manifest.host_permissions = kept;
|
|
140
|
+
else
|
|
141
|
+
manifest.externally_connectable = { ...manifest.externally_connectable, matches: kept };
|
|
142
|
+
for (const p of gone)
|
|
143
|
+
did.push(`${field === 'host_permissions' ? 'the host permission' : 'externally_connectable'} for ${p.slice('https://'.length, -2)} taken out: a Test address that is not this key's`);
|
|
144
|
+
}
|
|
127
145
|
if (!(Array.isArray(manifest.host_permissions) && manifest.host_permissions.includes(pattern))) {
|
|
128
146
|
manifest.host_permissions = add(manifest.host_permissions, pattern);
|
|
129
147
|
did.push(`a host permission for ${host}`);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Generated from wall/src/packages/wiring/test-address.ts by wall/scripts/pack-create.mjs — edit there.
|
|
2
|
+
/**
|
|
3
|
+
* A Test workspace's address, as Clerk gives a development instance one (`<slug>.clerk.accounts.dev`): made by the Wall,
|
|
4
|
+
* never chosen, never changed — `quiet-otter-4172.toolaby.app/test`. Test and Live share the Wall's addresses, and a
|
|
5
|
+
* name is Live's: a Test workspace served under its chosen name sat at the address that name has on Live, which
|
|
6
|
+
* someone else could hold (29 Sep 2026). A Test address is of a shape no workspace may take as its name, on either side
|
|
7
|
+
* (isReservedSlug), so no Live workspace ever answers at one.
|
|
8
|
+
*
|
|
9
|
+
* The database computes it, from the workspace's id, which never changes (the column `test_address`, generated; its
|
|
10
|
+
* migration writes testAddressSql() out as it stands here). So neither list may ever change: every Test workspace's
|
|
11
|
+
* address, and every Test key that names one, would move.
|
|
12
|
+
*/
|
|
13
|
+
export const TEST_ADDRESS_ADJECTIVES = [
|
|
14
|
+
'amber', 'bold', 'brave', 'bright', 'brisk', 'calm', 'clever', 'cosmic', 'crisp', 'curious', 'daring', 'eager', 'early', 'fancy', 'fluffy', 'gentle',
|
|
15
|
+
'glad', 'golden', 'happy', 'hardy', 'honest', 'humble', 'jolly', 'keen', 'kind', 'lively', 'lucky', 'lunar', 'mellow', 'merry', 'mighty', 'misty',
|
|
16
|
+
'modest', 'nimble', 'noble', 'patient', 'plucky', 'polite', 'proud', 'quick', 'quiet', 'rapid', 'ready', 'rosy', 'rustic', 'shiny', 'silent', 'silver',
|
|
17
|
+
'smooth', 'snowy', 'solar', 'spry', 'steady', 'sturdy', 'sunny', 'swift', 'tidy', 'tranquil', 'trusty', 'vivid', 'warm', 'wise', 'witty', 'zesty',
|
|
18
|
+
];
|
|
19
|
+
export const TEST_ADDRESS_ANIMALS = [
|
|
20
|
+
'badger', 'beaver', 'bison', 'bobcat', 'camel', 'cheetah', 'crane', 'dingo', 'dolphin', 'eagle', 'falcon', 'ferret', 'finch', 'fox', 'gazelle', 'gecko',
|
|
21
|
+
'heron', 'hippo', 'ibis', 'jaguar', 'koala', 'lemur', 'leopard', 'llama', 'lynx', 'magpie', 'marmot', 'marten', 'meerkat', 'mink', 'moose', 'narwhal',
|
|
22
|
+
'newt', 'ocelot', 'orca', 'osprey', 'otter', 'owl', 'panda', 'panther', 'parrot', 'pelican', 'penguin', 'puffin', 'quail', 'rabbit', 'raven', 'robin',
|
|
23
|
+
'salmon', 'seal', 'sparrow', 'stork', 'swan', 'tapir', 'tiger', 'toucan', 'turtle', 'walrus', 'weasel', 'whale', 'wombat', 'wren', 'yak', 'zebra',
|
|
24
|
+
];
|
|
25
|
+
const ADJECTIVES = new Set(TEST_ADDRESS_ADJECTIVES);
|
|
26
|
+
const ANIMALS = new Set(TEST_ADDRESS_ANIMALS);
|
|
27
|
+
const SHAPE = /^([a-z]+)-([a-z]+)-([1-9]\d{3})$/;
|
|
28
|
+
/** Whether a name is of a Test address's shape: one of the adjectives, one of the animals, a number of four digits. */
|
|
29
|
+
export function isTestAddress(s) {
|
|
30
|
+
if (typeof s !== 'string')
|
|
31
|
+
return false;
|
|
32
|
+
const m = SHAPE.exec(s);
|
|
33
|
+
return !!m && ADJECTIVES.has(m[1]) && ANIMALS.has(m[2]);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The address from the four first bytes of md5 of the id: an adjective, an animal, 1000 + a number below 9000. As SQL,
|
|
37
|
+
* for the column the database generates; a test holds the migration to it, and computes the same in Node.
|
|
38
|
+
*/
|
|
39
|
+
export function testAddressSql(id = 'id') {
|
|
40
|
+
const h = `decode(md5(${id}), 'hex')`;
|
|
41
|
+
const list = (words) => `(array[${words.map((w) => `'${w}'`).join(', ')}]::text[])`;
|
|
42
|
+
return `${list(TEST_ADDRESS_ADJECTIVES)}[1 + get_byte(${h}, 0) % ${TEST_ADDRESS_ADJECTIVES.length}] || '-' || ${list(TEST_ADDRESS_ANIMALS)}[1 + get_byte(${h}, 1) % ${TEST_ADDRESS_ANIMALS.length}] || '-' || (1000 + (get_byte(${h}, 2) * 256 + get_byte(${h}, 3)) % 9000)::text`;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolaby",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "The Toolaby command line: sign in once, then wire any Chrome extension to your tool on the Wall — sign-in, the Free plan, licences and subscriptions — or start a new one; check it, and give coding agents the Wall as an MCP server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|