@gradial/aci 0.1.20-preview.3 → 0.1.20

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 (224) hide show
  1. package/README.md +48 -108
  2. package/bin/{aci → aci-darwin-arm64} +0 -0
  3. package/bin/aci.js +99 -6
  4. package/dist/assets/index.d.ts +3 -3
  5. package/dist/assets/index.js +3 -3
  6. package/dist/astro/index.d.ts +12 -3
  7. package/dist/astro/index.js +20 -5
  8. package/dist/content/assets.d.ts +17 -0
  9. package/dist/content/assets.js +65 -0
  10. package/dist/content/index.d.ts +1 -0
  11. package/dist/content/index.js +1 -0
  12. package/dist/define-component.d.ts +1 -2
  13. package/dist/define-component.js +73 -5
  14. package/dist/dev/content-watch.d.ts +37 -0
  15. package/dist/dev/content-watch.js +154 -0
  16. package/dist/dev/index.d.ts +24 -43
  17. package/dist/dev/index.js +4 -169
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +8 -9
  20. package/dist/next/asset-route.js +2 -2
  21. package/dist/next/config.d.ts +2 -2
  22. package/dist/next/config.js +5 -5
  23. package/dist/next/content-watch.js +6 -1
  24. package/dist/next/index.d.ts +2 -2
  25. package/dist/next/index.js +2 -2
  26. package/dist/next/middleware.d.ts +2 -2
  27. package/dist/next/middleware.js +6 -6
  28. package/dist/next/page.d.ts +1 -1
  29. package/dist/next/page.js +14 -12
  30. package/dist/next/render.d.ts +3 -3
  31. package/dist/next/render.js +11 -9
  32. package/dist/next/server.d.ts +12 -12
  33. package/dist/next/server.js +1 -1
  34. package/dist/react/Media.d.ts +24 -0
  35. package/dist/react/Media.js +30 -0
  36. package/dist/react/Picture.d.ts +12 -0
  37. package/dist/react/Picture.js +11 -0
  38. package/dist/react/VideoPlayer.d.ts +13 -0
  39. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  40. package/dist/react/index.d.ts +333 -3
  41. package/dist/react/index.js +89 -3
  42. package/dist/registry.d.ts +2 -2
  43. package/dist/registry.js +3 -3
  44. package/dist/types/block-ref.d.ts +26 -0
  45. package/dist/types/block-ref.js +28 -0
  46. package/dist/types/component.d.ts +36 -32
  47. package/dist/types/config.d.ts +1 -1
  48. package/dist/types/image.d.ts +33 -20
  49. package/dist/types/image.js +42 -50
  50. package/dist/types/index.d.ts +1 -0
  51. package/dist/types/index.js +1 -0
  52. package/dist/types/link.d.ts +38 -0
  53. package/dist/types/link.js +58 -0
  54. package/dist/types/media.d.ts +16 -35
  55. package/dist/types/media.js +15 -84
  56. package/dist/types/renderer.d.ts +1 -1
  57. package/dist/types/rich-text.d.ts +40 -0
  58. package/dist/types/rich-text.js +39 -0
  59. package/dist/types/video.d.ts +7 -13
  60. package/dist/types/video.js +3 -3
  61. package/package.json +28 -76
  62. package/src/cli/compile-registry.mjs +120 -63
  63. package/src/cli/validate-content.mjs +38 -75
  64. package/src/types/image.ts +79 -60
  65. package/templates/astro/template/.aci.yaml +27 -0
  66. package/templates/astro/template/.storybook/main.ts +79 -0
  67. package/templates/astro/template/.storybook/manager.ts +6 -0
  68. package/templates/astro/template/.storybook/preview.ts +33 -0
  69. package/templates/astro/template/astro.config.mjs +37 -0
  70. package/templates/astro/template/package.json.tmpl +41 -0
  71. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  72. package/templates/astro/template/src/cms/registry.ts +28 -0
  73. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  74. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  75. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  76. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  77. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  78. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  79. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  80. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  81. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  82. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  83. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  84. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  85. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  86. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  87. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  88. package/templates/astro/template/src/design-system/styles.css +399 -0
  89. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  90. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  91. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  92. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  93. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  94. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  95. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  96. package/templates/astro/template/src/env.d.ts +1 -0
  97. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  98. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  99. package/templates/astro/template/src/fixtures/index.ts +17 -0
  100. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  101. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  102. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  103. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  104. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  105. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  106. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  107. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  108. package/templates/astro/template/tsconfig.json +11 -0
  109. package/templates/common/.agents/AGENTS.md +37 -0
  110. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  111. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  112. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  113. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  114. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  115. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  116. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  117. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  118. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  119. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  120. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  121. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  122. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  123. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  125. package/templates/common/.content/config/site.json +192 -0
  126. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  127. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  128. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  134. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  135. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  136. package/templates/common/.content/pages/about/_index.json +51 -0
  137. package/templates/common/.content/pages/home/_index.json +112 -0
  138. package/templates/common/.content/schemas/site.schema.json +123 -0
  139. package/templates/common/README.md.tmpl +45 -0
  140. package/templates/common/contracts/components/button.contract.ts +19 -0
  141. package/templates/common/contracts/components/container.contract.ts +19 -0
  142. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  143. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  144. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  145. package/templates/common/contracts/components/index.ts +21 -0
  146. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  147. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  148. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  149. package/templates/common/design-system/styles.css +346 -0
  150. package/templates/common/design-system/tokens/colors.css +110 -0
  151. package/templates/common/design-system/tokens/components.css +86 -0
  152. package/templates/common/design-system/tokens/index.css +6 -0
  153. package/templates/common/design-system/tokens/radii.css +5 -0
  154. package/templates/common/design-system/tokens/shadows.css +9 -0
  155. package/templates/common/design-system/tokens/spacing.css +26 -0
  156. package/templates/common/design-system/tokens/typography.css +32 -0
  157. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  158. package/templates/common/public/assets/Dwire-model.png +0 -0
  159. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  160. package/templates/common/public/assets/meridian-logo.svg +8 -0
  161. package/templates/common/public/assets/seattle.avif +0 -0
  162. package/templates/nextjs/template/.aci.yaml +25 -0
  163. package/templates/nextjs/template/.storybook/main.ts +13 -0
  164. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  165. package/templates/nextjs/template/eslint.config.mjs +36 -0
  166. package/templates/nextjs/template/next-env.d.ts +6 -0
  167. package/templates/nextjs/template/next.config.ts +8 -0
  168. package/templates/nextjs/template/package.json.tmpl +46 -0
  169. package/templates/nextjs/template/postcss.config.mjs +7 -0
  170. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  171. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  172. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  173. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  174. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  175. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  179. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  180. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  181. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  182. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  183. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  184. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  185. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  186. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  187. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  188. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  189. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  190. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  191. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  192. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  193. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  194. package/templates/nextjs/template/src/middleware.ts +4 -0
  195. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  196. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  197. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  198. package/templates/nextjs/template/tsconfig.json +23 -0
  199. package/templates/nextjs/template/vercel.json +6 -0
  200. package/dist/content/contract.d.ts +0 -83
  201. package/dist/content/contract.js +0 -104
  202. package/dist/content/tailwind-validator.d.ts +0 -6
  203. package/dist/content/tailwind-validator.js +0 -31
  204. package/dist/content/validation.d.ts +0 -108
  205. package/dist/content/validation.js +0 -183
  206. package/dist/react/GradialMedia.d.ts +0 -24
  207. package/dist/react/GradialMedia.js +0 -31
  208. package/dist/react/GradialPicture.d.ts +0 -14
  209. package/dist/react/GradialPicture.js +0 -30
  210. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  211. package/dist/sveltekit/index.d.ts +0 -25
  212. package/dist/sveltekit/index.js +0 -66
  213. package/dist/sveltekit/preview.d.ts +0 -5
  214. package/dist/sveltekit/preview.js +0 -33
  215. package/src/types/component.ts +0 -49
  216. package/src/types/config.ts +0 -37
  217. package/src/types/data.ts +0 -47
  218. package/src/types/index.ts +0 -10
  219. package/src/types/layout.ts +0 -29
  220. package/src/types/media.ts +0 -125
  221. package/src/types/page.ts +0 -47
  222. package/src/types/render-mode.ts +0 -10
  223. package/src/types/renderer.ts +0 -83
  224. package/src/types/video.ts +0 -66
@@ -0,0 +1,37 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { type DevRefreshOptions } from './browser.js';
3
+ export interface ContentWatchOptions extends DevRefreshOptions {
4
+ contentRoot?: string;
5
+ compiledRoot?: string;
6
+ bin?: string;
7
+ enabled?: boolean;
8
+ }
9
+ interface ViteModuleGraph {
10
+ idToModuleMap: Map<unknown, {
11
+ id: string | null;
12
+ }>;
13
+ invalidateModule(mod: unknown): void;
14
+ }
15
+ interface ViteDevServerLike {
16
+ middlewares?: {
17
+ use(path: string, handler: (req: IncomingMessage, res: ServerResponse, next: () => void) => void): void;
18
+ };
19
+ watcher: {
20
+ add(path: string): void;
21
+ on(event: string, callback: (eventName: string, filePath: string) => void): void;
22
+ };
23
+ ws: {
24
+ send(payload: unknown): void;
25
+ };
26
+ moduleGraph?: ViteModuleGraph;
27
+ }
28
+ export interface VitePluginLike {
29
+ name: string;
30
+ apply?: 'serve' | 'build';
31
+ configureServer?(server: ViteDevServerLike): void;
32
+ transformIndexHtml?(html: string): string;
33
+ }
34
+ export declare function devRefreshPort(options?: DevRefreshOptions): number;
35
+ export declare function contentWatchPlugin(options?: ContentWatchOptions): VitePluginLike;
36
+ export declare function damAssetPlugin(options?: ContentWatchOptions): VitePluginLike;
37
+ export {};
@@ -0,0 +1,154 @@
1
+ import fs from 'node:fs/promises';
2
+ import { spawnSync } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { compiledContentRoot } from '../content/routes.js';
5
+ import { DEFAULT_DEV_REFRESH_PORT } from './browser.js';
6
+ export function devRefreshPort(options = {}) {
7
+ const value = options.wsPort ?? process.env.ACI_DEV_WS_PORT;
8
+ if (value === 0 || value === '0') {
9
+ return 0;
10
+ }
11
+ const parsed = Number(value);
12
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_DEV_REFRESH_PORT;
13
+ }
14
+ function sourceContentRoot(options) {
15
+ return path.resolve(options.contentRoot || process.env.ACI_CONTENT_SOURCE || './.content');
16
+ }
17
+ function resolveBin(options) {
18
+ return options.bin || process.env.ACI_BIN || 'aci';
19
+ }
20
+ function recompileContent(options, reason) {
21
+ const siteDir = process.cwd();
22
+ const src = sourceContentRoot(options);
23
+ const out = path.resolve(options.compiledRoot || process.env.ACI_CONTENT_ROOT || '.aci/compiled');
24
+ const bin = resolveBin(options);
25
+ console.log(`[aci] compiling content (${reason})`);
26
+ const result = spawnSync(bin, ['-s', siteDir, 'build', '--content', src, '--out', out, '--skip-code'], {
27
+ cwd: siteDir,
28
+ stdio: 'inherit',
29
+ env: process.env,
30
+ });
31
+ if (result.status !== 0) {
32
+ console.error(`[aci] content compile failed with exit code ${result.status ?? 'unknown'}`);
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ export function contentWatchPlugin(options = {}) {
38
+ const enabled = options.enabled ?? process.env.ACI_DISABLE_CONTENT_WATCH !== '1';
39
+ if (!enabled) {
40
+ return { name: 'content-watch-disabled', apply: 'serve' };
41
+ }
42
+ let timer;
43
+ let running = false;
44
+ let queued = false;
45
+ function rebuild(server, reason) {
46
+ if (running) {
47
+ queued = true;
48
+ return;
49
+ }
50
+ running = true;
51
+ const success = recompileContent(options, reason);
52
+ running = false;
53
+ if (success) {
54
+ if (server.moduleGraph) {
55
+ for (const mod of server.moduleGraph.idToModuleMap.values()) {
56
+ server.moduleGraph.invalidateModule(mod);
57
+ }
58
+ }
59
+ server.ws.send({ type: 'full-reload' });
60
+ }
61
+ if (queued) {
62
+ queued = false;
63
+ rebuild(server, 'queued change');
64
+ }
65
+ }
66
+ return {
67
+ name: 'content-watch',
68
+ apply: 'serve',
69
+ configureServer(server) {
70
+ const src = sourceContentRoot(options);
71
+ const compiled = path.resolve(options.compiledRoot || process.env.ACI_CONTENT_ROOT || compiledContentRoot());
72
+ server.watcher.add(src);
73
+ server.watcher.add(compiled);
74
+ rebuild(server, 'startup');
75
+ server.watcher.on('all', (_event, filePath) => {
76
+ const changed = path.resolve(filePath);
77
+ const isSource = changed.startsWith(src + path.sep);
78
+ const isCompiled = changed.startsWith(compiled + path.sep);
79
+ if (!isSource && !isCompiled)
80
+ return;
81
+ if (isCompiled) {
82
+ server.ws.send({ type: 'full-reload' });
83
+ return;
84
+ }
85
+ clearTimeout(timer);
86
+ timer = setTimeout(() => rebuild(server, path.relative(src, changed)), 100);
87
+ });
88
+ },
89
+ };
90
+ }
91
+ export function damAssetPlugin(options = {}) {
92
+ return {
93
+ name: 'dam-assets',
94
+ apply: 'serve',
95
+ configureServer(server) {
96
+ if (!server.middlewares)
97
+ return;
98
+ server.middlewares.use('/.gradial-dam', async (req, res, next) => {
99
+ const root = path.resolve(options.compiledRoot || compiledContentRoot());
100
+ const requestPath = safeRequestPath(req.url || '');
101
+ if (!requestPath) {
102
+ res.statusCode = 404;
103
+ res.end('asset not found');
104
+ return;
105
+ }
106
+ const filePath = path.resolve(root, '.gradial-dam', requestPath.replace(/^\/+/, ''));
107
+ if (!isInside(root, filePath)) {
108
+ res.statusCode = 404;
109
+ res.end('asset not found');
110
+ return;
111
+ }
112
+ try {
113
+ const body = await fs.readFile(filePath);
114
+ res.statusCode = 200;
115
+ res.setHeader('Content-Type', contentType(filePath));
116
+ res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
117
+ res.end(body);
118
+ }
119
+ catch {
120
+ next();
121
+ }
122
+ });
123
+ },
124
+ };
125
+ }
126
+ function safeRequestPath(url) {
127
+ const rawPath = url.split('?')[0] || '';
128
+ try {
129
+ const decoded = decodeURIComponent(rawPath);
130
+ return decoded.startsWith('/.gradial-dam/') ? decoded.slice('/.gradial-dam/'.length) : decoded;
131
+ }
132
+ catch {
133
+ return '';
134
+ }
135
+ }
136
+ function isInside(root, filePath) {
137
+ const rel = path.relative(root, filePath);
138
+ return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
139
+ }
140
+ function contentType(filePath) {
141
+ switch (path.extname(filePath).toLowerCase()) {
142
+ case '.webp':
143
+ return 'image/webp';
144
+ case '.svg':
145
+ return 'image/svg+xml';
146
+ case '.jpg':
147
+ case '.jpeg':
148
+ return 'image/jpeg';
149
+ case '.png':
150
+ return 'image/png';
151
+ default:
152
+ return 'application/octet-stream';
153
+ }
154
+ }
@@ -1,48 +1,29 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { type DevRefreshOptions } from './browser.js';
3
- export { DEFAULT_DEV_REFRESH_PATH, DEFAULT_DEV_REFRESH_PORT, type DevRefreshOptions } from './browser.js';
1
+ export type DevRefreshMessage = {
2
+ type: 'connected';
3
+ siteId?: string;
4
+ } | {
5
+ type: 'compile-started';
6
+ reason?: string;
7
+ } | {
8
+ type: 'compile-succeeded';
9
+ releaseId?: string;
10
+ } | {
11
+ type: 'compile-failed';
12
+ errors?: string[];
13
+ } | {
14
+ type: 'content-updated';
15
+ releaseId?: string;
16
+ };
17
+ interface DevRefreshScriptOptions {
18
+ wsPort?: number | string;
19
+ path?: string;
20
+ reconnectMs?: number;
21
+ }
4
22
  declare global {
5
23
  interface Window {
6
24
  __gradialDevRefresh?: boolean;
7
25
  }
8
26
  }
9
- export interface GradialContentWatchOptions extends DevRefreshOptions {
10
- /** Source content root to watch. Defaults to ACI_CONTENT_SOURCE env or '.content' */
11
- contentRoot?: string;
12
- /** Compiled content output root. Defaults to ACI_CONTENT_ROOT env or '.aci/compiled' */
13
- compiledRoot?: string;
14
- /** Path to the ACI CLI binary. Defaults to ACI_BIN env or 'aci' */
15
- aciBin?: string;
16
- /** Disable content watching entirely. Defaults to ACI_DISABLE_CONTENT_WATCH env */
17
- enabled?: boolean;
18
- }
19
- interface ViteModuleGraph {
20
- idToModuleMap: Map<unknown, {
21
- id: string | null;
22
- }>;
23
- invalidateModule(mod: unknown): void;
24
- }
25
- interface ViteDevServerLike {
26
- middlewares?: {
27
- use(path: string, handler: (req: IncomingMessage, res: ServerResponse, next: () => void) => void): void;
28
- };
29
- watcher: {
30
- add(path: string): void;
31
- on(event: string, callback: (eventName: string, filePath: string) => void): void;
32
- };
33
- ws: {
34
- send(payload: unknown): void;
35
- };
36
- moduleGraph?: ViteModuleGraph;
37
- }
38
- export interface VitePluginLike {
39
- name: string;
40
- apply?: 'serve' | 'build';
41
- configureServer?(server: ViteDevServerLike): void;
42
- transformIndexHtml?(html: string): string;
43
- }
44
- export declare function devRefreshPort(options?: DevRefreshOptions): number;
45
- export declare function devRefreshScript(options?: DevRefreshOptions): string;
46
- export declare function devRefreshScriptTag(options?: DevRefreshOptions): string;
47
- export declare function gradialContentWatchPlugin(options?: GradialContentWatchOptions): VitePluginLike;
48
- export declare function gradialDamAssetPlugin(options?: GradialContentWatchOptions): VitePluginLike;
27
+ export declare function createDevRefreshBrowserScript(options?: DevRefreshScriptOptions): string;
28
+ export declare function createDevRefreshScriptTag(options?: DevRefreshScriptOptions): string;
29
+ export {};
package/dist/dev/index.js CHANGED
@@ -1,9 +1,4 @@
1
- import fs from 'node:fs/promises';
2
- import { spawnSync } from 'node:child_process';
3
- import path from 'node:path';
4
- import { compiledContentRoot } from '../content/routes.js';
5
1
  import { DEFAULT_DEV_REFRESH_PATH, DEFAULT_DEV_REFRESH_PORT, } from './browser.js';
6
- export { DEFAULT_DEV_REFRESH_PATH, DEFAULT_DEV_REFRESH_PORT } from './browser.js';
7
2
  function numberOption(value, fallback) {
8
3
  if (value === undefined || value === '') {
9
4
  return fallback;
@@ -11,14 +6,14 @@ function numberOption(value, fallback) {
11
6
  const parsed = Number(value);
12
7
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
13
8
  }
14
- export function devRefreshPort(options = {}) {
9
+ function devRefreshPort(options = {}) {
15
10
  const value = options.wsPort ?? process.env.ACI_DEV_WS_PORT;
16
11
  if (value === 0 || value === '0') {
17
12
  return 0;
18
13
  }
19
14
  return numberOption(value, DEFAULT_DEV_REFRESH_PORT);
20
15
  }
21
- export function devRefreshScript(options = {}) {
16
+ export function createDevRefreshBrowserScript(options = {}) {
22
17
  const wsPort = devRefreshPort(options);
23
18
  if (wsPort <= 0) {
24
19
  return '';
@@ -46,166 +41,6 @@ export function devRefreshScript(options = {}) {
46
41
  connect();
47
42
  })();`;
48
43
  }
49
- export function devRefreshScriptTag(options = {}) {
50
- return `<script>${devRefreshScript(options)}</script>`;
51
- }
52
- function sourceContentRoot(options) {
53
- return path.resolve(options.contentRoot ||
54
- process.env.ACI_CONTENT_SOURCE ||
55
- './.content');
56
- }
57
- function resolveAciBin(options) {
58
- return options.aciBin || process.env.ACI_BIN || 'aci';
59
- }
60
- function recompileContent(options, reason) {
61
- const siteDir = process.cwd();
62
- const src = sourceContentRoot(options);
63
- const out = path.resolve(options.compiledRoot ||
64
- process.env.ACI_CONTENT_ROOT ||
65
- '.aci/compiled');
66
- const bin = resolveAciBin(options);
67
- console.log(`[aci] compiling content (${reason})`);
68
- const result = spawnSync(bin, [
69
- '-s', siteDir,
70
- 'build',
71
- '--content', src,
72
- '--out', out,
73
- '--skip-code',
74
- ], {
75
- cwd: siteDir,
76
- stdio: 'inherit',
77
- env: process.env,
78
- });
79
- if (result.status !== 0) {
80
- console.error(`[aci] content compile failed with exit code ${result.status ?? 'unknown'}`);
81
- return false;
82
- }
83
- return true;
84
- }
85
- export function gradialContentWatchPlugin(options = {}) {
86
- const enabled = options.enabled ?? process.env.ACI_DISABLE_CONTENT_WATCH !== '1';
87
- if (!enabled) {
88
- return {
89
- name: 'gradial-content-watch-disabled',
90
- apply: 'serve',
91
- };
92
- }
93
- let timer;
94
- let running = false;
95
- let queued = false;
96
- function rebuild(server, reason) {
97
- if (running) {
98
- queued = true;
99
- return;
100
- }
101
- running = true;
102
- const success = recompileContent(options, reason);
103
- running = false;
104
- if (success) {
105
- if (server.moduleGraph) {
106
- for (const mod of server.moduleGraph.idToModuleMap.values()) {
107
- server.moduleGraph.invalidateModule(mod);
108
- }
109
- }
110
- server.ws.send({ type: 'full-reload' });
111
- }
112
- if (queued) {
113
- queued = false;
114
- rebuild(server, 'queued change');
115
- }
116
- }
117
- return {
118
- name: 'gradial-content-watch',
119
- apply: 'serve',
120
- configureServer(server) {
121
- const src = sourceContentRoot(options);
122
- const compiled = path.resolve(options.compiledRoot ||
123
- process.env.ACI_CONTENT_ROOT ||
124
- compiledContentRoot());
125
- server.watcher.add(src);
126
- server.watcher.add(compiled);
127
- rebuild(server, 'startup');
128
- server.watcher.on('all', (_event, filePath) => {
129
- const changed = path.resolve(filePath);
130
- const isSource = changed.startsWith(src + path.sep);
131
- const isCompiled = changed.startsWith(compiled + path.sep);
132
- if (!isSource && !isCompiled)
133
- return;
134
- if (isCompiled) {
135
- server.ws.send({ type: 'full-reload' });
136
- return;
137
- }
138
- clearTimeout(timer);
139
- timer = setTimeout(() => {
140
- const relative = path.relative(src, changed);
141
- rebuild(server, relative);
142
- }, 100);
143
- });
144
- },
145
- };
146
- }
147
- export function gradialDamAssetPlugin(options = {}) {
148
- return {
149
- name: 'gradial-dam-assets',
150
- apply: 'serve',
151
- configureServer(server) {
152
- if (!server.middlewares) {
153
- return;
154
- }
155
- server.middlewares.use('/.gradial-dam', async (req, res, next) => {
156
- const root = path.resolve(options.compiledRoot || compiledContentRoot());
157
- const requestPath = safeRequestPath(req.url || '');
158
- if (!requestPath) {
159
- res.statusCode = 404;
160
- res.end('asset not found');
161
- return;
162
- }
163
- const filePath = path.resolve(root, '.gradial-dam', requestPath.replace(/^\/+/, ''));
164
- if (!isInside(root, filePath)) {
165
- res.statusCode = 404;
166
- res.end('asset not found');
167
- return;
168
- }
169
- try {
170
- const body = await fs.readFile(filePath);
171
- res.statusCode = 200;
172
- res.setHeader('Content-Type', contentType(filePath));
173
- res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
174
- res.end(body);
175
- }
176
- catch {
177
- next();
178
- }
179
- });
180
- },
181
- };
182
- }
183
- function safeRequestPath(url) {
184
- const rawPath = url.split('?')[0] || '';
185
- try {
186
- const decoded = decodeURIComponent(rawPath);
187
- return decoded.startsWith('/.gradial-dam/') ? decoded.slice('/.gradial-dam/'.length) : decoded;
188
- }
189
- catch {
190
- return '';
191
- }
192
- }
193
- function isInside(root, filePath) {
194
- const rel = path.relative(root, filePath);
195
- return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
196
- }
197
- function contentType(filePath) {
198
- switch (path.extname(filePath).toLowerCase()) {
199
- case '.webp':
200
- return 'image/webp';
201
- case '.svg':
202
- return 'image/svg+xml';
203
- case '.jpg':
204
- case '.jpeg':
205
- return 'image/jpeg';
206
- case '.png':
207
- return 'image/png';
208
- default:
209
- return 'application/octet-stream';
210
- }
44
+ export function createDevRefreshScriptTag(options = {}) {
45
+ return `<script>${createDevRefreshBrowserScript(options)}</script>`;
211
46
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
- export * from './block-ref.js';
2
- export * from './define-component.js';
3
- export * from './define-data-model.js';
4
- export * from './define-layout.js';
5
- export * from './registry.js';
6
- export * from './types/index.js';
1
+ export { defineComponentContract } from './define-component.js';
2
+ export { defineLayoutContract, slot, fragmentDefault } from './define-layout.js';
3
+ export { createRegistry, registryLookup } from './registry.js';
4
+ export type { Registry, RegistryEntry, AnyComponent } from './registry.js';
5
+ export { blockRef, blockRefArray } from './types/block-ref.js';
6
+ export type { BlockRef, BlockRefEntry, BlockRefMeta, BlockRefUnion } from './types/block-ref.js';
7
+ export type { ComponentContract, ComponentContractID, ComponentContractValidator, ComponentRegistry, ComponentValidationContext, ComponentValidationIssue, InferComponentProps, } from './types/component.js';
8
+ export { ImageSchema, imageAttrs, primaryImageSource, type Image, type ImageSource, type ImageAttrs, type ImageSlotContract, type SlotOutput, } from './types/image.js';
9
+ export { LinkSchema, type Link, type LinkTarget, type LinkResolverContext, resolveLink, resolveHref, assertSafeHref, normalizeLinkRel, } from './types/link.js';
10
+ export { HeadingSchema, InlineContentSchema, RichTextValueSchema, type Heading, type InlineContent, type RichTextValue, } from './types/rich-text.js';
11
+ export type { Config, RouteConfig, ExternalDependency, DAMConfig, } from './types/config.js';
12
+ export type { Renderer, RenderCapabilities, RenderPageRequest, RenderPageResult, RequestContext, ReleaseContext, RenderFragmentRequest, RenderIslandRequest, RenderResult, IslandDescriptor, CachePolicy, GeoContext, } from './types/renderer.js';
13
+ export type { Asset, } from './types/media.js';
14
+ export { AssetSchema, isImage, isAsset, } from './types/media.js';
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
- export * from './block-ref.js';
2
- export * from './define-component.js';
3
- export * from './define-data-model.js';
4
- export * from './define-layout.js';
5
- export * from './registry.js';
6
- export * from './types/index.js';
7
- // Note: content/ is NOT re-exported here because it imports node:path,
8
- // making it incompatible with client-side bundlers. Import server-only
9
- // content utilities from '@gradial/aci/content' explicitly.
1
+ export { defineComponentContract } from './define-component.js';
2
+ export { defineLayoutContract, slot, fragmentDefault } from './define-layout.js';
3
+ export { createRegistry, registryLookup } from './registry.js';
4
+ export { blockRef, blockRefArray } from './types/block-ref.js';
5
+ export { ImageSchema, imageAttrs, primaryImageSource, } from './types/image.js';
6
+ export { LinkSchema, resolveLink, resolveHref, assertSafeHref, normalizeLinkRel, } from './types/link.js';
7
+ export { HeadingSchema, InlineContentSchema, RichTextValueSchema, } from './types/rich-text.js';
8
+ export { AssetSchema, isImage, isAsset, } from './types/media.js';
@@ -1,5 +1,5 @@
1
1
  import { FileContentProvider } from '../providers/file.js';
2
- import { getReleaseAssetResponse } from './server.js';
2
+ import { getReleaseAssetResponse } from '../content/assets.js';
3
3
  const LOCAL_RELEASE_ID = 'local';
4
4
  export const runtime = 'nodejs';
5
5
  export const dynamic = 'force-dynamic';
@@ -15,7 +15,7 @@ export async function GET(_request, { params }) {
15
15
  return provider.fetchRaw(assetPath);
16
16
  }
17
17
  try {
18
- return await getReleaseAssetResponse(releaseId, assetPath);
18
+ return await getReleaseAssetResponse({ releaseId, assetPath });
19
19
  }
20
20
  catch {
21
21
  return new Response('asset not found', { status: 404 });
@@ -1,6 +1,6 @@
1
1
  import type { NextConfig } from 'next';
2
- export interface WithGradialOptions {
2
+ export interface WithAciOptions {
3
3
  /** Asset rewrite prefix. Defaults to '/.gradial-dam' */
4
4
  assetPrefix?: string;
5
5
  }
6
- export declare function withGradialAci(nextConfig?: NextConfig, options?: WithGradialOptions): NextConfig;
6
+ export declare function withAci(nextConfig?: NextConfig, options?: WithAciOptions): NextConfig;
@@ -1,26 +1,26 @@
1
1
  import { createContentWatchWebpackPlugin } from './content-watch.js';
2
- export function withGradialAci(nextConfig = {}, options = {}) {
2
+ export function withAci(nextConfig = {}, options = {}) {
3
3
  const assetPrefix = options.assetPrefix || '/.gradial-dam';
4
4
  const userRewrites = nextConfig.rewrites;
5
5
  const userWebpack = nextConfig.webpack;
6
6
  return {
7
7
  ...nextConfig,
8
8
  rewrites: async () => {
9
- const gradialRewrites = [
9
+ const rewrites = [
10
10
  {
11
11
  source: `${assetPrefix}/:path*`,
12
12
  destination: `/gradial/assets/local${assetPrefix}/:path*`,
13
13
  },
14
14
  ];
15
15
  if (!userRewrites)
16
- return gradialRewrites;
16
+ return rewrites;
17
17
  const userResult = await (typeof userRewrites === 'function' ? userRewrites() : userRewrites);
18
18
  if (Array.isArray(userResult)) {
19
- return [...gradialRewrites, ...userResult];
19
+ return [...rewrites, ...userResult];
20
20
  }
21
21
  return {
22
22
  ...userResult,
23
- beforeFiles: [...gradialRewrites, ...(userResult.beforeFiles ?? [])],
23
+ beforeFiles: [...rewrites, ...(userResult.beforeFiles ?? [])],
24
24
  };
25
25
  },
26
26
  webpack: (config, context) => {
@@ -80,14 +80,19 @@ function startContentWatcher() {
80
80
  }
81
81
  rebuild('startup');
82
82
  try {
83
- fs.watch(src, { recursive: true }, (_event, filename) => {
83
+ const watcher = fs.watch(src, { recursive: true }, (_event, filename) => {
84
84
  if (!filename)
85
85
  return;
86
+ if (filename.split(path.sep).includes('.gradial-dam'))
87
+ return;
86
88
  clearTimeout(timer);
87
89
  timer = setTimeout(() => {
88
90
  rebuild(path.relative(src, path.resolve(src, filename)));
89
91
  }, 100);
90
92
  });
93
+ watcher.on('error', (error) => {
94
+ console.warn(`[aci] content watch error: ${error.message}`);
95
+ });
91
96
  }
92
97
  catch {
93
98
  console.warn('[aci] fs.watch not supported on this platform, content watch disabled');
@@ -1,4 +1,4 @@
1
1
  export { DevRefresh, type DevRefreshProps } from './dev-refresh.js';
2
- export { withGradialAci, type WithGradialOptions } from './config.js';
2
+ export { withAci, type WithAciOptions } from './config.js';
3
3
  export { isPreviewMode } from './preview-mode.js';
4
- export { createPreviewBannerHTML, createPreviewCookies, extractPreviewToken, resolvePreviewContext, PREVIEW_HEADER, RELEASE_HEADER, PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, type PreviewContext, type PreviewClaims, type PreviewCookie, } from '../preview/core.js';
4
+ export { createPage, type CreatePageOptions, type SlotPropsFn } from './page.js';
@@ -1,4 +1,4 @@
1
1
  export { DevRefresh } from './dev-refresh.js';
2
- export { withGradialAci } from './config.js';
2
+ export { withAci } from './config.js';
3
3
  export { isPreviewMode } from './preview-mode.js';
4
- export { createPreviewBannerHTML, createPreviewCookies, extractPreviewToken, resolvePreviewContext, PREVIEW_HEADER, RELEASE_HEADER, PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, } from '../preview/core.js';
4
+ export { createPage } from './page.js';
@@ -1,11 +1,11 @@
1
1
  import { NextResponse, type NextRequest } from 'next/server.js';
2
- export interface GradialMiddlewareConfig {
2
+ export interface MiddlewareConfig {
3
3
  siteId?: string;
4
4
  edgeConfig?: string;
5
5
  previewSignKey?: string;
6
6
  deploymentId?: string;
7
7
  }
8
- export declare function createGradialMiddleware(config?: GradialMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
8
+ export declare function createMiddleware(config?: MiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
9
9
  export declare const config: {
10
10
  matcher: string[];
11
11
  };
@@ -3,8 +3,8 @@ import { getUncachedEdgeConfigValue } from './edge-config.js';
3
3
  import { PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, PREVIEW_HEADER, RELEASE_HEADER, extractPreviewToken, resolvePreviewContext, createPreviewCookies, previewSignKey, } from '../preview/core.js';
4
4
  const ROUTE_HEADER = 'x-gradial-route';
5
5
  const DISPATCH_HEADER = 'x-gradial-dispatch';
6
- export function createGradialMiddleware(config = {}) {
7
- return async function gradialMiddleware(request) {
6
+ export function createMiddleware(config = {}) {
7
+ return async function middleware(request) {
8
8
  const url = request.nextUrl;
9
9
  // ?leave_preview=1 → clear cookies, redirect to clean URL
10
10
  if (url.searchParams.get('leave_preview') === '1') {
@@ -14,7 +14,7 @@ export function createGradialMiddleware(config = {}) {
14
14
  response.cookies.delete(PREVIEW_RELEASE_COOKIE);
15
15
  return response;
16
16
  }
17
- const requestHeaders = gradialHeaders(request.headers);
17
+ const requestHeaders = headers(request.headers);
18
18
  // Try preview token first; if valid, use that release.
19
19
  // If no token or invalid, fall through to active release from edge config.
20
20
  const preview = await resolvePreviewFromRequest(request, config);
@@ -43,7 +43,7 @@ export const config = {
43
43
  '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
44
44
  ],
45
45
  };
46
- function gradialHeaders(headers) {
46
+ function headers(headers) {
47
47
  const next = new Headers(headers);
48
48
  next.delete(RELEASE_HEADER);
49
49
  next.delete(ROUTE_HEADER);
@@ -59,9 +59,9 @@ async function resolvePreviewFromRequest(request, config) {
59
59
  });
60
60
  if (!token)
61
61
  return null;
62
- const signKey = previewSignKey();
62
+ const signKey = config.previewSignKey || previewSignKey();
63
63
  if (!signKey) {
64
- console.warn('[gradial/mw] GRADIAL_PREVIEW_SIGN_KEY not set — preview tokens will be ignored');
64
+ console.warn('[aci/mw] GRADIAL_PREVIEW_SIGN_KEY not set — preview tokens will be ignored');
65
65
  return null;
66
66
  }
67
67
  return await resolvePreviewContext({ token, siteId: config.siteId || '', signKey });
@@ -16,7 +16,7 @@ export interface CreatePageOptions {
16
16
  * Usage in `src/app/[[...slug]]/page.tsx`:
17
17
  *
18
18
  * ```tsx
19
- * import { createPage } from '@gradial/aci/next/page';
19
+ * import { createPage } from '@gradial/aci/next';
20
20
  * import { registry } from '@/cms/registry';
21
21
  *
22
22
  * const page = createPage(registry);