@pro-laico/payload-dev-tools 0.0.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.
Files changed (91) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +9 -0
  3. package/dist/components/DevToolbar.d.ts +27 -0
  4. package/dist/components/DevToolbar.d.ts.map +1 -0
  5. package/dist/components/DevToolbar.js +32 -0
  6. package/dist/components/DevToolbar.js.map +1 -0
  7. package/dist/components/DevToolbarClient.d.ts +16 -0
  8. package/dist/components/DevToolbarClient.d.ts.map +1 -0
  9. package/dist/components/DevToolbarClient.js +983 -0
  10. package/dist/components/DevToolbarClient.js.map +1 -0
  11. package/dist/components/resolveDevChrome.d.ts +33 -0
  12. package/dist/components/resolveDevChrome.d.ts.map +1 -0
  13. package/dist/components/resolveDevChrome.js +42 -0
  14. package/dist/components/resolveDevChrome.js.map +1 -0
  15. package/dist/components/resolveDevChrome.spec.d.ts +2 -0
  16. package/dist/components/resolveDevChrome.spec.d.ts.map +1 -0
  17. package/dist/components/resolveDevChrome.spec.js +98 -0
  18. package/dist/components/resolveDevChrome.spec.js.map +1 -0
  19. package/dist/components/styles.d.ts +5 -0
  20. package/dist/components/styles.d.ts.map +1 -0
  21. package/dist/components/styles.js +110 -0
  22. package/dist/components/styles.js.map +1 -0
  23. package/dist/cookies.d.ts +12 -0
  24. package/dist/cookies.d.ts.map +1 -0
  25. package/dist/cookies.js +12 -0
  26. package/dist/cookies.js.map +1 -0
  27. package/dist/endpoints/activateIconSet.d.ts +10 -0
  28. package/dist/endpoints/activateIconSet.d.ts.map +1 -0
  29. package/dist/endpoints/activateIconSet.js +55 -0
  30. package/dist/endpoints/activateIconSet.js.map +1 -0
  31. package/dist/endpoints/dev.d.ts +12 -0
  32. package/dist/endpoints/dev.d.ts.map +1 -0
  33. package/dist/endpoints/dev.js +31 -0
  34. package/dist/endpoints/dev.js.map +1 -0
  35. package/dist/endpoints/stage.d.ts +14 -0
  36. package/dist/endpoints/stage.d.ts.map +1 -0
  37. package/dist/endpoints/stage.js +42 -0
  38. package/dist/endpoints/stage.js.map +1 -0
  39. package/dist/harness.d.ts +40 -0
  40. package/dist/harness.d.ts.map +1 -0
  41. package/dist/harness.js +30 -0
  42. package/dist/harness.js.map +1 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +9 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/lib/getPayloadClient.d.ts +15 -0
  48. package/dist/lib/getPayloadClient.d.ts.map +1 -0
  49. package/dist/lib/getPayloadClient.js +29 -0
  50. package/dist/lib/getPayloadClient.js.map +1 -0
  51. package/dist/lib/snapshot.d.ts +89 -0
  52. package/dist/lib/snapshot.d.ts.map +1 -0
  53. package/dist/lib/snapshot.js +183 -0
  54. package/dist/lib/snapshot.js.map +1 -0
  55. package/dist/next/client.d.ts +27 -0
  56. package/dist/next/client.d.ts.map +1 -0
  57. package/dist/next/client.js +275 -0
  58. package/dist/next/client.js.map +1 -0
  59. package/dist/next/createDevPage.d.ts +37 -0
  60. package/dist/next/createDevPage.d.ts.map +1 -0
  61. package/dist/next/createDevPage.js +287 -0
  62. package/dist/next/createDevPage.js.map +1 -0
  63. package/dist/next/pageStyles.d.ts +5 -0
  64. package/dist/next/pageStyles.d.ts.map +1 -0
  65. package/dist/next/pageStyles.js +83 -0
  66. package/dist/next/pageStyles.js.map +1 -0
  67. package/dist/next/specimen.d.ts +24 -0
  68. package/dist/next/specimen.d.ts.map +1 -0
  69. package/dist/next/specimen.js +48 -0
  70. package/dist/next/specimen.js.map +1 -0
  71. package/dist/next/views.d.ts +31 -0
  72. package/dist/next/views.d.ts.map +1 -0
  73. package/dist/next/views.js +431 -0
  74. package/dist/next/views.js.map +1 -0
  75. package/dist/next.d.ts +5 -0
  76. package/dist/next.d.ts.map +1 -0
  77. package/dist/next.js +6 -0
  78. package/dist/next.js.map +1 -0
  79. package/dist/options.d.ts +17 -0
  80. package/dist/options.d.ts.map +1 -0
  81. package/dist/options.js +3 -0
  82. package/dist/options.js.map +1 -0
  83. package/dist/plugin.d.ts +20 -0
  84. package/dist/plugin.d.ts.map +1 -0
  85. package/dist/plugin.js +51 -0
  86. package/dist/plugin.js.map +1 -0
  87. package/dist/toolbar.d.ts +8 -0
  88. package/dist/toolbar.d.ts.map +1 -0
  89. package/dist/toolbar.js +8 -0
  90. package/dist/toolbar.js.map +1 -0
  91. package/package.json +77 -0
@@ -0,0 +1,12 @@
1
+ import type { Endpoint } from 'payload';
2
+ /**
3
+ * `GET /api/dev` — the machine-readable snapshot (see {@link buildDevSnapshot}) for `fetch`,
4
+ * `curl`, and AI agents. A browser asking for HTML is redirected to the dev pages (`devRoute`,
5
+ * where the host mounts `createDevPage`) — the human view lives there, inside the app;
6
+ * `?format=json` skips the redirect. Outside dev it 404s (see {@link devToolsEnabled}).
7
+ */
8
+ export declare function createDevEndpoint({ enabled, devRoute }: {
9
+ enabled?: boolean;
10
+ devRoute: string;
11
+ }): Endpoint;
12
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/endpoints/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CAc1G"}
@@ -0,0 +1,31 @@
1
+ import { buildDevSnapshot } from "../lib/snapshot.js";
2
+ import { devToolsEnabled } from "../options.js";
3
+ /**
4
+ * `GET /api/dev` — the machine-readable snapshot (see {@link buildDevSnapshot}) for `fetch`,
5
+ * `curl`, and AI agents. A browser asking for HTML is redirected to the dev pages (`devRoute`,
6
+ * where the host mounts `createDevPage`) — the human view lives there, inside the app;
7
+ * `?format=json` skips the redirect. Outside dev it 404s (see {@link devToolsEnabled}).
8
+ */ export function createDevEndpoint({ enabled, devRoute }) {
9
+ return {
10
+ path: '/dev',
11
+ method: 'get',
12
+ handler: async (req)=>{
13
+ if (!devToolsEnabled(enabled)) return Response.json({
14
+ error: 'Not found'
15
+ }, {
16
+ status: 404
17
+ });
18
+ const url = new URL(req.url ?? '/api/dev', 'http://localhost');
19
+ const wantsHtml = url.searchParams.get('format') !== 'json' && (req.headers.get('accept') ?? '').includes('text/html');
20
+ if (wantsHtml) return new Response(null, {
21
+ status: 307,
22
+ headers: {
23
+ location: devRoute
24
+ }
25
+ });
26
+ return Response.json(await buildDevSnapshot(req.payload));
27
+ }
28
+ };
29
+ }
30
+
31
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/dev.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\nimport { buildDevSnapshot } from '../lib/snapshot'\nimport { devToolsEnabled } from '../options'\n\n/**\n * `GET /api/dev` — the machine-readable snapshot (see {@link buildDevSnapshot}) for `fetch`,\n * `curl`, and AI agents. A browser asking for HTML is redirected to the dev pages (`devRoute`,\n * where the host mounts `createDevPage`) — the human view lives there, inside the app;\n * `?format=json` skips the redirect. Outside dev it 404s (see {@link devToolsEnabled}).\n */\nexport function createDevEndpoint({ enabled, devRoute }: { enabled?: boolean; devRoute: string }): Endpoint {\n return {\n path: '/dev',\n method: 'get',\n handler: async (req) => {\n if (!devToolsEnabled(enabled)) return Response.json({ error: 'Not found' }, { status: 404 })\n\n const url = new URL(req.url ?? '/api/dev', 'http://localhost')\n const wantsHtml = url.searchParams.get('format') !== 'json' && (req.headers.get('accept') ?? '').includes('text/html')\n if (wantsHtml) return new Response(null, { status: 307, headers: { location: devRoute } })\n\n return Response.json(await buildDevSnapshot(req.payload))\n },\n }\n}\n"],"names":["buildDevSnapshot","devToolsEnabled","createDevEndpoint","enabled","devRoute","path","method","handler","req","Response","json","error","status","url","URL","wantsHtml","searchParams","get","headers","includes","location","payload"],"mappings":"AACA,SAASA,gBAAgB,QAAQ,qBAAiB;AAClD,SAASC,eAAe,QAAQ,gBAAY;AAE5C;;;;;CAKC,GACD,OAAO,SAASC,kBAAkB,EAAEC,OAAO,EAAEC,QAAQ,EAA2C;IAC9F,OAAO;QACLC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,IAAI,CAACP,gBAAgBE,UAAU,OAAOM,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAY,GAAG;gBAAEC,QAAQ;YAAI;YAE1F,MAAMC,MAAM,IAAIC,IAAIN,IAAIK,GAAG,IAAI,YAAY;YAC3C,MAAME,YAAYF,IAAIG,YAAY,CAACC,GAAG,CAAC,cAAc,UAAU,AAACT,CAAAA,IAAIU,OAAO,CAACD,GAAG,CAAC,aAAa,EAAC,EAAGE,QAAQ,CAAC;YAC1G,IAAIJ,WAAW,OAAO,IAAIN,SAAS,MAAM;gBAAEG,QAAQ;gBAAKM,SAAS;oBAAEE,UAAUhB;gBAAS;YAAE;YAExF,OAAOK,SAASC,IAAI,CAAC,MAAMV,iBAAiBQ,IAAIa,OAAO;QACzD;IACF;AACF"}
@@ -0,0 +1,14 @@
1
+ import type { Endpoint } from 'payload';
2
+ /**
3
+ * `GET /api/dev/stage?test=<key>&version=<id>` — URL-addressable version selection. Sets the
4
+ * selection cookie and redirects to the test's page (`<devRoute>/tests/<key>`, or `to` when
5
+ * given), which renders that version. `?slot=header|footer` targets a chrome-override cookie
6
+ * instead (redirecting to `/` — the override applies site-wide via `resolveDevChrome`).
7
+ * `?clear=1` clears the targeted cookie. Exists so a screenshot script or an AI agent can put a
8
+ * specific version on screen by navigating to one URL instead of driving the toolbar UI.
9
+ */
10
+ export declare function createStageEndpoint({ enabled, devRoute }: {
11
+ enabled?: boolean;
12
+ devRoute: string;
13
+ }): Endpoint;
14
+ //# sourceMappingURL=stage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/endpoints/stage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CA0B5G"}
@@ -0,0 +1,42 @@
1
+ import { CHROME_COOKIES, STAGE_COOKIE } from "../cookies.js";
2
+ import { devToolsEnabled } from "../options.js";
3
+ /**
4
+ * `GET /api/dev/stage?test=<key>&version=<id>` — URL-addressable version selection. Sets the
5
+ * selection cookie and redirects to the test's page (`<devRoute>/tests/<key>`, or `to` when
6
+ * given), which renders that version. `?slot=header|footer` targets a chrome-override cookie
7
+ * instead (redirecting to `/` — the override applies site-wide via `resolveDevChrome`).
8
+ * `?clear=1` clears the targeted cookie. Exists so a screenshot script or an AI agent can put a
9
+ * specific version on screen by navigating to one URL instead of driving the toolbar UI.
10
+ */ export function createStageEndpoint({ enabled, devRoute }) {
11
+ return {
12
+ path: '/dev/stage',
13
+ method: 'get',
14
+ handler: async (req)=>{
15
+ if (!devToolsEnabled(enabled)) return Response.json({
16
+ error: 'Not found'
17
+ }, {
18
+ status: 404
19
+ });
20
+ const url = new URL(req.url ?? '/api/dev/stage', 'http://localhost');
21
+ const test = url.searchParams.get('test');
22
+ const version = url.searchParams.get('version');
23
+ const slotParam = url.searchParams.get('slot');
24
+ const slot = slotParam === 'header' || slotParam === 'footer' ? slotParam : null;
25
+ const cookieName = slot ? CHROME_COOKIES[slot] : STAGE_COOKIE;
26
+ const clearing = url.searchParams.get('clear') !== null || !test || !version;
27
+ const rawTo = url.searchParams.get('to') ?? (clearing || slot ? '/' : `${devRoute}/tests/${test}`);
28
+ // Same-site paths only — no open redirect, even in dev.
29
+ const to = rawTo.startsWith('/') && !rawTo.startsWith('//') ? rawTo : '/';
30
+ const cookie = clearing ? `${cookieName}=; Path=/; Max-Age=0; SameSite=Lax` : `${cookieName}=${encodeURIComponent(`${test}:${version}`)}; Path=/; SameSite=Lax`;
31
+ return new Response(null, {
32
+ status: 303,
33
+ headers: {
34
+ location: to,
35
+ 'set-cookie': cookie
36
+ }
37
+ });
38
+ }
39
+ };
40
+ }
41
+
42
+ //# sourceMappingURL=stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/stage.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\nimport { CHROME_COOKIES, STAGE_COOKIE } from '../cookies'\nimport { devToolsEnabled } from '../options'\n\n/**\n * `GET /api/dev/stage?test=<key>&version=<id>` — URL-addressable version selection. Sets the\n * selection cookie and redirects to the test's page (`<devRoute>/tests/<key>`, or `to` when\n * given), which renders that version. `?slot=header|footer` targets a chrome-override cookie\n * instead (redirecting to `/` — the override applies site-wide via `resolveDevChrome`).\n * `?clear=1` clears the targeted cookie. Exists so a screenshot script or an AI agent can put a\n * specific version on screen by navigating to one URL instead of driving the toolbar UI.\n */\nexport function createStageEndpoint({ enabled, devRoute }: { enabled?: boolean; devRoute: string }): Endpoint {\n return {\n path: '/dev/stage',\n method: 'get',\n handler: async (req) => {\n if (!devToolsEnabled(enabled)) return Response.json({ error: 'Not found' }, { status: 404 })\n\n const url = new URL(req.url ?? '/api/dev/stage', 'http://localhost')\n const test = url.searchParams.get('test')\n const version = url.searchParams.get('version')\n const slotParam = url.searchParams.get('slot')\n const slot = slotParam === 'header' || slotParam === 'footer' ? slotParam : null\n const cookieName = slot ? CHROME_COOKIES[slot] : STAGE_COOKIE\n const clearing = url.searchParams.get('clear') !== null || !test || !version\n\n const rawTo = url.searchParams.get('to') ?? (clearing || slot ? '/' : `${devRoute}/tests/${test}`)\n // Same-site paths only — no open redirect, even in dev.\n const to = rawTo.startsWith('/') && !rawTo.startsWith('//') ? rawTo : '/'\n\n const cookie = clearing\n ? `${cookieName}=; Path=/; Max-Age=0; SameSite=Lax`\n : `${cookieName}=${encodeURIComponent(`${test}:${version}`)}; Path=/; SameSite=Lax`\n\n return new Response(null, { status: 303, headers: { location: to, 'set-cookie': cookie } })\n },\n }\n}\n"],"names":["CHROME_COOKIES","STAGE_COOKIE","devToolsEnabled","createStageEndpoint","enabled","devRoute","path","method","handler","req","Response","json","error","status","url","URL","test","searchParams","get","version","slotParam","slot","cookieName","clearing","rawTo","to","startsWith","cookie","encodeURIComponent","headers","location"],"mappings":"AACA,SAASA,cAAc,EAAEC,YAAY,QAAQ,gBAAY;AACzD,SAASC,eAAe,QAAQ,gBAAY;AAE5C;;;;;;;CAOC,GACD,OAAO,SAASC,oBAAoB,EAAEC,OAAO,EAAEC,QAAQ,EAA2C;IAChG,OAAO;QACLC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,IAAI,CAACP,gBAAgBE,UAAU,OAAOM,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAY,GAAG;gBAAEC,QAAQ;YAAI;YAE1F,MAAMC,MAAM,IAAIC,IAAIN,IAAIK,GAAG,IAAI,kBAAkB;YACjD,MAAME,OAAOF,IAAIG,YAAY,CAACC,GAAG,CAAC;YAClC,MAAMC,UAAUL,IAAIG,YAAY,CAACC,GAAG,CAAC;YACrC,MAAME,YAAYN,IAAIG,YAAY,CAACC,GAAG,CAAC;YACvC,MAAMG,OAAOD,cAAc,YAAYA,cAAc,WAAWA,YAAY;YAC5E,MAAME,aAAaD,OAAOrB,cAAc,CAACqB,KAAK,GAAGpB;YACjD,MAAMsB,WAAWT,IAAIG,YAAY,CAACC,GAAG,CAAC,aAAa,QAAQ,CAACF,QAAQ,CAACG;YAErE,MAAMK,QAAQV,IAAIG,YAAY,CAACC,GAAG,CAAC,SAAUK,CAAAA,YAAYF,OAAO,MAAM,GAAGhB,SAAS,OAAO,EAAEW,MAAM,AAAD;YAChG,wDAAwD;YACxD,MAAMS,KAAKD,MAAME,UAAU,CAAC,QAAQ,CAACF,MAAME,UAAU,CAAC,QAAQF,QAAQ;YAEtE,MAAMG,SAASJ,WACX,GAAGD,WAAW,kCAAkC,CAAC,GACjD,GAAGA,WAAW,CAAC,EAAEM,mBAAmB,GAAGZ,KAAK,CAAC,EAAEG,SAAS,EAAE,sBAAsB,CAAC;YAErF,OAAO,IAAIT,SAAS,MAAM;gBAAEG,QAAQ;gBAAKgB,SAAS;oBAAEC,UAAUL;oBAAI,cAAcE;gBAAO;YAAE;QAC3F;IACF;AACF"}
@@ -0,0 +1,40 @@
1
+ import type { ReactNode } from 'react';
2
+ /** How the toolbar groups and labels a test — purely presentational in v1 (every version stages
3
+ * in the same full-screen overlay). */
4
+ export type TestKind = 'page' | 'header' | 'footer' | 'block' | 'custom';
5
+ export type TestVersion = {
6
+ /** Stable id — the cookie value segment. Keep it URL-safe (`[a-z0-9-]`). */
7
+ id: string;
8
+ label: string;
9
+ /** A prop-less (optionally async) server component — fetch your own data inside it. Runs only
10
+ * when this version is staged, and only in dev. */
11
+ render: () => ReactNode | Promise<ReactNode>;
12
+ };
13
+ export type Test = {
14
+ /** Stable key — the cookie value segment. Keep it URL-safe (`[a-z0-9-]`). */
15
+ key: string;
16
+ label: string;
17
+ kind: TestKind;
18
+ versions: TestVersion[];
19
+ };
20
+ /** Identity helper — defines a test with full type-checking of its versions. */
21
+ export declare const defineTest: (test: Test) => Test;
22
+ /** Client-safe test metadata (no render fns) — what the toolbar UI receives. */
23
+ export type TestMeta = {
24
+ key: string;
25
+ label: string;
26
+ kind: TestKind;
27
+ versions: {
28
+ id: string;
29
+ label: string;
30
+ }[];
31
+ };
32
+ export declare const toTestMeta: (tests: Test[]) => TestMeta[];
33
+ export type ActiveStage = {
34
+ test: Test;
35
+ version: TestVersion;
36
+ };
37
+ /** Resolve a raw stage-cookie value (`testKey:versionId`) against the registered tests. Unknown
38
+ * or malformed values resolve to null — a stale cookie never breaks a page. */
39
+ export declare const parseStage: (raw: string | undefined, tests: Test[]) => ActiveStage | null;
40
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC;wCACwC;AACxC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAExE,MAAM,MAAM,WAAW,GAAG;IACxB,4EAA4E;IAC5E,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb;wDACoD;IACpD,MAAM,EAAE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,WAAW,EAAE,CAAA;CACxB,CAAA;AAED,gFAAgF;AAChF,eAAO,MAAM,UAAU,GAAI,MAAM,IAAI,KAAG,IAAY,CAAA;AAEpD,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAA;AAEhH,eAAO,MAAM,UAAU,GAAI,OAAO,IAAI,EAAE,KAAG,QAAQ,EACgF,CAAA;AAEnI,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAA;AAE9D;gFACgF;AAChF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,OAAO,IAAI,EAAE,KAAG,WAAW,GAAG,IAajF,CAAA"}
@@ -0,0 +1,30 @@
1
+ /** Identity helper — defines a test with full type-checking of its versions. */ export const defineTest = (test)=>test;
2
+ export const toTestMeta = (tests)=>tests.map((t)=>({
3
+ key: t.key,
4
+ label: t.label,
5
+ kind: t.kind,
6
+ versions: t.versions.map((v)=>({
7
+ id: v.id,
8
+ label: v.label
9
+ }))
10
+ }));
11
+ /** Resolve a raw stage-cookie value (`testKey:versionId`) against the registered tests. Unknown
12
+ * or malformed values resolve to null — a stale cookie never breaks a page. */ export const parseStage = (raw, tests)=>{
13
+ if (!raw) return null;
14
+ let decoded = raw;
15
+ try {
16
+ decoded = decodeURIComponent(raw);
17
+ } catch {
18
+ return null;
19
+ }
20
+ const sep = decoded.indexOf(':');
21
+ if (sep < 1) return null;
22
+ const test = tests.find((t)=>t.key === decoded.slice(0, sep));
23
+ const version = test?.versions.find((v)=>v.id === decoded.slice(sep + 1));
24
+ return test && version ? {
25
+ test,
26
+ version
27
+ } : null;
28
+ };
29
+
30
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/harness.ts"],"sourcesContent":["import type { ReactNode } from 'react'\n\n/** How the toolbar groups and labels a test — purely presentational in v1 (every version stages\n * in the same full-screen overlay). */\nexport type TestKind = 'page' | 'header' | 'footer' | 'block' | 'custom'\n\nexport type TestVersion = {\n /** Stable id — the cookie value segment. Keep it URL-safe (`[a-z0-9-]`). */\n id: string\n label: string\n /** A prop-less (optionally async) server component — fetch your own data inside it. Runs only\n * when this version is staged, and only in dev. */\n render: () => ReactNode | Promise<ReactNode>\n}\n\nexport type Test = {\n /** Stable key — the cookie value segment. Keep it URL-safe (`[a-z0-9-]`). */\n key: string\n label: string\n kind: TestKind\n versions: TestVersion[]\n}\n\n/** Identity helper — defines a test with full type-checking of its versions. */\nexport const defineTest = (test: Test): Test => test\n\n/** Client-safe test metadata (no render fns) — what the toolbar UI receives. */\nexport type TestMeta = { key: string; label: string; kind: TestKind; versions: { id: string; label: string }[] }\n\nexport const toTestMeta = (tests: Test[]): TestMeta[] =>\n tests.map((t) => ({ key: t.key, label: t.label, kind: t.kind, versions: t.versions.map((v) => ({ id: v.id, label: v.label })) }))\n\nexport type ActiveStage = { test: Test; version: TestVersion }\n\n/** Resolve a raw stage-cookie value (`testKey:versionId`) against the registered tests. Unknown\n * or malformed values resolve to null — a stale cookie never breaks a page. */\nexport const parseStage = (raw: string | undefined, tests: Test[]): ActiveStage | null => {\n if (!raw) return null\n let decoded = raw\n try {\n decoded = decodeURIComponent(raw)\n } catch {\n return null\n }\n const sep = decoded.indexOf(':')\n if (sep < 1) return null\n const test = tests.find((t) => t.key === decoded.slice(0, sep))\n const version = test?.versions.find((v) => v.id === decoded.slice(sep + 1))\n return test && version ? { test, version } : null\n}\n"],"names":["defineTest","test","toTestMeta","tests","map","t","key","label","kind","versions","v","id","parseStage","raw","decoded","decodeURIComponent","sep","indexOf","find","slice","version"],"mappings":"AAuBA,8EAA8E,GAC9E,OAAO,MAAMA,aAAa,CAACC,OAAqBA,KAAI;AAKpD,OAAO,MAAMC,aAAa,CAACC,QACzBA,MAAMC,GAAG,CAAC,CAACC,IAAO,CAAA;YAAEC,KAAKD,EAAEC,GAAG;YAAEC,OAAOF,EAAEE,KAAK;YAAEC,MAAMH,EAAEG,IAAI;YAAEC,UAAUJ,EAAEI,QAAQ,CAACL,GAAG,CAAC,CAACM,IAAO,CAAA;oBAAEC,IAAID,EAAEC,EAAE;oBAAEJ,OAAOG,EAAEH,KAAK;gBAAC,CAAA;QAAI,CAAA,GAAG;AAInI;8EAC8E,GAC9E,OAAO,MAAMK,aAAa,CAACC,KAAyBV;IAClD,IAAI,CAACU,KAAK,OAAO;IACjB,IAAIC,UAAUD;IACd,IAAI;QACFC,UAAUC,mBAAmBF;IAC/B,EAAE,OAAM;QACN,OAAO;IACT;IACA,MAAMG,MAAMF,QAAQG,OAAO,CAAC;IAC5B,IAAID,MAAM,GAAG,OAAO;IACpB,MAAMf,OAAOE,MAAMe,IAAI,CAAC,CAACb,IAAMA,EAAEC,GAAG,KAAKQ,QAAQK,KAAK,CAAC,GAAGH;IAC1D,MAAMI,UAAUnB,MAAMQ,SAASS,KAAK,CAACR,IAAMA,EAAEC,EAAE,KAAKG,QAAQK,KAAK,CAACH,MAAM;IACxE,OAAOf,QAAQmB,UAAU;QAAEnB;QAAMmB;IAAQ,IAAI;AAC/C,EAAC"}
@@ -0,0 +1,7 @@
1
+ export { default, devToolsPlugin } from './plugin';
2
+ export type { DevToolsPluginOptions } from './options';
3
+ export { defineTest } from './harness';
4
+ export type { Test, TestKind, TestMeta, TestVersion } from './harness';
5
+ export { STAGE_COOKIE } from './cookies';
6
+ export type { CollectionCount, DevSnapshot, FontsSnapshot, IconsSnapshot, ImagesSnapshot, MuxSnapshot, SeedSnapshot, } from './lib/snapshot';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAItD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,YAAY,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // The plugin (safe to import from payload.config — no next/react-client imports here)
2
+ export { default, devToolsPlugin } from "./plugin.js";
3
+ // The test harness authoring helper + types. `defineTest` lives here (not just /toolbar) so seed
4
+ // scripts, screenshot tooling, and payload-side code can import it without pulling in next.
5
+ export { defineTest } from "./harness.js";
6
+ // The stage cookie name — for custom tooling that stages a version itself.
7
+ export { STAGE_COOKIE } from "./cookies.js";
8
+
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// The plugin (safe to import from payload.config — no next/react-client imports here)\nexport { default, devToolsPlugin } from './plugin'\nexport type { DevToolsPluginOptions } from './options'\n\n// The test harness authoring helper + types. `defineTest` lives here (not just /toolbar) so seed\n// scripts, screenshot tooling, and payload-side code can import it without pulling in next.\nexport { defineTest } from './harness'\nexport type { Test, TestKind, TestMeta, TestVersion } from './harness'\n\n// The stage cookie name — for custom tooling that stages a version itself.\nexport { STAGE_COOKIE } from './cookies'\n\n// Response shape of `GET /api/dev`, for typed consumers (scripts, agents, custom panels).\nexport type {\n CollectionCount,\n DevSnapshot,\n FontsSnapshot,\n IconsSnapshot,\n ImagesSnapshot,\n MuxSnapshot,\n SeedSnapshot,\n} from './lib/snapshot'\n"],"names":["default","devToolsPlugin","defineTest","STAGE_COOKIE"],"mappings":"AAAA,sFAAsF;AACtF,SAASA,OAAO,EAAEC,cAAc,QAAQ,cAAU;AAGlD,iGAAiG;AACjG,4FAA4F;AAC5F,SAASC,UAAU,QAAQ,eAAW;AAGtC,2EAA2E;AAC3E,SAASC,YAAY,QAAQ,eAAW"}
@@ -0,0 +1,15 @@
1
+ import { type Payload, type SanitizedConfig } from 'payload';
2
+ /** Called from the plugin's `onInit`: remember the running app's config for the dev pages. */
3
+ export declare const stashConfig: (config: SanitizedConfig) => void;
4
+ /**
5
+ * Resolve the host app's Payload config, in order:
6
+ * 1. the globalThis stash filled the moment Payload boots — covers every render after init with
7
+ * no bundler involvement, or
8
+ * 2. the `@payload-config` alias `withPayload` sets up — which resolves from inside a published
9
+ * package only when the consumer transpiles it. The `as string` keeps TS from resolving the
10
+ * alias at this package's own build time.
11
+ */
12
+ export declare const getConfig: () => Promise<SanitizedConfig>;
13
+ /** A booted Payload instance using the host app's config — the server entry for the dev pages. */
14
+ export declare const getPayloadClient: () => Promise<Payload>;
15
+ //# sourceMappingURL=getPayloadClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPayloadClient.d.ts","sourceRoot":"","sources":["../../src/lib/getPayloadClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AASxE,8FAA8F;AAC9F,eAAO,MAAM,WAAW,GAAI,QAAQ,eAAe,KAAG,IAErD,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,QAAa,OAAO,CAAC,eAAe,CAYzD,CAAA;AAED,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,OAAO,CAA8C,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { getPayload } from "payload";
2
+ /** The globalThis slot the plugin's `onInit` fills with the app's sanitized config. `Symbol.for`
3
+ * → one shared registry entry across every pro-laico package (payload-icons stashes the same
4
+ * slot), so whichever plugin boots first covers them all. */ const CONFIG_SLOT = Symbol.for('pro-laico.payload-config');
5
+ /** Called from the plugin's `onInit`: remember the running app's config for the dev pages. */ export const stashConfig = (config)=>{
6
+ ;
7
+ globalThis[CONFIG_SLOT] = config;
8
+ };
9
+ /**
10
+ * Resolve the host app's Payload config, in order:
11
+ * 1. the globalThis stash filled the moment Payload boots — covers every render after init with
12
+ * no bundler involvement, or
13
+ * 2. the `@payload-config` alias `withPayload` sets up — which resolves from inside a published
14
+ * package only when the consumer transpiles it. The `as string` keeps TS from resolving the
15
+ * alias at this package's own build time.
16
+ */ export const getConfig = async ()=>{
17
+ const stashed = globalThis[CONFIG_SLOT];
18
+ if (stashed) return stashed;
19
+ try {
20
+ return await (await import("@payload-config")).default;
21
+ } catch {
22
+ throw new Error("[payload-dev-tools] could not resolve the app's Payload config: Payload hasn't initialized in this process yet, and the '@payload-config' alias didn't resolve from inside this package. Either add '@pro-laico/payload-dev-tools' to `transpilePackages` in next.config, or ensure something calls getPayload() before the dev pages render.");
23
+ }
24
+ };
25
+ /** A booted Payload instance using the host app's config — the server entry for the dev pages. */ export const getPayloadClient = async ()=>getPayload({
26
+ config: await getConfig()
27
+ });
28
+
29
+ //# sourceMappingURL=getPayloadClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/getPayloadClient.ts"],"sourcesContent":["import { getPayload, type Payload, type SanitizedConfig } from 'payload'\n\ntype Awaitable<T> = T | Promise<T>\n\n/** The globalThis slot the plugin's `onInit` fills with the app's sanitized config. `Symbol.for`\n * → one shared registry entry across every pro-laico package (payload-icons stashes the same\n * slot), so whichever plugin boots first covers them all. */\nconst CONFIG_SLOT = Symbol.for('pro-laico.payload-config')\n\n/** Called from the plugin's `onInit`: remember the running app's config for the dev pages. */\nexport const stashConfig = (config: SanitizedConfig): void => {\n ;(globalThis as Record<symbol, unknown>)[CONFIG_SLOT] = config\n}\n\n/**\n * Resolve the host app's Payload config, in order:\n * 1. the globalThis stash filled the moment Payload boots — covers every render after init with\n * no bundler involvement, or\n * 2. the `@payload-config` alias `withPayload` sets up — which resolves from inside a published\n * package only when the consumer transpiles it. The `as string` keeps TS from resolving the\n * alias at this package's own build time.\n */\nexport const getConfig = async (): Promise<SanitizedConfig> => {\n const stashed = (globalThis as Record<symbol, unknown>)[CONFIG_SLOT] as SanitizedConfig | undefined\n if (stashed) return stashed\n try {\n return (await ((\n await import('@payload-config' as string)\n ).default as Awaitable<SanitizedConfig>)) as SanitizedConfig\n } catch {\n throw new Error(\n \"[payload-dev-tools] could not resolve the app's Payload config: Payload hasn't initialized in this process yet, and the '@payload-config' alias didn't resolve from inside this package. Either add '@pro-laico/payload-dev-tools' to `transpilePackages` in next.config, or ensure something calls getPayload() before the dev pages render.\",\n )\n }\n}\n\n/** A booted Payload instance using the host app's config — the server entry for the dev pages. */\nexport const getPayloadClient = async (): Promise<Payload> => getPayload({ config: await getConfig() })\n"],"names":["getPayload","CONFIG_SLOT","Symbol","for","stashConfig","config","globalThis","getConfig","stashed","default","Error","getPayloadClient"],"mappings":"AAAA,SAASA,UAAU,QAA4C,UAAS;AAIxE;;4DAE4D,GAC5D,MAAMC,cAAcC,OAAOC,GAAG,CAAC;AAE/B,4FAA4F,GAC5F,OAAO,MAAMC,cAAc,CAACC;;IACxBC,UAAsC,CAACL,YAAY,GAAGI;AAC1D,EAAC;AAED;;;;;;;CAOC,GACD,OAAO,MAAME,YAAY;IACvB,MAAMC,UAAU,AAACF,UAAsC,CAACL,YAAY;IACpE,IAAIO,SAAS,OAAOA;IACpB,IAAI;QACF,OAAQ,MAAO,AACb,CAAA,MAAM,MAAM,CAAC,kBAA2B,EACxCC,OAAO;IACX,EAAE,OAAM;QACN,MAAM,IAAIC,MACR;IAEJ;AACF,EAAC;AAED,gGAAgG,GAChG,OAAO,MAAMC,mBAAmB,UAA8BX,WAAW;QAAEK,QAAQ,MAAME;IAAY,GAAE"}
@@ -0,0 +1,89 @@
1
+ import type { Payload } from 'payload';
2
+ /** One collection's row in the snapshot. `count` is null when counting failed (e.g. a slug the
3
+ * adapter can't count) — distinct from an honest 0. */
4
+ export type CollectionCount = {
5
+ slug: string;
6
+ count: number | null;
7
+ };
8
+ export type SeedSnapshot = {
9
+ /** Whether `ENABLE_SEED=true` is set — the kill switch every seed path checks. */
10
+ enabled: boolean;
11
+ endpoint: string;
12
+ definitions: {
13
+ slug: string;
14
+ kind: 'collection' | 'global';
15
+ disabled?: string;
16
+ }[];
17
+ /** Doc counts per collection-kind definition slug (globals always exist, so they're skipped). */
18
+ counts: Record<string, number>;
19
+ totalDocs: number;
20
+ /** True once any seeded collection has documents. */
21
+ seeded: boolean;
22
+ };
23
+ export type ImagesSnapshot = {
24
+ sourceSlug: string;
25
+ variantSlug: string | null;
26
+ basePath: string;
27
+ sourceCount: number | null;
28
+ variantCount: number | null;
29
+ };
30
+ export type IconsSnapshot = {
31
+ iconSlug: string;
32
+ iconSetSlug: string | null;
33
+ iconCount: number | null;
34
+ /** Title of the active (published) icon set, or null when none is active. */
35
+ activeSet: string | null;
36
+ /** Runtime misses from the `iconRequest` diagnostic collection — names requested in code that
37
+ * did not resolve through the active set. Empty when request tracking is off. */
38
+ misses: {
39
+ name: string;
40
+ count: number;
41
+ lastRequestedAt: string | null;
42
+ }[];
43
+ };
44
+ export type FontsSnapshot = {
45
+ fontSlug: string;
46
+ fontSetSlug: string | null;
47
+ fontOptimizedSlug: string | null;
48
+ familyKeys: string[];
49
+ /** Active typeface title per family slot (from the `fontSet` global), or null when unset. */
50
+ slots: Record<string, string | null>;
51
+ fontCount: number | null;
52
+ exportPath: string;
53
+ };
54
+ export type MuxSnapshot = {
55
+ slug: string;
56
+ credentialed: boolean;
57
+ total: number | null;
58
+ ready: number | null;
59
+ };
60
+ /** Everything `GET /api/dev` reports: environment, per-plugin panels (null = plugin not
61
+ * installed), and doc counts for every collection. Built fresh on each request — dev only. */
62
+ export type DevSnapshot = {
63
+ generatedAt: string;
64
+ env: {
65
+ nodeEnv: string;
66
+ nodeVersion: string;
67
+ };
68
+ adminRoute: string;
69
+ /** Where the host mounts the `createDevPage` catch-all (the plugin's `devRoute` option). */
70
+ devRoute: string;
71
+ plugins: {
72
+ seed: boolean;
73
+ images: boolean;
74
+ icons: boolean;
75
+ fonts: boolean;
76
+ mux: boolean;
77
+ };
78
+ seed: SeedSnapshot | null;
79
+ images: ImagesSnapshot | null;
80
+ icons: IconsSnapshot | null;
81
+ fonts: FontsSnapshot | null;
82
+ mux: MuxSnapshot | null;
83
+ collections: CollectionCount[];
84
+ globals: string[];
85
+ };
86
+ /** Build the full dev snapshot from a booted Payload instance. Sibling @pro-laico plugins are
87
+ * discovered through their `config.custom` markers — no imports, so none of them are required. */
88
+ export declare function buildDevSnapshot(payload: Payload): Promise<DevSnapshot>;
89
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/lib/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,183 @@
1
+ const countDocs = async (payload, slug, where)=>{
2
+ try {
3
+ return (await payload.count({
4
+ collection: slug,
5
+ overrideAccess: true,
6
+ ...where ? {
7
+ where
8
+ } : {}
9
+ })).totalDocs;
10
+ } catch {
11
+ return null;
12
+ }
13
+ };
14
+ const seedSnapshot = async (payload, marker)=>{
15
+ const definitions = (marker.options?.definitions ?? []).map((d)=>({
16
+ slug: d.slug,
17
+ kind: d.kind,
18
+ ...d.disabled ? {
19
+ disabled: typeof d.disabled === 'string' ? d.disabled : 'disabled'
20
+ } : {}
21
+ }));
22
+ const counts = {};
23
+ for (const d of definitions){
24
+ if (d.kind !== 'collection') continue;
25
+ const n = await countDocs(payload, d.slug);
26
+ if (n !== null) counts[d.slug] = n;
27
+ }
28
+ const totalDocs = Object.values(counts).reduce((sum, n)=>sum + n, 0);
29
+ return {
30
+ enabled: process.env.ENABLE_SEED === 'true',
31
+ endpoint: '/api/seed',
32
+ definitions,
33
+ counts,
34
+ totalDocs,
35
+ seeded: totalDocs > 0
36
+ };
37
+ };
38
+ const imagesSnapshot = async (payload, marker)=>{
39
+ const sourceSlug = marker.sourceSlug ?? 'images';
40
+ const variantSlug = marker.variantSlug ?? null;
41
+ return {
42
+ sourceSlug,
43
+ variantSlug,
44
+ // The marker stores the endpoint-relative path ('/img'); report it as requested (/api/img).
45
+ basePath: `/api${marker.basePath ?? '/img'}`,
46
+ sourceCount: await countDocs(payload, sourceSlug),
47
+ variantCount: variantSlug ? await countDocs(payload, variantSlug) : null
48
+ };
49
+ };
50
+ const iconsSnapshot = async (payload, marker)=>{
51
+ const iconSlug = marker.iconSlug ?? 'icon';
52
+ const iconSetSlug = marker.iconSetSlug ?? null;
53
+ let activeSet = null;
54
+ if (iconSetSlug) {
55
+ try {
56
+ const res = await payload.find({
57
+ collection: iconSetSlug,
58
+ where: {
59
+ active: {
60
+ equals: true
61
+ }
62
+ },
63
+ limit: 1,
64
+ depth: 0,
65
+ overrideAccess: true,
66
+ pagination: false
67
+ });
68
+ const doc = res.docs[0];
69
+ activeSet = doc?.title ?? null;
70
+ } catch {}
71
+ }
72
+ let misses = [];
73
+ if (marker.iconRequestSlug) {
74
+ try {
75
+ const res = await payload.find({
76
+ collection: marker.iconRequestSlug,
77
+ sort: '-count',
78
+ limit: 20,
79
+ depth: 0,
80
+ overrideAccess: true,
81
+ pagination: false
82
+ });
83
+ misses = res.docs.flatMap((d)=>d.name ? [
84
+ {
85
+ name: d.name,
86
+ count: d.count ?? 1,
87
+ lastRequestedAt: d.lastRequestedAt ?? null
88
+ }
89
+ ] : []);
90
+ } catch {}
91
+ }
92
+ return {
93
+ iconSlug,
94
+ iconSetSlug,
95
+ iconCount: await countDocs(payload, iconSlug),
96
+ activeSet,
97
+ misses
98
+ };
99
+ };
100
+ const fontsSnapshot = async (payload, marker)=>{
101
+ const fontSlug = marker.fontSlug ?? 'font';
102
+ const fontSetSlug = marker.fontSetSlug ?? null;
103
+ const familyKeys = marker.familyKeys ?? [];
104
+ const slots = {};
105
+ for (const key of familyKeys)slots[key] = null;
106
+ if (fontSetSlug && familyKeys.length) {
107
+ try {
108
+ // Through `unknown`: in an app context `findGlobal` returns the app's generated global type.
109
+ const set = await payload.findGlobal({
110
+ slug: fontSetSlug,
111
+ depth: 1,
112
+ overrideAccess: true
113
+ });
114
+ for (const key of familyKeys){
115
+ const value = set[key];
116
+ slots[key] = value && typeof value === 'object' && 'title' in value ? value.title ?? null : null;
117
+ }
118
+ } catch {}
119
+ }
120
+ return {
121
+ fontSlug,
122
+ fontSetSlug,
123
+ fontOptimizedSlug: marker.fontOptimizedSlug ?? null,
124
+ familyKeys,
125
+ slots,
126
+ fontCount: await countDocs(payload, fontSlug),
127
+ exportPath: `/api${marker.exportPath ?? '/fonts/export'}`
128
+ };
129
+ };
130
+ const muxSnapshot = async (payload, marker)=>{
131
+ const slug = marker.options?.extendCollection ?? 'mux-video';
132
+ const collection = payload.config.collections.find((c)=>c.slug === slug);
133
+ return {
134
+ slug,
135
+ // The mux plugin marks its collection `custom.seedDisabled` when MUX_TOKEN_ID/SECRET are absent.
136
+ credentialed: !collection?.custom?.seedDisabled,
137
+ total: await countDocs(payload, slug),
138
+ ready: await countDocs(payload, slug, {
139
+ status: {
140
+ equals: 'ready'
141
+ }
142
+ })
143
+ };
144
+ };
145
+ /** Build the full dev snapshot from a booted Payload instance. Sibling @pro-laico plugins are
146
+ * discovered through their `config.custom` markers — no imports, so none of them are required. */ export async function buildDevSnapshot(payload) {
147
+ const custom = payload.config.custom ?? {};
148
+ const seedMarker = custom.payloadSeed;
149
+ const imagesMarker = custom.payloadImages;
150
+ const iconsMarker = custom.payloadIcons;
151
+ const fontsMarker = custom.payloadFonts;
152
+ const muxMarker = custom.payloadMux;
153
+ const collections = [];
154
+ for (const c of payload.config.collections)collections.push({
155
+ slug: c.slug,
156
+ count: await countDocs(payload, c.slug)
157
+ });
158
+ return {
159
+ generatedAt: new Date().toISOString(),
160
+ env: {
161
+ nodeEnv: process.env.NODE_ENV ?? 'development',
162
+ nodeVersion: process.version
163
+ },
164
+ adminRoute: payload.config.routes?.admin ?? '/admin',
165
+ devRoute: custom.payloadDevTools?.devRoute ?? '/dev',
166
+ plugins: {
167
+ seed: !!seedMarker,
168
+ images: !!imagesMarker,
169
+ icons: !!iconsMarker,
170
+ fonts: !!fontsMarker,
171
+ mux: !!muxMarker
172
+ },
173
+ seed: seedMarker ? await seedSnapshot(payload, seedMarker) : null,
174
+ images: imagesMarker ? await imagesSnapshot(payload, imagesMarker) : null,
175
+ icons: iconsMarker ? await iconsSnapshot(payload, iconsMarker) : null,
176
+ fonts: fontsMarker ? await fontsSnapshot(payload, fontsMarker) : null,
177
+ mux: muxMarker ? await muxSnapshot(payload, muxMarker) : null,
178
+ collections,
179
+ globals: (payload.config.globals ?? []).map((g)=>g.slug)
180
+ };
181
+ }
182
+
183
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/snapshot.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug, Payload, Where } from 'payload'\n\n/** One collection's row in the snapshot. `count` is null when counting failed (e.g. a slug the\n * adapter can't count) — distinct from an honest 0. */\nexport type CollectionCount = { slug: string; count: number | null }\n\nexport type SeedSnapshot = {\n /** Whether `ENABLE_SEED=true` is set — the kill switch every seed path checks. */\n enabled: boolean\n endpoint: string\n definitions: { slug: string; kind: 'collection' | 'global'; disabled?: string }[]\n /** Doc counts per collection-kind definition slug (globals always exist, so they're skipped). */\n counts: Record<string, number>\n totalDocs: number\n /** True once any seeded collection has documents. */\n seeded: boolean\n}\n\nexport type ImagesSnapshot = {\n sourceSlug: string\n variantSlug: string | null\n basePath: string\n sourceCount: number | null\n variantCount: number | null\n}\n\nexport type IconsSnapshot = {\n iconSlug: string\n iconSetSlug: string | null\n iconCount: number | null\n /** Title of the active (published) icon set, or null when none is active. */\n activeSet: string | null\n /** Runtime misses from the `iconRequest` diagnostic collection — names requested in code that\n * did not resolve through the active set. Empty when request tracking is off. */\n misses: { name: string; count: number; lastRequestedAt: string | null }[]\n}\n\nexport type FontsSnapshot = {\n fontSlug: string\n fontSetSlug: string | null\n fontOptimizedSlug: string | null\n familyKeys: string[]\n /** Active typeface title per family slot (from the `fontSet` global), or null when unset. */\n slots: Record<string, string | null>\n fontCount: number | null\n exportPath: string\n}\n\nexport type MuxSnapshot = { slug: string; credentialed: boolean; total: number | null; ready: number | null }\n\n/** Everything `GET /api/dev` reports: environment, per-plugin panels (null = plugin not\n * installed), and doc counts for every collection. Built fresh on each request — dev only. */\nexport type DevSnapshot = {\n generatedAt: string\n env: { nodeEnv: string; nodeVersion: string }\n adminRoute: string\n /** Where the host mounts the `createDevPage` catch-all (the plugin's `devRoute` option). */\n devRoute: string\n plugins: { seed: boolean; images: boolean; icons: boolean; fonts: boolean; mux: boolean }\n seed: SeedSnapshot | null\n images: ImagesSnapshot | null\n icons: IconsSnapshot | null\n fonts: FontsSnapshot | null\n mux: MuxSnapshot | null\n collections: CollectionCount[]\n globals: string[]\n}\n\nconst countDocs = async (payload: Payload, slug: string, where?: Where): Promise<number | null> => {\n try {\n return (await payload.count({ collection: slug as CollectionSlug, overrideAccess: true, ...(where ? { where } : {}) })).totalDocs\n } catch {\n return null\n }\n}\n\ntype SeedMarker = { options?: { definitions?: { slug: string; kind: 'collection' | 'global'; disabled?: string | boolean }[] } }\n\nconst seedSnapshot = async (payload: Payload, marker: SeedMarker): Promise<SeedSnapshot> => {\n const definitions = (marker.options?.definitions ?? []).map((d) => ({\n slug: d.slug,\n kind: d.kind,\n ...(d.disabled ? { disabled: typeof d.disabled === 'string' ? d.disabled : 'disabled' } : {}),\n }))\n const counts: Record<string, number> = {}\n for (const d of definitions) {\n if (d.kind !== 'collection') continue\n const n = await countDocs(payload, d.slug)\n if (n !== null) counts[d.slug] = n\n }\n const totalDocs = Object.values(counts).reduce((sum, n) => sum + n, 0)\n return { enabled: process.env.ENABLE_SEED === 'true', endpoint: '/api/seed', definitions, counts, totalDocs, seeded: totalDocs > 0 }\n}\n\ntype ImagesMarker = { sourceSlug?: string; variantSlug?: string | null; basePath?: string }\n\nconst imagesSnapshot = async (payload: Payload, marker: ImagesMarker): Promise<ImagesSnapshot> => {\n const sourceSlug = marker.sourceSlug ?? 'images'\n const variantSlug = marker.variantSlug ?? null\n return {\n sourceSlug,\n variantSlug,\n // The marker stores the endpoint-relative path ('/img'); report it as requested (/api/img).\n basePath: `/api${marker.basePath ?? '/img'}`,\n sourceCount: await countDocs(payload, sourceSlug),\n variantCount: variantSlug ? await countDocs(payload, variantSlug) : null,\n }\n}\n\ntype IconsMarker = { iconSlug?: string; iconSetSlug?: string | null; iconRequestSlug?: string | null }\n\nconst iconsSnapshot = async (payload: Payload, marker: IconsMarker): Promise<IconsSnapshot> => {\n const iconSlug = marker.iconSlug ?? 'icon'\n const iconSetSlug = marker.iconSetSlug ?? null\n\n let activeSet: string | null = null\n if (iconSetSlug) {\n try {\n const res = await payload.find({\n collection: iconSetSlug as CollectionSlug,\n where: { active: { equals: true } },\n limit: 1,\n depth: 0,\n overrideAccess: true,\n pagination: false,\n })\n const doc = res.docs[0] as { title?: string } | undefined\n activeSet = doc?.title ?? null\n } catch {}\n }\n\n let misses: IconsSnapshot['misses'] = []\n if (marker.iconRequestSlug) {\n try {\n const res = await payload.find({\n collection: marker.iconRequestSlug as CollectionSlug,\n sort: '-count',\n limit: 20,\n depth: 0,\n overrideAccess: true,\n pagination: false,\n })\n misses = (res.docs as { name?: string; count?: number; lastRequestedAt?: string }[]).flatMap((d) =>\n d.name ? [{ name: d.name, count: d.count ?? 1, lastRequestedAt: d.lastRequestedAt ?? null }] : [],\n )\n } catch {}\n }\n\n return { iconSlug, iconSetSlug, iconCount: await countDocs(payload, iconSlug), activeSet, misses }\n}\n\ntype FontsMarker = {\n fontSlug?: string\n fontSetSlug?: string | null\n fontOptimizedSlug?: string | null\n familyKeys?: string[]\n exportPath?: string\n}\n\nconst fontsSnapshot = async (payload: Payload, marker: FontsMarker): Promise<FontsSnapshot> => {\n const fontSlug = marker.fontSlug ?? 'font'\n const fontSetSlug = marker.fontSetSlug ?? null\n const familyKeys = marker.familyKeys ?? []\n\n const slots: Record<string, string | null> = {}\n for (const key of familyKeys) slots[key] = null\n if (fontSetSlug && familyKeys.length) {\n try {\n // Through `unknown`: in an app context `findGlobal` returns the app's generated global type.\n const set = (await payload.findGlobal({ slug: fontSetSlug as GlobalSlug, depth: 1, overrideAccess: true })) as unknown as Record<\n string,\n unknown\n >\n for (const key of familyKeys) {\n const value = set[key]\n slots[key] = value && typeof value === 'object' && 'title' in value ? ((value as { title?: string }).title ?? null) : null\n }\n } catch {}\n }\n\n return {\n fontSlug,\n fontSetSlug,\n fontOptimizedSlug: marker.fontOptimizedSlug ?? null,\n familyKeys,\n slots,\n fontCount: await countDocs(payload, fontSlug),\n exportPath: `/api${marker.exportPath ?? '/fonts/export'}`,\n }\n}\n\ntype MuxMarker = { options?: { extendCollection?: string } }\n\nconst muxSnapshot = async (payload: Payload, marker: MuxMarker): Promise<MuxSnapshot> => {\n const slug = marker.options?.extendCollection ?? 'mux-video'\n const collection = payload.config.collections.find((c) => c.slug === slug)\n return {\n slug,\n // The mux plugin marks its collection `custom.seedDisabled` when MUX_TOKEN_ID/SECRET are absent.\n credentialed: !collection?.custom?.seedDisabled,\n total: await countDocs(payload, slug),\n ready: await countDocs(payload, slug, { status: { equals: 'ready' } }),\n }\n}\n\n/** Build the full dev snapshot from a booted Payload instance. Sibling @pro-laico plugins are\n * discovered through their `config.custom` markers — no imports, so none of them are required. */\nexport async function buildDevSnapshot(payload: Payload): Promise<DevSnapshot> {\n const custom = (payload.config.custom ?? {}) as Record<string, Record<string, unknown> | undefined>\n const seedMarker = custom.payloadSeed\n const imagesMarker = custom.payloadImages\n const iconsMarker = custom.payloadIcons\n const fontsMarker = custom.payloadFonts\n const muxMarker = custom.payloadMux\n\n const collections: CollectionCount[] = []\n for (const c of payload.config.collections) collections.push({ slug: c.slug, count: await countDocs(payload, c.slug) })\n\n return {\n generatedAt: new Date().toISOString(),\n env: { nodeEnv: process.env.NODE_ENV ?? 'development', nodeVersion: process.version },\n adminRoute: payload.config.routes?.admin ?? '/admin',\n devRoute: (custom.payloadDevTools?.devRoute as string | undefined) ?? '/dev',\n plugins: { seed: !!seedMarker, images: !!imagesMarker, icons: !!iconsMarker, fonts: !!fontsMarker, mux: !!muxMarker },\n seed: seedMarker ? await seedSnapshot(payload, seedMarker) : null,\n images: imagesMarker ? await imagesSnapshot(payload, imagesMarker) : null,\n icons: iconsMarker ? await iconsSnapshot(payload, iconsMarker) : null,\n fonts: fontsMarker ? await fontsSnapshot(payload, fontsMarker) : null,\n mux: muxMarker ? await muxSnapshot(payload, muxMarker) : null,\n collections,\n globals: (payload.config.globals ?? []).map((g) => g.slug),\n }\n}\n"],"names":["countDocs","payload","slug","where","count","collection","overrideAccess","totalDocs","seedSnapshot","marker","definitions","options","map","d","kind","disabled","counts","n","Object","values","reduce","sum","enabled","process","env","ENABLE_SEED","endpoint","seeded","imagesSnapshot","sourceSlug","variantSlug","basePath","sourceCount","variantCount","iconsSnapshot","iconSlug","iconSetSlug","activeSet","res","find","active","equals","limit","depth","pagination","doc","docs","title","misses","iconRequestSlug","sort","flatMap","name","lastRequestedAt","iconCount","fontsSnapshot","fontSlug","fontSetSlug","familyKeys","slots","key","length","set","findGlobal","value","fontOptimizedSlug","fontCount","exportPath","muxSnapshot","extendCollection","config","collections","c","credentialed","custom","seedDisabled","total","ready","status","buildDevSnapshot","seedMarker","payloadSeed","imagesMarker","payloadImages","iconsMarker","payloadIcons","fontsMarker","payloadFonts","muxMarker","payloadMux","push","generatedAt","Date","toISOString","nodeEnv","NODE_ENV","nodeVersion","version","adminRoute","routes","admin","devRoute","payloadDevTools","plugins","seed","images","icons","fonts","mux","globals","g"],"mappings":"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"}