@ruvyxa/adapter-netlify 1.0.18 → 1.0.19
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/dist/index.d.ts +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,12 +7,24 @@ export interface NetlifyAdapterOptions {
|
|
|
7
7
|
functionsDir?: string;
|
|
8
8
|
/**
|
|
9
9
|
* Also emit a `netlify.toml` at the project root pointing Netlify at the
|
|
10
|
-
* generated publish directory and functions
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* generated publish directory and functions. An existing project
|
|
11
|
+
* `netlify.toml` is never overwritten.
|
|
12
|
+
*
|
|
13
|
+
* Off by default: the adapter already emits the serverless function and
|
|
14
|
+
* cache headers through Netlify's Frameworks API (`.netlify/v1/`, a
|
|
15
|
+
* gitignored build artifact), so the only remaining setup is the publish
|
|
16
|
+
* directory — set once in the Netlify dashboard, or opt into this file.
|
|
17
|
+
* @default false
|
|
14
18
|
*/
|
|
15
19
|
projectConfig?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Emit the Netlify Frameworks API directory (`.netlify/v1/`) at the project
|
|
22
|
+
* root during `ruvyxa build`: the SSR/API function and the immutable cache
|
|
23
|
+
* headers for hashed client bundles. Netlify picks the directory up
|
|
24
|
+
* automatically on the next deploy — no config file at the project root.
|
|
25
|
+
* @default true
|
|
26
|
+
*/
|
|
27
|
+
frameworksApi?: boolean;
|
|
16
28
|
}
|
|
17
29
|
/**
|
|
18
30
|
* Create a Netlify deployment adapter for Ruvyxa.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgD,MAAM,cAAc,CAAA;AAGzF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgD,MAAM,cAAc,CAAA;AAGzF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AA6ED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAmH3E;eAEc,cAAc"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clientBuildOutput, validateBuildContext } from '@ruvyxa/core';
|
|
1
|
+
import { clientBuildOutput, projectRelativeOutDir, validateBuildContext } from '@ruvyxa/core';
|
|
2
2
|
/**
|
|
3
3
|
* Netlify Functions v2 handler source code.
|
|
4
4
|
*
|
|
@@ -10,11 +10,22 @@ function netlifyHandlerSource() {
|
|
|
10
10
|
return `import { createHandler, prerenderRelativePath } from './serverless-handler.mjs';
|
|
11
11
|
import { loadRouteModule } from './route-modules.mjs';
|
|
12
12
|
import { readFileSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
|
|
13
|
+
import os from 'node:os';
|
|
13
14
|
import path from 'node:path';
|
|
14
15
|
|
|
15
16
|
const manifestPath = path.join(import.meta.dirname, 'manifest.json');
|
|
16
17
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
17
18
|
const prerenderDir = path.join(import.meta.dirname, 'prerender');
|
|
19
|
+
// The function bundle directory is read-only at runtime; only the platform
|
|
20
|
+
// tmp directory accepts writes. ISR revalidations land there and are read
|
|
21
|
+
// back before the bundled deploy-time prerender output.
|
|
22
|
+
const isrCacheDir = path.join(os.tmpdir(), 'ruvyxa-isr-cache');
|
|
23
|
+
|
|
24
|
+
const readEntry = (htmlPath, revalidate) => {
|
|
25
|
+
const html = readFileSync(htmlPath, 'utf8');
|
|
26
|
+
const stale = Date.now() - statSync(htmlPath).mtimeMs >= revalidate * 1000;
|
|
27
|
+
return { html, stale };
|
|
28
|
+
};
|
|
18
29
|
|
|
19
30
|
const handler = createHandler({
|
|
20
31
|
routes: manifest.routes,
|
|
@@ -22,14 +33,16 @@ const handler = createHandler({
|
|
|
22
33
|
importApi: loadRouteModule,
|
|
23
34
|
readPrerendered: (pathname, revalidate = 60) => {
|
|
24
35
|
// prerenderRelativePath rejects any request path that cannot be mapped to a
|
|
25
|
-
// location inside
|
|
36
|
+
// location inside the cache directories, so reads can never escape them.
|
|
26
37
|
const relative = prerenderRelativePath(pathname);
|
|
27
38
|
if (relative === null) return null;
|
|
28
39
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
return readEntry(path.join(isrCacheDir, relative), revalidate);
|
|
41
|
+
} catch {
|
|
42
|
+
// fall through to the bundled prerender output
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
return readEntry(path.join(prerenderDir, relative), revalidate);
|
|
33
46
|
} catch {
|
|
34
47
|
return null;
|
|
35
48
|
}
|
|
@@ -37,7 +50,7 @@ const handler = createHandler({
|
|
|
37
50
|
writePrerendered: (pathname, html, revalidate) => {
|
|
38
51
|
const relative = prerenderRelativePath(pathname);
|
|
39
52
|
if (relative === null) return;
|
|
40
|
-
const htmlPath = path.join(
|
|
53
|
+
const htmlPath = path.join(isrCacheDir, relative);
|
|
41
54
|
try {
|
|
42
55
|
mkdirSync(path.dirname(htmlPath), { recursive: true });
|
|
43
56
|
writeFileSync(htmlPath, html, 'utf8');
|
|
@@ -91,17 +104,30 @@ export function netlifyAdapter(options = {}) {
|
|
|
91
104
|
build(ctx) {
|
|
92
105
|
validateBuildContext(ctx, 'netlifyAdapter');
|
|
93
106
|
const functionsDir = options.functionsDir ?? `${ctx.outDir}/netlify/functions`;
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
// Config files are committed or read on other machines; never embed the
|
|
108
|
+
// absolute build-machine outDir in them.
|
|
109
|
+
const relativeOutDir = projectRelativeOutDir(ctx);
|
|
110
|
+
// Hashed client bundles are served under /__ruvyxa/client/ (see the
|
|
111
|
+
// chunk manifest src fields); the immutable header must match that URL.
|
|
112
|
+
const immutableHeaderToml = '[[headers]]\n for = "/__ruvyxa/client/*"\n [headers.values]\n' +
|
|
97
113
|
' Cache-Control = "public, max-age=31536000, immutable"\n';
|
|
98
|
-
//
|
|
114
|
+
// Netlify.toml for the deploy directory
|
|
115
|
+
const netlifyToml = '[build]\n publish = "publish"\n functions = "functions"\n\n' + immutableHeaderToml;
|
|
116
|
+
// Project-root netlify.toml pointing at the build output (opt-in)
|
|
99
117
|
const projectNetlifyToml = '[build]\n' +
|
|
100
118
|
' command = "npx --no-install ruvyxa build"\n' +
|
|
101
|
-
` publish = "${
|
|
102
|
-
` functions = "${
|
|
103
|
-
|
|
104
|
-
|
|
119
|
+
` publish = "${relativeOutDir}/deploy/netlify/publish"\n` +
|
|
120
|
+
` functions = "${relativeOutDir}/deploy/netlify/functions"\n\n` +
|
|
121
|
+
immutableHeaderToml;
|
|
122
|
+
// Frameworks API deploy configuration (.netlify/v1/config.json)
|
|
123
|
+
const frameworksApiConfig = JSON.stringify({
|
|
124
|
+
headers: [
|
|
125
|
+
{
|
|
126
|
+
for: '/__ruvyxa/client/*',
|
|
127
|
+
values: { 'Cache-Control': 'public, max-age=31536000, immutable' },
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
}, null, 2);
|
|
105
131
|
return {
|
|
106
132
|
name: 'netlify',
|
|
107
133
|
target: 'serverless',
|
|
@@ -112,8 +138,11 @@ export function netlifyAdapter(options = {}) {
|
|
|
112
138
|
functionsDir,
|
|
113
139
|
configFiles: ['netlify.toml'],
|
|
114
140
|
artifacts: [
|
|
115
|
-
// Static assets (pre-rendered pages + client bundles)
|
|
116
|
-
|
|
141
|
+
// Static assets (pre-rendered pages + client bundles). `optional`:
|
|
142
|
+
// an API-only or all-SSR app has no prerendered pages; the function
|
|
143
|
+
// still serves every route, so the missing prerender directory must
|
|
144
|
+
// not fail the build.
|
|
145
|
+
{ kind: 'static-site', path: 'deploy/netlify/publish', optional: true },
|
|
117
146
|
// Serverless function bundle
|
|
118
147
|
{
|
|
119
148
|
kind: 'function',
|
|
@@ -126,9 +155,27 @@ export function netlifyAdapter(options = {}) {
|
|
|
126
155
|
path: 'deploy/netlify/netlify.toml',
|
|
127
156
|
contents: netlifyToml,
|
|
128
157
|
},
|
|
129
|
-
|
|
158
|
+
// Frameworks API artifacts: Netlify discovers .netlify/v1/ at the
|
|
159
|
+
// project root automatically, so a fresh site needs only the publish
|
|
160
|
+
// directory set once in the dashboard — no committed config file.
|
|
161
|
+
...(options.frameworksApi === false
|
|
130
162
|
? []
|
|
131
163
|
: [
|
|
164
|
+
{
|
|
165
|
+
kind: 'function',
|
|
166
|
+
path: '.netlify/v1/functions/ruvyxa-handler',
|
|
167
|
+
scope: 'project',
|
|
168
|
+
handlerSource: netlifyHandlerSource(),
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
kind: 'file',
|
|
172
|
+
path: '.netlify/v1/config.json',
|
|
173
|
+
scope: 'project',
|
|
174
|
+
contents: frameworksApiConfig + '\n',
|
|
175
|
+
},
|
|
176
|
+
]),
|
|
177
|
+
...(options.projectConfig === true
|
|
178
|
+
? [
|
|
132
179
|
{
|
|
133
180
|
kind: 'file',
|
|
134
181
|
path: 'netlify.toml',
|
|
@@ -136,7 +183,8 @@ export function netlifyAdapter(options = {}) {
|
|
|
136
183
|
skipIfExists: true,
|
|
137
184
|
contents: projectNetlifyToml,
|
|
138
185
|
},
|
|
139
|
-
]
|
|
186
|
+
]
|
|
187
|
+
: []),
|
|
140
188
|
],
|
|
141
189
|
};
|
|
142
190
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvyxa/adapter-netlify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "Shape Ruvyxa builds for Netlify functions and assets with a small typed adapter contract.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@ruvyxa/core": "^1.0.
|
|
41
|
+
"@ruvyxa/core": "^1.0.19"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.json",
|