@loopwise/sdk 0.1.0-beta.2 → 0.1.0-beta.3
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 +69 -0
- package/README.md +42 -38
- package/dist/config.d.mts +18 -6
- package/dist/index.d.mts +21 -11
- package/dist/index.mjs +27 -22
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@loopwise/sdk` are documented here.
|
|
4
|
+
|
|
5
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
Versioning: [SemVer](https://semver.org/) with pre-1.0 semantics — minor bumps
|
|
7
|
+
(`0.x → 0.x+1`) may include breaking changes; beta tags (`0.1.0-beta.N`)
|
|
8
|
+
follow the same rules as a single 0.x line.
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
## [0.1.0-beta.3] — 2026-05-20
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `LoopwiseConfig.site` — preferred name for the site this client reads
|
|
17
|
+
from. Accepts a subdomain (`'acme'`) or full domain
|
|
18
|
+
(`'acme.myteachify.com'`, `'nii.school'`). Replaces the deprecated
|
|
19
|
+
`tenant` field; both fields are accepted, `site` wins when both are set.
|
|
20
|
+
- `LoopwiseError.site` — mirror of the deprecated `tenant` property.
|
|
21
|
+
Catch-and-read consumers can migrate at their own pace.
|
|
22
|
+
|
|
23
|
+
### Deprecated
|
|
24
|
+
|
|
25
|
+
- `LoopwiseConfig.tenant` — renamed to `site`. Both fields still work;
|
|
26
|
+
`site` wins when both are set. **Removed in `0.2.0`.**
|
|
27
|
+
- `LoopwiseError.tenant` — renamed to `site`. **Removed in `0.2.0`.**
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
|
|
31
|
+
- `LoopwiseErrorCode = '…' | 'TENANT_NOT_FOUND'` — the literal was never
|
|
32
|
+
emitted by any SDK code path (it was a reserved/aspirational shape
|
|
33
|
+
that never got runtime mapping). Removed instead of renaming to
|
|
34
|
+
`'SITE_NOT_FOUND'` — no point preserving phantom API surface. If a
|
|
35
|
+
future SDK release adds actual runtime mapping (e.g. translating
|
|
36
|
+
Rails' `School-000` GraphQL error into a typed code), the canonical
|
|
37
|
+
`'SITE_NOT_FOUND'` literal will be added then. Removal is type-only
|
|
38
|
+
(narrowing checks like `case 'TENANT_NOT_FOUND':` were unreachable
|
|
39
|
+
branches in any consumer code).
|
|
40
|
+
|
|
41
|
+
### Changed (non-breaking)
|
|
42
|
+
|
|
43
|
+
- README + every user-visible JSDoc reframed to use "site" language
|
|
44
|
+
instead of "tenant" / "multi-tenant" / "BFF derives tenant from host"
|
|
45
|
+
— SDK consumers don't need to learn the platform's multi-tenancy
|
|
46
|
+
model, just the SDK's behaviour and limits (`createClient({})` reads
|
|
47
|
+
from the page's own site; `createClient({ site: '…' })` reads from a
|
|
48
|
+
different site at the cost of authenticated calls).
|
|
49
|
+
|
|
50
|
+
## [0.1.0-beta.2] — 2026-05-19
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- `orders.get` returns `null` from a null GraphQL payload instead of
|
|
55
|
+
throwing.
|
|
56
|
+
- `orders.get` passes the `id` as an inline GraphQL argument rather than
|
|
57
|
+
a `$variable`, avoiding collision when composed via `batch()`.
|
|
58
|
+
|
|
59
|
+
### Documentation
|
|
60
|
+
|
|
61
|
+
- `orders.get` JSDoc clarifies `OrderItem.amount` is per-unit price
|
|
62
|
+
(not line total), and null-guards the `tradeNo` URL-param lookup
|
|
63
|
+
example.
|
|
64
|
+
|
|
65
|
+
## [0.1.0-beta.1]
|
|
66
|
+
|
|
67
|
+
Initial public beta. `courses.list/get`, `posts.list/get`, `orders.get`,
|
|
68
|
+
`batch()`, raw `query()`. Schema-lock pipeline. Same-origin BFF and
|
|
69
|
+
explicit cross-origin endpoint resolution.
|
package/README.md
CHANGED
|
@@ -15,15 +15,15 @@ Same package powers all three; the difference is the loader.
|
|
|
15
15
|
```ts
|
|
16
16
|
import { createClient } from '@loopwise/sdk';
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// Reads from the site this page is on. No config needed.
|
|
19
19
|
const loopwise = createClient({});
|
|
20
20
|
const { items } = await loopwise.courses.list({ limit: 20 });
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
That's
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
That's it. The SDK calls the site that's serving the page
|
|
24
|
+
(`acme.kaik.io`, `acme.myteachify.com`, `nii.school`, etc.) and the
|
|
25
|
+
site's API binds the response to itself — you never identify the site
|
|
26
|
+
yourself. To call a different site, see [Calling a different site](#calling-a-different-site).
|
|
27
27
|
|
|
28
28
|
## Quick start — single-file HTML (no build)
|
|
29
29
|
|
|
@@ -32,44 +32,47 @@ response on the trusted server side.
|
|
|
32
32
|
<script type="module">
|
|
33
33
|
import { createClient } from 'https://esm.sh/@loopwise/sdk@beta';
|
|
34
34
|
|
|
35
|
-
//
|
|
36
|
-
// (e.g. acme.kaik.io). Empty config; BFF derives the tenant from host.
|
|
35
|
+
// Reads from the site this HTML is loaded on.
|
|
37
36
|
const loopwise = createClient({});
|
|
38
37
|
const { items } = await loopwise.courses.list({ limit: 20 });
|
|
39
38
|
document.body.textContent = items.map(c => c.title).join(', ');
|
|
40
39
|
</script>
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
##
|
|
42
|
+
## Calling a different site
|
|
44
43
|
|
|
45
|
-
When
|
|
46
|
-
|
|
44
|
+
When your code runs **somewhere other than the site itself** — a Loopwise
|
|
45
|
+
Pages preview at `<scriptName>.loopwise.page`, a build / SSR pipeline,
|
|
46
|
+
server-to-server tooling — name the site you want to read from:
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
49
|
const loopwise = createClient({
|
|
50
|
-
|
|
51
|
-
apiKey: process.env.LOOPWISE_API_KEY,
|
|
50
|
+
site: 'acme', // 'acme' or 'acme.myteachify.com'
|
|
51
|
+
apiKey: process.env.LOOPWISE_API_KEY, // build/SSR only; browser ignores
|
|
52
52
|
});
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
`site` accepts a subdomain (`'acme'`) or a full domain
|
|
56
|
+
(`'acme.myteachify.com'`, `'nii.school'`). The SDK uses it to pick the
|
|
57
|
+
right API origin.
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
— that is **not** a tenant origin, so:
|
|
59
|
+
### Limits when not on the site itself
|
|
59
60
|
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
Cross-origin requests **do not carry first-party cookies**. So calls
|
|
62
|
+
that require a signed-in visitor — `cart`, `viewer.profile`,
|
|
63
|
+
authenticated mutations — **will not work** from off-site code.
|
|
64
|
+
Public, anonymous reads (`courses.list`, `posts.list`, etc.) work fine.
|
|
65
|
+
|
|
66
|
+
This is the dominant case for `deploy_static_page` bundles (which
|
|
67
|
+
serve at `<scriptName>.loopwise.page`):
|
|
65
68
|
|
|
66
69
|
```ts
|
|
67
70
|
// Inside an HTML bundle deployed to https://lw-acme-home.loopwise.page/
|
|
68
|
-
const loopwise = createClient({
|
|
71
|
+
const loopwise = createClient({ site: 'acme' });
|
|
69
72
|
const { items } = await loopwise.courses.list({ limit: 20 }, { cache: 60 });
|
|
70
73
|
```
|
|
71
74
|
|
|
72
|
-
For preview UX that needs authenticated
|
|
75
|
+
For preview UX that needs an authenticated viewer, see
|
|
73
76
|
[Preview modes](#preview-modes) below.
|
|
74
77
|
|
|
75
78
|
## `cache` option
|
|
@@ -124,22 +127,21 @@ content; use `cache: 'no-store'` for admin previews.
|
|
|
124
127
|
|
|
125
128
|
Two preview surfaces exist, each with different capability:
|
|
126
129
|
|
|
127
|
-
| Surface |
|
|
130
|
+
| Surface | URL | Hosted on the site? | Authenticated viewer? | Use for |
|
|
128
131
|
|---|---|---|---|---|
|
|
129
|
-
| **Loopwise Pages preview** | `<scriptName>.loopwise.page` | ❌
|
|
130
|
-
| **
|
|
132
|
+
| **Loopwise Pages preview** | `<scriptName>.loopwise.page` | ❌ separate origin | ❌ no first-party cookies | Anonymous storefront, marketing pages, public listings |
|
|
133
|
+
| **Site-origin preview** | `<site>/_preview/<scriptName>/` | ✅ same origin as the site | ✅ admins can preview signed in | Cart, checkout, member-gated content, full storefront |
|
|
131
134
|
|
|
132
|
-
The
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`<TENANT_ORIGIN>` placeholder).
|
|
135
|
+
The site URL can be `<sub>.kaik.io`, `<sub>.myteachify.com`, or a custom
|
|
136
|
+
domain like `nii.school`. `deploy_static_page` returns both URLs in its
|
|
137
|
+
response.
|
|
136
138
|
|
|
137
|
-
Pick the surface that matches what you're testing — anonymous
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Pick the surface that matches what you're testing — anonymous reads on
|
|
140
|
+
Surface A (faster, edge-cacheable), authenticated flows on Surface B
|
|
141
|
+
(signed-in only, never edge-cached). Surface B requires relative asset
|
|
142
|
+
paths in your bundle (the proxy injects `<base>` so relative paths
|
|
143
|
+
resolve under `/_preview/<scriptName>/`; root-absolute paths like
|
|
144
|
+
`/style.css` still go to the site root and 404).
|
|
143
145
|
|
|
144
146
|
## React — coming soon
|
|
145
147
|
|
|
@@ -155,10 +157,12 @@ your own state (`useEffect` + `useState`, TanStack Query, etc.).
|
|
|
155
157
|
|
|
156
158
|
## Public API
|
|
157
159
|
|
|
158
|
-
- `createClient(config)` — storefront client. `config.
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
- `createClient(config)` — storefront client. Pass `config.site` only
|
|
161
|
+
when calling a different site than the one your code is running on
|
|
162
|
+
(see [Calling a different site](#calling-a-different-site)).
|
|
161
163
|
- `loopwise.courses.list(args, options?)` / `.get(args, options?)`.
|
|
164
|
+
- `loopwise.posts.list(args, options?)` / `.get(args, options?)`.
|
|
165
|
+
- `loopwise.orders.get(args, options?)` — post-checkout pixel-tracking pattern; see the method's JSDoc for the `?tradeNo=…` → `fbq('track', 'Purchase', …)` recipe.
|
|
162
166
|
- `loopwise.batch(builders, options?)` — composes N queries into one HTTP request.
|
|
163
167
|
- `loopwise.query<T>(document, variables?, operationName?, options?)` — raw GraphQL escape hatch.
|
|
164
168
|
|
package/dist/config.d.mts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
//#region src/config.d.ts
|
|
2
2
|
interface LoopwiseConfig {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* The site this client reads from. Accepts a subdomain (`'acme'`) or a
|
|
5
|
+
* full domain (`'acme.myteachify.com'`, `'nii.school'`).
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Omit when your code runs on the site itself — the SDK calls the
|
|
8
|
+
* page's own origin. Required when running off-origin: cross-domain
|
|
9
|
+
* embeds (Loopwise Pages previews at `*.loopwise.page`), SSR / build
|
|
10
|
+
* pipelines, server-to-server tooling.
|
|
11
|
+
*
|
|
12
|
+
* Cross-origin requests carry no first-party cookies, so authenticated
|
|
13
|
+
* calls (`cart`, `viewer.profile`, mutations that need a signed-in
|
|
14
|
+
* visitor) won't work in that mode — public reads do.
|
|
15
|
+
*/
|
|
16
|
+
site?: string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Renamed to `site`. Both fields work for now; if both are
|
|
19
|
+
* set, `site` wins. **Will be removed in `0.2.0`.**
|
|
8
20
|
*/
|
|
9
21
|
tenant?: string;
|
|
10
22
|
/**
|
|
@@ -15,9 +27,9 @@ interface LoopwiseConfig {
|
|
|
15
27
|
*/
|
|
16
28
|
apiKey?: string;
|
|
17
29
|
/**
|
|
18
|
-
* Override the GraphQL endpoint.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
30
|
+
* Override the GraphQL endpoint. You normally never set this — the SDK
|
|
31
|
+
* picks the right URL from `site` (or the page's own origin when `site`
|
|
32
|
+
* is omitted).
|
|
21
33
|
*/
|
|
22
34
|
endpoint?: string;
|
|
23
35
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LoopwiseConfig } from "./config.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/error.d.ts
|
|
4
|
-
type LoopwiseErrorCode = 'NETWORK' | 'AUTH' | 'GRAPHQL' | 'RATE_LIMIT' | '
|
|
4
|
+
type LoopwiseErrorCode = 'NETWORK' | 'AUTH' | 'GRAPHQL' | 'RATE_LIMIT' | 'CONFIG';
|
|
5
5
|
interface GraphQLError {
|
|
6
6
|
message: string;
|
|
7
7
|
path?: (string | number)[];
|
|
@@ -9,11 +9,15 @@ interface GraphQLError {
|
|
|
9
9
|
}
|
|
10
10
|
declare class LoopwiseError extends Error {
|
|
11
11
|
readonly code: LoopwiseErrorCode;
|
|
12
|
+
/** The site this client was configured for. */
|
|
13
|
+
readonly site?: string;
|
|
14
|
+
/** @deprecated Renamed to `site`. Holds the same resolved value. Removed in 0.2.0. */
|
|
12
15
|
readonly tenant?: string;
|
|
13
16
|
readonly endpoint?: string;
|
|
14
17
|
readonly graphqlErrors?: GraphQLError[];
|
|
15
18
|
readonly requestId?: string;
|
|
16
19
|
constructor(code: LoopwiseErrorCode, message: string, detail?: {
|
|
20
|
+
site?: string; /** @deprecated Renamed to `site`. Removed in 0.2.0. */
|
|
17
21
|
tenant?: string;
|
|
18
22
|
endpoint?: string;
|
|
19
23
|
graphqlErrors?: GraphQLError[];
|
|
@@ -79,9 +83,7 @@ declare class QueryBuilder<T> implements PromiseLike<T> {
|
|
|
79
83
|
//#endregion
|
|
80
84
|
//#region src/client.d.ts
|
|
81
85
|
declare class LoopwiseClient implements BatchedFetcher {
|
|
82
|
-
readonly config:
|
|
83
|
-
tenant?: string;
|
|
84
|
-
} & LoopwiseConfig;
|
|
86
|
+
readonly config: LoopwiseConfig;
|
|
85
87
|
private endpoint;
|
|
86
88
|
constructor(config: LoopwiseConfig);
|
|
87
89
|
private defaultEndpoint;
|
|
@@ -201,7 +203,7 @@ declare class CoursesResource {
|
|
|
201
203
|
private client;
|
|
202
204
|
constructor(client: LoopwiseClient);
|
|
203
205
|
/**
|
|
204
|
-
* List courses
|
|
206
|
+
* List published courses.
|
|
205
207
|
* @example
|
|
206
208
|
* const { items, pageInfo } = await loopwise.courses.list({ limit: 20 })
|
|
207
209
|
* @example
|
|
@@ -248,9 +250,8 @@ declare class OrdersResource {
|
|
|
248
250
|
* Look up a PII-safe order projection by id (the value the storefront
|
|
249
251
|
* appends to a merchant's `checkoutSuccessUrl` as `?tradeNo=...`).
|
|
250
252
|
*
|
|
251
|
-
* Returns `null
|
|
252
|
-
*
|
|
253
|
-
* returned `status` to gate Meta Pixel `Purchase` events:
|
|
253
|
+
* Returns `null` when the id doesn't resolve on this site — does NOT
|
|
254
|
+
* throw. Use the returned `status` to gate Meta Pixel `Purchase` events:
|
|
254
255
|
*
|
|
255
256
|
* @example
|
|
256
257
|
* const id = new URLSearchParams(location.search).get('tradeNo');
|
|
@@ -289,7 +290,7 @@ declare class PostsResource {
|
|
|
289
290
|
private client;
|
|
290
291
|
constructor(client: LoopwiseClient);
|
|
291
292
|
/**
|
|
292
|
-
* List published posts
|
|
293
|
+
* List published posts, ordered by publishedAt desc.
|
|
293
294
|
* @example
|
|
294
295
|
* const { items, pageInfo } = await loopwise.posts.list({ limit: 10 })
|
|
295
296
|
* @example
|
|
@@ -334,9 +335,18 @@ interface Loopwise {
|
|
|
334
335
|
/**
|
|
335
336
|
* Raw GraphQL escape hatch. Use when a typed resource method doesn't cover
|
|
336
337
|
* what you need (new schema fields, custom queries, ad-hoc inspection).
|
|
338
|
+
* Variables are sent as-is; errors are still mapped to LoopwiseError.
|
|
339
|
+
*
|
|
340
|
+
* Most storefront fields (`courses`, `posts`, `order`, ...) take a
|
|
341
|
+
* required `subdomain: String!` argument. The BFF rewrites that variable
|
|
342
|
+
* to the trusted server-derived value on every request, so consumers
|
|
343
|
+
* declaring `$subdomain` see whatever value the BFF binds — not what
|
|
344
|
+
* they pass.
|
|
345
|
+
*
|
|
337
346
|
* @example
|
|
338
|
-
*
|
|
339
|
-
*
|
|
347
|
+
* // Minimal shape demo (always valid, no scoping required):
|
|
348
|
+
* const data = await loopwise.query<{ __typename: string }>(`
|
|
349
|
+
* query { __typename }
|
|
340
350
|
* `)
|
|
341
351
|
*/
|
|
342
352
|
query<T = unknown>(document: string, variables?: Record<string, unknown>, operationName?: string, options?: FetchOptions): Promise<T>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
//#region src/error.ts
|
|
2
2
|
var LoopwiseError = class extends Error {
|
|
3
3
|
code;
|
|
4
|
+
/** The site this client was configured for. */
|
|
5
|
+
site;
|
|
6
|
+
/** @deprecated Renamed to `site`. Holds the same resolved value. Removed in 0.2.0. */
|
|
4
7
|
tenant;
|
|
5
8
|
endpoint;
|
|
6
9
|
graphqlErrors;
|
|
@@ -9,7 +12,9 @@ var LoopwiseError = class extends Error {
|
|
|
9
12
|
super(message);
|
|
10
13
|
this.name = "LoopwiseError";
|
|
11
14
|
this.code = code;
|
|
12
|
-
|
|
15
|
+
const site = detail.site ?? detail.tenant;
|
|
16
|
+
this.site = site;
|
|
17
|
+
this.tenant = site;
|
|
13
18
|
this.endpoint = detail.endpoint;
|
|
14
19
|
this.graphqlErrors = detail.graphqlErrors;
|
|
15
20
|
this.requestId = detail.requestId;
|
|
@@ -29,20 +34,21 @@ var LoopwiseClient = class {
|
|
|
29
34
|
config;
|
|
30
35
|
endpoint;
|
|
31
36
|
constructor(config) {
|
|
32
|
-
const
|
|
33
|
-
if (detectRuntime() !== "browser" && !
|
|
37
|
+
const site = config.site ?? config.tenant;
|
|
38
|
+
if (detectRuntime() !== "browser" && !site) throw new LoopwiseError("CONFIG", "site is required outside browser runtime. Pass it to createClient({ site }).");
|
|
34
39
|
this.config = {
|
|
35
40
|
...config,
|
|
36
|
-
|
|
41
|
+
site,
|
|
42
|
+
tenant: site
|
|
37
43
|
};
|
|
38
44
|
this.endpoint = config.endpoint ?? this.defaultEndpoint();
|
|
39
45
|
}
|
|
40
46
|
defaultEndpoint() {
|
|
41
|
-
const
|
|
42
|
-
if (detectRuntime() === "browser" && !
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
return `https://${
|
|
47
|
+
const site = this.config.site;
|
|
48
|
+
if (detectRuntime() === "browser" && !site) return "/api/graphql";
|
|
49
|
+
const s = site;
|
|
50
|
+
if (s.includes(".")) return `https://${s}/api/graphql`;
|
|
51
|
+
return `https://${s}.kaik.io/api/graphql`;
|
|
46
52
|
}
|
|
47
53
|
async execute(descriptor, options = {}) {
|
|
48
54
|
const document = renderSingleDocument(descriptor);
|
|
@@ -115,26 +121,26 @@ var LoopwiseClient = class {
|
|
|
115
121
|
});
|
|
116
122
|
} catch (err) {
|
|
117
123
|
throw new LoopwiseError("NETWORK", `Network error: ${err.message}`, {
|
|
118
|
-
|
|
124
|
+
site: this.config.site,
|
|
119
125
|
endpoint: this.endpoint
|
|
120
126
|
});
|
|
121
127
|
}
|
|
122
128
|
if (response.status === 401 || response.status === 403) throw new LoopwiseError("AUTH", `Auth failed (${response.status})`, {
|
|
123
|
-
|
|
129
|
+
site: this.config.site,
|
|
124
130
|
endpoint: this.endpoint,
|
|
125
131
|
requestId: response.headers.get("x-request-id") ?? void 0
|
|
126
132
|
});
|
|
127
133
|
if (response.status === 429) throw new LoopwiseError("RATE_LIMIT", "Rate limited", {
|
|
128
|
-
|
|
134
|
+
site: this.config.site,
|
|
129
135
|
endpoint: this.endpoint
|
|
130
136
|
});
|
|
131
137
|
if (!response.ok) throw new LoopwiseError("NETWORK", `Upstream ${response.status}`, {
|
|
132
|
-
|
|
138
|
+
site: this.config.site,
|
|
133
139
|
endpoint: this.endpoint
|
|
134
140
|
});
|
|
135
141
|
const body = await response.json();
|
|
136
142
|
if (body.errors?.length) throw new LoopwiseError("GRAPHQL", body.errors[0]?.message ?? "GraphQL error", {
|
|
137
|
-
|
|
143
|
+
site: this.config.site,
|
|
138
144
|
endpoint: this.endpoint,
|
|
139
145
|
graphqlErrors: body.errors
|
|
140
146
|
});
|
|
@@ -319,7 +325,7 @@ const DEFAULT_GET_FIELDS$2 = {
|
|
|
319
325
|
function tenantVars$2(client) {
|
|
320
326
|
return { subdomain: {
|
|
321
327
|
type: "String!",
|
|
322
|
-
value: client.config.
|
|
328
|
+
value: client.config.site ?? ""
|
|
323
329
|
} };
|
|
324
330
|
}
|
|
325
331
|
var CoursesResource = class {
|
|
@@ -328,7 +334,7 @@ var CoursesResource = class {
|
|
|
328
334
|
this.client = client;
|
|
329
335
|
}
|
|
330
336
|
/**
|
|
331
|
-
* List courses
|
|
337
|
+
* List published courses.
|
|
332
338
|
* @example
|
|
333
339
|
* const { items, pageInfo } = await loopwise.courses.list({ limit: 20 })
|
|
334
340
|
* @example
|
|
@@ -433,7 +439,7 @@ const DEFAULT_GET_FIELDS$1 = {
|
|
|
433
439
|
function tenantVars$1(client) {
|
|
434
440
|
return { subdomain: {
|
|
435
441
|
type: "String!",
|
|
436
|
-
value: client.config.
|
|
442
|
+
value: client.config.site ?? ""
|
|
437
443
|
} };
|
|
438
444
|
}
|
|
439
445
|
var OrdersResource = class {
|
|
@@ -445,9 +451,8 @@ var OrdersResource = class {
|
|
|
445
451
|
* Look up a PII-safe order projection by id (the value the storefront
|
|
446
452
|
* appends to a merchant's `checkoutSuccessUrl` as `?tradeNo=...`).
|
|
447
453
|
*
|
|
448
|
-
* Returns `null
|
|
449
|
-
*
|
|
450
|
-
* returned `status` to gate Meta Pixel `Purchase` events:
|
|
454
|
+
* Returns `null` when the id doesn't resolve on this site — does NOT
|
|
455
|
+
* throw. Use the returned `status` to gate Meta Pixel `Purchase` events:
|
|
451
456
|
*
|
|
452
457
|
* @example
|
|
453
458
|
* const id = new URLSearchParams(location.search).get('tradeNo');
|
|
@@ -563,7 +568,7 @@ const DEFAULT_GET_FIELDS = {
|
|
|
563
568
|
function tenantVars(client) {
|
|
564
569
|
return { subdomain: {
|
|
565
570
|
type: "String!",
|
|
566
|
-
value: client.config.
|
|
571
|
+
value: client.config.site ?? ""
|
|
567
572
|
} };
|
|
568
573
|
}
|
|
569
574
|
var PostsResource = class {
|
|
@@ -572,7 +577,7 @@ var PostsResource = class {
|
|
|
572
577
|
this.client = client;
|
|
573
578
|
}
|
|
574
579
|
/**
|
|
575
|
-
* List published posts
|
|
580
|
+
* List published posts, ordered by publishedAt desc.
|
|
576
581
|
* @example
|
|
577
582
|
* const { items, pageInfo } = await loopwise.posts.list({ limit: 10 })
|
|
578
583
|
* @example
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopwise/sdk",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "Loopwise platform SDK — agent-friendly headless API client",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"files": [
|
|
38
38
|
"dist/*.mjs",
|
|
39
39
|
"dist/*.d.mts",
|
|
40
|
-
"README.md"
|
|
40
|
+
"README.md",
|
|
41
|
+
"CHANGELOG.md"
|
|
41
42
|
],
|
|
42
43
|
"scripts": {
|
|
43
44
|
"build": "tsdown",
|