@volter/twin-standard 1.0.157 → 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.
@@ -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
+ ];