@gradial/aci 0.1.18 → 0.1.20-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -8
- package/bin/aci +0 -0
- package/dist/astro/index.d.ts +4 -2
- package/dist/astro/index.js +9 -1
- package/dist/astro/preview.d.ts +5 -0
- package/dist/astro/preview.js +33 -0
- package/dist/content/index.d.ts +1 -0
- package/dist/content/index.js +1 -0
- package/dist/content/provider.d.ts +19 -0
- package/dist/content/provider.js +7 -0
- package/dist/content/resolve-slots.d.ts +9 -0
- package/dist/content/resolve-slots.js +24 -0
- package/dist/content/types.d.ts +1 -1
- package/dist/content/validation.js +0 -1
- package/dist/define-component.js +0 -6
- package/dist/define-data-model.d.ts +2 -0
- package/dist/define-data-model.js +3 -0
- package/dist/define-layout.d.ts +2 -0
- package/dist/define-layout.js +3 -0
- package/dist/dev/index.d.ts +12 -0
- package/dist/dev/index.js +84 -9
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/next/asset-route.d.ts +2 -0
- package/dist/next/asset-route.js +10 -2
- package/dist/next/config.d.ts +1 -1
- package/dist/next/config.js +14 -2
- package/dist/next/content-watch.d.ts +11 -0
- package/dist/next/content-watch.js +106 -0
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +2 -2
- package/dist/next/middleware.d.ts +6 -2
- package/dist/next/middleware.js +41 -83
- package/dist/next/page.d.ts +41 -0
- package/dist/next/page.js +77 -0
- package/dist/next/preview-mode.js +4 -13
- package/dist/next/render.d.ts +5 -0
- package/dist/next/render.js +15 -0
- package/dist/next/root-layout.d.ts +4 -0
- package/dist/next/root-layout.js +5 -0
- package/dist/next/server.d.ts +3 -2
- package/dist/next/server.js +12 -8
- package/dist/preview/core.d.ts +41 -0
- package/dist/preview/core.js +116 -0
- package/dist/providers/file.d.ts +2 -0
- package/dist/providers/file.js +61 -1
- package/dist/providers/s3.d.ts +1 -0
- package/dist/providers/s3.js +14 -1
- package/dist/registry.d.ts +15 -0
- package/dist/registry.js +10 -0
- package/dist/sveltekit/index.d.ts +4 -1
- package/dist/sveltekit/index.js +9 -1
- package/dist/sveltekit/preview.d.ts +5 -0
- package/dist/sveltekit/preview.js +33 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.js +15 -2
- package/dist/types/component.d.ts +0 -9
- package/dist/types/config.d.ts +1 -1
- package/dist/types/data.d.ts +19 -0
- package/dist/types/data.js +11 -0
- package/dist/types/image.d.ts +1 -1
- package/dist/types/image.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/page.d.ts +1 -2
- package/dist/types/render-mode.d.ts +0 -1
- package/package.json +40 -6
- package/src/cli/compile-registry.mjs +167 -19
- package/src/types/component.ts +0 -10
- package/src/types/config.ts +1 -1
- package/src/types/data.ts +47 -0
- package/src/types/image.ts +2 -2
- package/src/types/index.ts +1 -0
- package/src/types/page.ts +1 -2
- package/src/types/render-mode.ts +0 -8
- package/dist/next/preview-banner.d.ts +0 -4
- package/dist/next/preview-banner.js +0 -51
- package/dist/next/preview.d.ts +0 -7
- package/dist/next/preview.js +0 -51
- package/dist/render.d.ts +0 -14
- package/dist/render.js +0 -33
- package/src/cli/verify-renderer.mjs +0 -73
package/README.md
CHANGED
|
@@ -5,9 +5,31 @@ installing `@gradial/aci`, Zod 4, and TypeScript tooling. The
|
|
|
5
5
|
SDK exposes component and layout helpers, renderer types, compiler tooling,
|
|
6
6
|
content provider helpers, and framework-specific subpaths from one package.
|
|
7
7
|
|
|
8
|
+
## Getting Started
|
|
9
|
+
|
|
10
|
+
The fastest way to create a new ACI site is via the scaffolding script:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm exec tsx scripts/create-site.ts --framework astro --name my-site --dir ./my-site
|
|
14
|
+
cd my-site
|
|
15
|
+
pnpm run dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Available frameworks: `astro`, `nextjs`, `sveltekit`.
|
|
19
|
+
|
|
20
|
+
Generated starters include:
|
|
21
|
+
- `.aci/docs/` — Understanding ACI, running, and testing guides
|
|
22
|
+
- `.aci/guides/` — Component development, design system, content authoring
|
|
23
|
+
- `.aci/migration/` — Migrating existing sites to ACI
|
|
24
|
+
- Design system tokens, ESLint rules, and demo content
|
|
25
|
+
|
|
26
|
+
See the [templates directory](templates/) for the canonical starter source.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
8
30
|
```bash
|
|
9
|
-
|
|
10
|
-
|
|
31
|
+
pnpm add @gradial/aci zod@^4
|
|
32
|
+
pnpm add -D typescript tsx
|
|
11
33
|
```
|
|
12
34
|
|
|
13
35
|
Common imports:
|
|
@@ -56,7 +78,6 @@ export const heroContract = defineComponentContract({
|
|
|
56
78
|
headline: z.string(),
|
|
57
79
|
image: GradialImageSchema,
|
|
58
80
|
}),
|
|
59
|
-
renderModes: { canStatic: true, canSSR: true, canClientIsland: false },
|
|
60
81
|
});
|
|
61
82
|
|
|
62
83
|
export type HeroProps = z.infer<typeof heroContract.schema>;
|
|
@@ -85,7 +106,6 @@ const content = new FixtureContentProvider({
|
|
|
85
106
|
$type: 'page',
|
|
86
107
|
status: 'published',
|
|
87
108
|
layout: 'marketing',
|
|
88
|
-
renderMode: 'static',
|
|
89
109
|
metadata: { title: 'Test Home' },
|
|
90
110
|
regions: { main: [] }
|
|
91
111
|
}
|
|
@@ -101,7 +121,7 @@ Use this in unit tests when you want the same provider API as
|
|
|
101
121
|
Publish from this package directory:
|
|
102
122
|
|
|
103
123
|
```bash
|
|
104
|
-
|
|
124
|
+
pnpm publish --access public
|
|
105
125
|
```
|
|
106
126
|
|
|
107
127
|
The package includes a `prepack` script that builds `dist` before packing or
|
|
@@ -109,15 +129,15 @@ publishing.
|
|
|
109
129
|
|
|
110
130
|
## Verify the Published Shape Locally
|
|
111
131
|
|
|
112
|
-
Before publishing, inspect the exact tarball
|
|
132
|
+
Before publishing, inspect the exact tarball pnpm will upload. This catches
|
|
113
133
|
package `files` mistakes where local source imports work from the repo but fail
|
|
114
|
-
after
|
|
134
|
+
after pnpm filters the packed files.
|
|
115
135
|
|
|
116
136
|
From `packages/sdk`:
|
|
117
137
|
|
|
118
138
|
```bash
|
|
119
139
|
tmpdir="$(mktemp -d /tmp/gradial-aci-pack.XXXXXX)"
|
|
120
|
-
filename="$(
|
|
140
|
+
filename="$(pnpm pack --pack-destination "$tmpdir" | tail -n 1)"
|
|
121
141
|
tar -tzf "$tmpdir/$filename" | sort | rg '^(package/src/cli/|package/src/types/|package/dist/types/)'
|
|
122
142
|
echo "tarball=$tmpdir/$filename"
|
|
123
143
|
```
|
package/bin/aci
CHANGED
|
Binary file
|
package/dist/astro/index.d.ts
CHANGED
|
@@ -33,9 +33,11 @@ export declare function getGradialStaticPaths(): Promise<Array<{
|
|
|
33
33
|
};
|
|
34
34
|
}>>;
|
|
35
35
|
export declare function getPageRuntimeRenderInput(request: Request): RenderInput | null;
|
|
36
|
+
export { createRegistry, registryLookup } from '../registry.js';
|
|
37
|
+
export type { Registry, RegistryEntry, AnyComponent } from '../registry.js';
|
|
38
|
+
export { getPreviewMode, createPreviewBannerHTML, createPreviewCookies, type PreviewContext, type PreviewCookie, } from './preview.js';
|
|
36
39
|
export interface GradialAstroOptions extends GradialContentWatchOptions {
|
|
37
40
|
/** Path to compiled content root. Defaults to ACI_CONTENT_ROOT env or '.aci/compiled' */
|
|
38
41
|
compiledRoot?: string;
|
|
39
42
|
}
|
|
40
|
-
export declare function
|
|
41
|
-
export {};
|
|
43
|
+
export declare function withGradialAci(options?: GradialAstroOptions): AstroIntegrationLike;
|
package/dist/astro/index.js
CHANGED
|
@@ -31,7 +31,15 @@ export async function getGradialStaticPaths() {
|
|
|
31
31
|
export function getPageRuntimeRenderInput(request) {
|
|
32
32
|
return getPendingRenderInputFromHeaders(request.headers);
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Registry helpers
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
export { createRegistry, registryLookup } from '../registry.js';
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Preview support
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
export { getPreviewMode, createPreviewBannerHTML, createPreviewCookies, } from './preview.js';
|
|
42
|
+
export function withGradialAci(options = {}) {
|
|
35
43
|
return {
|
|
36
44
|
name: 'gradial-astro',
|
|
37
45
|
hooks: {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type PreviewContext, type PreviewCookie } from '../preview/core.js';
|
|
2
|
+
export declare function getPreviewMode(request: Request, siteId: string): Promise<PreviewContext>;
|
|
3
|
+
export declare function createPreviewBannerHTML(releaseId: string): string;
|
|
4
|
+
export declare function createPreviewCookies(token: string, releaseId: string): PreviewCookie[];
|
|
5
|
+
export type { PreviewContext, PreviewCookie };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { extractPreviewToken, resolvePreviewContext, createPreviewBannerHTML as coreCreatePreviewBannerHTML, createPreviewCookies as coreCreatePreviewCookies, previewSignKey, } from '../preview/core.js';
|
|
2
|
+
export async function getPreviewMode(request, siteId) {
|
|
3
|
+
const url = new URL(request.url);
|
|
4
|
+
const token = extractPreviewToken({
|
|
5
|
+
query: url.searchParams,
|
|
6
|
+
cookies: parseCookieHeader(request.headers.get('cookie') || ''),
|
|
7
|
+
authorization: request.headers.get('authorization') || undefined,
|
|
8
|
+
});
|
|
9
|
+
if (!token)
|
|
10
|
+
return { isPreview: false };
|
|
11
|
+
return resolvePreviewContext({ token, siteId, signKey: previewSignKey() });
|
|
12
|
+
}
|
|
13
|
+
export function createPreviewBannerHTML(releaseId) {
|
|
14
|
+
return coreCreatePreviewBannerHTML(releaseId);
|
|
15
|
+
}
|
|
16
|
+
export function createPreviewCookies(token, releaseId) {
|
|
17
|
+
return coreCreatePreviewCookies(token, releaseId);
|
|
18
|
+
}
|
|
19
|
+
function parseCookieHeader(header) {
|
|
20
|
+
const cookies = new Map();
|
|
21
|
+
for (const part of header.split(';')) {
|
|
22
|
+
const trimmed = part.trim();
|
|
23
|
+
if (!trimmed)
|
|
24
|
+
continue;
|
|
25
|
+
const idx = trimmed.indexOf('=');
|
|
26
|
+
if (idx < 0)
|
|
27
|
+
continue;
|
|
28
|
+
const name = trimmed.slice(0, idx).trim();
|
|
29
|
+
const value = trimmed.slice(idx + 1).trim();
|
|
30
|
+
cookies.set(name, decodeURIComponent(value));
|
|
31
|
+
}
|
|
32
|
+
return cookies;
|
|
33
|
+
}
|
package/dist/content/index.d.ts
CHANGED
package/dist/content/index.js
CHANGED
|
@@ -12,17 +12,33 @@ export interface FragmentEntry {
|
|
|
12
12
|
digest: string;
|
|
13
13
|
fragmentRefs?: string[];
|
|
14
14
|
}
|
|
15
|
+
export interface LayoutEntry {
|
|
16
|
+
name: string;
|
|
17
|
+
slots: LayoutSlot[];
|
|
18
|
+
defaults?: Record<string, FragmentRef[]>;
|
|
19
|
+
}
|
|
20
|
+
export interface LayoutSlot {
|
|
21
|
+
name: string;
|
|
22
|
+
required: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface FragmentRef {
|
|
25
|
+
kind: string;
|
|
26
|
+
fragmentId: string;
|
|
27
|
+
inline: boolean;
|
|
28
|
+
}
|
|
15
29
|
export interface CompiledManifest {
|
|
16
30
|
manifestVersion: string;
|
|
17
31
|
buildDigest: string;
|
|
18
32
|
siteConfigRef: string;
|
|
19
33
|
routes: Record<string, RouteEntry>;
|
|
20
34
|
fragments: Record<string, FragmentEntry>;
|
|
35
|
+
layouts?: Record<string, LayoutEntry>;
|
|
21
36
|
}
|
|
22
37
|
export interface ContentProvider {
|
|
23
38
|
getSiteConfig<T = unknown>(): Promise<T>;
|
|
24
39
|
getPage<T = unknown>(route: string): Promise<T>;
|
|
25
40
|
getFragment<T = unknown>(id: string): Promise<T>;
|
|
41
|
+
getLayout<T = unknown>(name: string): Promise<T>;
|
|
26
42
|
listRoutes(): Promise<RouteEntry[]>;
|
|
27
43
|
}
|
|
28
44
|
export declare class PageNotFoundError extends Error {
|
|
@@ -31,6 +47,9 @@ export declare class PageNotFoundError extends Error {
|
|
|
31
47
|
export declare class FragmentNotFoundError extends Error {
|
|
32
48
|
constructor(id: string, cause?: unknown);
|
|
33
49
|
}
|
|
50
|
+
export declare class LayoutNotFoundError extends Error {
|
|
51
|
+
constructor(name: string, cause?: unknown);
|
|
52
|
+
}
|
|
34
53
|
export interface RenderInputOptions {
|
|
35
54
|
domain?: string;
|
|
36
55
|
locale?: string;
|
package/dist/content/provider.js
CHANGED
|
@@ -16,6 +16,13 @@ export class FragmentNotFoundError extends Error {
|
|
|
16
16
|
this.cause = cause;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
export class LayoutNotFoundError extends Error {
|
|
20
|
+
constructor(name, cause) {
|
|
21
|
+
super(`Layout not found: ${name}`);
|
|
22
|
+
this.name = 'LayoutNotFoundError';
|
|
23
|
+
this.cause = cause;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
19
26
|
import { getCachedSiteConfig } from './cache.js';
|
|
20
27
|
export async function loadRenderInput(provider, route = '/', options = {}) {
|
|
21
28
|
const normalized = normalizeRoute(route);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LayoutEntry } from './provider.js';
|
|
2
|
+
import type { KernelPageBlock } from './types.js';
|
|
3
|
+
export interface FragmentData {
|
|
4
|
+
id: string;
|
|
5
|
+
component: string;
|
|
6
|
+
props?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export type FragmentLoader = (id: string) => Promise<FragmentData>;
|
|
9
|
+
export declare function resolveSlots(layout: LayoutEntry, pageRegions: Record<string, KernelPageBlock[]>, getFragment: FragmentLoader): Promise<Record<string, KernelPageBlock[]>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export async function resolveSlots(layout, pageRegions, getFragment) {
|
|
2
|
+
const resolved = {};
|
|
3
|
+
for (const slot of layout.slots) {
|
|
4
|
+
const pageBlocks = pageRegions[slot.name];
|
|
5
|
+
if (pageBlocks && pageBlocks.length > 0) {
|
|
6
|
+
resolved[slot.name] = pageBlocks;
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
const defaults = layout.defaults?.[slot.name];
|
|
10
|
+
if (defaults?.length) {
|
|
11
|
+
const blocks = [];
|
|
12
|
+
for (const ref of defaults) {
|
|
13
|
+
const fragment = await getFragment(ref.fragmentId);
|
|
14
|
+
blocks.push({
|
|
15
|
+
id: fragment.id,
|
|
16
|
+
component: fragment.component,
|
|
17
|
+
props: fragment.props || {},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
resolved[slot.name] = blocks;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
package/dist/content/types.d.ts
CHANGED
|
@@ -55,7 +55,6 @@ export interface KernelPage {
|
|
|
55
55
|
$type: 'page';
|
|
56
56
|
status: string;
|
|
57
57
|
layout: string;
|
|
58
|
-
renderMode: string;
|
|
59
58
|
metadata: KernelPageSeo;
|
|
60
59
|
regions: Record<string, KernelPageBlock[]>;
|
|
61
60
|
}
|
|
@@ -93,6 +92,7 @@ export interface RenderInput<TPage extends KernelPage = KernelPage, TSiteConfig
|
|
|
93
92
|
siteConfig: TSiteConfig;
|
|
94
93
|
page: TPage | null;
|
|
95
94
|
fragments?: Record<string, unknown>;
|
|
95
|
+
layouts?: Record<string, unknown>;
|
|
96
96
|
}
|
|
97
97
|
export interface RenderOutput {
|
|
98
98
|
route: string;
|
|
@@ -121,7 +121,6 @@ export function createContentSchemas(contracts = {}) {
|
|
|
121
121
|
$type: z.literal('page'),
|
|
122
122
|
status: z.string().min(1),
|
|
123
123
|
layout: z.string().min(1),
|
|
124
|
-
renderMode: z.string().min(1),
|
|
125
124
|
metadata: z.looseObject({
|
|
126
125
|
title: z.string().optional(),
|
|
127
126
|
description: z.string().optional(),
|
package/dist/define-component.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
export function defineComponent(definition) {
|
|
2
|
-
const renderModes = definition.renderModes ?? definition.render;
|
|
3
|
-
if (!renderModes) {
|
|
4
|
-
throw new Error(`component ${definition.name} must define renderModes`);
|
|
5
|
-
}
|
|
6
2
|
return {
|
|
7
3
|
...definition,
|
|
8
|
-
renderModes,
|
|
9
|
-
render: renderModes,
|
|
10
4
|
varyDimensions: definition.varyDimensions ?? definition.vary,
|
|
11
5
|
vary: definition.vary ?? definition.varyDimensions,
|
|
12
6
|
};
|
package/dist/define-layout.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { LayoutContract, LayoutDefinition, LayoutSlot } from './types/layout.js';
|
|
2
|
+
import type { FragmentRefNode } from './types/page.js';
|
|
2
3
|
export declare function defineLayout(definition: LayoutDefinition): LayoutContract;
|
|
3
4
|
export declare const defineLayoutContract: typeof defineLayout;
|
|
4
5
|
export declare function slot(name: string, required?: boolean): LayoutSlot;
|
|
6
|
+
export declare function fragmentDefault(fragmentId: string): FragmentRefNode;
|
package/dist/define-layout.js
CHANGED
package/dist/dev/index.d.ts
CHANGED
|
@@ -7,10 +7,21 @@ declare global {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
export interface GradialContentWatchOptions extends DevRefreshOptions {
|
|
10
|
+
/** Source content root to watch. Defaults to ACI_CONTENT_SOURCE env or '.content' */
|
|
10
11
|
contentRoot?: string;
|
|
12
|
+
/** Compiled content output root. Defaults to ACI_CONTENT_ROOT env or '.aci/compiled' */
|
|
11
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 */
|
|
12
17
|
enabled?: boolean;
|
|
13
18
|
}
|
|
19
|
+
interface ViteModuleGraph {
|
|
20
|
+
idToModuleMap: Map<unknown, {
|
|
21
|
+
id: string | null;
|
|
22
|
+
}>;
|
|
23
|
+
invalidateModule(mod: unknown): void;
|
|
24
|
+
}
|
|
14
25
|
interface ViteDevServerLike {
|
|
15
26
|
middlewares?: {
|
|
16
27
|
use(path: string, handler: (req: IncomingMessage, res: ServerResponse, next: () => void) => void): void;
|
|
@@ -22,6 +33,7 @@ interface ViteDevServerLike {
|
|
|
22
33
|
ws: {
|
|
23
34
|
send(payload: unknown): void;
|
|
24
35
|
};
|
|
36
|
+
moduleGraph?: ViteModuleGraph;
|
|
25
37
|
}
|
|
26
38
|
export interface VitePluginLike {
|
|
27
39
|
name: string;
|
package/dist/dev/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { compiledContentRoot } from '../content/routes.js';
|
|
4
5
|
import { DEFAULT_DEV_REFRESH_PATH, DEFAULT_DEV_REFRESH_PORT, } from './browser.js';
|
|
@@ -48,23 +49,97 @@ export function devRefreshScript(options = {}) {
|
|
|
48
49
|
export function devRefreshScriptTag(options = {}) {
|
|
49
50
|
return `<script>${devRefreshScript(options)}</script>`;
|
|
50
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
|
+
}
|
|
51
85
|
export function gradialContentWatchPlugin(options = {}) {
|
|
52
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
|
+
}
|
|
53
117
|
return {
|
|
54
118
|
name: 'gradial-content-watch',
|
|
55
119
|
apply: 'serve',
|
|
56
120
|
configureServer(server) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
server.watcher.add(
|
|
62
|
-
server.watcher.
|
|
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) => {
|
|
63
129
|
const changed = path.resolve(filePath);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
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;
|
|
67
137
|
}
|
|
138
|
+
clearTimeout(timer);
|
|
139
|
+
timer = setTimeout(() => {
|
|
140
|
+
const relative = path.relative(src, changed);
|
|
141
|
+
rebuild(server, relative);
|
|
142
|
+
}, 100);
|
|
68
143
|
});
|
|
69
144
|
},
|
|
70
145
|
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './block-ref.js';
|
|
2
2
|
export * from './define-component.js';
|
|
3
|
+
export * from './define-data-model.js';
|
|
3
4
|
export * from './define-layout.js';
|
|
5
|
+
export * from './registry.js';
|
|
4
6
|
export * from './types/index.js';
|
|
5
7
|
// Note: content/ is NOT re-exported here because it imports node:path,
|
|
6
8
|
// making it incompatible with client-side bundlers. Import server-only
|
|
@@ -5,5 +5,7 @@ type AssetRouteParams = {
|
|
|
5
5
|
releaseId?: string;
|
|
6
6
|
path?: string[];
|
|
7
7
|
};
|
|
8
|
+
export declare const runtime = "nodejs";
|
|
9
|
+
export declare const dynamic = "force-dynamic";
|
|
8
10
|
export declare function GET(_request: Request, { params }: AssetRouteContext): Promise<Response>;
|
|
9
11
|
export {};
|
package/dist/next/asset-route.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
import { FileContentProvider } from '../providers/file.js';
|
|
1
2
|
import { getReleaseAssetResponse } from './server.js';
|
|
3
|
+
const LOCAL_RELEASE_ID = 'local';
|
|
4
|
+
export const runtime = 'nodejs';
|
|
5
|
+
export const dynamic = 'force-dynamic';
|
|
2
6
|
export async function GET(_request, { params }) {
|
|
3
7
|
const resolvedParams = await params;
|
|
4
8
|
const releaseId = resolvedParams.releaseId || '';
|
|
5
|
-
const assetPath = (resolvedParams.path || []).join('/');
|
|
6
|
-
if (!releaseId ||
|
|
9
|
+
const assetPath = '/' + (resolvedParams.path || []).join('/');
|
|
10
|
+
if (!releaseId || assetPath === '/') {
|
|
7
11
|
return new Response('asset not found', { status: 404 });
|
|
8
12
|
}
|
|
13
|
+
if (releaseId === LOCAL_RELEASE_ID) {
|
|
14
|
+
const provider = new FileContentProvider();
|
|
15
|
+
return provider.fetchRaw(assetPath);
|
|
16
|
+
}
|
|
9
17
|
try {
|
|
10
18
|
return await getReleaseAssetResponse(releaseId, assetPath);
|
|
11
19
|
}
|
package/dist/next/config.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export interface WithGradialOptions {
|
|
|
3
3
|
/** Asset rewrite prefix. Defaults to '/.gradial-dam' */
|
|
4
4
|
assetPrefix?: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function withGradialAci(nextConfig?: NextConfig, options?: WithGradialOptions): NextConfig;
|
package/dist/next/config.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { createContentWatchWebpackPlugin } from './content-watch.js';
|
|
2
|
+
export function withGradialAci(nextConfig = {}, options = {}) {
|
|
2
3
|
const assetPrefix = options.assetPrefix || '/.gradial-dam';
|
|
3
4
|
const userRewrites = nextConfig.rewrites;
|
|
5
|
+
const userWebpack = nextConfig.webpack;
|
|
4
6
|
return {
|
|
5
7
|
...nextConfig,
|
|
6
8
|
rewrites: async () => {
|
|
7
9
|
const gradialRewrites = [
|
|
8
10
|
{
|
|
9
11
|
source: `${assetPrefix}/:path*`,
|
|
10
|
-
destination: `/
|
|
12
|
+
destination: `/gradial/assets/local${assetPrefix}/:path*`,
|
|
11
13
|
},
|
|
12
14
|
];
|
|
13
15
|
if (!userRewrites)
|
|
@@ -21,5 +23,15 @@ export function withGradial(nextConfig = {}, options = {}) {
|
|
|
21
23
|
beforeFiles: [...gradialRewrites, ...(userResult.beforeFiles ?? [])],
|
|
22
24
|
};
|
|
23
25
|
},
|
|
26
|
+
webpack: (config, context) => {
|
|
27
|
+
if (context?.isServer && process.env.NODE_ENV !== 'production') {
|
|
28
|
+
if (!config.plugins)
|
|
29
|
+
config.plugins = [];
|
|
30
|
+
config.plugins.push(createContentWatchWebpackPlugin());
|
|
31
|
+
}
|
|
32
|
+
return typeof userWebpack === 'function'
|
|
33
|
+
? userWebpack(config, context)
|
|
34
|
+
: config;
|
|
35
|
+
},
|
|
24
36
|
};
|
|
25
37
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface ContentWatchWebpackPlugin {
|
|
2
|
+
apply(compiler: {
|
|
3
|
+
hooks: {
|
|
4
|
+
[key: string]: {
|
|
5
|
+
tap: (name: string, fn: () => void) => void;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
}): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createContentWatchWebpackPlugin(): ContentWatchWebpackPlugin;
|
|
11
|
+
export {};
|