@loxtep/sdk 0.7.19 → 0.7.22
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/CHANGELOG.md +36 -0
- package/README.md +12 -13
- package/dist/cli/commands/attach-cmd.d.ts.map +1 -1
- package/dist/cli/commands/attach-cmd.js +8 -3
- package/dist/cli/commands/attach-cmd.js.map +1 -1
- package/dist/cli/commands/config-cmd.d.ts.map +1 -1
- package/dist/cli/commands/config-cmd.js +3 -2
- package/dist/cli/commands/config-cmd.js.map +1 -1
- package/dist/cli/commands/ingest-cmd.d.ts.map +1 -1
- package/dist/cli/commands/ingest-cmd.js +1 -2
- package/dist/cli/commands/ingest-cmd.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +0 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/client/instances-types.d.ts +11 -0
- package/dist/client/instances-types.d.ts.map +1 -1
- package/dist/client/instances.d.ts +9 -13
- package/dist/client/instances.d.ts.map +1 -1
- package/dist/client/instances.js +6 -5
- package/dist/client/instances.js.map +1 -1
- package/dist/errors/parse-http.d.ts +0 -9
- package/dist/errors/parse-http.d.ts.map +1 -1
- package/dist/errors/parse-http.js +28 -4
- package/dist/errors/parse-http.js.map +1 -1
- package/dist/http/client.d.ts +8 -4
- package/dist/http/client.d.ts.map +1 -1
- package/dist/http/client.js +13 -13
- package/dist/http/client.js.map +1 -1
- package/dist/lib/instance-stream-config.d.ts +19 -3
- package/dist/lib/instance-stream-config.d.ts.map +1 -1
- package/dist/lib/instance-stream-config.js +94 -2
- package/dist/lib/instance-stream-config.js.map +1 -1
- package/docs/getting-started.md +4 -16
- package/docs/quick-reference.md +8 -9
- package/docs/sdk-first-ingest.md +53 -232
- package/package.json +1 -1
- package/docs/examples/generate-ingest-bundle.mjs +0 -133
- package/docs/examples/write-events.mjs +0 -54
package/docs/sdk-first-ingest.md
CHANGED
|
@@ -1,263 +1,80 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Write to a data product from your app
|
|
2
2
|
|
|
3
|
-
You
|
|
4
|
-
**
|
|
3
|
+
You installed the SDK, initialized a workspace, and attached an instance. Next:
|
|
4
|
+
**create a data product**, open a writer, and send events from your code.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
first — you want your app (or ETL job) to push events into a **source** data
|
|
8
|
-
product on your attached instance.
|
|
9
|
-
|
|
10
|
-
> **Full CLI workspace setup:** [Getting Started](./getting-started.md) steps 1–4.
|
|
11
|
-
> **Code-first workflow modules:** [Code-first CLI](./code-first-cli.md).
|
|
6
|
+
> Already set up login, init, and attach? [Getting started](./getting-started.md).
|
|
12
7
|
|
|
13
8
|
---
|
|
14
9
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
```text
|
|
18
|
-
Your app ──get_writer──▶ rstreams queue ──▶ source data product (catalog)
|
|
19
|
-
▲ ▲
|
|
20
|
-
│ │
|
|
21
|
-
@loxtep/sdk provisioned at deploy time
|
|
22
|
-
fromWorkspace()
|
|
23
|
-
```
|
|
10
|
+
## Phase 1 — Workspace ready
|
|
24
11
|
|
|
25
|
-
|
|
26
|
-
**deployment metadata** (`deployment_bindings` on the data product). A catalog
|
|
27
|
-
row alone is not enough — the ingestion workflow must be **saved and deployed**
|
|
28
|
-
on your attached instance first.
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Prerequisites
|
|
33
|
-
|
|
34
|
-
Run from your scaffolded workspace (directory with `.loxtep/project.json`):
|
|
12
|
+
Run commands from your project directory (the folder with `.loxtep/project.json`).
|
|
35
13
|
|
|
36
14
|
```bash
|
|
37
|
-
pnpm exec loxtep
|
|
38
|
-
pnpm exec loxtep
|
|
15
|
+
pnpm exec loxtep login
|
|
16
|
+
pnpm exec loxtep init
|
|
17
|
+
pnpm exec loxtep attach --instance <instance-id>
|
|
18
|
+
pnpm exec loxtep config list
|
|
39
19
|
```
|
|
40
20
|
|
|
41
|
-
|
|
21
|
+
You should see `project_id` and `instance_id` from `attach`.
|
|
42
22
|
|
|
43
23
|
---
|
|
44
24
|
|
|
45
|
-
##
|
|
46
|
-
|
|
47
|
-
| Phase | What | How |
|
|
48
|
-
| ----- | ---- | --- |
|
|
49
|
-
| 1 | Workspace ready | `login` → `init` → `attach` (done) |
|
|
50
|
-
| 2 | Provision runtime | SDK connector + workflow bundle + deploy |
|
|
51
|
-
| 3 | Verify | `data-products list` / `data-products get` |
|
|
52
|
-
| 4 | Write events | `LoxtepClient.fromWorkspace()` + `get_writer` |
|
|
53
|
-
|
|
54
|
-
Phases 2–4 below.
|
|
55
|
-
|
|
56
|
-
---
|
|
25
|
+
## Phase 2 — Create your data product
|
|
57
26
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Runtime provisioning creates the workflow graph (SDK connection node → source
|
|
61
|
-
data product node), saves it to your project workspace, and **deploys** it to your
|
|
62
|
-
instance so queues and bots exist.
|
|
63
|
-
|
|
64
|
-
### Option A — CLI one-shot (recommended, no MCP)
|
|
65
|
-
|
|
66
|
-
From your workspace root (after `login`, `init`, `attach`):
|
|
27
|
+
Pick a name your app will use (example: `app-events`):
|
|
67
28
|
|
|
68
29
|
```bash
|
|
69
30
|
pnpm exec loxtep ingest provision --name app-events
|
|
70
31
|
```
|
|
71
32
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
1. Creates an org-level **SDK connector** (`connector_type: "sdk"`).
|
|
75
|
-
2. Builds and saves the workflow bundle (`workflow.json` + connection + source data product).
|
|
76
|
-
3. **Deploys** to your attached instance (unless you pass `--no-deploy` or `--dry-run`).
|
|
77
|
-
|
|
78
|
-
Validate first without writing:
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
pnpm exec loxtep ingest provision --name app-events --dry-run
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Option B — Helper script + bundle save
|
|
85
|
-
|
|
86
|
-
Generate bundle JSON only:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
node node_modules/@loxtep/sdk/docs/examples/generate-ingest-bundle.mjs
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Then persist and deploy via CLI:
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
pnpm exec loxtep bundle save --dry-run --file .loxtep/sdk-ingest-bundle.json
|
|
96
|
-
pnpm exec loxtep bundle save --file .loxtep/sdk-ingest-bundle.json
|
|
97
|
-
pnpm exec loxtep workflows deploy \
|
|
98
|
-
--project-id <project-id-from-config-list> \
|
|
99
|
-
--instance-id <instance-id-from-config-list>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Or set `LOXTEP_AUTO_SAVE=1` on the helper script to save + deploy in one step.
|
|
103
|
-
|
|
104
|
-
Poll until deployment completes (Web UI **Observe**, or `loxtep observe status`).
|
|
105
|
-
|
|
106
|
-
### Option C — Loxtep MCP (Cursor / agent)
|
|
107
|
-
|
|
108
|
-
Use **`loxtep_build`** → `save_workflow_bundle` if you prefer MCP authoring.
|
|
109
|
-
Same bundle shape as below; deploy with `loxtep workflows deploy` or MCP
|
|
110
|
-
`deploy_project`.
|
|
111
|
-
|
|
112
|
-
### Option D — Web UI (Studio)
|
|
113
|
-
|
|
114
|
-
Create an **ingestion** workflow with an **SDK** connection node and a **source**
|
|
115
|
-
data product node, then deploy to your attached instance from the Studio deploy
|
|
116
|
-
flow.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
### Workflow bundle shape
|
|
121
|
-
|
|
122
|
-
Minimal ingestion bundle (SDK connection → source data product). Replace UUIDs
|
|
123
|
-
and names; `connector_id` must be the SDK connector from step 2A or 2B.
|
|
124
|
-
|
|
125
|
-
```json
|
|
126
|
-
{
|
|
127
|
-
"workflow.json": {
|
|
128
|
-
"workflow_id": "<workflow-uuid>",
|
|
129
|
-
"organization_id": "<org-uuid>",
|
|
130
|
-
"project_id": "<project-uuid>",
|
|
131
|
-
"name": "SDK App Events Ingest",
|
|
132
|
-
"workflow_type": "ingestion",
|
|
133
|
-
"domain_id": "<domain-uuid>",
|
|
134
|
-
"status": "active",
|
|
135
|
-
"configuration": {},
|
|
136
|
-
"metadata": {},
|
|
137
|
-
"created_at": "2026-07-23T00:00:00.000Z",
|
|
138
|
-
"updated_at": "2026-07-23T00:00:00.000Z"
|
|
139
|
-
},
|
|
140
|
-
"connections/<connection-uuid>.json": {
|
|
141
|
-
"connection_id": "<connection-uuid>",
|
|
142
|
-
"organization_id": "<org-uuid>",
|
|
143
|
-
"project_id": "<project-uuid>",
|
|
144
|
-
"workflow_id": "<workflow-uuid>",
|
|
145
|
-
"connector_id": "<sdk-connector-uuid>",
|
|
146
|
-
"key": "sdk-input",
|
|
147
|
-
"name": "SDK Input",
|
|
148
|
-
"type": "sdk",
|
|
149
|
-
"status": "active",
|
|
150
|
-
"configuration": {
|
|
151
|
-
"sdk_type": "nodejs",
|
|
152
|
-
"event_type": "app-events"
|
|
153
|
-
},
|
|
154
|
-
"created_at": "2026-07-23T00:00:00.000Z",
|
|
155
|
-
"updated_at": "2026-07-23T00:00:00.000Z"
|
|
156
|
-
},
|
|
157
|
-
"data-products/<data-product-uuid>.json": {
|
|
158
|
-
"data_product_id": "<data-product-uuid>",
|
|
159
|
-
"organization_id": "<org-uuid>",
|
|
160
|
-
"project_id": "<project-uuid>",
|
|
161
|
-
"workflow_id": "<workflow-uuid>",
|
|
162
|
-
"upstream_entity_id": "<connection-uuid>",
|
|
163
|
-
"upstream_entity_type": "connections",
|
|
164
|
-
"domain_id": "<domain-uuid>",
|
|
165
|
-
"name": "app-events",
|
|
166
|
-
"kind": "source",
|
|
167
|
-
"status": "draft",
|
|
168
|
-
"owner": {},
|
|
169
|
-
"governance": {
|
|
170
|
-
"classification": "internal",
|
|
171
|
-
"pii_fields": [],
|
|
172
|
-
"compliance_requirements": [],
|
|
173
|
-
"tags": []
|
|
174
|
-
},
|
|
175
|
-
"metadata": {},
|
|
176
|
-
"created_at": "2026-07-23T00:00:00.000Z",
|
|
177
|
-
"updated_at": "2026-07-23T00:00:00.000Z"
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
The **`name`** on the data product node (`app-events` above) is what you pass
|
|
183
|
-
to `get_writer('app-events')`.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
### Do not stop at `data-products create`
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
# Creates a catalog row only — get_writer will fail with "not deployed"
|
|
191
|
-
pnpm exec loxtep data-products create --name app-events --domain-id <uuid> --kind source
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Use **`data-products create`** only when you already have (or will immediately
|
|
195
|
-
add) a deployed workflow that sets `deployment_bindings`. For greenfield SDK
|
|
196
|
-
ingest, prefer the bundle + deploy path above.
|
|
33
|
+
That is all you need for SDK writes — one command, one name.
|
|
197
34
|
|
|
198
35
|
---
|
|
199
36
|
|
|
200
|
-
## Phase 3 —
|
|
37
|
+
## Phase 3 — Confirm it exists
|
|
201
38
|
|
|
202
39
|
```bash
|
|
203
40
|
pnpm exec loxtep data-products list
|
|
204
|
-
pnpm exec loxtep data-products get <data-product-id>
|
|
205
41
|
```
|
|
206
42
|
|
|
207
|
-
|
|
208
|
-
`queue_name`, `bot_id`, and `instance_id`. If those are missing, finish Phase 2
|
|
209
|
-
before writing.
|
|
210
|
-
|
|
211
|
-
Re-run code generation after platform changes:
|
|
212
|
-
|
|
213
|
-
```bash
|
|
214
|
-
pnpm exec loxtep generate
|
|
215
|
-
```
|
|
43
|
+
You should see `app-events` (or whatever name you chose).
|
|
216
44
|
|
|
217
45
|
---
|
|
218
46
|
|
|
219
|
-
## Phase 4 — Write
|
|
220
|
-
|
|
221
|
-
Copy or run the example:
|
|
222
|
-
|
|
223
|
-
```bash
|
|
224
|
-
node node_modules/@loxtep/sdk/docs/examples/write-events.mjs
|
|
225
|
-
```
|
|
47
|
+
## Phase 4 — Write from your application
|
|
226
48
|
|
|
227
|
-
|
|
49
|
+
The SDK reads your workspace (`.loxtep/project.json` + credentials). No manual
|
|
50
|
+
URL or token wiring.
|
|
228
51
|
|
|
229
52
|
```typescript
|
|
230
53
|
import { LoxtepClient } from '@loxtep/sdk';
|
|
231
54
|
|
|
232
55
|
const client = await LoxtepClient.fromWorkspace();
|
|
233
56
|
|
|
234
|
-
// Name from Phase 2 bundle / data-products list (case-sensitive)
|
|
235
57
|
const writer = await client.get_writer('app-events');
|
|
236
58
|
|
|
237
59
|
writer.write({
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
payload: { user_id: 'u_1', action: 'signup' },
|
|
60
|
+
user_id: 'u_1',
|
|
61
|
+
action: 'signup',
|
|
241
62
|
});
|
|
242
63
|
|
|
243
|
-
await writer.close();
|
|
64
|
+
await writer.close();
|
|
244
65
|
```
|
|
245
66
|
|
|
246
|
-
|
|
67
|
+
Pass your **business fields** to `write()`. The SDK wraps them for transport —
|
|
68
|
+
you do not build an envelope or use a `payload` property yourself.
|
|
247
69
|
|
|
248
|
-
|
|
249
|
-
await client.get_writer('app-events', {
|
|
250
|
-
batch_size: 500,
|
|
251
|
-
max_retries: 5,
|
|
252
|
-
});
|
|
253
|
-
```
|
|
70
|
+
Use the same name you passed to `ingest provision`.
|
|
254
71
|
|
|
255
|
-
Read back (
|
|
72
|
+
### Read back (optional)
|
|
256
73
|
|
|
257
74
|
```typescript
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
75
|
+
const client = await LoxtepClient.fromWorkspace();
|
|
76
|
+
const reader = await client.get_reader('app-events');
|
|
77
|
+
|
|
261
78
|
for await (const event of reader) {
|
|
262
79
|
console.log(event);
|
|
263
80
|
break;
|
|
@@ -266,39 +83,43 @@ for await (const event of reader) {
|
|
|
266
83
|
|
|
267
84
|
---
|
|
268
85
|
|
|
269
|
-
##
|
|
86
|
+
## Quick checklist
|
|
270
87
|
|
|
271
88
|
```bash
|
|
272
89
|
pnpm exec loxtep login
|
|
273
90
|
pnpm exec loxtep init
|
|
274
91
|
pnpm exec loxtep attach --instance <instance-id>
|
|
275
|
-
pnpm exec loxtep domains list
|
|
276
|
-
|
|
277
92
|
pnpm exec loxtep ingest provision --name app-events
|
|
278
|
-
# or: generate-ingest-bundle.mjs + loxtep bundle save
|
|
279
|
-
|
|
280
93
|
pnpm exec loxtep data-products list
|
|
281
|
-
node node_modules/@loxtep/sdk/docs/examples/write-events.mjs
|
|
282
94
|
```
|
|
283
95
|
|
|
96
|
+
Then `get_writer('app-events')` in your app.
|
|
97
|
+
|
|
284
98
|
---
|
|
285
99
|
|
|
286
|
-
##
|
|
100
|
+
## If something goes wrong
|
|
287
101
|
|
|
288
|
-
|
|
|
289
|
-
|
|
|
290
|
-
|
|
|
291
|
-
|
|
|
292
|
-
|
|
|
293
|
-
|
|
|
102
|
+
| What you see | What to do |
|
|
103
|
+
| ------------ | ---------- |
|
|
104
|
+
| Data product not found | Run `data-products list`. Check the name matches `get_writer('…')` exactly. |
|
|
105
|
+
| Not ready to accept writes | Run `ingest provision` again for that name. Make sure you ran `attach` first. |
|
|
106
|
+
| Multiple products with the same name | Pass the data product id to `get_writer`, or ensure `attach` points at the right instance. |
|
|
107
|
+
| No domain available | Create a domain in the Loxtep UI, or pass `--domain-id` to `ingest provision`. |
|
|
294
108
|
|
|
295
109
|
---
|
|
296
110
|
|
|
297
|
-
##
|
|
111
|
+
## Other ways to create a data product
|
|
112
|
+
|
|
113
|
+
**Loxtep MCP (AI assistant)** — If you use the Loxtep MCP in Cursor, Claude Code,
|
|
114
|
+
or another client, describe what you want in plain language, for example:
|
|
115
|
+
|
|
116
|
+
> Create a data product named `app-events` on my current Loxtep project and
|
|
117
|
+
> deploy it to the instance I already attached. I want to write events from my
|
|
118
|
+
> app with the SDK.
|
|
119
|
+
|
|
120
|
+
The assistant provisions the same end state as `ingest provision`. After that,
|
|
121
|
+
Phase 4 above is unchanged: `get_writer('app-events')` and `write()`.
|
|
298
122
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
| [Quick Reference](./quick-reference.md) | CLI + SDK cheat sheet |
|
|
303
|
-
| [Code-first CLI](./code-first-cli.md) | TypeScript workflow modules + `loxtep deploy` |
|
|
304
|
-
| [Event Replay Cookbook](./event-replay-cookbook.md) | Replay and reprocess |
|
|
123
|
+
**Loxtep Studio (web app)** — *Beta.* You can also design and publish a data
|
|
124
|
+
product in the Loxtep UI. Once it exists on your instance, the SDK code in
|
|
125
|
+
Phase 4 is the same.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loxtep/sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.22",
|
|
4
4
|
"description": "Loxtep SDK for Node.js — the Enterprise Context Layer: data products, workflows, projects, queues, and machine-usable context for AI",
|
|
5
5
|
"author": "Loxtep <engineering@loxtep.io>",
|
|
6
6
|
"homepage": "https://loxtep.io",
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Greenfield SDK ingest — one-shot provision via CLI (preferred) or bundle JSON for manual save.
|
|
4
|
-
*
|
|
5
|
-
* Run from your Loxtep workspace root (after login, init, attach):
|
|
6
|
-
*
|
|
7
|
-
* pnpm exec loxtep ingest provision --name app-events
|
|
8
|
-
*
|
|
9
|
-
* Or generate bundle JSON only:
|
|
10
|
-
*
|
|
11
|
-
* node node_modules/@loxtep/sdk/docs/examples/generate-ingest-bundle.mjs
|
|
12
|
-
* pnpm exec loxtep bundle save --dry-run
|
|
13
|
-
* pnpm exec loxtep bundle save
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { LoxtepClient, buildSdkIngestBundle } from '@loxtep/sdk';
|
|
17
|
-
import { randomUUID } from 'node:crypto';
|
|
18
|
-
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
19
|
-
import { join } from 'node:path';
|
|
20
|
-
|
|
21
|
-
const DATA_PRODUCT_NAME = process.env.LOXTEP_DATA_PRODUCT_NAME ?? 'app-events';
|
|
22
|
-
const WORKFLOW_NAME = process.env.LOXTEP_WORKFLOW_NAME ?? 'SDK App Events Ingest';
|
|
23
|
-
const AUTO_SAVE = process.env.LOXTEP_AUTO_SAVE === '1';
|
|
24
|
-
|
|
25
|
-
async function main() {
|
|
26
|
-
const client = await LoxtepClient.fromWorkspace();
|
|
27
|
-
|
|
28
|
-
const user = await client.session.get_current_user();
|
|
29
|
-
const organizationId = user.organization_id ?? client.organization_id;
|
|
30
|
-
const projectId = client.project_id;
|
|
31
|
-
const instanceId = client.instance_id;
|
|
32
|
-
|
|
33
|
-
if (!organizationId || !projectId) {
|
|
34
|
-
console.error(
|
|
35
|
-
'Missing organization_id or project_id. Run from a workspace after `loxtep init`.'
|
|
36
|
-
);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
if (!instanceId) {
|
|
40
|
-
console.error('Missing instance_id. Run `loxtep attach --instance <id>` first.');
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
let domainId = process.env.LOXTEP_DOMAIN_ID;
|
|
45
|
-
if (!domainId) {
|
|
46
|
-
const domains = await client.define.domains.list({ page_size: 20 });
|
|
47
|
-
const items = domains.items ?? [];
|
|
48
|
-
if (items.length === 0) {
|
|
49
|
-
console.error(
|
|
50
|
-
'No domains found. Create one in the Web UI (Governance → Domains) or set LOXTEP_DOMAIN_ID.'
|
|
51
|
-
);
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
domainId = items[0].domain_id;
|
|
55
|
-
console.error(`Using domain: ${items[0].name} (${domainId})`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
console.error('Creating SDK connector…');
|
|
59
|
-
const connector = await client.connect.connectors.create({
|
|
60
|
-
connector_type: 'sdk',
|
|
61
|
-
metadata: { name: 'SDK Connector', created_by: 'generate-ingest-bundle' },
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const bundle = buildSdkIngestBundle({
|
|
65
|
-
organization_id: organizationId,
|
|
66
|
-
project_id: projectId,
|
|
67
|
-
domain_id: domainId,
|
|
68
|
-
connector_id: connector.connector_id,
|
|
69
|
-
data_product_name: DATA_PRODUCT_NAME,
|
|
70
|
-
workflow_name: WORKFLOW_NAME,
|
|
71
|
-
user_id: user.user_id,
|
|
72
|
-
workflow_id: randomUUID(),
|
|
73
|
-
connection_id: randomUUID(),
|
|
74
|
-
data_product_id: randomUUID(),
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
mkdirSync('.loxtep', { recursive: true });
|
|
78
|
-
const outPath = join('.loxtep', 'sdk-ingest-bundle.json');
|
|
79
|
-
writeFileSync(outPath, JSON.stringify({ project_id: projectId, files: bundle.files }, null, 2));
|
|
80
|
-
|
|
81
|
-
console.log(
|
|
82
|
-
JSON.stringify(
|
|
83
|
-
{
|
|
84
|
-
connector_id: connector.connector_id,
|
|
85
|
-
workflow_id: bundle.workflow_id,
|
|
86
|
-
data_product_id: bundle.data_product_id,
|
|
87
|
-
data_product_name: bundle.data_product_name,
|
|
88
|
-
bundle_path: outPath,
|
|
89
|
-
},
|
|
90
|
-
null,
|
|
91
|
-
2
|
|
92
|
-
)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
if (AUTO_SAVE) {
|
|
96
|
-
console.error('Saving workflow bundle (LOXTEP_AUTO_SAVE=1)…');
|
|
97
|
-
const saveResult = await client.build.workflows.save_workflow_bundle(projectId, {
|
|
98
|
-
files: bundle.files,
|
|
99
|
-
dry_run: false,
|
|
100
|
-
});
|
|
101
|
-
console.error('Deploying…');
|
|
102
|
-
const deployResult = await client.build.workflows.deploy({
|
|
103
|
-
project_id: projectId,
|
|
104
|
-
instance_id: instanceId,
|
|
105
|
-
});
|
|
106
|
-
console.log(JSON.stringify({ save: saveResult, deploy: deployResult }, null, 2));
|
|
107
|
-
console.error(`
|
|
108
|
-
Provisioned. Write events:
|
|
109
|
-
LOXTEP_DATA_PRODUCT_NAME=${DATA_PRODUCT_NAME} node node_modules/@loxtep/sdk/docs/examples/write-events.mjs
|
|
110
|
-
`);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.error(`
|
|
115
|
-
Next steps (no MCP required)
|
|
116
|
-
────────────────────────────
|
|
117
|
-
Preferred — one command:
|
|
118
|
-
pnpm exec loxtep ingest provision --name ${DATA_PRODUCT_NAME}
|
|
119
|
-
|
|
120
|
-
Or save the generated bundle:
|
|
121
|
-
pnpm exec loxtep bundle save --dry-run --file ${outPath}
|
|
122
|
-
pnpm exec loxtep bundle save --file ${outPath}
|
|
123
|
-
pnpm exec loxtep workflows deploy --project-id ${projectId} --instance-id ${instanceId}
|
|
124
|
-
|
|
125
|
-
Write events:
|
|
126
|
-
LOXTEP_DATA_PRODUCT_NAME=${DATA_PRODUCT_NAME} node node_modules/@loxtep/sdk/docs/examples/write-events.mjs
|
|
127
|
-
`);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
main().catch(err => {
|
|
131
|
-
console.error(err instanceof Error ? err.message : err);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Write sample events to a deployed source data product via get_writer.
|
|
4
|
-
*
|
|
5
|
-
* Prerequisites: login, init, attach, SDK ingest workflow deployed (see sdk-first-ingest.md).
|
|
6
|
-
*
|
|
7
|
-
* node node_modules/@loxtep/sdk/docs/examples/write-events.mjs
|
|
8
|
-
*
|
|
9
|
-
* Env:
|
|
10
|
-
* LOXTEP_DATA_PRODUCT_NAME default: app-events
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { LoxtepClient } from '@loxtep/sdk';
|
|
14
|
-
|
|
15
|
-
const DATA_PRODUCT_NAME = process.env.LOXTEP_DATA_PRODUCT_NAME ?? 'app-events';
|
|
16
|
-
|
|
17
|
-
async function main() {
|
|
18
|
-
const client = await LoxtepClient.fromWorkspace();
|
|
19
|
-
|
|
20
|
-
console.error(`Opening writer for data product "${DATA_PRODUCT_NAME}"…`);
|
|
21
|
-
const writer = await client.get_writer(DATA_PRODUCT_NAME);
|
|
22
|
-
|
|
23
|
-
const events = [
|
|
24
|
-
{
|
|
25
|
-
event_id: `evt_${Date.now()}_1`,
|
|
26
|
-
occurred_at: new Date().toISOString(),
|
|
27
|
-
payload: { source: 'write-events.mjs', action: 'example_write', index: 1 },
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
event_id: `evt_${Date.now()}_2`,
|
|
31
|
-
occurred_at: new Date().toISOString(),
|
|
32
|
-
payload: { source: 'write-events.mjs', action: 'example_write', index: 2 },
|
|
33
|
-
},
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
for (const event of events) {
|
|
37
|
-
writer.write(event);
|
|
38
|
-
console.log(JSON.stringify({ written: event.event_id }));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
await writer.close();
|
|
42
|
-
console.error('Writer closed — events flushed.');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
main().catch(err => {
|
|
46
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
47
|
-
console.error(message);
|
|
48
|
-
if (/not deployed/i.test(message)) {
|
|
49
|
-
console.error(
|
|
50
|
-
'\nDeploy an SDK ingestion workflow first. See nodejs/docs/sdk-first-ingest.md'
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
process.exit(1);
|
|
54
|
-
});
|