@obelism/content 0.29.0 → 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/{types-mqo1osjh.d.ts → types-e32p5mys.d.ts} +10 -3
- 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-mqo1osjh.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;
|
|
@@ -72,11 +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;
|
|
79
|
-
fallback?: string;
|
|
85
|
+
fallback?: string | null;
|
|
86
|
+
mode?: 'instant' | 'after-load' | null;
|
|
80
87
|
variants: Record<string, TBlock[]>;
|
|
81
88
|
}, '_improve'>;
|
|
82
89
|
type RichTextMark = {
|
|
@@ -226,5 +233,5 @@ type ModelFile = {
|
|
|
226
233
|
contentTypes: ContentTypeDefinition[];
|
|
227
234
|
};
|
|
228
235
|
|
|
229
|
-
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 };
|
|
230
|
-
//# 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-mqo1osjh.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;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":[]}
|