@tapi-dev/sdk 0.1.32 → 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")}
@@ -2436,35 +2438,35 @@ async function isPortAvailable(port) {
2436
2438
  });
2437
2439
  }
2438
2440
  async function reapPortableStudioServersBlockingPorts(preferred, count) {
2441
+ void preferred;
2442
+ void count;
2443
+ return 0;
2444
+ }
2445
+ async function stopPortableStudioServerProcesses() {
2439
2446
  if (process.platform !== "win32") {
2440
2447
  return 0;
2441
2448
  }
2442
- const start = Math.max(1, Math.min(65535, Math.trunc(preferred)));
2443
- const end = Math.max(start, Math.min(65535, start + Math.max(1, Math.trunc(count)) - 1));
2444
2449
  const script = `
2445
2450
  $ErrorActionPreference = 'SilentlyContinue'
2446
- $ports = ${start}..${end}
2447
- $connections = @(Get-NetTCPConnection -State Listen | Where-Object { $ports -contains $_.LocalPort })
2448
- $owners = @{}
2449
- foreach ($conn in $connections) {
2450
- $pidValue = [int]$conn.OwningProcess
2451
- if ($pidValue -le 0 -or $owners.ContainsKey($pidValue)) { continue }
2452
- $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$pidValue"
2453
- if ($null -eq $proc) { continue }
2454
- $path = [string]$proc.ExecutablePath
2455
- $cmd = [string]$proc.CommandLine
2456
- $isPortableStudio = (
2457
- $path -match '\\\\Tapi\\\\Studio\\\\server\\\\releases\\\\' -or
2458
- $cmd -match 'tapi-studio-server'
2459
- )
2460
- if ($isPortableStudio) {
2461
- $owners[$pidValue] = $true
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
+ )
2462
2464
  }
2463
- }
2465
+ })
2464
2466
  $stopped = 0
2465
- foreach ($pidValue in $owners.Keys) {
2467
+ foreach ($process in $processes) {
2466
2468
  try {
2467
- Stop-Process -Id $pidValue -Force -ErrorAction Stop
2469
+ Stop-Process -Id ([int]$process.Id) -Force -ErrorAction Stop
2468
2470
  $stopped += 1
2469
2471
  } catch {}
2470
2472
  }
@@ -2477,54 +2479,7 @@ foreach ($pidValue in $owners.Keys) {
2477
2479
  "Bypass",
2478
2480
  "-Command",
2479
2481
  script,
2480
- ]);
2481
- const payload = JSON.parse(output.trim() || "{}");
2482
- return typeof payload.stopped === "number" ? payload.stopped : 0;
2483
- }
2484
- catch {
2485
- return 0;
2486
- }
2487
- }
2488
- async function stopPortableStudioServerProcesses() {
2489
- if (process.platform !== "win32") {
2490
- return 0;
2491
- }
2492
- const script = `
2493
- $ErrorActionPreference = 'SilentlyContinue'
2494
- $currentPid = $PID
2495
- $processes = @(Get-CimInstance Win32_Process | Where-Object {
2496
- $pidValue = [int]$_.ProcessId
2497
- if ($pidValue -le 0 -or $pidValue -eq $currentPid) {
2498
- $false
2499
- } else {
2500
- $path = [string]$_.ExecutablePath
2501
- $cmd = [string]$_.CommandLine
2502
- $name = [string]$_.Name
2503
- (
2504
- $name -ieq 'tapi-studio-server.exe' -or
2505
- $path -match '\\\\Tapi\\\\Studio\\\\server\\\\releases\\\\' -or
2506
- $cmd -match 'tapi-studio-server' -or
2507
- $cmd -match 'scripts[\\\\/]studio\\.py'
2508
- )
2509
- }
2510
- })
2511
- $stopped = 0
2512
- foreach ($process in $processes) {
2513
- try {
2514
- Stop-Process -Id ([int]$process.ProcessId) -Force -ErrorAction Stop
2515
- $stopped += 1
2516
- } catch {}
2517
- }
2518
- [pscustomobject]@{ stopped = $stopped } | ConvertTo-Json -Compress
2519
- `;
2520
- try {
2521
- const output = await runProcessCapture("powershell.exe", [
2522
- "-NoProfile",
2523
- "-ExecutionPolicy",
2524
- "Bypass",
2525
- "-Command",
2526
- script,
2527
- ]);
2482
+ ], { timeoutMs: WINDOWS_SERVICE_STATUS_TIMEOUT_MS });
2528
2483
  const payload = JSON.parse(output.trim() || "{}");
2529
2484
  return typeof payload.stopped === "number" ? payload.stopped : 0;
2530
2485
  }
@@ -3607,9 +3562,9 @@ Usage:
3607
3562
  tapi studio
3608
3563
  tapi studio open
3609
3564
  tapi studio doctor
3610
- tapi apis describe <namespace.operation>
3611
- tapi apis sync
3612
- tapi apis generate
3565
+ tapi services describe <servicemap.run>
3566
+ tapi services sync
3567
+ tapi services generate
3613
3568
  tapi triggers sync
3614
3569
  tapi sessions
3615
3570
  tapi service status
@@ -3622,10 +3577,12 @@ Commands:
3622
3577
  studio Open Tapi Studio for this repo
3623
3578
  studio open Open Tapi Studio for this repo
3624
3579
  studio doctor Check local SDK and Studio release configuration
3625
- apis describe Print a generated website API input/output contract
3626
- apis sync Save the published API catalog to .tapi/generated
3627
- apis generate Generate a TypeScript runtime wrapper from the catalog
3628
- 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
3629
3586
  sessions List dev-mode API sessions and open takeover sessions
3630
3587
  service Inspect or control the local Tapi Windows service
3631
3588
  doctor Alias for studio doctor
@@ -3649,13 +3606,13 @@ Options:
3649
3606
  --no-interactive Print the grouped list without the arrow-key picker
3650
3607
  `);
3651
3608
  }
3652
- function printApisHelp() {
3653
- console.log(`Tapi generated website API commands
3609
+ function printServicesHelp() {
3610
+ console.log(`Tapi ServiceMap service-run commands
3654
3611
 
3655
3612
  Usage:
3656
- tapi apis describe <namespace.operation> [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3657
- tapi apis sync [--api-base-url URL] [--api-key KEY] [--project PROJECT]
3658
- 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]
3659
3616
 
3660
3617
  Options:
3661
3618
  --api-base-url <url> Tapi API base URL
@@ -3663,11 +3620,11 @@ Options:
3663
3620
  --api-key <key> Tapi API key; defaults to TAPI_API_KEY
3664
3621
  --project <id> Tapi project id; defaults to TAPI_PROJECT_ID or .tapi/project.json
3665
3622
  --catalog <path> Catalog JSON output path
3666
- --out <path> Generated TypeScript output path
3623
+ --out <path> TypeScript wrapper output path
3667
3624
  `);
3668
3625
  }
3669
3626
  function printTriggersHelp() {
3670
- console.log(`Tapi API trigger commands
3627
+ console.log(`Tapi service trigger commands
3671
3628
 
3672
3629
  Usage:
3673
3630
  tapi triggers sync [--config FILE] [--api-base-url URL] [--api-key KEY] [--project PROJECT]
@@ -3683,7 +3640,7 @@ Config:
3683
3640
  export default {
3684
3641
  triggers: {
3685
3642
  nightlyBalance: {
3686
- apiRequest: "schwab.get_balance",
3643
+ serviceRun: "schwab.get_balance",
3687
3644
  interval: "1h",
3688
3645
  inputs: { accountId: "main" },
3689
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.32",
3
+ "version": "0.1.34",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",