@volter/twin-standard 1.0.156 → 1.0.158

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.
@@ -0,0 +1,73 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ // Vercel's unchanged REST SDK and Dub's Edge Config client, using the enclosing World's routing.
10
+ import { standardPackageFile } from "../package-file.js";
11
+ const { importSdk } = await import(__rewriteRelativeImportExtension(new URL('import.mjs', standardPackageFile('client-sdks/')).href));
12
+ const { Vercel } = await importSdk('@vercel/sdk');
13
+ const { VercelError } = await importSdk('@vercel/sdk/models/vercelerror.js');
14
+ const { createClient } = await importSdk('@vercel/edge-config');
15
+ const PROJECTS = 'https://unpkg.com/@vercel/sdk@1.28.38/esm/sdk/projects.js';
16
+ const EDGE = 'https://unpkg.com/@vercel/edge-config@0.4.1/dist/index.d.ts';
17
+ export const cases = [
18
+ {
19
+ id: 'project-domain-add-and-read',
20
+ asks: 'the issued project token adds a domain, and an independent SDK read preserves its name, project and verification state',
21
+ source: `${PROJECTS} "Add a domain to the project by passing its domain name"; ${PROJECTS} "Get project domain by project id/name and domain name."`,
22
+ async run(c) {
23
+ const vercel = new Vercel({ bearerToken: c.env.VERCEL_API_KEY });
24
+ const project = c.env.VERCEL_PROJECT_ID;
25
+ const name = 'sdk-client.example.test';
26
+ const added = await vercel.projects.addProjectDomain({ idOrName: project, requestBody: { name } });
27
+ const got = await vercel.projects.getProjectDomain({ idOrName: project, domain: name });
28
+ const wanted = { name, apexName: 'example.test', projectId: project, verified: true };
29
+ return Object.entries(wanted).flatMap(([field, value]) => added[field] === value && got[field] === value ? [] : [`project domain ${field} did not survive SDK create/read`]);
30
+ },
31
+ },
32
+ {
33
+ id: 'invalid-project-token',
34
+ asks: 'an invalid token cannot read the project domain and the SDK preserves the HTTP refusal status',
35
+ source: `${PROJECTS} "Get project domain by project id/name and domain name."; https://unpkg.com/@vercel/sdk@1.28.38/esm/models/vercelerror.js "HTTP status code"`,
36
+ async run(c) {
37
+ const vercel = new Vercel({ bearerToken: 'throwaway-invalid-token' });
38
+ try {
39
+ await vercel.projects.getProjectDomain({ idOrName: c.env.VERCEL_PROJECT_ID, domain: 'sdk-client.example.test' });
40
+ return ['an invalid token read the project domain'];
41
+ }
42
+ catch (error) {
43
+ return error instanceof Error && error instanceof VercelError && 'statusCode' in error && error.statusCode === 403
44
+ ? [] : [`invalid token refusal differs: ${String(error)}`];
45
+ }
46
+ },
47
+ },
48
+ {
49
+ id: 'edge-config-get-and-selected-get-all',
50
+ asks: 'the issued Edge Config connection string reads a stored value and only the selected keys through the unchanged SDK',
51
+ source: `${EDGE} "Read a single value."; ${EDGE} "Returns all entries when called with no arguments or only entries matching the given keys otherwise."`,
52
+ async run(c) {
53
+ const domains = ['phish-bank.example.test'];
54
+ const terms = ['gift-card'];
55
+ const written = await c.fetch(`https://api.vercel.com/v1/edge-config/${c.env.EDGE_CONFIG_ID}/items`, {
56
+ method: 'PATCH', headers: { authorization: `Bearer ${c.env.VERCEL_API_KEY}`, 'content-type': 'application/json' },
57
+ body: JSON.stringify({ items: [
58
+ { operation: 'upsert', key: 'sdk_domains', value: domains },
59
+ { operation: 'upsert', key: 'sdk_terms', value: terms },
60
+ { operation: 'upsert', key: 'sdk_unselected', value: true },
61
+ ] }),
62
+ });
63
+ if (!written.ok || (await written.json()).status !== 'ok')
64
+ return ['the Edge Config items were not written through the vendor API'];
65
+ const edge = createClient(c.env.EDGE_CONFIG);
66
+ const value = await edge.get('sdk_domains');
67
+ const selected = await edge.getAll(['sdk_domains', 'sdk_terms']);
68
+ return JSON.stringify(value) === JSON.stringify(domains) && JSON.stringify(selected.sdk_domains) === JSON.stringify(domains)
69
+ && JSON.stringify(selected.sdk_terms) === JSON.stringify(terms) && Object.keys(selected).length === 2
70
+ ? [] : ['Edge Config get/getAll did not preserve the stored values and selected keys'];
71
+ },
72
+ },
73
+ ];
@@ -611,8 +611,8 @@ async function lifeServed(pack) {
611
611
  }, server.managedDatabaseUrl ? { managedDatabaseUrl: server.managedDatabaseUrl } : {}),
612
612
  // a socket opened as an application opens it: a WebSocket to the served port, the vendor's host in its Host header
613
613
  socket: (url, headers) => new WebSocket(`ws://127.0.0.1:${port}${url}`, { headers }),
614
- // a line connection opened as an application's client opens it: TCP to the protocol listener (the primary port)
615
- stream: lineConnection(server.port),
614
+ // TCP to the native wire: a separate listener beside HTTP, or the primary protocol port.
615
+ stream: lineConnection(server.wirePort ?? server.port),
616
616
  // bounded: Bun's server.stop(true) never settles once a WebSocket peer has closed under it (discord's life, Bun
617
617
  // 1.3.11: the walk ended and the stop spun at full CPU for 45 minutes), so the check waits 5 s and goes on
618
618
  stop: async () => { await within(5000, Promise.resolve(server.stop())); },
@@ -1,6 +1,7 @@
1
1
  export type ServedPack = {
2
2
  port: number;
3
3
  inspectPort?: number;
4
+ wirePort?: number;
4
5
  stop: () => void | Promise<void>;
5
6
  managedDatabaseUrl?: () => Promise<string>;
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/twin-standard",
3
- "version": "1.0.156",
3
+ "version": "1.0.158",
4
4
  "description": "The Protocol 3 standard for Volter twin packs: the criteria a pack is graded by, the grader, the gate a pack repository and the twin catalog run on every change and submission, and the spec derivation the grade checks against. Pin a version: every place a pack is judged judges by that standard.",
5
5
  "keywords": [
6
6
  "twin",
@@ -20,6 +20,7 @@
20
20
  "README.md",
21
21
  "LICENSE",
22
22
  "client-sdks/package.json",
23
+ "client-sdks/import.mjs",
23
24
  "client-sdks/pnpm-lock.yaml",
24
25
  "!**/*.test.ts",
25
26
  "client-sdks/pnpm-workspace.yaml",
package/src/cli.ts CHANGED
@@ -78,7 +78,7 @@ if (command === '--version') {
78
78
  });
79
79
  } else if (command === 'create') {
80
80
  if (args.includes('--init') && !args.includes('--package')) throw new Error('Name your scoped package with --package');
81
- await (await import('./create-pack.ts')).createPack(args);
81
+ await (await import('./create-pack.js')).createPack(args);
82
82
  } else if (command === 'prepare-consumer') {
83
83
  if (!args[0]) usage();
84
84
  const value = (name: string) => { const at = args.indexOf(name); if (at < 0 || !args[at + 1]) usage(); return args[at + 1]!; };
@@ -88,7 +88,7 @@ if (command === '--version') {
88
88
  if (!/^sha512-[A-Za-z0-9+/]{86}==$/.test(artifactIntegrity)) throw new Error('Consumer preparation requires candidate SHA-512 integrity');
89
89
  const out = resolve(value('--out'));
90
90
  if (existsSync(out)) throw new Error('Prepared consumer output already exists');
91
- const { prepareConsumerApp } = await import('./consumer.ts');
91
+ const { prepareConsumerApp } = await import('./consumer.js');
92
92
  const candidateAt = args.indexOf('--candidate');
93
93
  const artifact = candidateAt >= 0 ? resolve(value('--candidate')) : undefined;
94
94
  const fixture = prepareConsumerApp(resolve(args[0]!), appDir, { cli, artifact });
@@ -102,7 +102,7 @@ if (command === '--version') {
102
102
  const outputAt = args.indexOf('--out');
103
103
  if (outputAt >= 0 && !args[outputAt + 1]) usage();
104
104
  const consumer = JSON.parse(readFileSync(resolve(args[at + 1]!), 'utf8'));
105
- const { runConsumerWorkflow } = await import('./consumer.ts');
105
+ const { runConsumerWorkflow } = await import('./consumer.js');
106
106
  const report = await runConsumerWorkflow(resolve(args[0]!), consumer);
107
107
  const text = `${JSON.stringify(report, null, 2)}\n`;
108
108
  if (outputAt >= 0) {
@@ -112,7 +112,7 @@ if (command === '--version') {
112
112
  process.exit(report.passed ? 0 : 1);
113
113
  } else if (command === 'assess') {
114
114
  if (!args[0]) usage();
115
- const { assessPack } = await import('./assessment.ts');
115
+ const { assessPack } = await import('./assessment.js');
116
116
  const consumerAt = args.indexOf('--prepared-consumer');
117
117
  if (consumerAt >= 0 && !args[consumerAt + 1]) usage();
118
118
  const consumer = consumerAt >= 0 ? JSON.parse(readFileSync(resolve(args[consumerAt + 1]!), 'utf8')) : undefined;
@@ -126,7 +126,7 @@ if (command === '--version') {
126
126
  process.exit(report.ready ? 0 : 1);
127
127
  } else if (command === 'facts') {
128
128
  if (!args[0]) usage();
129
- const { compilePackFacts, renderPackFacts } = await import('./pack-facts.ts');
129
+ const { compilePackFacts, renderPackFacts } = await import('./pack-facts.js');
130
130
  const { mkdirSync, writeFileSync } = await import('node:fs');
131
131
  const { join, dirname } = await import('node:path');
132
132
  const dir = resolve(args[0]!);
@@ -145,19 +145,19 @@ if (command === '--version') {
145
145
  if (!args[0] || args[0].startsWith('-')) usage();
146
146
  const tool = { walk: 'score-pack', examples: 'vendor-examples', coverage: 'life-coverage', 'judge-brief': 'judge-brief' }[command];
147
147
  process.argv = [process.argv[0]!, process.argv[1]!, ...args];
148
- await import((await import('./tools/packs-root.ts')).toolPath(tool));
148
+ await import((await import('./tools/packs-root.js')).toolPath(tool));
149
149
  } else if (command === 'derive') {
150
150
  if (!args[0]) usage();
151
151
  // the derivation is a script over process.argv: it reads the unit from its first argument
152
152
  process.argv = [process.argv[0]!, process.argv[1]!, ...args];
153
- await import('./derive.ts');
153
+ await import('./derive.js');
154
154
  } else if (command === 'check-sources') {
155
155
  if (!args[0]) usage();
156
- await (await import('./check-sources.ts')).checkSources(args);
156
+ await (await import('./check-sources.js')).checkSources(args);
157
157
  } else if (command === 'read-page') {
158
158
  // a documentation page's text, read as the citation check reads it: where an author finds the vendor's examples and words
159
159
  if (!args[0]) usage();
160
- const { status, readable, raw, error } = await (await import('./check-sources.ts')).readPage(args[0]);
160
+ const { status, readable, raw, error } = await (await import('./check-sources.js')).readPage(args[0]);
161
161
  if (status !== 200) { console.error(`read-page: ${args[0]} answered ${status || 'nothing'}${error ? `: ${error}` : ''}`); process.exit(1); }
162
162
  // --raw: the page's own bytes, as fetched (a spec writer reads its tables, which the readable text drops)
163
163
  if (args.includes('--raw')) process.stdout.write(raw); else console.log(readable);
@@ -169,8 +169,8 @@ if (command === '--version') {
169
169
  // `.tgz` the tarball `npm pack` makes of one, the bytes a publish would send
170
170
  const published = target.endsWith('.tgz') || (!existsSync(target) && /^@?[^@]+@[^@]+$/.test(target));
171
171
  const results = published
172
- ? await (await import('./published.ts')).conformPublished(target, at >= 0 ? { registry: args[at + 1]! } : {})
173
- : await (await import('./conformance.ts')).conformance(target, { onCheck: (id) => console.error(` … ${id} (${new Date().toISOString().slice(11, 19)})`) });
172
+ ? await (await import('./published.js')).conformPublished(target, at >= 0 ? { registry: args[at + 1]! } : {})
173
+ : await (await import('./conformance.js')).conformance(target, { onCheck: (id) => console.error(` … ${id} (${new Date().toISOString().slice(11, 19)})`) });
174
174
  for (const r of results) {
175
175
  console.log(`${r.failures.length ? '✗' : '✓'} ${r.id.padEnd(15)} ${r.asks}${r.note ? ` (${r.note})` : ''}`);
176
176
  for (const f of r.failures) console.log(` ${f}`);
@@ -1,11 +1,14 @@
1
1
  // Tinybird's official API wrapper, unmodified, with the World credential and routed fetch.
2
2
  // The pinned package names Forward; its decoupled API wrapper uses the Classic /v0 APIs.
3
3
  import type { ClientCase, ClientContext } from './harness.ts';
4
+ import { standardPackageFile } from '../package-file.ts';
5
+
6
+ const { importSdk } = await import(new URL('import.mjs', standardPackageFile('client-sdks/')).href);
7
+ const { createTinybirdApi, TinybirdApiError }: typeof import('@tinybirdco/sdk/api') = await importSdk('@tinybirdco/sdk/api');
4
8
 
5
9
  const SDK = 'https://unpkg.com/@tinybirdco/sdk@0.0.84/src/api/api.ts';
6
10
 
7
- async function client(c: ClientContext, fetch: typeof globalThis.fetch = c.fetch) {
8
- const { createTinybirdApi } = await import('@tinybirdco/sdk/api');
11
+ function client(c: ClientContext, fetch: typeof globalThis.fetch = c.fetch) {
9
12
  return createTinybirdApi({ baseUrl: `https://${c.host}`, token: c.env.TINYBIRD_API_KEY ?? c.env.TINYBIRD_TOKEN ?? '', fetch });
10
13
  }
11
14
 
@@ -15,8 +18,7 @@ export const cases: ClientCase[] = [
15
18
  asks: 'a request token override is used instead of the Workspace token, and its refusal retains the status and JSON error in TinybirdApiError',
16
19
  source: `${SDK} "Error thrown by TinybirdApi when a response is not OK"`,
17
20
  async run(c) {
18
- const { TinybirdApiError } = await import('@tinybirdco/sdk/api');
19
- const api = await client(c);
21
+ const api = client(c);
20
22
  try {
21
23
  await api.ingest('client_case_events', { label: 'refused' }, { token: 'throwaway-invalid-token' });
22
24
  return ['the invalid request token was accepted'];
@@ -37,7 +39,7 @@ export const cases: ClientCase[] = [
37
39
  async run(c) {
38
40
  let calls = 0;
39
41
  const routed = ((input: RequestInfo | URL, init?: RequestInit) => { calls++; return c.fetch(input, init); }) as typeof fetch;
40
- const api = await client(c, routed);
42
+ const api = client(c, routed);
41
43
  try {
42
44
  await api.ingest('client_case_events', { timestamp: new Date('2024-01-15T10:30:00Z') });
43
45
  return ['a Date object was accepted for ingestion'];
@@ -58,7 +60,7 @@ export const cases: ClientCase[] = [
58
60
  asks: 'an object query parameter becomes JSON and the Endpoint uses its value rather than the object string representation',
59
61
  source: `${SDK} "Plain objects (e.g. p.json() params) become JSON strings; Dates are rejected;"`,
60
62
  async run(c) {
61
- const api = await client(c);
63
+ const api = client(c);
62
64
  await api.requestJson('/v0/datasources', { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ name: 'client_json_rows', schema: 'name String' }).toString() });
63
65
  await api.ingestBatch('client_json_rows', [{ name: 'selected' }, { name: 'excluded' }], { wait: true });
64
66
  await api.requestJson('/v0/pipes', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ name: 'client_json_filter', nodes: [{ name: 'endpoint', type: 'endpoint', sql: "%\nSELECT name FROM client_json_rows WHERE name = {{JSON(filters, '{\"name\":\"selected\"}').get('name')}}" }] }) });
@@ -0,0 +1,67 @@
1
+ // Vercel's unchanged REST SDK and Dub's Edge Config client, using the enclosing World's routing.
2
+ import { standardPackageFile } from '../package-file.ts';
3
+ import type { ClientCase } from './harness.ts';
4
+
5
+ const { importSdk } = await import(new URL('import.mjs', standardPackageFile('client-sdks/')).href);
6
+ const { Vercel } = await importSdk('@vercel/sdk');
7
+ const { VercelError } = await importSdk('@vercel/sdk/models/vercelerror.js');
8
+ const { createClient } = await importSdk('@vercel/edge-config');
9
+ const PROJECTS = 'https://unpkg.com/@vercel/sdk@1.28.38/esm/sdk/projects.js';
10
+ const EDGE = 'https://unpkg.com/@vercel/edge-config@0.4.1/dist/index.d.ts';
11
+
12
+ export const cases: ClientCase[] = [
13
+ {
14
+ id: 'project-domain-add-and-read',
15
+ asks: 'the issued project token adds a domain, and an independent SDK read preserves its name, project and verification state',
16
+ source: `${PROJECTS} "Add a domain to the project by passing its domain name"; ${PROJECTS} "Get project domain by project id/name and domain name."`,
17
+ async run(c) {
18
+ const vercel = new Vercel({ bearerToken: c.env.VERCEL_API_KEY });
19
+ const project = c.env.VERCEL_PROJECT_ID;
20
+ const name = 'sdk-client.example.test';
21
+ const added = await vercel.projects.addProjectDomain({ idOrName: project, requestBody: { name } });
22
+ const got = await vercel.projects.getProjectDomain({ idOrName: project, domain: name });
23
+ const wanted = { name, apexName: 'example.test', projectId: project, verified: true };
24
+ return Object.entries(wanted).flatMap(([field, value]) =>
25
+ added[field] === value && got[field] === value ? [] : [`project domain ${field} did not survive SDK create/read`]);
26
+ },
27
+ },
28
+ {
29
+ id: 'invalid-project-token',
30
+ asks: 'an invalid token cannot read the project domain and the SDK preserves the HTTP refusal status',
31
+ source: `${PROJECTS} "Get project domain by project id/name and domain name."; https://unpkg.com/@vercel/sdk@1.28.38/esm/models/vercelerror.js "HTTP status code"`,
32
+ async run(c) {
33
+ const vercel = new Vercel({ bearerToken: 'throwaway-invalid-token' });
34
+ try {
35
+ await vercel.projects.getProjectDomain({ idOrName: c.env.VERCEL_PROJECT_ID, domain: 'sdk-client.example.test' });
36
+ return ['an invalid token read the project domain'];
37
+ } catch (error) {
38
+ return error instanceof Error && error instanceof VercelError && 'statusCode' in error && error.statusCode === 403
39
+ ? [] : [`invalid token refusal differs: ${String(error)}`];
40
+ }
41
+ },
42
+ },
43
+ {
44
+ id: 'edge-config-get-and-selected-get-all',
45
+ asks: 'the issued Edge Config connection string reads a stored value and only the selected keys through the unchanged SDK',
46
+ source: `${EDGE} "Read a single value."; ${EDGE} "Returns all entries when called with no arguments or only entries matching the given keys otherwise."`,
47
+ async run(c) {
48
+ const domains = ['phish-bank.example.test'];
49
+ const terms = ['gift-card'];
50
+ const written = await c.fetch(`https://api.vercel.com/v1/edge-config/${c.env.EDGE_CONFIG_ID}/items`, {
51
+ method: 'PATCH', headers: { authorization: `Bearer ${c.env.VERCEL_API_KEY}`, 'content-type': 'application/json' },
52
+ body: JSON.stringify({ items: [
53
+ { operation: 'upsert', key: 'sdk_domains', value: domains },
54
+ { operation: 'upsert', key: 'sdk_terms', value: terms },
55
+ { operation: 'upsert', key: 'sdk_unselected', value: true },
56
+ ] }),
57
+ });
58
+ if (!written.ok || (await written.json() as { status?: string }).status !== 'ok') return ['the Edge Config items were not written through the vendor API'];
59
+ const edge = createClient(c.env.EDGE_CONFIG);
60
+ const value = await edge.get('sdk_domains');
61
+ const selected = await edge.getAll(['sdk_domains', 'sdk_terms']);
62
+ return JSON.stringify(value) === JSON.stringify(domains) && JSON.stringify(selected.sdk_domains) === JSON.stringify(domains)
63
+ && JSON.stringify(selected.sdk_terms) === JSON.stringify(terms) && Object.keys(selected).length === 2
64
+ ? [] : ['Edge Config get/getAll did not preserve the stored values and selected keys'];
65
+ },
66
+ },
67
+ ];
@@ -499,8 +499,8 @@ async function lifeServed(pack: string): Promise<string[]> {
499
499
  }, server.managedDatabaseUrl ? { managedDatabaseUrl: server.managedDatabaseUrl } : {}),
500
500
  // a socket opened as an application opens it: a WebSocket to the served port, the vendor's host in its Host header
501
501
  socket: (url: string, headers: Record<string, string>) => new WebSocket(`ws://127.0.0.1:${port}${url}`, { headers } as unknown as string[]),
502
- // a line connection opened as an application's client opens it: TCP to the protocol listener (the primary port)
503
- stream: lineConnection(server.port),
502
+ // TCP to the native wire: a separate listener beside HTTP, or the primary protocol port.
503
+ stream: lineConnection(server.wirePort ?? server.port),
504
504
  // bounded: Bun's server.stop(true) never settles once a WebSocket peer has closed under it (discord's life, Bun
505
505
  // 1.3.11: the walk ended and the stop spun at full CPU for 45 minutes), so the check waits 5 s and goes on
506
506
  stop: async () => { await within(5000, Promise.resolve(server.stop())); },
@@ -6,6 +6,7 @@ import { startTwinDatabase, type TwinDatabase } from './walk-database.ts';
6
6
  export type ServedPack = {
7
7
  port: number;
8
8
  inspectPort?: number;
9
+ wirePort?: number;
9
10
  stop: () => void | Promise<void>;
10
11
  managedDatabaseUrl?: () => Promise<string>;
11
12
  };