@loxtep/sdk 0.7.7 → 0.7.10

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +119 -116
  3. package/dist/auth/browser-login.d.ts +6 -0
  4. package/dist/auth/browser-login.d.ts.map +1 -1
  5. package/dist/auth/browser-login.js +54 -26
  6. package/dist/auth/browser-login.js.map +1 -1
  7. package/dist/cli/commands/deploy-cmd.d.ts +2 -0
  8. package/dist/cli/commands/deploy-cmd.d.ts.map +1 -1
  9. package/dist/cli/commands/deploy-cmd.js +1 -1
  10. package/dist/cli/commands/deploy-cmd.js.map +1 -1
  11. package/dist/cli/commands/generate-cmd.d.ts +7 -1
  12. package/dist/cli/commands/generate-cmd.d.ts.map +1 -1
  13. package/dist/cli/commands/generate-cmd.js +4 -3
  14. package/dist/cli/commands/generate-cmd.js.map +1 -1
  15. package/dist/cli/commands/test-cmd.d.ts +2 -0
  16. package/dist/cli/commands/test-cmd.d.ts.map +1 -1
  17. package/dist/cli/commands/test-cmd.js +1 -1
  18. package/dist/cli/commands/test-cmd.js.map +1 -1
  19. package/dist/cli/commands/whoami.d.ts +10 -12
  20. package/dist/cli/commands/whoami.d.ts.map +1 -1
  21. package/dist/cli/commands/whoami.js +6 -2
  22. package/dist/cli/commands/whoami.js.map +1 -1
  23. package/dist/cli/create-cli-client.d.ts +2 -0
  24. package/dist/cli/create-cli-client.d.ts.map +1 -1
  25. package/dist/cli/create-cli-client.js +5 -1
  26. package/dist/cli/create-cli-client.js.map +1 -1
  27. package/dist/cli/index.js +0 -0
  28. package/dist/cli/version.d.ts.map +1 -1
  29. package/dist/cli/version.js +1 -6
  30. package/dist/cli/version.js.map +1 -1
  31. package/dist/client/current-user-response.d.ts +18 -0
  32. package/dist/client/current-user-response.d.ts.map +1 -0
  33. package/dist/client/current-user-response.js +50 -0
  34. package/dist/client/current-user-response.js.map +1 -0
  35. package/dist/client/session.d.ts.map +1 -1
  36. package/dist/client/session.js +4 -2
  37. package/dist/client/session.js.map +1 -1
  38. package/docs/code-first-cli.md +10 -8
  39. package/docs/event-replay-cookbook.md +3 -4
  40. package/docs/getting-started.md +152 -201
  41. package/docs/quick-reference.md +10 -11
  42. package/package.json +1 -1
  43. package/dist/cli/commands/connections-cmd.d.ts +0 -19
  44. package/dist/cli/commands/connections-cmd.d.ts.map +0 -1
  45. package/dist/cli/commands/connections-cmd.js +0 -39
  46. package/dist/cli/commands/connections-cmd.js.map +0 -1
  47. package/dist/cli/commands/data-assets-cmd.d.ts +0 -12
  48. package/dist/cli/commands/data-assets-cmd.d.ts.map +0 -1
  49. package/dist/cli/commands/data-assets-cmd.js +0 -75
  50. package/dist/cli/commands/data-assets-cmd.js.map +0 -1
  51. package/dist/cli/commands/flows-cmd.d.ts +0 -19
  52. package/dist/cli/commands/flows-cmd.d.ts.map +0 -1
  53. package/dist/cli/commands/flows-cmd.js +0 -37
  54. package/dist/cli/commands/flows-cmd.js.map +0 -1
  55. package/dist/cli/commands/pipelines-cmd.d.ts +0 -17
  56. package/dist/cli/commands/pipelines-cmd.d.ts.map +0 -1
  57. package/dist/cli/commands/pipelines-cmd.js +0 -52
  58. package/dist/cli/commands/pipelines-cmd.js.map +0 -1
  59. package/dist/cli/commands/promises-cmd.d.ts +0 -11
  60. package/dist/cli/commands/promises-cmd.d.ts.map +0 -1
  61. package/dist/cli/commands/promises-cmd.js +0 -53
  62. package/dist/cli/commands/promises-cmd.js.map +0 -1
  63. package/dist/client/connection-types.d.ts +0 -98
  64. package/dist/client/connection-types.d.ts.map +0 -1
  65. package/dist/client/connection-types.js +0 -18
  66. package/dist/client/connection-types.js.map +0 -1
  67. package/dist/client/connections.d.ts +0 -18
  68. package/dist/client/connections.d.ts.map +0 -1
  69. package/dist/client/connections.js +0 -66
  70. package/dist/client/connections.js.map +0 -1
  71. package/dist/client/consumptions-types.d.ts +0 -80
  72. package/dist/client/consumptions-types.d.ts.map +0 -1
  73. package/dist/client/consumptions-types.js +0 -5
  74. package/dist/client/consumptions-types.js.map +0 -1
  75. package/dist/client/consumptions.d.ts +0 -14
  76. package/dist/client/consumptions.d.ts.map +0 -1
  77. package/dist/client/consumptions.js +0 -47
  78. package/dist/client/consumptions.js.map +0 -1
  79. package/dist/client/data-assets-types.d.ts +0 -150
  80. package/dist/client/data-assets-types.d.ts.map +0 -1
  81. package/dist/client/data-assets-types.js +0 -5
  82. package/dist/client/data-assets-types.js.map +0 -1
  83. package/dist/client/data-assets.d.ts +0 -31
  84. package/dist/client/data-assets.d.ts.map +0 -1
  85. package/dist/client/data-assets.js +0 -182
  86. package/dist/client/data-assets.js.map +0 -1
  87. package/dist/client/delivery-types.d.ts +0 -97
  88. package/dist/client/delivery-types.d.ts.map +0 -1
  89. package/dist/client/delivery-types.js +0 -10
  90. package/dist/client/delivery-types.js.map +0 -1
  91. package/dist/client/delivery.d.ts +0 -23
  92. package/dist/client/delivery.d.ts.map +0 -1
  93. package/dist/client/delivery.js +0 -105
  94. package/dist/client/delivery.js.map +0 -1
  95. package/dist/client/flows.d.ts +0 -33
  96. package/dist/client/flows.d.ts.map +0 -1
  97. package/dist/client/flows.js +0 -218
  98. package/dist/client/flows.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,44 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to
7
7
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.7.10] - 2026-07-23
10
+
11
+ ### Fixed
12
+
13
+ - **`loxtep whoami`** parses the production `{ success, data: { user, organization } }`
14
+ envelope instead of expecting flat top-level fields (which showed `—` for email/org).
15
+
16
+ ### Added
17
+
18
+ - **CLI integration test suite** — mock platform API, read-only and mutating command
19
+ tests, local lifecycle (`init` → `attach` → `generate` → `deploy`), and opt-in
20
+ staging smoke (`LOXTEP_CLI_SMOKE=1`).
21
+ - **`parseCurrentUserResponse`** shared helper for session/whoami envelope parsing.
22
+ - **`fetch_fn`** on CLI client creation; **`cliOptions`** injection on
23
+ `generate`, `deploy`, and `test` commands for integration tests.
24
+
25
+ ### Changed
26
+
27
+ - **README and docs** rewritten for greenfield onboarding:
28
+ `login` → `init` → `attach` → `generate` before stream I/O or manual client config.
29
+ - **`tsconfig.json`** excludes `**/__tests__/**` from the publish build.
30
+
31
+ ## [0.7.9] - 2026-07-23
32
+
33
+ ### Fixed
34
+
35
+ - **Browser login** no longer hangs after printing success: the localhost callback
36
+ server now destroys keep-alive connections and closes immediately so the CLI
37
+ process exits as soon as tokens are saved.
38
+
39
+ ## [0.7.8] - 2026-07-23
40
+
41
+ ### Changed
42
+
43
+ - **README and quick reference** use customer-facing API area names instead of
44
+ internal MCP facade terminology (`loxtep_session`, "MCP-aligned facades", etc.).
45
+ SDK paths (`client.build`, …) are unchanged.
46
+
9
47
  ## [0.7.7] - 2026-07-23
10
48
 
11
49
  ### Changed
package/README.md CHANGED
@@ -1,55 +1,47 @@
1
1
  # Loxtep Node.js SDK
2
2
 
3
- Client for the Loxtep API. Since **v0.7.0**, the public surface mirrors the
4
- **10 hosted MCP tool facades** (no flat top-level namespaces like
5
- `client.workflows` or `client.data_products`).
3
+ Client for the Loxtep API. `LoxtepClient` groups platform APIs under
4
+ **namespaced areas** on the client:
6
5
 
7
- | MCP facade | SDK namespace | Examples |
6
+ | Area | SDK namespace | Examples |
8
7
  | --- | --- | --- |
9
- | `loxtep_session` | `client.session` | `get_current_user()` |
10
- | `loxtep_connect` | `client.connect` | `.connectors.*`, `.templates.*` |
11
- | `loxtep_workspace` | `client.workspace` | `.projects.*`, `.instances.*` |
12
- | `loxtep_build` | `client.build` | `.workflows.*`, `.triggers.*`, `.data_products.*`, `.targets.*` |
13
- | `loxtep_define` | `client.define` | `.schemas.*`, `.quality.*`, `.domains.*`, … |
14
- | `loxtep_meaning` | `client.meaning` | `.thesaurus.*` |
15
- | `loxtep_review` | `client.review` | `.approvals.*`, `.improvements.*` |
16
- | `loxtep_query` | `client.query` | `.catalog.*`, `.discovery.*`, `.query()` |
17
- | `loxtep_observe` | `client.observe` | `.stream_config()`, `.open_reader()` |
18
- | `loxtep_context` | `client.context` | `.procedures.*`, `.activity.*`, … |
19
-
20
- **Stream I/O** uses top-level helpers (not nested under a facade):
8
+ | Authentication | `client.session` | `get_current_user()` |
9
+ | Connect | `client.connect` | `.connectors.*`, `.templates.*` |
10
+ | Workspace | `client.workspace` | `.projects.*`, `.instances.*` |
11
+ | Build & deploy | `client.build` | `.workflows.*`, `.triggers.*`, `.data_products.*`, `.targets.*` |
12
+ | Governance | `client.define` | `.schemas.*`, `.quality.*`, `.domains.*`, … |
13
+ | Semantics | `client.meaning` | `.thesaurus.*` |
14
+ | Review | `client.review` | `.approvals.*`, `.improvements.*` |
15
+ | Analytics | `client.query` | `.catalog.*`, `.discovery.*`, `.query()` |
16
+ | Observe | `client.observe` | `.stream_config()`, `.open_reader()` |
17
+ | Context | `client.context` | `.procedures.*`, `.activity.*`, … |
18
+
19
+ **Stream I/O** uses top-level helpers on the client:
21
20
  `await client.get_writer('data-product-name')` and
22
- `await client.get_reader('data-product-name')`.
21
+ `await client.get_reader('data-product-name')` — but only after that data
22
+ product is **deployed** on your attached instance.
23
23
 
24
- Full mapping table: [`docs/sdk-mcp-mapping.md`](./docs/sdk-mcp-mapping.md).
25
- **Upgrading from 0.6.x:** replace `client.data_products` →
26
- `client.build.data_products` (CRUD/stream/replay) or `client.get_writer` /
27
- `client.get_reader` (recommended write/read path); `client.workflows` →
28
- `client.build.workflows`; etc.
29
-
30
- **Node.js 22+** is the supported runtime (`engines` in `package.json`). **Live**
24
+ **Node.js 22+** is the supported runtime (`engines` in `package.json`). Live
31
25
  queue/flow writes use the **Loxtep stream** data plane; configure stream bus
32
26
  resources (`streams` on `LoxtepClient` and instance env from your stack) and AWS
33
27
  credentials for SigV4 on both REST and the bus.
34
28
 
35
29
  ## Ways to get started
36
30
 
37
- This SDK supports two developer workflows:
38
-
39
31
  | Path | Use case | Entry point |
40
32
  |------|----------|-------------|
41
- | **Programmatic** | Write/read events from application code (microservices, lambdas, scripts) | `LoxtepClient``get_writer` / `get_reader` |
42
- | **Code-first CLI** | Author workflows as TypeScript, test locally, deploy via CI | `loxtep init attach → generate → test → deploy` |
43
-
44
- There are also two additional paths that don't require this SDK:
45
- - **Agent-first (MCP)** — drive Loxtep conversationally from Cursor, Kiro, Claude, etc. See [loxtep-plugins-skills](https://github.com/LoxtepInc/loxtep-plugins-skills).
46
- - **Web UI** — visual project setup and management at [app.loxtep.io](https://app.loxtep.io).
33
+ | **Code-first CLI** | New project on Loxtep scaffold, attach, author, deploy | `loxtep init attach generate → test → deploy` |
34
+ | **Programmatic** | App code that reads/writes events or calls APIs | `LoxtepClient.fromWorkspace()` after login + attach |
35
+ | **Agent-first (MCP)** | Conversational setup from your IDE | [loxtep-plugins-skills](https://github.com/LoxtepInc/loxtep-plugins-skills) |
36
+ | **Web UI** | Visual project and workflow management | [app.loxtep.io](https://app.loxtep.io) |
47
37
 
48
- All paths are documented in the [Loxtep Quickstart](https://docs.loxtep.io/quickstart).
38
+ All paths: [Loxtep Quickstart](https://docs.loxtep.io/quickstart).
49
39
 
50
40
  ---
51
41
 
52
- ## Quick start — Programmatic (< 5 min to first stream)
42
+ ## Quick start — First run (recommended)
43
+
44
+ Run these in an **empty directory** you want to turn into a Loxtep workspace.
53
45
 
54
46
  1. **Install**
55
47
 
@@ -57,124 +49,138 @@ All paths are documented in the [Loxtep Quickstart](https://docs.loxtep.io/quick
57
49
  pnpm add @loxtep/sdk
58
50
  ```
59
51
 
60
- 2. **Log in**
52
+ 2. **Log in and confirm identity**
61
53
 
62
54
  ```bash
63
55
  pnpm exec loxtep login
56
+ pnpm exec loxtep whoami
64
57
  ```
65
58
 
66
- A browser window opens — sign in to Loxtep and you're authenticated.
67
- Tokens are saved to `./.loxtep/credentials.json` (use `--global` for home dir).
59
+ Tokens are saved to `./.loxtep/credentials.json` by default (use
60
+ `--global` for `~/.loxtep/credentials.json`).
68
61
 
69
- > **CI/headless:** Use `pnpm exec loxtep login --email you@co.com --password ...`
70
- > or set `LOXTEP_AUTH_TOKEN` in your environment.
62
+ > **CI/headless:** `pnpm exec loxtep login --email you@co.com --password …`
63
+ > or set `LOXTEP_AUTH_TOKEN`.
71
64
 
72
- 3. **Create a client, write and read events**
65
+ 3. **Scaffold the workspace**
73
66
 
74
- ```ts
75
- import { LoxtepClient } from '@loxtep/sdk';
67
+ ```bash
68
+ pnpm exec loxtep init
69
+ # optional: pnpm exec loxtep init --template shopify-orders
70
+ ```
76
71
 
77
- const client = new LoxtepClient({
78
- api_url: 'https://api.loxtep.com',
79
- auth: { type: 'jwt', token: process.env.LOXTEP_AUTH_TOKEN! },
80
- });
72
+ Creates `.loxtep/project.json`, `workflows/`, `connectors/`, `domains/`,
73
+ and `data-products/`.
81
74
 
82
- // Write events to a data product (top-level — resolves deployment metadata)
83
- const writer = await client.get_writer('shopify_gql_customer');
84
- writer.write({
85
- customer_id: '123',
86
- name: 'Alice',
87
- email: 'alice@example.com',
88
- });
89
- await writer.close();
75
+ 4. **Attach to a runtime instance**
90
76
 
91
- // Read events from a data product
92
- const reader = await client.get_reader('shopify_gql_customer');
93
- for await (const event of reader) {
94
- console.log(event);
95
- }
77
+ ```bash
78
+ pnpm exec loxtep instances list
79
+ pnpm exec loxtep attach --instance <instance-id>
96
80
  ```
97
81
 
98
- That's it. The SDK resolves the data product's queue, bot identity, and
99
- stream bus configuration automatically from the deployment metadata. No
100
- manual queue names, no stream config, no bot IDs.
82
+ Writes `instance_id` and `api_url` into `.loxtep/project.json`. Required
83
+ before `generate`, `test`, and `deploy`.
101
84
 
102
- 4. **Stream config from the platform (optional)** — after login,
103
- `await client.observe.stream_config()` returns stream resource names
104
- needed for the data plane. Merge into
105
- `new LoxtepClient({ ...opts, streams: { ...partial } })` with your
106
- JWT-backed client. `get_writer` / `get_reader` resolve stream config
107
- automatically — this step is only needed for manual bus access via
108
- `client.observe.open_reader()`.
85
+ 5. **Generate typed workspace constants**
109
86
 
110
- ---
87
+ ```bash
88
+ pnpm exec loxtep generate
89
+ ```
111
90
 
112
- ## Quick start Code-first CLI (init → deploy)
91
+ Emits `.loxtep/generated/index.ts` from live platform metadata.
113
92
 
114
- For developers who author workflows as TypeScript and want the full local-dev-to-production lifecycle, see the dedicated **[Code-first CLI guide](./docs/code-first-cli.md)**. Quick version:
93
+ 6. **See what's on the instance**
115
94
 
116
- ```bash
117
- # 1. Install
118
- pnpm add @loxtep/sdk
95
+ ```bash
96
+ pnpm exec loxtep data-products list
97
+ pnpm exec loxtep workflows list --project-id <project-id-from-project.json>
98
+ ```
99
+
100
+ A brand-new org may have **no data products yet** — that's expected. Create
101
+ and deploy workflows (below, or via MCP/UI) before calling `get_writer`.
102
+
103
+ 7. **Author, test, and deploy** (when you're ready)
104
+
105
+ ```bash
106
+ pnpm exec loxtep test <module> --event ./events/sample.json
107
+ pnpm exec loxtep deploy
108
+ ```
119
109
 
120
- # 2. Authenticate
121
- pnpm exec loxtep login
110
+ See **[Code-first CLI guide](./docs/code-first-cli.md)** for workflow
111
+ modules and templates.
122
112
 
123
- # 3. Scaffold a project from a template
124
- pnpm exec loxtep init --template shopify-orders
113
+ ### Bootstrap the SDK from your workspace
125
114
 
126
- # 4. Bind to a runtime instance
127
- pnpm exec loxtep attach --instance prod
115
+ After steps 1–4 above, application code can use auto-config — no hand-built
116
+ client options:
128
117
 
129
- # 5. Generate typed workspace constants
130
- pnpm exec loxtep generate
118
+ ```ts
119
+ import { LoxtepClient } from '@loxtep/sdk';
120
+
121
+ const client = await LoxtepClient.fromWorkspace();
122
+ const { user, organization } = await client.session.get_current_user();
123
+ console.log(user.email, organization?.name);
124
+ ```
131
125
 
132
- # 6. Author a workflow (see authoring module docs below)
126
+ ### Write and read events (after deploy)
133
127
 
134
- # 7. Test locally with a sample event
135
- pnpm exec loxtep test orders-enricher --event ./events/order-created.json
128
+ `get_writer` / `get_reader` resolve queue, bot, and stream config from
129
+ **deployment metadata**. Use a name from `loxtep data-products list` after
130
+ your workflow is deployed:
131
+
132
+ ```ts
133
+ const client = await LoxtepClient.fromWorkspace();
134
+
135
+ const writer = await client.get_writer('orders');
136
+ writer.write({ order_id: '1', total: 42.0 });
137
+ await writer.close();
136
138
 
137
- # 8. Deploy to the workflow engine
138
- pnpm exec loxtep deploy
139
+ const reader = await client.get_reader('orders');
140
+ for await (const event of reader) {
141
+ console.log(event);
142
+ break;
143
+ }
139
144
  ```
140
145
 
141
- The `generate` step produces `.loxtep/generated/index.ts` with typed constants for every data product, connector, domain, and queue in your workspace. Import them in your workflow modules for compile-time safety:
146
+ ---
147
+
148
+ ## Quick start — Code-first workflow module
149
+
150
+ After `init`, `attach`, and `generate`, import typed constants in workflow
151
+ modules:
142
152
 
143
153
  ```ts
144
- import { defineDataWorkflow, on } from '@loxtep/sdk'
145
- import { workspace } from './.loxtep/generated'
154
+ import { defineDataWorkflow, on } from '@loxtep/sdk';
155
+ import { workspace } from './.loxtep/generated';
146
156
 
147
157
  export default defineDataWorkflow({
148
158
  name: 'orders-enricher',
149
- triggers: [on.queueEvent(workspace.queues.orders_raw)],
150
- async handler(ctx, event) {
151
- await ctx.toolbox.dataProducts.upsert({
152
- dataProduct: workspace.dataProducts.orders_enriched,
153
- domain: workspace.domains.commerce,
154
- record: event,
155
- })
159
+ triggers: [on.webhook('/orders')],
160
+ async handler(_ctx, event) {
161
+ console.log('received', event);
156
162
  },
157
- })
163
+ });
158
164
  ```
159
165
 
160
- See `loxtep init --help`, `loxtep attach --help`, etc. for all flags. The full CLI reference is in the [CLI reference](#cli-reference) section below.
166
+ See `loxtep init --help`, `loxtep attach --help`, etc. CLI reference below.
161
167
 
162
168
  ---
163
169
 
164
170
  ## API surface
165
171
 
166
- Every method is `snake_case`. Use the **10 MCP-aligned facades** on
167
- `LoxtepClient` (see table at the top). Nested APIs keep descriptive names
168
- (`workflows`, `data_products`, `connectors`, …) under their facade.
172
+ Every method is `snake_case`. APIs live on **namespaced areas** of
173
+ `LoxtepClient` (see table at the top). Nested APIs use descriptive names
174
+ (`workflows`, `data_products`, `connectors`, …) under each area.
169
175
 
170
176
  ### Top-level stream I/O (preferred)
171
177
 
172
178
  - **`get_writer(name_or_id)`** — write path; resolves queue, bot, stream config
173
179
  - **`get_reader(name_or_id)`** — async iterable read path
174
180
  - **`LoxtepClient.fromWorkspace()`** — construct from `.loxtep/project.json` +
175
- `~/.loxtep/credentials.json` (env overrides: `LOXTEP_API_URL`, `LOXTEP_TOKEN`, …)
181
+ `./.loxtep/credentials.json` (env overrides: `LOXTEP_API_URL`, `LOXTEP_TOKEN`, …)
176
182
 
177
- ### `client.build` (MCP: loxtep_build)
183
+ ### Build & deploy (`client.build`)
178
184
 
179
185
  - **`.workflows`** — `list`, `get`, `create`, `get_graph`, `deploy`; low-level
180
186
  `.get_writer(workflow_id, { bot_id, … })` escape hatch
@@ -184,30 +190,30 @@ Every method is `snake_case`. Use the **10 MCP-aligned facades** on
184
190
  `client.get_writer` / `get_reader`)
185
191
  - **`.targets`** — delivery sink bindings (`list`, `get`, `create`, `update`, `delete`)
186
192
 
187
- ### `client.connect` (MCP: loxtep_connect)
193
+ ### Connect (`client.connect`)
188
194
 
189
195
  - **`.connectors`** — org-level connector credentials
190
196
  - **`.templates`** — starter templates (`list`, `get`, `apply_template` on projects)
191
197
 
192
- ### `client.workspace` (MCP: loxtep_workspace)
198
+ ### Workspace (`client.workspace`)
193
199
 
194
200
  - **`.projects`** — `list`, `get`, `create`, `update`, `delete`, `apply_template`
195
201
  - **`.instances`** — `list`, `get`, stream config helpers
196
202
 
197
- ### `client.define` (MCP: loxtep_define)
203
+ ### Governance (`client.define`)
198
204
 
199
205
  - **`.schemas`**, **`.quality`**, **`.standards`**, **`.data_contracts`**, **`.domains`**
200
206
 
201
- ### `client.query` (MCP: loxtep_query)
207
+ ### Analytics (`client.query`)
202
208
 
203
209
  - **`.catalog`**, **`.discovery`**, **`.query()`**, **`.list_tables()`**, **`.search()`**
204
210
 
205
- ### `client.observe` (MCP: loxtep_observe)
211
+ ### Observe (`client.observe`)
206
212
 
207
213
  - **`status()`**, **`stream_config()`**, **`open_reader()`**, **`open_writer()`**,
208
214
  **`get_queue_metadata()`**, **`get_reader_checkpoint()`**
209
215
 
210
- ### Other facades
216
+ ### Authentication, semantics, review, and context
211
217
 
212
218
  - **`client.session`** — `get_current_user`, `get_current_organization`, `logout`
213
219
  - **`client.meaning`** — `.thesaurus.*`
@@ -215,8 +221,6 @@ Every method is `snake_case`. Use the **10 MCP-aligned facades** on
215
221
  - **`client.context`** — `.procedures.*`, `.activity.*`, `.process_intelligence.*`
216
222
  - **`client.metrics`** — `log`, `get_reporter` (stub until metrics wiring lands)
217
223
 
218
- See [`docs/sdk-mcp-mapping.md`](./docs/sdk-mcp-mapping.md) for the full MCP ↔ SDK table.
219
-
220
224
  ## Data product writer and reader
221
225
 
222
226
  `await client.get_writer('name')` resolves the data product's queue, bot
@@ -300,12 +304,11 @@ await client.build.targets.delete('dp_abc123', webhook.consumption_id);
300
304
 
301
305
  ## Documentation
302
306
 
303
- - **[Getting started](./docs/getting-started.md)** – Zero to first event in under 5 minutes (programmatic; no init).
307
+ - **[Getting started](./docs/getting-started.md)** – Login, init, attach, generate then stream I/O after deploy.
304
308
  - **[Code-first CLI](./docs/code-first-cli.md)** – `loxtep init`, attach, generate, test, deploy.
305
309
  - **[Quick reference](./docs/quick-reference.md)** – Single-page cheat sheet.
306
310
  - **[Event replay cookbook](./docs/event-replay-cookbook.md)** – Replay events from a data product or queue.
307
- - **[MCP + SDK pairing](./docs/sdk-pairing.md)** – One auth story, when MCP vs SDK.
308
- - **[MCP → SDK mapping](./docs/sdk-mcp-mapping.md)** – Agent-oriented table.
311
+ - **[SDK + agent pairing](./docs/sdk-pairing.md)** – When to use the SDK vs IDE agent integrations.
309
312
  - **Typed errors** – `import { … } from '@loxtep/sdk/errors'`.
310
313
  - **API reference** – `pnpm run docs` (Typedoc).
311
314
 
@@ -12,6 +12,8 @@
12
12
  * 4. App redirects to our localhost callback with access_token + refresh_token
13
13
  * 5. Return tokens to caller, shut down server
14
14
  */
15
+ import { type Server } from 'node:http';
16
+ import type { Socket } from 'node:net';
15
17
  export interface BrowserLoginOptions {
16
18
  /** Loxtep app URL (e.g. https://app.loxtep.io or https://appdev.loxtep.io). */
17
19
  app_url: string;
@@ -21,6 +23,8 @@ export interface BrowserLoginOptions {
21
23
  timeout_ms?: number;
22
24
  /** If true, don't auto-open the browser — just print the URL. */
23
25
  no_open?: boolean;
26
+ /** For tests: invoked once the callback server is listening (with bound port). */
27
+ on_listening?: (port: number) => void;
24
28
  }
25
29
  export interface BrowserLoginResult {
26
30
  access_token: string;
@@ -33,6 +37,8 @@ export interface BrowserLoginResult {
33
37
  expiration: string;
34
38
  };
35
39
  }
40
+ /** Force-close keep-alive sockets so the CLI process can exit immediately. */
41
+ export declare function shutdownCallbackServer(server: Server, sockets: Set<Socket>): void;
36
42
  /**
37
43
  * Run the browser-based OAuth login flow.
38
44
  * Returns tokens on success, throws on timeout or failure.
@@ -1 +1 @@
1
- {"version":3,"file":"browser-login.d.ts","sourceRoot":"","sources":["../../src/auth/browser-login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE;QAChB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAYD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwFtF"}
1
+ {"version":3,"file":"browser-login.d.ts","sourceRoot":"","sources":["../../src/auth/browser-login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AACjG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAKvC,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE;QAChB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAID,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CASjF;AAmBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyGtF"}
@@ -16,31 +16,65 @@ import { createServer } from 'node:http';
16
16
  import { URL } from 'node:url';
17
17
  import { exec } from 'node:child_process';
18
18
  import { platform } from 'node:os';
19
+ const CLOSE_HEADERS = { Connection: 'close' };
20
+ /** Force-close keep-alive sockets so the CLI process can exit immediately. */
21
+ export function shutdownCallbackServer(server, sockets) {
22
+ for (const socket of sockets) {
23
+ socket.destroy();
24
+ }
25
+ sockets.clear();
26
+ const maybeCloseAll = server;
27
+ maybeCloseAll.closeAllConnections?.();
28
+ server.close();
29
+ }
19
30
  /**
20
31
  * Open a URL in the user's default browser.
21
32
  */
22
33
  function openBrowser(url) {
23
34
  const os = platform();
24
35
  const cmd = os === 'darwin' ? 'open' : os === 'win32' ? 'start' : 'xdg-open';
25
- exec(`${cmd} "${url}"`);
36
+ const child = exec(`${cmd} "${url}"`);
37
+ child.unref?.();
38
+ }
39
+ function finishResponse(res, body, status = 200) {
40
+ res.writeHead(status, { 'Content-Type': 'text/html', ...CLOSE_HEADERS });
41
+ res.end(body);
42
+ res.socket?.destroy();
26
43
  }
27
44
  /**
28
45
  * Run the browser-based OAuth login flow.
29
46
  * Returns tokens on success, throws on timeout or failure.
30
47
  */
31
48
  export function browserLogin(options) {
32
- const { app_url, timeout_ms = 300_000, no_open = false } = options;
49
+ const { app_url, timeout_ms = 300_000, no_open = false, on_listening } = options;
33
50
  return new Promise((resolve, reject) => {
34
51
  let settled = false;
35
52
  let timeoutId;
53
+ const sockets = new Set();
54
+ const settleSuccess = (result) => {
55
+ if (settled)
56
+ return;
57
+ settled = true;
58
+ if (timeoutId)
59
+ clearTimeout(timeoutId);
60
+ shutdownCallbackServer(server, sockets);
61
+ resolve(result);
62
+ };
63
+ const settleFailure = (err) => {
64
+ if (settled)
65
+ return;
66
+ settled = true;
67
+ if (timeoutId)
68
+ clearTimeout(timeoutId);
69
+ shutdownCallbackServer(server, sockets);
70
+ reject(err);
71
+ };
36
72
  const server = createServer((req, res) => {
37
73
  const reqUrl = new URL(req.url ?? '/', `http://localhost`);
38
74
  if (reqUrl.pathname === '/callback') {
39
- // Tokens come as query params from the Loxtep app redirect
40
75
  const access_token = reqUrl.searchParams.get('access_token');
41
76
  const refresh_token = reqUrl.searchParams.get('refresh_token') ?? undefined;
42
77
  const expires_at = reqUrl.searchParams.get('expires_at') ?? undefined;
43
- // AWS credentials (optional, URL-encoded JSON)
44
78
  let aws_credentials;
45
79
  const awsCredsParam = reqUrl.searchParams.get('aws_credentials');
46
80
  if (awsCredsParam) {
@@ -52,30 +86,31 @@ export function browserLogin(options) {
52
86
  }
53
87
  }
54
88
  if (!access_token) {
55
- res.writeHead(400, { 'Content-Type': 'text/html' });
56
- res.end('<html><body><h2>Login failed</h2><p>No access token received. Close this window and try again.</p></body></html>');
89
+ finishResponse(res, '<html><body><h2>Login failed</h2><p>No access token received. Close this window and try again.</p></body></html>', 400);
57
90
  return;
58
91
  }
59
- res.writeHead(200, { 'Content-Type': 'text/html' });
60
- res.end('<html><body><h2>Login successful!</h2><p>You can close this window and return to your terminal.</p></body></html>');
61
- settled = true;
62
- if (timeoutId)
63
- clearTimeout(timeoutId);
64
- server.close();
65
- resolve({ access_token, refresh_token, expires_at, aws_credentials });
92
+ finishResponse(res, '<html><body><h2>Login successful!</h2><p>You can close this window and return to your terminal.</p></body></html>');
93
+ settleSuccess({ access_token, refresh_token, expires_at, aws_credentials });
66
94
  return;
67
95
  }
68
- // Health check / catch-all
69
- res.writeHead(200, { 'Content-Type': 'text/plain' });
96
+ res.writeHead(200, { 'Content-Type': 'text/plain', ...CLOSE_HEADERS });
70
97
  res.end('Loxtep SDK login callback server');
98
+ res.socket?.destroy();
99
+ });
100
+ server.on('connection', socket => {
101
+ sockets.add(socket);
102
+ socket.on('close', () => {
103
+ sockets.delete(socket);
104
+ });
71
105
  });
72
106
  server.listen(0, '127.0.0.1', () => {
73
107
  const addr = server.address();
74
108
  if (!addr || typeof addr === 'string') {
75
- reject(new Error('Failed to start callback server'));
109
+ settleFailure(new Error('Failed to start callback server'));
76
110
  return;
77
111
  }
78
112
  const port = addr.port;
113
+ on_listening?.(port);
79
114
  const callbackUrl = `http://localhost:${port}/callback`;
80
115
  const loginUrl = `${app_url.replace(/\/$/, '')}/auth/mcp?callback_url=${encodeURIComponent(callbackUrl)}`;
81
116
  if (no_open) {
@@ -89,19 +124,12 @@ export function browserLogin(options) {
89
124
  console.log('Waiting for login to complete...');
90
125
  });
91
126
  server.on('error', err => {
92
- if (!settled) {
93
- settled = true;
94
- reject(new Error(`Callback server error: ${err.message}`));
95
- }
127
+ settleFailure(new Error(`Callback server error: ${err.message}`));
96
128
  });
97
- // Timeout
98
129
  timeoutId = setTimeout(() => {
99
- if (!settled) {
100
- settled = true;
101
- server.close();
102
- reject(new Error(`Login timed out after ${timeout_ms / 1000} seconds. Try again.`));
103
- }
130
+ settleFailure(new Error(`Login timed out after ${timeout_ms / 1000} seconds. Try again.`));
104
131
  }, timeout_ms);
132
+ timeoutId.unref?.();
105
133
  });
106
134
  }
107
135
  //# sourceMappingURL=browser-login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-login.js","sourceRoot":"","sources":["../../src/auth/browser-login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-login.js","sourceRoot":"","sources":["../../src/auth/browser-login.ts"],"names":[],"mappings":"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"}
@@ -82,6 +82,8 @@ export declare function validateReferencedResources(compiledModules: Array<{
82
82
  export interface DeployCommandOptions {
83
83
  /** Working directory (defaults to process.cwd()). */
84
84
  cwd?: string;
85
+ /** Mock fetch / config paths for integration tests. */
86
+ cliOptions?: import('../create-cli-client.js').CreateCliClientOptions;
85
87
  }
86
88
  /**
87
89
  * Execute the `loxtep deploy` command.
@@ -1 +1 @@
1
- {"version":3,"file":"deploy-cmd.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/deploy-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAK/B,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,6BAA6B,CAAC;AAGjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAMhE,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,YAAY,EAAE,UAAU,CAAA;CAAE,CAAC;AAE9D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAYjG;AAwBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAgBpE;AAMD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACpE,GAAG,EAAE,iBAAiB,GACrB,eAAe,EAAE,CA2CnB;AAiFD,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,SAAS,CAAC,CA0Q7F;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAW/C"}
1
+ {"version":3,"file":"deploy-cmd.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/deploy-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAK/B,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,6BAA6B,CAAC;AAGjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAMhE,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qDAAqD;AACrD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,YAAY,EAAE,UAAU,CAAA;CAAE,CAAC;AAE9D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAYjG;AAwBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAgBpE;AAMD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACpE,GAAG,EAAE,iBAAiB,GACrB,eAAe,EAAE,CA2CnB;AAiFD,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,yBAAyB,EAAE,sBAAsB,CAAC;CACvE;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,SAAS,CAAC,CA0Q7F;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAW/C"}
@@ -213,7 +213,7 @@ export async function runDeployCommand(options = {}) {
213
213
  const { projectDir, project } = precondition;
214
214
  const { project_id: projectId, instance_id: instanceId } = project;
215
215
  // 2. Get an authenticated client
216
- const clientResult = await requireCliClient();
216
+ const clientResult = await requireCliClient(options.cliOptions);
217
217
  const { client } = clientResult;
218
218
  // 3. Load workspace context (needed for compilation and validation)
219
219
  let context;