@obelism/content 0.28.4 → 0.30.0
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/README.md +30 -5
- package/dist/bin/content.js +342 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +44 -4
- package/dist/index.mjs +44 -4
- package/dist/{types-b6jbj3g6.d.ts → types-e32p5mys.d.ts} +10 -2
- package/dist/types-e32p5mys.d.ts.map +1 -0
- package/dist/webhooks.d.mts +22 -2
- package/dist/webhooks.d.mts.map +1 -1
- package/dist/webhooks.d.ts +22 -2
- package/dist/webhooks.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/types-b6jbj3g6.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -371,8 +371,14 @@ path, paths }`, plus `previousPath` and `previousPaths` when moved), `asset.upda
|
|
|
371
371
|
`locales.changed` (`data.defaultLocale`, `data.locales`),
|
|
372
372
|
`entry.review_requested` (`data.entry`, `data.revision`, `data.note`) and
|
|
373
373
|
`entry.review_closed` (`data.outcome`: `approved` or `sent_back` with
|
|
374
|
-
`data.reason`) for environments whose publishing is reviewed,
|
|
375
|
-
`
|
|
374
|
+
`data.reason`) for environments whose publishing is reviewed,
|
|
375
|
+
`block.published` (`data.entry`: the shared block, `data.entries`: the
|
|
376
|
+
published pages it updated), `release.published` and
|
|
377
|
+
`release.review_requested` (`data.release`: `{ id, name }`, `data.entries`
|
|
378
|
+
with each entry's `action`, `publish` or `unpublish`, and `data.note` on a
|
|
379
|
+
review request), `product.updated`, `product.deleted`, `collection.updated`
|
|
380
|
+
and `collection.deleted` (`data.entries` and `data.tags` a store's change
|
|
381
|
+
touches), and `webhook.test`.
|
|
376
382
|
|
|
377
383
|
## Click rates
|
|
378
384
|
|
|
@@ -477,8 +483,26 @@ const blocks = layout.flatMap((block) => {
|
|
|
477
483
|
```
|
|
478
484
|
|
|
479
485
|
`pickImproveVariant(block, option, fallback?)` falls back to `fallback`'s
|
|
480
|
-
variant, else the first one, when the option
|
|
481
|
-
active or the visitor isn't in it) or has no
|
|
486
|
+
variant, else the block's own `fallback`, else the first one, when the option
|
|
487
|
+
is `null` (the test isn't active or the visitor isn't in it) or has no
|
|
488
|
+
variant.
|
|
489
|
+
|
|
490
|
+
That is for a page rendered per request. A prerendered page carries every
|
|
491
|
+
variant, tagged, and a script in its head shows the visitor's before the
|
|
492
|
+
first paint, with `seedTestCookies` from `@obelism/improve-sdk/server` at the
|
|
493
|
+
edge; the block's `mode` (`instant` or `after-load`, from the page type's
|
|
494
|
+
fold) says whether the other variants are markup or JSON. `content init`
|
|
495
|
+
writes the whole pattern to `content/examples/_improve.md`, and Content's
|
|
496
|
+
[A/B tests guide](https://content.obelism.studio/docs/guides/ab-tests) has
|
|
497
|
+
the same.
|
|
498
|
+
|
|
499
|
+
## Shared blocks
|
|
500
|
+
|
|
501
|
+
A block shared between pages arrives as the block it is, with its fields,
|
|
502
|
+
plus `_sharedFrom: { id, name }`: the block entry it comes from. Render it
|
|
503
|
+
like any other block. A page left out of the block's last publish keeps the
|
|
504
|
+
copy that was live then, marked with `heldAt` (ISO 8601). Publishing a shared
|
|
505
|
+
block sends `block.published` (see Webhooks) instead of `entry.published`.
|
|
482
506
|
|
|
483
507
|
## Shopify
|
|
484
508
|
|
|
@@ -545,7 +569,8 @@ npx @obelism/content init
|
|
|
545
569
|
|
|
546
570
|
It writes the model file (`content/content-model.json`), an example of what
|
|
547
571
|
the delivery API answers for every content type (`content/examples/`, with
|
|
548
|
-
the A/B test or flag block while your organization has
|
|
572
|
+
the A/B test or flag block and how to render it while your organization has
|
|
573
|
+
improve on),
|
|
549
574
|
installs `@obelism/content` with your package manager, and adds the token variables to
|
|
550
575
|
`.env.example`. Options: `--dir` (default `content`), `--url`,
|
|
551
576
|
`--skip-install`. Agents get the same steps from the CMS's
|
package/dist/bin/content.js
CHANGED
|
@@ -87,6 +87,8 @@ const buildExamples = (model, improve)=>{
|
|
|
87
87
|
_type: '_improve',
|
|
88
88
|
kind: source.kind,
|
|
89
89
|
slug: source.slug,
|
|
90
|
+
fallback: source.defaultValue ?? source.options[0]?.slug ?? null,
|
|
91
|
+
mode: 'instant',
|
|
90
92
|
variants: Object.fromEntries(source.options.map((option)=>[
|
|
91
93
|
option.slug,
|
|
92
94
|
first && depth < MAX_DEPTH ? [
|
|
@@ -212,6 +214,341 @@ const buildExamples = (model, improve)=>{
|
|
|
212
214
|
return examples;
|
|
213
215
|
};
|
|
214
216
|
|
|
217
|
+
// The CMS's docs/adr/0035: one copy of the site's half, beside the example.
|
|
218
|
+
const IMPROVE_GUIDE = `# Rendering the improve block
|
|
219
|
+
|
|
220
|
+
\`_improve.json\` is what the delivery API answers for the improve block: one
|
|
221
|
+
list of blocks per option of an Obelism Improve test or flag. Editors add,
|
|
222
|
+
run and end these tests without you, so set the site up once and a page can
|
|
223
|
+
carry any number of tests without a build, a route or a deploy per test.
|
|
224
|
+
|
|
225
|
+
Written by \`content init\`; the guide is
|
|
226
|
+
https://content.obelism.studio/docs/guides/ab-tests.
|
|
227
|
+
|
|
228
|
+
## Rendered per request
|
|
229
|
+
|
|
230
|
+
If the page is rendered per request, pick the variant while you render and
|
|
231
|
+
skip the rest of this file:
|
|
232
|
+
|
|
233
|
+
\`\`\`ts
|
|
234
|
+
import { isImproveBlock, pickImproveVariant } from '@obelism/content'
|
|
235
|
+
|
|
236
|
+
// \`improve\` is Improve's server SDK (@obelism/improve-sdk/server) with its
|
|
237
|
+
// datafile loaded; \`visitorId\` its cookie on the request.
|
|
238
|
+
const blocks = fields.body.flatMap((block) => {
|
|
239
|
+
if (!isImproveBlock(block)) return [block]
|
|
240
|
+
const option =
|
|
241
|
+
block.kind === 'flag'
|
|
242
|
+
? improve.getFlagValue(block.slug, visitorId, userAgent, { country })
|
|
243
|
+
: improve.getTestValue(block.slug, visitorId, userAgent, { country })
|
|
244
|
+
return pickImproveVariant(block, option)
|
|
245
|
+
})
|
|
246
|
+
\`\`\`
|
|
247
|
+
|
|
248
|
+
## Prerendered: every variant in the page
|
|
249
|
+
|
|
250
|
+
A page built once (static, ISR) is the same bytes for every visitor. It
|
|
251
|
+
carries every variant, tagged, and a script in the head shows one before the
|
|
252
|
+
first paint. Five pieces, set up once.
|
|
253
|
+
|
|
254
|
+
### 1. The block renderer
|
|
255
|
+
|
|
256
|
+
The branch of your block renderer that meets \`_improve\`. \`mode\` is stamped
|
|
257
|
+
when the entry is published: \`instant\` puts every variant in the markup,
|
|
258
|
+
\`after-load\` only the \`fallback\` one, with the others as JSON beside it.
|
|
259
|
+
|
|
260
|
+
\`\`\`tsx
|
|
261
|
+
import { isImproveBlock, type Block, type ImproveBlock } from '@obelism/content'
|
|
262
|
+
|
|
263
|
+
import { AfterLoadVariants } from './AfterLoadVariants'
|
|
264
|
+
|
|
265
|
+
export const BlockRenderer = ({ block }: { block: Block }) => {
|
|
266
|
+
if (isImproveBlock(block)) {
|
|
267
|
+
return block.mode === 'after-load' ? (
|
|
268
|
+
<AfterLoadVariants block={block} />
|
|
269
|
+
) : (
|
|
270
|
+
<ImproveVariants block={block} />
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
const Component = components[block._type]
|
|
274
|
+
return Component ? <Component block={block} /> : null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const ImproveVariants = ({ block }: { block: ImproveBlock }) => (
|
|
278
|
+
<>
|
|
279
|
+
{Object.entries(block.variants ?? {}).map(([option, blocks]) => (
|
|
280
|
+
<div key={option} data-ob-imp={block.slug} data-ob-opt={option}>
|
|
281
|
+
{blocks.map((child) => (
|
|
282
|
+
<BlockRenderer block={child} key={child._uid} />
|
|
283
|
+
))}
|
|
284
|
+
</div>
|
|
285
|
+
))}
|
|
286
|
+
</>
|
|
287
|
+
)
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
The element around a variant gets \`display: contents\` from the style below,
|
|
291
|
+
so a block in a grid or a flex row keeps its place.
|
|
292
|
+
|
|
293
|
+
### 2. The head
|
|
294
|
+
|
|
295
|
+
The instant tests of the page, their option lists, a classic script and one
|
|
296
|
+
style rule per test, all in \`<head>\` before the body. Never \`type="module"\`,
|
|
297
|
+
\`defer\` or \`async\`: those run after the variants are painted. Allow the
|
|
298
|
+
script in a CSP by its hash; Cloudflare's Rocket Loader needs
|
|
299
|
+
\`data-cfasync="false"\` on it.
|
|
300
|
+
|
|
301
|
+
\`\`\`ts
|
|
302
|
+
import type { ImproveBlock } from '@obelism/content'
|
|
303
|
+
|
|
304
|
+
const SAFE = /^[a-z0-9-]+$/
|
|
305
|
+
|
|
306
|
+
// Every improve block in an entry, however deep.
|
|
307
|
+
export const improveBlocks = (value: unknown, found: ImproveBlock[] = []) => {
|
|
308
|
+
if (Array.isArray(value)) value.forEach((item) => improveBlocks(item, found))
|
|
309
|
+
else if (value && typeof value === 'object') {
|
|
310
|
+
const record = value as Record<string, unknown>
|
|
311
|
+
if (record._type === '_improve') found.push(value as ImproveBlock)
|
|
312
|
+
for (const child of Object.values(record)) improveBlocks(child, found)
|
|
313
|
+
}
|
|
314
|
+
return found
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// The meta's content and the style, from the page's instant placements.
|
|
318
|
+
// Nothing (and no script) when it has none.
|
|
319
|
+
export const improveHead = (entry: unknown) => {
|
|
320
|
+
const tests = new Map<string, { options: string[]; fallback: string }>()
|
|
321
|
+
for (const block of improveBlocks(entry)) {
|
|
322
|
+
if (block.mode === 'after-load' || !SAFE.test(block.slug)) continue
|
|
323
|
+
const options = Object.keys(block.variants ?? {}).filter((option) =>
|
|
324
|
+
SAFE.test(option),
|
|
325
|
+
)
|
|
326
|
+
const fallback =
|
|
327
|
+
block.fallback && options.includes(block.fallback)
|
|
328
|
+
? block.fallback
|
|
329
|
+
: options[0]
|
|
330
|
+
if (fallback) tests.set(block.slug, { options, fallback })
|
|
331
|
+
}
|
|
332
|
+
if (tests.size === 0) return null
|
|
333
|
+
|
|
334
|
+
const meta = JSON.stringify(
|
|
335
|
+
Object.fromEntries([...tests].map(([slug, { options }]) => [slug, options])),
|
|
336
|
+
)
|
|
337
|
+
const hidden = [...tests].flatMap(([slug, { options, fallback }]) => [
|
|
338
|
+
\`html:not([data-imp-\${slug}]) [data-ob-imp="\${slug}"]:not([data-ob-opt="\${fallback}"])\`,
|
|
339
|
+
...options.map(
|
|
340
|
+
(option) =>
|
|
341
|
+
\`html[data-imp-\${slug}="\${option}"] [data-ob-imp="\${slug}"]:not([data-ob-opt="\${option}"])\`,
|
|
342
|
+
),
|
|
343
|
+
])
|
|
344
|
+
const style = \`[data-ob-imp]{display:contents}\\n\${hidden.join(',\\n')}{display:none}\`
|
|
345
|
+
return { meta, style }
|
|
346
|
+
}
|
|
347
|
+
\`\`\`
|
|
348
|
+
|
|
349
|
+
\`\`\`html
|
|
350
|
+
<meta name="obelism-improve" content='{"homepage-hero":["control","variation"]}' />
|
|
351
|
+
<script data-cfasync="false">
|
|
352
|
+
;(function () {
|
|
353
|
+
var meta = document.querySelector('meta[name="obelism-improve"]')
|
|
354
|
+
if (!meta) return
|
|
355
|
+
var tests = JSON.parse(meta.content)
|
|
356
|
+
var cookies = document.cookie.split('; ')
|
|
357
|
+
for (var slug in tests) {
|
|
358
|
+
for (var i = 0; i < cookies.length; i++) {
|
|
359
|
+
if (cookies[i].indexOf(slug + '=') !== 0) continue
|
|
360
|
+
var value = cookies[i].slice(slug.length + 1)
|
|
361
|
+
if (tests[slug].indexOf(value) > -1)
|
|
362
|
+
document.documentElement.setAttribute('data-imp-' + slug, value)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
})()
|
|
366
|
+
</script>
|
|
367
|
+
<style>
|
|
368
|
+
/* improveHead(entry).style */
|
|
369
|
+
</style>
|
|
370
|
+
\`\`\`
|
|
371
|
+
|
|
372
|
+
In React, \`improveHead(entry)\` gives the meta's \`content\` and the style's
|
|
373
|
+
text: \`<meta name="obelism-improve" content={head.meta} />\`, then the script
|
|
374
|
+
as a string in \`<script dangerouslySetInnerHTML={{ __html: RUNTIME }} />\`,
|
|
375
|
+
then \`<style dangerouslySetInnerHTML={{ __html: head.style }} />\`. The slugs
|
|
376
|
+
and options in both passed \`SAFE\`, so neither can close its tag.
|
|
377
|
+
|
|
378
|
+
The option list matters: a cookie can name an option the block no longer
|
|
379
|
+
has, and without the check every variant of that block would hide. Only the
|
|
380
|
+
variants that lost are ever hidden; the one that shows keeps your styles.
|
|
381
|
+
|
|
382
|
+
### 3. The edge
|
|
383
|
+
|
|
384
|
+
An edge function in front of the page decides every active test and flag
|
|
385
|
+
before the page is served, and keeps the cookies a visitor already has.
|
|
386
|
+
Without one, every visitor gets the fallback and the test measures nothing.
|
|
387
|
+
|
|
388
|
+
\`\`\`ts
|
|
389
|
+
import { ImproveServerSDK } from '@obelism/improve-sdk/server'
|
|
390
|
+
|
|
391
|
+
// Per request: the instance keeps its datafile for as long as it lives.
|
|
392
|
+
const improve = new ImproveServerSDK({
|
|
393
|
+
organizationId: 'org_…',
|
|
394
|
+
spaceId: 'space_…',
|
|
395
|
+
environment: 'production',
|
|
396
|
+
token: env.IMPROVE_TOKEN,
|
|
397
|
+
})
|
|
398
|
+
await improve.fetchConfig()
|
|
399
|
+
|
|
400
|
+
const { cookies } = improve.seedTestCookies({
|
|
401
|
+
cookieHeader: request.headers.get('Cookie'),
|
|
402
|
+
userAgent: request.headers.get('User-Agent') ?? '',
|
|
403
|
+
geo: { country: request.headers.get('CF-IPCountry') ?? undefined },
|
|
404
|
+
})
|
|
405
|
+
for (const { header } of cookies) response.headers.append('Set-Cookie', header)
|
|
406
|
+
\`\`\`
|
|
407
|
+
|
|
408
|
+
Leave bots out (they get the fallback and no cookie), never send
|
|
409
|
+
\`Vary: Cookie\`, and keep caching the page itself: only the cookies are per
|
|
410
|
+
visitor.
|
|
411
|
+
|
|
412
|
+
### 4. The exposure
|
|
413
|
+
|
|
414
|
+
Results count exposures, and nothing has recorded one: the page decided
|
|
415
|
+
nothing. After paint, ask Improve's client SDK once per test the edge
|
|
416
|
+
decided; it reads the cookie, records the exposure and does not bucket again.
|
|
417
|
+
|
|
418
|
+
\`\`\`ts
|
|
419
|
+
// improveExposure.ts
|
|
420
|
+
import type { ImproveBlock } from '@obelism/content'
|
|
421
|
+
import { ImproveClientSDK } from '@obelism/improve-sdk/client'
|
|
422
|
+
|
|
423
|
+
let ready: Promise<ImproveClientSDK> | undefined
|
|
424
|
+
const recorded = new Set<string>()
|
|
425
|
+
|
|
426
|
+
// Once per test, however many placements the page has.
|
|
427
|
+
export const recordExposure = async ({ slug, kind }: ImproveBlock) => {
|
|
428
|
+
if (recorded.has(slug)) return
|
|
429
|
+
recorded.add(slug)
|
|
430
|
+
ready ??= (async () => {
|
|
431
|
+
const improve = new ImproveClientSDK({
|
|
432
|
+
organizationId: 'org_…',
|
|
433
|
+
spaceId: 'space_…',
|
|
434
|
+
environment: 'production',
|
|
435
|
+
})
|
|
436
|
+
await improve.fetchConfig()
|
|
437
|
+
return improve
|
|
438
|
+
})()
|
|
439
|
+
const improve = await ready
|
|
440
|
+
if (kind === 'flag') improve.getFlagValue(slug)
|
|
441
|
+
else improve.getTestValue(slug)
|
|
442
|
+
}
|
|
443
|
+
\`\`\`
|
|
444
|
+
|
|
445
|
+
\`\`\`tsx
|
|
446
|
+
'use client'
|
|
447
|
+
import { useEffect } from 'react'
|
|
448
|
+
import type { ImproveBlock } from '@obelism/content'
|
|
449
|
+
|
|
450
|
+
import { recordExposure } from './improveExposure'
|
|
451
|
+
|
|
452
|
+
// Once per page, with improveBlocks(entry).
|
|
453
|
+
export const ImproveExposures = ({ blocks }: { blocks: ImproveBlock[] }) => {
|
|
454
|
+
useEffect(() => {
|
|
455
|
+
for (const block of blocks) {
|
|
456
|
+
if (block.mode === 'after-load') continue
|
|
457
|
+
if (document.documentElement.hasAttribute(\`data-imp-\${block.slug}\`))
|
|
458
|
+
recordExposure(block)
|
|
459
|
+
}
|
|
460
|
+
}, [blocks])
|
|
461
|
+
return null
|
|
462
|
+
}
|
|
463
|
+
\`\`\`
|
|
464
|
+
|
|
465
|
+
### 5. After-load placements
|
|
466
|
+
|
|
467
|
+
Below the page type's fold, publishing stamps \`mode: "after-load"\`: the
|
|
468
|
+
fallback variant is markup, the others JSON in the page, swapped in on mount.
|
|
469
|
+
No second variant's markup or images, and no head script for a page that has
|
|
470
|
+
only these. It needs a block renderer that runs in the browser.
|
|
471
|
+
|
|
472
|
+
\`\`\`tsx
|
|
473
|
+
'use client'
|
|
474
|
+
import { useEffect, useState } from 'react'
|
|
475
|
+
import type { Block, ImproveBlock } from '@obelism/content'
|
|
476
|
+
|
|
477
|
+
import { BlockRenderer } from './BlockRenderer'
|
|
478
|
+
import { recordExposure } from './improveExposure'
|
|
479
|
+
|
|
480
|
+
// \`<\` escaped, so a block's text can't close the script.
|
|
481
|
+
const json = (value: unknown) =>
|
|
482
|
+
JSON.stringify(value).replace(/</g, '\\\\u003c')
|
|
483
|
+
|
|
484
|
+
const readCookie = (name: string) =>
|
|
485
|
+
document.cookie
|
|
486
|
+
.split('; ')
|
|
487
|
+
.find((row) => row.startsWith(\`\${name}=\`))
|
|
488
|
+
?.slice(name.length + 1)
|
|
489
|
+
|
|
490
|
+
export const AfterLoadVariants = ({ block }: { block: ImproveBlock }) => {
|
|
491
|
+
const variants = block.variants ?? {}
|
|
492
|
+
const fallback =
|
|
493
|
+
block.fallback && variants[block.fallback]
|
|
494
|
+
? block.fallback
|
|
495
|
+
: Object.keys(variants)[0]
|
|
496
|
+
const others = Object.fromEntries(
|
|
497
|
+
Object.entries(variants).filter(([option]) => option !== fallback),
|
|
498
|
+
)
|
|
499
|
+
const [shown, setShown] = useState<{ option: string | undefined; blocks: Block[] }>({
|
|
500
|
+
option: fallback,
|
|
501
|
+
blocks: (fallback && variants[fallback]) || [],
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
useEffect(() => {
|
|
505
|
+
const option = readCookie(block.slug)
|
|
506
|
+
if (!option) return
|
|
507
|
+
const script = document.querySelector(
|
|
508
|
+
\`script[data-ob-variants="\${CSS.escape(block.slug)}"]\`,
|
|
509
|
+
)
|
|
510
|
+
const arms: Record<string, Block[]> =
|
|
511
|
+
option === fallback ? variants : JSON.parse(script?.textContent || '{}')
|
|
512
|
+
// The cookie is the visitor's to edit: only an option the block has.
|
|
513
|
+
const blocks = Object.hasOwn(arms, option) ? arms[option] : undefined
|
|
514
|
+
if (!Array.isArray(blocks)) return
|
|
515
|
+
setShown({ option, blocks })
|
|
516
|
+
document.documentElement.setAttribute(\`data-imp-\${block.slug}\`, option)
|
|
517
|
+
recordExposure(block)
|
|
518
|
+
}, [block.slug])
|
|
519
|
+
|
|
520
|
+
return (
|
|
521
|
+
<>
|
|
522
|
+
<div
|
|
523
|
+
data-ob-imp={block.slug}
|
|
524
|
+
data-ob-opt={shown.option}
|
|
525
|
+
style={{ display: 'contents' }}
|
|
526
|
+
>
|
|
527
|
+
{shown.blocks.map((child) => (
|
|
528
|
+
<BlockRenderer block={child} key={child._uid} />
|
|
529
|
+
))}
|
|
530
|
+
</div>
|
|
531
|
+
<script
|
|
532
|
+
type="application/json"
|
|
533
|
+
data-ob-variants={block.slug}
|
|
534
|
+
dangerouslySetInnerHTML={{ __html: json(others) }}
|
|
535
|
+
/>
|
|
536
|
+
</>
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
\`\`\`
|
|
540
|
+
|
|
541
|
+
Its own \`display: contents\` is inline: a page with only after-load
|
|
542
|
+
placements has no head style. The exposure is recorded when the swap lands, not before: a visitor who never
|
|
543
|
+
gets the variant is not counted as seeing it.
|
|
544
|
+
|
|
545
|
+
## Ending a test
|
|
546
|
+
|
|
547
|
+
Pausing it in Improve only stops new assignments. In Content, **Keep a
|
|
548
|
+
variant** on the block replaces it with that option's blocks; publishing the
|
|
549
|
+
page ends the test for everyone.
|
|
550
|
+
`;
|
|
551
|
+
|
|
215
552
|
// Turns a model plan from the management API into text for a terminal, or
|
|
216
553
|
// Markdown for a GitHub step summary or pull request comment.
|
|
217
554
|
const ACTION_SIGN = {
|
|
@@ -535,8 +872,11 @@ const runInitCommand = async ({ url, token, dir, install: shouldInstall, cwd = p
|
|
|
535
872
|
for (const [apiId, example] of Object.entries(examples)){
|
|
536
873
|
await writeJson(node_path.join(examplesDir, `${apiId}.json`), example);
|
|
537
874
|
}
|
|
875
|
+
if (improve.enabled) {
|
|
876
|
+
await promises.writeFile(node_path.join(examplesDir, '_improve.md'), IMPROVE_GUIDE);
|
|
877
|
+
}
|
|
538
878
|
const count = Object.keys(examples).length;
|
|
539
|
-
log(`Wrote ${count} ${count === 1 ? 'example' : 'examples'} to ${node_path.join(dir, 'examples')}${improve.enabled ? ', with the A/B test or flag block (_improve.json): improve is on' : ''}.`);
|
|
879
|
+
log(`Wrote ${count} ${count === 1 ? 'example' : 'examples'} to ${node_path.join(dir, 'examples')}${improve.enabled ? ', with the A/B test or flag block (_improve.json) and how to render it (_improve.md): improve is on' : ''}.`);
|
|
540
880
|
if (await writeEnvExample(cwd, url)) {
|
|
541
881
|
log('Added the token variables to .env.example.');
|
|
542
882
|
}
|
|
@@ -548,7 +888,7 @@ const runInitCommand = async ({ url, token, dir, install: shouldInstall, cwd = p
|
|
|
548
888
|
'- Set CONTENT_SPACE_ID and CONTENT_ENVIRONMENT, and pass them as space and environment to the ContentClient you read cms_token with, so a cms_token for another space reads nothing.',
|
|
549
889
|
'- Fetch content with ContentClient from @obelism/content; the examples show what each type looks like.',
|
|
550
890
|
...improve.enabled ? [
|
|
551
|
-
|
|
891
|
+
`- Render _improve blocks as ${node_path.join(dir, 'examples', '_improve.md')} says: every variant tagged in the page, a script in the head, seedTestCookies at the edge and an exposure after paint (or pickImproveVariant on a page rendered per request).`
|
|
552
892
|
] : [],
|
|
553
893
|
`- Keep the model in step with \`content model pull|plan|apply\` (${node_path.join(dir, 'content-model.json')}).`
|
|
554
894
|
].join('\n'));
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TokenSource } from './oidc.mjs';
|
|
2
|
-
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-
|
|
3
|
-
export { g as AssetProduct, C as ContentTypeAccent, h as ContentTypeDefinition, i as ContentTypeKind, j as Environment, F as FieldCondition, k as FieldDefinition, l as FieldGroup, m as FieldType, n as RichTextDocument, o as RichTextMark } from './types-
|
|
2
|
+
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-e32p5mys.js';
|
|
3
|
+
export { g as AssetProduct, C as ContentTypeAccent, h as ContentTypeDefinition, i as ContentTypeKind, j as Environment, F as FieldCondition, k as FieldDefinition, l as FieldGroup, m as FieldType, n as RichTextDocument, o as RichTextMark, p as SharedFrom } from './types-e32p5mys.js';
|
|
4
4
|
|
|
5
5
|
type ContentClientOptions = {
|
|
6
6
|
token: TokenSource;
|
|
@@ -117,7 +117,7 @@ declare const imageSrcSet: (asset: (Pick<Asset, "url"> & Partial<Pick<Asset, "fo
|
|
|
117
117
|
|
|
118
118
|
declare const IMPROVE_BLOCK = "_improve";
|
|
119
119
|
declare const isImproveBlock: (block: Block) => block is ImproveBlock;
|
|
120
|
-
declare const pickImproveVariant: <TBlock extends Block>(block: ImproveBlock<TBlock>, option: string | null | undefined, fallback?: string) => TBlock[];
|
|
120
|
+
declare const pickImproveVariant: <TBlock extends Block>(block: ImproveBlock<TBlock>, option: string | null | undefined, fallback?: string | null) => TBlock[];
|
|
121
121
|
|
|
122
122
|
type LinkHrefOptions = {
|
|
123
123
|
url?: ((path: string) => string) | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TokenSource } from './oidc.js';
|
|
2
|
-
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-
|
|
3
|
-
export { g as AssetProduct, C as ContentTypeAccent, h as ContentTypeDefinition, i as ContentTypeKind, j as Environment, F as FieldCondition, k as FieldDefinition, l as FieldGroup, m as FieldType, n as RichTextDocument, o as RichTextMark } from './types-
|
|
2
|
+
import { R as RichTextFormat, E as Entry, a as RedirectList, b as Redirect, c as EntryList, M as ModelFile, A as Asset, B as Block, I as ImproveBlock, S as ShopifyItem, L as LinkTarget, d as Link, e as EntryStub, f as RichTextNode } from './types-e32p5mys.js';
|
|
3
|
+
export { g as AssetProduct, C as ContentTypeAccent, h as ContentTypeDefinition, i as ContentTypeKind, j as Environment, F as FieldCondition, k as FieldDefinition, l as FieldGroup, m as FieldType, n as RichTextDocument, o as RichTextMark, p as SharedFrom } from './types-e32p5mys.js';
|
|
4
4
|
|
|
5
5
|
type ContentClientOptions = {
|
|
6
6
|
token: TokenSource;
|
|
@@ -117,7 +117,7 @@ declare const imageSrcSet: (asset: (Pick<Asset, "url"> & Partial<Pick<Asset, "fo
|
|
|
117
117
|
|
|
118
118
|
declare const IMPROVE_BLOCK = "_improve";
|
|
119
119
|
declare const isImproveBlock: (block: Block) => block is ImproveBlock;
|
|
120
|
-
declare const pickImproveVariant: <TBlock extends Block>(block: ImproveBlock<TBlock>, option: string | null | undefined, fallback?: string) => TBlock[];
|
|
120
|
+
declare const pickImproveVariant: <TBlock extends Block>(block: ImproveBlock<TBlock>, option: string | null | undefined, fallback?: string | null) => TBlock[];
|
|
121
121
|
|
|
122
122
|
type LinkHrefOptions = {
|
|
123
123
|
url?: ((path: string) => string) | undefined;
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,9 @@ const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).ma
|
|
|
33
33
|
];
|
|
34
34
|
}));
|
|
35
35
|
const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
36
|
+
// `/space_…/<environment>`: the part of a scoped delivery path between
|
|
37
|
+
// DELIVERY_PATH and the operation.
|
|
38
|
+
const SCOPE = /^\/space_[^/]+\/[^/]+$/;
|
|
36
39
|
// Reads one space environment's content through the delivery API. The token
|
|
37
40
|
// decides the space, the environment and whether drafts are visible (for a
|
|
38
41
|
// host token, with `drafts`).
|
|
@@ -42,11 +45,17 @@ const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
|
42
45
|
class ContentClient {
|
|
43
46
|
#token;
|
|
44
47
|
#place;
|
|
48
|
+
// Where the API answers this client's token: it sends a token that reads
|
|
49
|
+
// published content to `/api/delivery/v1/{space}/{environment}/…` with a
|
|
50
|
+
// 308, so the client asks there directly after the first one. Never used
|
|
51
|
+
// for a request that reads drafts, which the scoped path refuses.
|
|
52
|
+
#scope;
|
|
45
53
|
#defaults;
|
|
46
54
|
#timeout;
|
|
47
55
|
#init;
|
|
48
56
|
#fetch;
|
|
49
57
|
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
58
|
+
this.#scope = null;
|
|
50
59
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
51
60
|
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
52
61
|
// paths (the default locale's when left out or `*`): pages can have a
|
|
@@ -171,7 +180,7 @@ class ContentClient {
|
|
|
171
180
|
}
|
|
172
181
|
// For a 404, null when `notFound` is set, or the body as is for 'body';
|
|
173
182
|
// throws ContentApiError otherwise.
|
|
174
|
-
async #request(path, query, { init, ...options }, { notFound = false, defaults = true } = {}) {
|
|
183
|
+
async #request(path, query, { init, ...options }, { notFound = false, defaults = true, scoped = true } = {}) {
|
|
175
184
|
// Checked here rather than in the constructor, so a module creating a
|
|
176
185
|
// client still loads (and a build still runs) without the variable.
|
|
177
186
|
if (!this.#token) throw new Error('ContentClient needs a token');
|
|
@@ -190,7 +199,8 @@ class ContentClient {
|
|
|
190
199
|
if (value !== undefined) params.set(key, String(value));
|
|
191
200
|
}
|
|
192
201
|
const search = params.size > 0 ? `?${params}` : '';
|
|
193
|
-
const
|
|
202
|
+
const scope = drafts || !scoped ? null : this.#scope;
|
|
203
|
+
const url = `${this.url}${config.DELIVERY_PATH}${scope ?? ''}${path}${search}`;
|
|
194
204
|
const merged = {
|
|
195
205
|
...this.#init,
|
|
196
206
|
...init
|
|
@@ -215,6 +225,21 @@ class ContentClient {
|
|
|
215
225
|
timeout
|
|
216
226
|
]) : timeout
|
|
217
227
|
});
|
|
228
|
+
// A token that changed, or now reads drafts, is refused on the path
|
|
229
|
+
// learned for the one before it: ask unscoped once, and learn again.
|
|
230
|
+
if (scope && (response.status === 401 || response.status === 403)) {
|
|
231
|
+
if (this.#scope === scope) this.#scope = null;
|
|
232
|
+
await response.body?.cancel();
|
|
233
|
+
return this.#request(path, query, {
|
|
234
|
+
init,
|
|
235
|
+
...options
|
|
236
|
+
}, {
|
|
237
|
+
notFound,
|
|
238
|
+
defaults,
|
|
239
|
+
scoped: false
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (!scope && !drafts && response.redirected) this.#learnScope(response, path);
|
|
218
243
|
if (notFound === true && response.status === 404) return null;
|
|
219
244
|
const text = await response.text();
|
|
220
245
|
let body = text;
|
|
@@ -229,6 +254,18 @@ class ContentClient {
|
|
|
229
254
|
if (!response.ok) throw new ContentApiError(response.status, url, body);
|
|
230
255
|
return body;
|
|
231
256
|
}
|
|
257
|
+
#learnScope(response, path) {
|
|
258
|
+
let redirected;
|
|
259
|
+
try {
|
|
260
|
+
redirected = new URL(response.url);
|
|
261
|
+
} catch {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const { origin, pathname } = redirected;
|
|
265
|
+
if (origin !== new URL(this.url).origin || !pathname.startsWith(`${config.DELIVERY_PATH}/`) || !pathname.endsWith(path)) return;
|
|
266
|
+
const scope = pathname.slice(config.DELIVERY_PATH.length, pathname.length - path.length);
|
|
267
|
+
if (SCOPE.test(scope)) this.#scope = scope;
|
|
268
|
+
}
|
|
232
269
|
}
|
|
233
270
|
const withoutUndefined = (value)=>Object.fromEntries(Object.entries(value).filter(([, entry])=>entry !== undefined));
|
|
234
271
|
const headersToObject = (headers)=>headers ? Object.fromEntries(new Headers(headers)) : {};
|
|
@@ -277,11 +314,14 @@ const isImproveBlock = (block)=>block._type === IMPROVE_BLOCK;
|
|
|
277
314
|
// improve's SDK returned for the visitor (getTestValue / getFlagValue). It
|
|
278
315
|
// is null when the test or flag isn't active or the visitor isn't in it;
|
|
279
316
|
// then, or for an option the block has no variant for, the `fallback`
|
|
280
|
-
// option's variant, else the first one
|
|
317
|
+
// option's variant, else the first one.
|
|
281
318
|
const pickImproveVariant = (block, option, fallback)=>{
|
|
282
319
|
const variants = block.variants ?? {};
|
|
283
320
|
if (option && variants[option]) return variants[option];
|
|
284
|
-
|
|
321
|
+
// The arm Improve gives a visitor outside the test, when the caller names
|
|
322
|
+
// none: it is not always the first variant.
|
|
323
|
+
const behind = fallback ?? block.fallback;
|
|
324
|
+
if (behind && variants[behind]) return variants[behind];
|
|
285
325
|
return Object.values(variants)[0] ?? [];
|
|
286
326
|
};
|
|
287
327
|
|
package/dist/index.mjs
CHANGED
|
@@ -31,6 +31,9 @@ const fieldParams = (fields)=>Object.fromEntries(Object.entries(fields ?? {}).ma
|
|
|
31
31
|
];
|
|
32
32
|
}));
|
|
33
33
|
const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
34
|
+
// `/space_…/<environment>`: the part of a scoped delivery path between
|
|
35
|
+
// DELIVERY_PATH and the operation.
|
|
36
|
+
const SCOPE = /^\/space_[^/]+\/[^/]+$/;
|
|
34
37
|
// Reads one space environment's content through the delivery API. The token
|
|
35
38
|
// decides the space, the environment and whether drafts are visible (for a
|
|
36
39
|
// host token, with `drafts`).
|
|
@@ -40,11 +43,17 @@ const trimSlashes = (path)=>path.replace(/^\/+|\/+$/g, '');
|
|
|
40
43
|
class ContentClient {
|
|
41
44
|
#token;
|
|
42
45
|
#place;
|
|
46
|
+
// Where the API answers this client's token: it sends a token that reads
|
|
47
|
+
// published content to `/api/delivery/v1/{space}/{environment}/…` with a
|
|
48
|
+
// 308, so the client asks there directly after the first one. Never used
|
|
49
|
+
// for a request that reads drafts, which the scoped path refuses.
|
|
50
|
+
#scope;
|
|
43
51
|
#defaults;
|
|
44
52
|
#timeout;
|
|
45
53
|
#init;
|
|
46
54
|
#fetch;
|
|
47
55
|
constructor({ token, drafts, space, environment, url, locale, depth, richText, timeout, init, fetch: fetchImpl }){
|
|
56
|
+
this.#scope = null;
|
|
48
57
|
// The page at a path (`blog/hello`), or null when there is none. A site's
|
|
49
58
|
// catch-all route asks for this. The path is looked up in `locale`'s
|
|
50
59
|
// paths (the default locale's when left out or `*`): pages can have a
|
|
@@ -169,7 +178,7 @@ class ContentClient {
|
|
|
169
178
|
}
|
|
170
179
|
// For a 404, null when `notFound` is set, or the body as is for 'body';
|
|
171
180
|
// throws ContentApiError otherwise.
|
|
172
|
-
async #request(path, query, { init, ...options }, { notFound = false, defaults = true } = {}) {
|
|
181
|
+
async #request(path, query, { init, ...options }, { notFound = false, defaults = true, scoped = true } = {}) {
|
|
173
182
|
// Checked here rather than in the constructor, so a module creating a
|
|
174
183
|
// client still loads (and a build still runs) without the variable.
|
|
175
184
|
if (!this.#token) throw new Error('ContentClient needs a token');
|
|
@@ -188,7 +197,8 @@ class ContentClient {
|
|
|
188
197
|
if (value !== undefined) params.set(key, String(value));
|
|
189
198
|
}
|
|
190
199
|
const search = params.size > 0 ? `?${params}` : '';
|
|
191
|
-
const
|
|
200
|
+
const scope = drafts || !scoped ? null : this.#scope;
|
|
201
|
+
const url = `${this.url}${DELIVERY_PATH}${scope ?? ''}${path}${search}`;
|
|
192
202
|
const merged = {
|
|
193
203
|
...this.#init,
|
|
194
204
|
...init
|
|
@@ -213,6 +223,21 @@ class ContentClient {
|
|
|
213
223
|
timeout
|
|
214
224
|
]) : timeout
|
|
215
225
|
});
|
|
226
|
+
// A token that changed, or now reads drafts, is refused on the path
|
|
227
|
+
// learned for the one before it: ask unscoped once, and learn again.
|
|
228
|
+
if (scope && (response.status === 401 || response.status === 403)) {
|
|
229
|
+
if (this.#scope === scope) this.#scope = null;
|
|
230
|
+
await response.body?.cancel();
|
|
231
|
+
return this.#request(path, query, {
|
|
232
|
+
init,
|
|
233
|
+
...options
|
|
234
|
+
}, {
|
|
235
|
+
notFound,
|
|
236
|
+
defaults,
|
|
237
|
+
scoped: false
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (!scope && !drafts && response.redirected) this.#learnScope(response, path);
|
|
216
241
|
if (notFound === true && response.status === 404) return null;
|
|
217
242
|
const text = await response.text();
|
|
218
243
|
let body = text;
|
|
@@ -227,6 +252,18 @@ class ContentClient {
|
|
|
227
252
|
if (!response.ok) throw new ContentApiError(response.status, url, body);
|
|
228
253
|
return body;
|
|
229
254
|
}
|
|
255
|
+
#learnScope(response, path) {
|
|
256
|
+
let redirected;
|
|
257
|
+
try {
|
|
258
|
+
redirected = new URL(response.url);
|
|
259
|
+
} catch {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const { origin, pathname } = redirected;
|
|
263
|
+
if (origin !== new URL(this.url).origin || !pathname.startsWith(`${DELIVERY_PATH}/`) || !pathname.endsWith(path)) return;
|
|
264
|
+
const scope = pathname.slice(DELIVERY_PATH.length, pathname.length - path.length);
|
|
265
|
+
if (SCOPE.test(scope)) this.#scope = scope;
|
|
266
|
+
}
|
|
230
267
|
}
|
|
231
268
|
const withoutUndefined = (value)=>Object.fromEntries(Object.entries(value).filter(([, entry])=>entry !== undefined));
|
|
232
269
|
const headersToObject = (headers)=>headers ? Object.fromEntries(new Headers(headers)) : {};
|
|
@@ -275,11 +312,14 @@ const isImproveBlock = (block)=>block._type === IMPROVE_BLOCK;
|
|
|
275
312
|
// improve's SDK returned for the visitor (getTestValue / getFlagValue). It
|
|
276
313
|
// is null when the test or flag isn't active or the visitor isn't in it;
|
|
277
314
|
// then, or for an option the block has no variant for, the `fallback`
|
|
278
|
-
// option's variant, else the first one
|
|
315
|
+
// option's variant, else the first one.
|
|
279
316
|
const pickImproveVariant = (block, option, fallback)=>{
|
|
280
317
|
const variants = block.variants ?? {};
|
|
281
318
|
if (option && variants[option]) return variants[option];
|
|
282
|
-
|
|
319
|
+
// The arm Improve gives a visitor outside the test, when the caller names
|
|
320
|
+
// none: it is not always the first variant.
|
|
321
|
+
const behind = fallback ?? block.fallback;
|
|
322
|
+
if (behind && variants[behind]) return variants[behind];
|
|
283
323
|
return Object.values(variants)[0] ?? [];
|
|
284
324
|
};
|
|
285
325
|
|
|
@@ -72,10 +72,18 @@ type Link = {
|
|
|
72
72
|
type Block<TFields extends Record<string, unknown> = Record<string, unknown>, TType extends string = string> = {
|
|
73
73
|
_uid: string;
|
|
74
74
|
_type: TType;
|
|
75
|
+
_sharedFrom?: SharedFrom;
|
|
75
76
|
} & TFields;
|
|
77
|
+
type SharedFrom = {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
heldAt?: string;
|
|
81
|
+
};
|
|
76
82
|
type ImproveBlock<TBlock extends Block = Block> = Block<{
|
|
77
83
|
kind: 'test' | 'flag';
|
|
78
84
|
slug: string;
|
|
85
|
+
fallback?: string | null;
|
|
86
|
+
mode?: 'instant' | 'after-load' | null;
|
|
79
87
|
variants: Record<string, TBlock[]>;
|
|
80
88
|
}, '_improve'>;
|
|
81
89
|
type RichTextMark = {
|
|
@@ -225,5 +233,5 @@ type ModelFile = {
|
|
|
225
233
|
contentTypes: ContentTypeDefinition[];
|
|
226
234
|
};
|
|
227
235
|
|
|
228
|
-
export type { Asset as A, Block as B, ContentTypeAccent as C, Entry as E, FieldCondition as F, ImproveBlock as I, LinkTarget as L, ModelFile as M, RichTextFormat as R, ShopifyItem as S, RedirectList as a, Redirect as b, EntryList as c, Link as d, EntryStub as e, RichTextNode as f, AssetProduct as g, ContentTypeDefinition as h, ContentTypeKind as i, Environment as j, FieldDefinition as k, FieldGroup as l, FieldType as m, RichTextDocument as n, RichTextMark as o };
|
|
229
|
-
//# sourceMappingURL=types-
|
|
236
|
+
export type { Asset as A, Block as B, ContentTypeAccent as C, Entry as E, FieldCondition as F, ImproveBlock as I, LinkTarget as L, ModelFile as M, RichTextFormat as R, ShopifyItem as S, RedirectList as a, Redirect as b, EntryList as c, Link as d, EntryStub as e, RichTextNode as f, AssetProduct as g, ContentTypeDefinition as h, ContentTypeKind as i, Environment as j, FieldDefinition as k, FieldGroup as l, FieldType as m, RichTextDocument as n, RichTextMark as o, SharedFrom as p };
|
|
237
|
+
//# sourceMappingURL=types-e32p5mys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-e32p5mys.d.ts","sources":["../src/types.ts"],"mappings":"AAAA,KAAK,WAAW;AAChB,KAAK,cAAc;AACnB,KAAK,KAAK;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,MAAM;AAC1B,kBAAkB,MAAM;AACxB;AACA;AACA;AACA;AACA,eAAe,YAAY;AAC3B;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS;AACd;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA,oBAAoB,MAAM;AAC1B;AACA;AACA;AACA,KAAK,IAAI;AACT;AACA,WAAW,UAAU;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,WAAW,UAAU;AACrB;AACA;AACA;AACA;AACA,gBAAgB,WAAW;AAC3B,WAAW,UAAU;AACrB;AACA;AACA;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA,kBAAkB,UAAU;AAC5B;AACA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA,KAAK,YAAY,gBAAgB,KAAK,GAAG,KAAK,IAAI,KAAK;AACvD;AACA;AACA;AACA;AACA,cAAc,MAAM;AACpB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB,cAAc,YAAY;AAC1B;AACA,YAAY,YAAY;AACxB;AACA,KAAK,gBAAgB,GAAG,YAAY;AACpC;AACA;AACA,KAAK,SAAS,gBAAgB,KAAK,GAAG,KAAK;AAC3C;AACA;AACA;AACA;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA,KAAK,YAAY;AACjB,WAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,KAAK,eAAe;AACpB,KAAK,SAAS;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,MAAM;AACvB;AACA,WAAW,cAAc;AACzB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA,KAAK,iBAAiB;AACtB,KAAK,eAAe,GAAG,SAAS;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS,GAAG,eAAe;AAChC,KAAK,qBAAqB;AAC1B;AACA;AACA,UAAU,eAAe;AACzB;AACA;AACA,aAAa,iBAAiB;AAC9B;AACA,aAAa,UAAU;AACvB,YAAY,eAAe;AAC3B;AACA,KAAK,SAAS;AACd;AACA;AACA,kBAAkB,qBAAqB;AACvC;;","names":[]}
|
package/dist/webhooks.d.mts
CHANGED
|
@@ -17,6 +17,10 @@ type WebhookEventOf<TType extends string, TData> = {
|
|
|
17
17
|
type EntryPublishedEvent = WebhookEventOf<'entry.published', {
|
|
18
18
|
entry: WebhookEntry;
|
|
19
19
|
}>;
|
|
20
|
+
type BlockPublishedEvent = WebhookEventOf<'block.published', {
|
|
21
|
+
entry: WebhookEntry;
|
|
22
|
+
entries: WebhookEntry[];
|
|
23
|
+
}>;
|
|
20
24
|
type EntryUnpublishedEvent = WebhookEventOf<'entry.unpublished', {
|
|
21
25
|
entry: WebhookEntry;
|
|
22
26
|
}>;
|
|
@@ -56,6 +60,22 @@ type EntryReviewClosedEvent = WebhookEventOf<'entry.review_closed', {
|
|
|
56
60
|
revision: number;
|
|
57
61
|
reason?: string;
|
|
58
62
|
}>;
|
|
63
|
+
type WebhookRelease = {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
};
|
|
67
|
+
type WebhookReleaseEntry = WebhookEntry & {
|
|
68
|
+
action: 'publish' | 'unpublish';
|
|
69
|
+
};
|
|
70
|
+
type ReleasePublishedEvent = WebhookEventOf<'release.published', {
|
|
71
|
+
release: WebhookRelease;
|
|
72
|
+
entries: WebhookReleaseEntry[];
|
|
73
|
+
}>;
|
|
74
|
+
type ReleaseReviewRequestedEvent = WebhookEventOf<'release.review_requested', {
|
|
75
|
+
release: WebhookRelease;
|
|
76
|
+
note: string | null;
|
|
77
|
+
entries: WebhookReleaseEntry[];
|
|
78
|
+
}>;
|
|
59
79
|
type WebhookShopifyItem = {
|
|
60
80
|
id: string;
|
|
61
81
|
handle: string | null;
|
|
@@ -79,7 +99,7 @@ type CollectionDeletedEvent = WebhookEventOf<'collection.deleted', StoreChange &
|
|
|
79
99
|
collection: WebhookShopifyItem;
|
|
80
100
|
}>;
|
|
81
101
|
type WebhookTestEvent = WebhookEventOf<'webhook.test', Record<string, never>>;
|
|
82
|
-
type WebhookEvent = EntryPublishedEvent | EntryUnpublishedEvent | EntryDeletedEvent | EntryMovedEvent | AssetUpdatedEvent | ModelChangedEvent | LocalesChangedEvent | EntryReviewRequestedEvent | EntryReviewClosedEvent | ProductUpdatedEvent | ProductDeletedEvent | CollectionUpdatedEvent | CollectionDeletedEvent | WebhookTestEvent;
|
|
102
|
+
type WebhookEvent = EntryPublishedEvent | BlockPublishedEvent | EntryUnpublishedEvent | EntryDeletedEvent | EntryMovedEvent | AssetUpdatedEvent | ModelChangedEvent | LocalesChangedEvent | EntryReviewRequestedEvent | EntryReviewClosedEvent | ReleasePublishedEvent | ReleaseReviewRequestedEvent | ProductUpdatedEvent | ProductDeletedEvent | CollectionUpdatedEvent | CollectionDeletedEvent | WebhookTestEvent;
|
|
83
103
|
type WebhookEventType = WebhookEvent['type'];
|
|
84
104
|
declare class WebhookVerificationError extends Error {
|
|
85
105
|
constructor(message: string);
|
|
@@ -103,5 +123,5 @@ type WebhookHandlerOptions = {
|
|
|
103
123
|
declare const createWebhookHandler: ({ secret, onEvent, tolerance }: WebhookHandlerOptions) => (request: Request) => Promise<Response>;
|
|
104
124
|
|
|
105
125
|
export { WebhookVerificationError, createWebhookHandler, verifyWebhook };
|
|
106
|
-
export type { AssetUpdatedEvent, CollectionDeletedEvent, CollectionUpdatedEvent, EntryDeletedEvent, EntryMovedEvent, EntryPublishedEvent, EntryReviewClosedEvent, EntryReviewRequestedEvent, EntryUnpublishedEvent, LocalesChangedEvent, ModelChangedEvent, ProductDeletedEvent, ProductUpdatedEvent, VerifyWebhookOptions, WebhookEntry, WebhookEvent, WebhookEventType, WebhookHandlerOptions, WebhookMessage, WebhookShopifyItem, WebhookTestEvent };
|
|
126
|
+
export type { AssetUpdatedEvent, BlockPublishedEvent, CollectionDeletedEvent, CollectionUpdatedEvent, EntryDeletedEvent, EntryMovedEvent, EntryPublishedEvent, EntryReviewClosedEvent, EntryReviewRequestedEvent, EntryUnpublishedEvent, LocalesChangedEvent, ModelChangedEvent, ProductDeletedEvent, ProductUpdatedEvent, ReleasePublishedEvent, ReleaseReviewRequestedEvent, VerifyWebhookOptions, WebhookEntry, WebhookEvent, WebhookEventType, WebhookHandlerOptions, WebhookMessage, WebhookRelease, WebhookReleaseEntry, WebhookShopifyItem, WebhookTestEvent };
|
|
107
127
|
//# sourceMappingURL=webhooks.d.mts.map
|
package/dist/webhooks.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.mts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA,mBAAmB,MAAM;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,yBAAyB,GAAG,cAAc;AAC/C,WAAW,YAAY;AACvB;AACA;AACA;AACA,KAAK,sBAAsB,GAAG,cAAc;AAC5C,WAAW,YAAY;AACvB;AACA;AACA;AACA;AACA,KAAK,kBAAkB;AACvB;AACA;AACA;AACA,KAAK,WAAW;AAChB,aAAa,YAAY;AACzB;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,yBAAyB,GAAG,sBAAsB,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB;
|
|
1
|
+
{"version":3,"file":"webhooks.d.mts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB,aAAa,YAAY;AACzB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA,mBAAmB,MAAM;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,yBAAyB,GAAG,cAAc;AAC/C,WAAW,YAAY;AACvB;AACA;AACA;AACA,KAAK,sBAAsB,GAAG,cAAc;AAC5C,WAAW,YAAY;AACvB;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,YAAY;AACvC;AACA;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,aAAa,cAAc;AAC3B,aAAa,mBAAmB;AAChC;AACA,KAAK,2BAA2B,GAAG,cAAc;AACjD,aAAa,cAAc;AAC3B;AACA,aAAa,mBAAmB;AAChC;AACA,KAAK,kBAAkB;AACvB;AACA;AACA;AACA,KAAK,WAAW;AAChB,aAAa,YAAY;AACzB;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,yBAAyB,GAAG,sBAAsB,GAAG,qBAAqB,GAAG,2BAA2B,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB;AACrZ,KAAK,gBAAgB,GAAG,YAAY;AACpC,cAAc,wBAAwB,SAAS,KAAK;AACpD;AACA;AACA,KAAK,cAAc;AACnB;AACA,aAAa,OAAO,GAAG,MAAM,0CAA0C,QAAQ;AAC/E;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA,cAAc,aAAa,YAAY,OAAO,GAAG,cAAc,wCAAwC,oBAAoB,KAAK,OAAO,CAAC,YAAY;AACpJ,KAAK,qBAAqB;AAC1B;AACA,qBAAqB,YAAY;AACjC;AACA;AACA;AACA;AACA,cAAc,oBAAoB,mCAAmC,qBAAqB,eAAe,OAAO,KAAK,OAAO,CAAC,QAAQ","names":[]}
|
package/dist/webhooks.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ type WebhookEventOf<TType extends string, TData> = {
|
|
|
17
17
|
type EntryPublishedEvent = WebhookEventOf<'entry.published', {
|
|
18
18
|
entry: WebhookEntry;
|
|
19
19
|
}>;
|
|
20
|
+
type BlockPublishedEvent = WebhookEventOf<'block.published', {
|
|
21
|
+
entry: WebhookEntry;
|
|
22
|
+
entries: WebhookEntry[];
|
|
23
|
+
}>;
|
|
20
24
|
type EntryUnpublishedEvent = WebhookEventOf<'entry.unpublished', {
|
|
21
25
|
entry: WebhookEntry;
|
|
22
26
|
}>;
|
|
@@ -56,6 +60,22 @@ type EntryReviewClosedEvent = WebhookEventOf<'entry.review_closed', {
|
|
|
56
60
|
revision: number;
|
|
57
61
|
reason?: string;
|
|
58
62
|
}>;
|
|
63
|
+
type WebhookRelease = {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
};
|
|
67
|
+
type WebhookReleaseEntry = WebhookEntry & {
|
|
68
|
+
action: 'publish' | 'unpublish';
|
|
69
|
+
};
|
|
70
|
+
type ReleasePublishedEvent = WebhookEventOf<'release.published', {
|
|
71
|
+
release: WebhookRelease;
|
|
72
|
+
entries: WebhookReleaseEntry[];
|
|
73
|
+
}>;
|
|
74
|
+
type ReleaseReviewRequestedEvent = WebhookEventOf<'release.review_requested', {
|
|
75
|
+
release: WebhookRelease;
|
|
76
|
+
note: string | null;
|
|
77
|
+
entries: WebhookReleaseEntry[];
|
|
78
|
+
}>;
|
|
59
79
|
type WebhookShopifyItem = {
|
|
60
80
|
id: string;
|
|
61
81
|
handle: string | null;
|
|
@@ -79,7 +99,7 @@ type CollectionDeletedEvent = WebhookEventOf<'collection.deleted', StoreChange &
|
|
|
79
99
|
collection: WebhookShopifyItem;
|
|
80
100
|
}>;
|
|
81
101
|
type WebhookTestEvent = WebhookEventOf<'webhook.test', Record<string, never>>;
|
|
82
|
-
type WebhookEvent = EntryPublishedEvent | EntryUnpublishedEvent | EntryDeletedEvent | EntryMovedEvent | AssetUpdatedEvent | ModelChangedEvent | LocalesChangedEvent | EntryReviewRequestedEvent | EntryReviewClosedEvent | ProductUpdatedEvent | ProductDeletedEvent | CollectionUpdatedEvent | CollectionDeletedEvent | WebhookTestEvent;
|
|
102
|
+
type WebhookEvent = EntryPublishedEvent | BlockPublishedEvent | EntryUnpublishedEvent | EntryDeletedEvent | EntryMovedEvent | AssetUpdatedEvent | ModelChangedEvent | LocalesChangedEvent | EntryReviewRequestedEvent | EntryReviewClosedEvent | ReleasePublishedEvent | ReleaseReviewRequestedEvent | ProductUpdatedEvent | ProductDeletedEvent | CollectionUpdatedEvent | CollectionDeletedEvent | WebhookTestEvent;
|
|
83
103
|
type WebhookEventType = WebhookEvent['type'];
|
|
84
104
|
declare class WebhookVerificationError extends Error {
|
|
85
105
|
constructor(message: string);
|
|
@@ -103,5 +123,5 @@ type WebhookHandlerOptions = {
|
|
|
103
123
|
declare const createWebhookHandler: ({ secret, onEvent, tolerance }: WebhookHandlerOptions) => (request: Request) => Promise<Response>;
|
|
104
124
|
|
|
105
125
|
export { WebhookVerificationError, createWebhookHandler, verifyWebhook };
|
|
106
|
-
export type { AssetUpdatedEvent, CollectionDeletedEvent, CollectionUpdatedEvent, EntryDeletedEvent, EntryMovedEvent, EntryPublishedEvent, EntryReviewClosedEvent, EntryReviewRequestedEvent, EntryUnpublishedEvent, LocalesChangedEvent, ModelChangedEvent, ProductDeletedEvent, ProductUpdatedEvent, VerifyWebhookOptions, WebhookEntry, WebhookEvent, WebhookEventType, WebhookHandlerOptions, WebhookMessage, WebhookShopifyItem, WebhookTestEvent };
|
|
126
|
+
export type { AssetUpdatedEvent, BlockPublishedEvent, CollectionDeletedEvent, CollectionUpdatedEvent, EntryDeletedEvent, EntryMovedEvent, EntryPublishedEvent, EntryReviewClosedEvent, EntryReviewRequestedEvent, EntryUnpublishedEvent, LocalesChangedEvent, ModelChangedEvent, ProductDeletedEvent, ProductUpdatedEvent, ReleasePublishedEvent, ReleaseReviewRequestedEvent, VerifyWebhookOptions, WebhookEntry, WebhookEvent, WebhookEventType, WebhookHandlerOptions, WebhookMessage, WebhookRelease, WebhookReleaseEntry, WebhookShopifyItem, WebhookTestEvent };
|
|
107
127
|
//# sourceMappingURL=webhooks.d.ts.map
|
package/dist/webhooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.ts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA,mBAAmB,MAAM;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,yBAAyB,GAAG,cAAc;AAC/C,WAAW,YAAY;AACvB;AACA;AACA;AACA,KAAK,sBAAsB,GAAG,cAAc;AAC5C,WAAW,YAAY;AACvB;AACA;AACA;AACA;AACA,KAAK,kBAAkB;AACvB;AACA;AACA;AACA,KAAK,WAAW;AAChB,aAAa,YAAY;AACzB;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,yBAAyB,GAAG,sBAAsB,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB;
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sources":["../src/webhooks.ts"],"mappings":";;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,iBAAiB,WAAW;AAC5B;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC,WAAW,YAAY;AACvB,aAAa,YAAY;AACzB;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,WAAW,YAAY;AACvB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC,WAAW,YAAY;AACvB;AACA,KAAK,eAAe,GAAG,cAAc;AACrC,WAAW,YAAY;AACvB;AACA,mBAAmB,MAAM;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA,aAAa,YAAY;AACzB;AACA,KAAK,iBAAiB,GAAG,cAAc;AACvC;AACA;AACA;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc;AACzC;AACA;AACA;AACA,KAAK,yBAAyB,GAAG,cAAc;AAC/C,WAAW,YAAY;AACvB;AACA;AACA;AACA,KAAK,sBAAsB,GAAG,cAAc;AAC5C,WAAW,YAAY;AACvB;AACA;AACA;AACA;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA,KAAK,mBAAmB,GAAG,YAAY;AACvC;AACA;AACA,KAAK,qBAAqB,GAAG,cAAc;AAC3C,aAAa,cAAc;AAC3B,aAAa,mBAAmB;AAChC;AACA,KAAK,2BAA2B,GAAG,cAAc;AACjD,aAAa,cAAc;AAC3B;AACA,aAAa,mBAAmB;AAChC;AACA,KAAK,kBAAkB;AACvB;AACA;AACA;AACA,KAAK,WAAW;AAChB,aAAa,YAAY;AACzB;AACA;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,WAAW;AACxE,aAAa,kBAAkB;AAC/B,iBAAiB,kBAAkB;AACnC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,sBAAsB,GAAG,cAAc,uBAAuB,WAAW;AAC9E,gBAAgB,kBAAkB;AAClC;AACA,KAAK,gBAAgB,GAAG,cAAc,iBAAiB,MAAM;AAC7D,KAAK,YAAY,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,mBAAmB,GAAG,yBAAyB,GAAG,sBAAsB,GAAG,qBAAqB,GAAG,2BAA2B,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,sBAAsB,GAAG,sBAAsB,GAAG,gBAAgB;AACrZ,KAAK,gBAAgB,GAAG,YAAY;AACpC,cAAc,wBAAwB,SAAS,KAAK;AACpD;AACA;AACA,KAAK,cAAc;AACnB;AACA,aAAa,OAAO,GAAG,MAAM,0CAA0C,QAAQ;AAC/E;AACA,KAAK,oBAAoB;AACzB;AACA;AACA;AACA,cAAc,aAAa,YAAY,OAAO,GAAG,cAAc,wCAAwC,oBAAoB,KAAK,OAAO,CAAC,YAAY;AACpJ,KAAK,qBAAqB;AAC1B;AACA,qBAAqB,YAAY;AACjC;AACA;AACA;AACA;AACA,cAAc,oBAAoB,mCAAmC,qBAAqB,eAAe,OAAO,KAAK,OAAO,CAAC,QAAQ","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obelism/content",
|
|
3
3
|
"description": "Obelism Content SDK: the delivery API client, the visual editor bridge with prompt editing, editing on your own site, webhook verification, and the content model CLI",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.30.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cms",
|
|
7
7
|
"headless-cms",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-b6jbj3g6.d.ts","sources":["../src/types.ts"],"mappings":"AAAA,KAAK,WAAW;AAChB,KAAK,cAAc;AACnB,KAAK,KAAK;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,MAAM;AAC1B,kBAAkB,MAAM;AACxB;AACA;AACA;AACA;AACA,eAAe,YAAY;AAC3B;AACA,KAAK,YAAY;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA;AACA;AACA;AACA,WAAW,MAAM;AACjB;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS;AACd;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA,oBAAoB,MAAM;AAC1B;AACA;AACA;AACA,KAAK,IAAI;AACT;AACA,WAAW,UAAU;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,WAAW;AACxB,WAAW,UAAU;AACrB;AACA;AACA;AACA;AACA,gBAAgB,WAAW;AAC3B,WAAW,UAAU;AACrB;AACA;AACA;AACA,KAAK,KAAK,iBAAiB,MAAM,oBAAoB,MAAM;AAC3D;AACA;AACA;AACA,KAAK,YAAY,gBAAgB,KAAK,GAAG,KAAK,IAAI,KAAK;AACvD;AACA;AACA,cAAc,MAAM;AACpB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB;AACA,KAAK,YAAY;AACjB;AACA,YAAY,MAAM;AAClB,cAAc,YAAY;AAC1B;AACA,YAAY,YAAY;AACxB;AACA,KAAK,gBAAgB,GAAG,YAAY;AACpC;AACA;AACA,KAAK,SAAS,gBAAgB,KAAK,GAAG,KAAK;AAC3C;AACA;AACA;AACA;AACA;AACA,KAAK,QAAQ;AACb;AACA;AACA;AACA;AACA,KAAK,YAAY;AACjB,WAAW,QAAQ;AACnB;AACA;AACA;AACA;AACA,KAAK,WAAW;AAChB;AACA;AACA;AACA,KAAK,eAAe;AACpB,KAAK,SAAS;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,MAAM;AACvB;AACA,WAAW,cAAc;AACzB;AACA,KAAK,cAAc;AACnB;AACA;AACA;AACA;AACA;AACA,KAAK,UAAU;AACf;AACA;AACA;AACA;AACA,KAAK,iBAAiB;AACtB,KAAK,eAAe,GAAG,SAAS;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK,SAAS,GAAG,eAAe;AAChC,KAAK,qBAAqB;AAC1B;AACA;AACA,UAAU,eAAe;AACzB;AACA;AACA,aAAa,iBAAiB;AAC9B;AACA,aAAa,UAAU;AACvB,YAAY,eAAe;AAC3B;AACA,KAAK,SAAS;AACd;AACA;AACA,kBAAkB,qBAAqB;AACvC;;","names":[]}
|