@tapi-dev/sdk 0.1.33 → 0.1.34

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/dist/cli.js CHANGED
@@ -144,22 +144,22 @@ export async function runCli(argv = process.argv.slice(2)) {
144
144
  }
145
145
  return runServiceCommand(subcommand, rest);
146
146
  }
147
- if (command === "apis") {
147
+ if (command === "services" || command === "apis") {
148
148
  if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h" || hasHelpFlag(rest)) {
149
- printApisHelp();
149
+ printServicesHelp();
150
150
  return 0;
151
151
  }
152
152
  if (subcommand === "describe") {
153
- return describeApiOperation(rest);
153
+ return describeServiceOperation(rest);
154
154
  }
155
155
  if (subcommand === "sync") {
156
- return syncApiCatalog(rest);
156
+ return syncServiceCatalog(rest);
157
157
  }
158
158
  if (subcommand === "generate") {
159
- return generateApiClient(rest);
159
+ return generateServiceClient(rest);
160
160
  }
161
- console.error(`Unknown apis command: ${subcommand}`);
162
- printApisHelp();
161
+ console.error(`Unknown service-run command: ${subcommand}`);
162
+ printServicesHelp();
163
163
  return 1;
164
164
  }
165
165
  if (command === "triggers") {
@@ -367,7 +367,7 @@ export function parseStudioOptions(args) {
367
367
  workspaceMode: Boolean(projectId || workspace),
368
368
  };
369
369
  }
370
- function parseApiOptions(args) {
370
+ function parseServiceOptions(args) {
371
371
  let operation = "";
372
372
  const workspace = loadWorkspace();
373
373
  let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
@@ -406,22 +406,22 @@ function parseApiOptions(args) {
406
406
  continue;
407
407
  }
408
408
  if (arg.startsWith("--")) {
409
- throw new Error(`Unknown apis option: ${arg}`);
409
+ throw new Error(`Unknown services option: ${arg}`);
410
410
  }
411
411
  if (!operation) {
412
412
  operation = arg;
413
413
  continue;
414
414
  }
415
- throw new Error(`Unexpected apis argument: ${arg}`);
415
+ throw new Error(`Unexpected services argument: ${arg}`);
416
416
  }
417
417
  if (!operation) {
418
- throw new Error("apis describe requires an operation like schwab.place_order.");
418
+ throw new Error("services describe requires a service run like schwab.place_order.");
419
419
  }
420
420
  if (!apiKey) {
421
- throw new Error("apis describe requires --api-key or TAPI_API_KEY.");
421
+ throw new Error("services describe requires --api-key or TAPI_API_KEY.");
422
422
  }
423
423
  if (!projectId) {
424
- throw new Error("apis describe requires --project, TAPI_PROJECT_ID, or .tapi/project.json.");
424
+ throw new Error("services describe requires --project, TAPI_PROJECT_ID, or .tapi/project.json.");
425
425
  }
426
426
  return {
427
427
  operation,
@@ -432,15 +432,15 @@ function parseApiOptions(args) {
432
432
  },
433
433
  };
434
434
  }
435
- async function describeApiOperation(args) {
435
+ async function describeServiceOperation(args) {
436
436
  try {
437
- const { operation, options } = parseApiOptions(args);
437
+ const { operation, options } = parseServiceOptions(args);
438
438
  const client = new TapiClient({
439
439
  baseUrl: options.apiBaseUrl,
440
440
  apiKey: options.apiKey,
441
441
  projectId: options.projectId,
442
442
  });
443
- const description = await withCliSpinner(`Fetching Tapi API description for ${operation}`, () => client.services.describe(operation));
443
+ const description = await withCliSpinner(`Fetching Tapi service-run contract for ${operation}`, () => client.services.describe(operation));
444
444
  console.log(JSON.stringify(description, null, 2));
445
445
  return 0;
446
446
  }
@@ -454,8 +454,8 @@ function parseApiWorkspaceOptions(args) {
454
454
  let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
455
455
  let apiKey = envString("TAPI_API_KEY") || "";
456
456
  let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
457
- let catalogPath = workspace?.config.generated?.catalog || ".tapi/generated/catalog.json";
458
- let typescriptPath = workspace?.config.generated?.typescript || "src/tapi.generated.ts";
457
+ let catalogPath = workspace?.config.services?.catalog || workspace?.config.generated?.catalog || ".tapi/services/catalog.json";
458
+ let typescriptPath = workspace?.config.services?.typescript || workspace?.config.generated?.typescript || "src/tapi.services.ts";
459
459
  for (let index = 0; index < args.length; index += 1) {
460
460
  const arg = args[index];
461
461
  if (!arg)
@@ -504,13 +504,13 @@ function parseApiWorkspaceOptions(args) {
504
504
  typescriptPath = arg.slice("--out=".length);
505
505
  continue;
506
506
  }
507
- throw new Error(`Unknown apis option: ${arg}`);
507
+ throw new Error(`Unknown services option: ${arg}`);
508
508
  }
509
509
  if (!apiKey) {
510
- throw new Error("apis command requires --api-key or TAPI_API_KEY.");
510
+ throw new Error("services command requires --api-key or TAPI_API_KEY.");
511
511
  }
512
512
  if (!projectId) {
513
- throw new Error("apis command requires --project, TAPI_PROJECT_ID, or .tapi/project.json.");
513
+ throw new Error("services command requires --project, TAPI_PROJECT_ID, or .tapi/project.json.");
514
514
  }
515
515
  const root = workspace?.root || process.cwd();
516
516
  return {
@@ -521,12 +521,12 @@ function parseApiWorkspaceOptions(args) {
521
521
  typescriptPath: resolve(root, typescriptPath),
522
522
  };
523
523
  }
524
- async function syncApiCatalog(args) {
524
+ async function syncServiceCatalog(args) {
525
525
  try {
526
526
  const options = parseApiWorkspaceOptions(args);
527
- const catalog = await withCliSpinner("Fetching Tapi API catalog", () => fetchApiCatalog(options));
527
+ const catalog = await withCliSpinner("Fetching Tapi service-run catalog", () => fetchApiCatalog(options));
528
528
  await writeJsonFile(options.catalogPath, catalog);
529
- console.log(`Synced Tapi API catalog: ${options.catalogPath}`);
529
+ console.log(`Synced Tapi service-run catalog: ${options.catalogPath}`);
530
530
  return 0;
531
531
  }
532
532
  catch (error) {
@@ -534,13 +534,13 @@ async function syncApiCatalog(args) {
534
534
  return 1;
535
535
  }
536
536
  }
537
- async function generateApiClient(args) {
537
+ async function generateServiceClient(args) {
538
538
  try {
539
539
  const options = parseApiWorkspaceOptions(args);
540
- const catalog = await withCliSpinner("Fetching Tapi API catalog", () => fetchApiCatalog(options));
540
+ const catalog = await withCliSpinner("Fetching Tapi service-run catalog", () => fetchApiCatalog(options));
541
541
  await writeJsonFile(options.catalogPath, catalog);
542
- await writeTextFile(options.typescriptPath, renderGeneratedApiClient(catalog));
543
- console.log(`Generated Tapi API client: ${options.typescriptPath}`);
542
+ await writeTextFile(options.typescriptPath, renderServiceRunClient(catalog));
543
+ console.log(`Wrote Tapi service-run client: ${options.typescriptPath}`);
544
544
  return 0;
545
545
  }
546
546
  catch (error) {
@@ -615,19 +615,19 @@ async function syncApiTriggers(args) {
615
615
  const options = parseTriggerSyncOptions(args);
616
616
  const triggers = await readApiTriggerConfig(options.configPath);
617
617
  if (triggers.length === 0) {
618
- throw new Error(`No Tapi API triggers found in ${options.configPath}.`);
618
+ throw new Error(`No Tapi service triggers found in ${options.configPath}.`);
619
619
  }
620
620
  const client = new TapiClient({
621
621
  baseUrl: options.apiBaseUrl,
622
622
  apiKey: options.apiKey,
623
623
  projectId: options.projectId,
624
624
  });
625
- await withCliSpinner(`Syncing ${triggers.length} Tapi API trigger(s)`, async () => {
625
+ await withCliSpinner(`Syncing ${triggers.length} Tapi service trigger(s)`, async () => {
626
626
  for (const trigger of triggers) {
627
627
  await client.triggers.create(trigger);
628
628
  }
629
629
  });
630
- console.log(`Synced ${triggers.length} Tapi API trigger(s) from ${options.configPath}.`);
630
+ console.log(`Synced ${triggers.length} Tapi service trigger(s) from ${options.configPath}.`);
631
631
  return 0;
632
632
  }
633
633
  catch (error) {
@@ -1051,19 +1051,21 @@ function normalizeTriggerEntry(entry, index, configPath) {
1051
1051
  throw new Error(`Trigger #${index + 1} in ${configPath} must be an object.`);
1052
1052
  }
1053
1053
  const name = stringField(entry.name, `Trigger #${index + 1} name`);
1054
- const apiRequest = optionalStringField(entry.apiRequest, "apiRequest") ??
1054
+ const serviceRun = optionalStringField(entry.serviceRun, "serviceRun") ??
1055
+ optionalStringField(entry.service, "service") ??
1056
+ optionalStringField(entry.apiRequest, "apiRequest") ??
1055
1057
  optionalStringField(entry.api, "api") ??
1056
- apiRequestFromParts(entry.apiName, entry.requestKey);
1057
- if (!apiRequest) {
1058
- throw new Error(`Trigger '${name}' requires apiRequest, api, or apiName/requestKey.`);
1058
+ serviceRunFromParts(entry.serviceName ?? entry.apiName, entry.requestKey);
1059
+ if (!serviceRun) {
1060
+ throw new Error(`Trigger '${name}' requires serviceRun, service, or serviceName/requestKey.`);
1059
1061
  }
1060
- if (!apiRequest.includes(".")) {
1061
- throw new Error(`Trigger '${name}' apiRequest must be formatted as '<apiName>.<requestKey>'.`);
1062
+ if (!serviceRun.includes(".")) {
1063
+ throw new Error(`Trigger '${name}' serviceRun must be formatted as '<serviceName>.<requestKey>'.`);
1062
1064
  }
1063
1065
  const schedule = normalizeTriggerSchedule(entry.schedule, entry.interval, name);
1064
1066
  const request = {
1065
1067
  name,
1066
- apiRequest,
1068
+ apiRequest: serviceRun,
1067
1069
  ...(entry.enabled === undefined ? {} : { enabled: booleanField(entry.enabled, `Trigger '${name}' enabled`) }),
1068
1070
  ...(schedule ? { schedule } : {}),
1069
1071
  ...(entry.inputs === undefined ? {} : { inputs: recordField(entry.inputs, `Trigger '${name}' inputs`) }),
@@ -1151,8 +1153,8 @@ function parseDurationSeconds(value, fieldName) {
1151
1153
  }
1152
1154
  return seconds;
1153
1155
  }
1154
- function apiRequestFromParts(apiName, requestKey) {
1155
- const api = optionalStringField(apiName, "apiName");
1156
+ function serviceRunFromParts(serviceName, requestKey) {
1157
+ const api = optionalStringField(serviceName, "serviceName");
1156
1158
  const request = optionalStringField(requestKey, "requestKey");
1157
1159
  return api && request ? `${api}.${request}` : undefined;
1158
1160
  }
@@ -1201,7 +1203,7 @@ async function writeTextFile(path, content) {
1201
1203
  await mkdir(dirname(path), { recursive: true });
1202
1204
  await writeFile(path, content, "utf8");
1203
1205
  }
1204
- function renderGeneratedApiClient(catalog) {
1206
+ function renderServiceRunClient(catalog) {
1205
1207
  const namespaces = new Map();
1206
1208
  for (const api of catalog.apis || []) {
1207
1209
  const namespace = safeIdentifier(api.name || "api");
@@ -1217,13 +1219,13 @@ function renderGeneratedApiClient(catalog) {
1217
1219
  }
1218
1220
  }
1219
1221
  const namespaceBlocks = [...namespaces.entries()].map(([namespace, operations]) => {
1220
- const lines = operations.map(({ key, operationName }) => ` ${operationName}: (inputs: Record<string, unknown> = {}, options: GeneratedRunOptions = {}) => client.services.run(${JSON.stringify(key)}, { ...options, inputs }),`);
1222
+ const lines = operations.map(({ key, operationName }) => ` ${operationName}: (inputs: Record<string, unknown> = {}, options: ServiceRunOptions = {}) => client.services.run(${JSON.stringify(key)}, { ...options, inputs }),`);
1221
1223
  return ` ${namespace}: {\n${lines.join("\n")}\n },`;
1222
1224
  });
1223
- return `/* Generated by Tapi. Do not edit by hand. */
1225
+ return `/* Created by Tapi. Do not edit by hand. */
1224
1226
  import { TapiClient, type TapiClientOptions, type RuntimeRunOptions } from "@tapi-dev/sdk";
1225
1227
 
1226
- export interface GeneratedRunOptions {
1228
+ export interface ServiceRunOptions {
1227
1229
  runtime?: RuntimeRunOptions;
1228
1230
  priority?: number;
1229
1231
  runnerId?: string;
@@ -1231,7 +1233,7 @@ export interface GeneratedRunOptions {
1231
1233
  site?: string;
1232
1234
  }
1233
1235
 
1234
- export function createTapiGeneratedClient(options: TapiClientOptions) {
1236
+ export function createTapiServicesClient(options: TapiClientOptions) {
1235
1237
  const client = new TapiClient(options);
1236
1238
  return {
1237
1239
  ${namespaceBlocks.join("\n")}
@@ -2444,31 +2446,31 @@ async function stopPortableStudioServerProcesses() {
2444
2446
  if (process.platform !== "win32") {
2445
2447
  return 0;
2446
2448
  }
2447
- const script = `
2448
- $ErrorActionPreference = 'SilentlyContinue'
2449
- $currentPid = $PID
2450
- $processes = @(Get-Process -ErrorAction SilentlyContinue | Where-Object {
2451
- $pidValue = [int]$_.Id
2452
- if ($pidValue -le 0 -or $pidValue -eq $currentPid) {
2453
- $false
2454
- } else {
2455
- $path = ''
2456
- try { $path = [string]$_.Path } catch {}
2457
- $name = [string]$_.ProcessName
2458
- (
2459
- $name -ieq 'tapi-studio-server' -or
2460
- $path -match '\\\\Tapi\\\\Studio\\\\server\\\\releases\\\\'
2461
- )
2462
- }
2463
- })
2464
- $stopped = 0
2465
- foreach ($process in $processes) {
2466
- try {
2467
- Stop-Process -Id ([int]$process.Id) -Force -ErrorAction Stop
2468
- $stopped += 1
2469
- } catch {}
2470
- }
2471
- [pscustomobject]@{ stopped = $stopped } | ConvertTo-Json -Compress
2449
+ const script = `
2450
+ $ErrorActionPreference = 'SilentlyContinue'
2451
+ $currentPid = $PID
2452
+ $processes = @(Get-Process -ErrorAction SilentlyContinue | Where-Object {
2453
+ $pidValue = [int]$_.Id
2454
+ if ($pidValue -le 0 -or $pidValue -eq $currentPid) {
2455
+ $false
2456
+ } else {
2457
+ $path = ''
2458
+ try { $path = [string]$_.Path } catch {}
2459
+ $name = [string]$_.ProcessName
2460
+ (
2461
+ $name -ieq 'tapi-studio-server' -or
2462
+ $path -match '\\\\Tapi\\\\Studio\\\\server\\\\releases\\\\'
2463
+ )
2464
+ }
2465
+ })
2466
+ $stopped = 0
2467
+ foreach ($process in $processes) {
2468
+ try {
2469
+ Stop-Process -Id ([int]$process.Id) -Force -ErrorAction Stop
2470
+ $stopped += 1
2471
+ } catch {}
2472
+ }
2473
+ [pscustomobject]@{ stopped = $stopped } | ConvertTo-Json -Compress
2472
2474
  `;
2473
2475
  try {
2474
2476
  const output = await runProcessCapture("powershell.exe", [
@@ -3560,9 +3562,9 @@ Usage:
3560
3562
  tapi studio
3561
3563
  tapi studio open
3562
3564
  tapi studio doctor
3563
- tapi apis describe <namespace.operation>
3564
- tapi apis sync
3565
- tapi apis generate
3565
+ tapi services describe <servicemap.run>
3566
+ tapi services sync
3567
+ tapi services generate
3566
3568
  tapi triggers sync
3567
3569
  tapi sessions
3568
3570
  tapi service status
@@ -3575,10 +3577,12 @@ Commands:
3575
3577
  studio Open Tapi Studio for this repo
3576
3578
  studio open Open Tapi Studio for this repo
3577
3579
  studio doctor Check local SDK and Studio release configuration
3578
- apis describe Print a generated website API input/output contract
3579
- apis sync Save the published API catalog to .tapi/generated
3580
- apis generate Generate a TypeScript runtime wrapper from the catalog
3581
- triggers sync Upsert API-call triggers from tapi.config
3580
+ services describe
3581
+ Print a ServiceMap service-run input/output contract
3582
+ services sync Save the service-run catalog to .tapi/services
3583
+ services generate
3584
+ Write a TypeScript service-run wrapper from the catalog
3585
+ triggers sync Upsert service triggers from tapi.config
3582
3586
  sessions List dev-mode API sessions and open takeover sessions
3583
3587
  service Inspect or control the local Tapi Windows service
3584
3588
  doctor Alias for studio doctor
@@ -3602,13 +3606,13 @@ Options:
3602
3606
  --no-interactive Print the grouped list without the arrow-key picker
3603
3607
  `);
3604
3608
  }
3605
- function printApisHelp() {
3606
- console.log(`Tapi generated website API commands
3609
+ function printServicesHelp() {
3610
+ console.log(`Tapi ServiceMap service-run commands
3607
3611
 
3608
3612
  Usage:
3609
- tapi apis describe <namespace.operation> [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3610
- tapi apis sync [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3611
- tapi apis generate [--api-base-url URL] [--api-key KEY] [--project PROJECT] [--out FILE]
3613
+ tapi services describe <servicemap.run> [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3614
+ tapi services sync [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3615
+ tapi services generate [--api-base-url URL] [--api-key KEY] [--project PROJECT] [--out FILE]
3612
3616
 
3613
3617
  Options:
3614
3618
  --api-base-url <url> Tapi API base URL
@@ -3616,11 +3620,11 @@ Options:
3616
3620
  --api-key <key> Tapi API key; defaults to TAPI_API_KEY
3617
3621
  --project <id> Tapi project id; defaults to TAPI_PROJECT_ID or .tapi/project.json
3618
3622
  --catalog <path> Catalog JSON output path
3619
- --out <path> Generated TypeScript output path
3623
+ --out <path> TypeScript wrapper output path
3620
3624
  `);
3621
3625
  }
3622
3626
  function printTriggersHelp() {
3623
- console.log(`Tapi API trigger commands
3627
+ console.log(`Tapi service trigger commands
3624
3628
 
3625
3629
  Usage:
3626
3630
  tapi triggers sync [--config FILE] [--api-base-url URL] [--api-key KEY] [--project PROJECT]
@@ -3636,7 +3640,7 @@ Config:
3636
3640
  export default {
3637
3641
  triggers: {
3638
3642
  nightlyBalance: {
3639
- apiRequest: "schwab.get_balance",
3643
+ serviceRun: "schwab.get_balance",
3640
3644
  interval: "1h",
3641
3645
  inputs: { accountId: "main" },
3642
3646
  runtime: { profileRef: "perm_default" },
package/dist/triggers.js CHANGED
@@ -7,7 +7,7 @@ export class TriggersResource {
7
7
  return this.http.get("/api/sdk/v1/service-triggers");
8
8
  }
9
9
  create(request) {
10
- return this.http.post("/api/sdk/v1/service-triggers", request);
10
+ return this.http.post("/api/sdk/v1/service-triggers", toServiceTriggerWireRequest(request));
11
11
  }
12
12
  get(triggerId) {
13
13
  return this.http.get(`/api/sdk/v1/service-triggers/${encodeURIComponent(triggerId)}`);
@@ -28,3 +28,14 @@ export class TriggersResource {
28
28
  return this.http.post(`/api/sdk/v1/service-triggers/${encodeURIComponent(triggerId)}/run`);
29
29
  }
30
30
  }
31
+ function toServiceTriggerWireRequest(request) {
32
+ const apiRequest = request.serviceRun ?? request.service ?? request.apiRequest;
33
+ if (!apiRequest) {
34
+ throw new Error("service trigger requires serviceRun.");
35
+ }
36
+ const { serviceRun, service, ...wireRequest } = request;
37
+ return {
38
+ ...wireRequest,
39
+ apiRequest,
40
+ };
41
+ }
package/dist/types.d.ts CHANGED
@@ -178,7 +178,9 @@ export interface WebsiteApiTriggerSchedule {
178
178
  }
179
179
  export interface WebsiteApiTriggerCreateRequest {
180
180
  name: string;
181
- apiRequest: string;
181
+ serviceRun?: string;
182
+ service?: string;
183
+ apiRequest?: string;
182
184
  enabled?: boolean;
183
185
  schedule?: WebsiteApiTriggerSchedule;
184
186
  inputs?: Record<string, unknown>;
@@ -5,11 +5,17 @@ export interface TapiGeneratedConfig {
5
5
  typescript?: string;
6
6
  [key: string]: unknown;
7
7
  }
8
+ export interface TapiServicesConfig {
9
+ catalog?: string;
10
+ typescript?: string;
11
+ [key: string]: unknown;
12
+ }
8
13
  export interface TapiWorkspaceConfig {
9
14
  version: 1;
10
15
  projectId: string;
11
16
  projectSlug?: string;
12
17
  apiBaseUrl?: string;
18
+ services?: TapiServicesConfig;
13
19
  generated?: TapiGeneratedConfig;
14
20
  [key: string]: unknown;
15
21
  }
package/dist/workspace.js CHANGED
@@ -51,6 +51,7 @@ export function readWorkspaceConfig(configPath) {
51
51
  const projectId = normalizeProjectValue(parsed.projectId, "projectId");
52
52
  const projectSlug = optionalProjectValue(parsed.projectSlug, "projectSlug");
53
53
  const apiBaseUrl = typeof parsed.apiBaseUrl === "string" && parsed.apiBaseUrl.trim() ? parsed.apiBaseUrl.trim() : undefined;
54
+ const services = isRecord(parsed.services) ? { ...parsed.services } : undefined;
54
55
  const generated = isRecord(parsed.generated) ? { ...parsed.generated } : undefined;
55
56
  return {
56
57
  ...parsed,
@@ -58,6 +59,7 @@ export function readWorkspaceConfig(configPath) {
58
59
  projectId,
59
60
  ...(projectSlug ? { projectSlug } : {}),
60
61
  ...(apiBaseUrl ? { apiBaseUrl } : {}),
62
+ ...(services ? { services } : {}),
61
63
  ...(generated ? { generated } : {}),
62
64
  };
63
65
  }
@@ -74,9 +76,9 @@ export async function writeWorkspaceConfig(options) {
74
76
  projectId,
75
77
  projectSlug,
76
78
  ...(options.apiBaseUrl ? { apiBaseUrl: options.apiBaseUrl } : {}),
77
- generated: {
78
- catalog: ".tapi/generated/catalog.json",
79
- typescript: "src/tapi.generated.ts",
79
+ services: {
80
+ catalog: ".tapi/services/catalog.json",
81
+ typescript: "src/tapi.services.ts",
80
82
  },
81
83
  };
82
84
  await mkdir(dirname(configPath), { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapi-dev/sdk",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",