@ruvyxa/adapter-netlify 1.0.16 → 1.0.17
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 +8 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ruvyxa/adapter-netlify
|
|
2
2
|
|
|
3
|
-
Netlify
|
|
3
|
+
Netlify deployment adapter for Ruvyxa production builds.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -35,8 +35,11 @@ export default config({
|
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
`ruvyxa build` creates `.ruvyxa/deploy/netlify/` with `publish
|
|
39
|
-
directory on Netlify.
|
|
38
|
+
`ruvyxa build` creates `.ruvyxa/deploy/netlify/` with `publish/`, Netlify Functions handlers, and
|
|
39
|
+
`netlify.toml`. Deploy that directory on Netlify.
|
|
40
40
|
|
|
41
|
-
This adapter
|
|
42
|
-
|
|
41
|
+
This adapter supports SSR, API, ISR, PPR, SSG, and CSR routes via the serverless runtime. Static
|
|
42
|
+
assets and pre-rendered pages are served through Netlify's publish directory; dynamic routes are
|
|
43
|
+
handled by Netlify Functions. Function output contains a compiled `.mjs` static route registry. ISR
|
|
44
|
+
checks file age against `revalidate` and coalesces concurrent stale refreshes within a warm function
|
|
45
|
+
instance.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import type { Adapter } from '@ruvyxa/core';
|
|
2
2
|
/**
|
|
3
|
-
* Options for Netlify
|
|
3
|
+
* Options for Netlify deployment.
|
|
4
4
|
*/
|
|
5
5
|
export interface NetlifyAdapterOptions {
|
|
6
6
|
/** Custom Netlify functions directory. Defaults to `${outDir}/netlify/functions`. */
|
|
7
7
|
functionsDir?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Also emit a `netlify.toml` at the project root pointing Netlify at the
|
|
10
|
+
* generated publish directory and functions, so a fresh site deploys
|
|
11
|
+
* without dashboard configuration. An existing project `netlify.toml` is
|
|
12
|
+
* never overwritten.
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
projectConfig?: boolean;
|
|
8
16
|
}
|
|
9
17
|
/**
|
|
10
|
-
* Create a Netlify
|
|
18
|
+
* Create a Netlify deployment adapter for Ruvyxa.
|
|
11
19
|
*
|
|
12
|
-
* Produces
|
|
13
|
-
*
|
|
20
|
+
* Produces a Functions v2 handler (Web-standard Request/Response) and static
|
|
21
|
+
* assets for deployment via Netlify CLI. Supports SSR, API routes, ISR, PPR,
|
|
22
|
+
* SSG, and CSR.
|
|
14
23
|
*
|
|
15
24
|
* @example
|
|
16
25
|
* ```ts
|
|
@@ -18,7 +27,7 @@ export interface NetlifyAdapterOptions {
|
|
|
18
27
|
* import { netlifyAdapter } from "@ruvyxa/adapter-netlify"
|
|
19
28
|
*
|
|
20
29
|
* export default config({
|
|
21
|
-
* adapter: netlifyAdapter(
|
|
30
|
+
* adapter: netlifyAdapter()
|
|
22
31
|
* })
|
|
23
32
|
* ```
|
|
24
33
|
*/
|
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,
|
|
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;AAgED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAyE3E;eAEc,cAAc"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,71 @@
|
|
|
1
1
|
import { clientBuildOutput, validateBuildContext } from '@ruvyxa/core';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Netlify Functions v2 handler source code.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Wraps the generic Ruvyxa serverless handler into a Netlify Functions v2
|
|
6
|
+
* handler using the Web-standard Request/Response API. Reads the route
|
|
7
|
+
* manifest and handles SSR/API/ISR/PPR requests.
|
|
8
|
+
*/
|
|
9
|
+
function netlifyHandlerSource() {
|
|
10
|
+
return `import { createHandler, prerenderRelativePath } from './serverless-handler.mjs';
|
|
11
|
+
import { loadRouteModule } from './route-modules.mjs';
|
|
12
|
+
import { readFileSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
|
|
15
|
+
const manifestPath = path.join(import.meta.dirname, 'manifest.json');
|
|
16
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
17
|
+
const prerenderDir = path.join(import.meta.dirname, 'prerender');
|
|
18
|
+
|
|
19
|
+
const handler = createHandler({
|
|
20
|
+
routes: manifest.routes,
|
|
21
|
+
importPage: loadRouteModule,
|
|
22
|
+
importApi: loadRouteModule,
|
|
23
|
+
readPrerendered: (pathname, revalidate = 60) => {
|
|
24
|
+
// prerenderRelativePath rejects any request path that cannot be mapped to a
|
|
25
|
+
// location inside prerenderDir, so the cache read can never escape it.
|
|
26
|
+
const relative = prerenderRelativePath(pathname);
|
|
27
|
+
if (relative === null) return null;
|
|
28
|
+
try {
|
|
29
|
+
const htmlPath = path.join(prerenderDir, relative);
|
|
30
|
+
const html = readFileSync(htmlPath, 'utf8');
|
|
31
|
+
const stale = Date.now() - statSync(htmlPath).mtimeMs >= revalidate * 1000;
|
|
32
|
+
return { html, stale };
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
writePrerendered: (pathname, html, revalidate) => {
|
|
38
|
+
const relative = prerenderRelativePath(pathname);
|
|
39
|
+
if (relative === null) return;
|
|
40
|
+
const htmlPath = path.join(prerenderDir, relative);
|
|
41
|
+
try {
|
|
42
|
+
mkdirSync(path.dirname(htmlPath), { recursive: true });
|
|
43
|
+
writeFileSync(htmlPath, html, 'utf8');
|
|
44
|
+
} catch {
|
|
45
|
+
// ISR cache write failures are non-fatal
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
supportedStrategies: ['ssr', 'ssg', 'csr', 'isr', 'ppr', 'api'],
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Netlify Functions v2 — Web-standard Request/Response
|
|
52
|
+
export default async function(request, context) {
|
|
53
|
+
return handler(request, context);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Netlify Functions v2 config
|
|
57
|
+
export const config = {
|
|
58
|
+
path: '/*',
|
|
59
|
+
preferStatic: true,
|
|
60
|
+
};
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a Netlify deployment adapter for Ruvyxa.
|
|
65
|
+
*
|
|
66
|
+
* Produces a Functions v2 handler (Web-standard Request/Response) and static
|
|
67
|
+
* assets for deployment via Netlify CLI. Supports SSR, API routes, ISR, PPR,
|
|
68
|
+
* SSG, and CSR.
|
|
7
69
|
*
|
|
8
70
|
* @example
|
|
9
71
|
* ```ts
|
|
@@ -11,7 +73,7 @@ import { clientBuildOutput, validateBuildContext } from '@ruvyxa/core';
|
|
|
11
73
|
* import { netlifyAdapter } from "@ruvyxa/adapter-netlify"
|
|
12
74
|
*
|
|
13
75
|
* export default config({
|
|
14
|
-
* adapter: netlifyAdapter(
|
|
76
|
+
* adapter: netlifyAdapter()
|
|
15
77
|
* })
|
|
16
78
|
* ```
|
|
17
79
|
*/
|
|
@@ -25,9 +87,21 @@ export function netlifyAdapter(options = {}) {
|
|
|
25
87
|
return {
|
|
26
88
|
name: 'netlify',
|
|
27
89
|
target: 'serverless',
|
|
90
|
+
supports: ['ssr', 'ssg', 'csr', 'isr', 'ppr', 'api'],
|
|
28
91
|
build(ctx) {
|
|
29
92
|
validateBuildContext(ctx, 'netlifyAdapter');
|
|
30
93
|
const functionsDir = options.functionsDir ?? `${ctx.outDir}/netlify/functions`;
|
|
94
|
+
// Netlify.toml for the deploy directory
|
|
95
|
+
const netlifyToml = '[build]\n publish = "publish"\n functions = "functions"\n\n' +
|
|
96
|
+
'[[headers]]\n for = "/client/*"\n [headers.values]\n' +
|
|
97
|
+
' Cache-Control = "public, max-age=31536000, immutable"\n';
|
|
98
|
+
// Project-root netlify.toml pointing at the build output
|
|
99
|
+
const projectNetlifyToml = '[build]\n' +
|
|
100
|
+
' command = "npx --no-install ruvyxa build"\n' +
|
|
101
|
+
` publish = "${ctx.outDir}/deploy/netlify/publish"\n` +
|
|
102
|
+
` functions = "${ctx.outDir}/deploy/netlify/functions"\n\n` +
|
|
103
|
+
'[[headers]]\n for = "/client/*"\n [headers.values]\n' +
|
|
104
|
+
' Cache-Control = "public, max-age=31536000, immutable"\n';
|
|
31
105
|
return {
|
|
32
106
|
name: 'netlify',
|
|
33
107
|
target: 'serverless',
|
|
@@ -38,12 +112,31 @@ export function netlifyAdapter(options = {}) {
|
|
|
38
112
|
functionsDir,
|
|
39
113
|
configFiles: ['netlify.toml'],
|
|
40
114
|
artifacts: [
|
|
115
|
+
// Static assets (pre-rendered pages + client bundles)
|
|
41
116
|
{ kind: 'static-site', path: 'deploy/netlify/publish' },
|
|
117
|
+
// Serverless function bundle
|
|
118
|
+
{
|
|
119
|
+
kind: 'function',
|
|
120
|
+
path: 'deploy/netlify/functions/ruvyxa-handler',
|
|
121
|
+
handlerSource: netlifyHandlerSource(),
|
|
122
|
+
},
|
|
123
|
+
// Netlify config for the deploy directory
|
|
42
124
|
{
|
|
43
125
|
kind: 'file',
|
|
44
126
|
path: 'deploy/netlify/netlify.toml',
|
|
45
|
-
contents:
|
|
127
|
+
contents: netlifyToml,
|
|
46
128
|
},
|
|
129
|
+
...(options.projectConfig === false
|
|
130
|
+
? []
|
|
131
|
+
: [
|
|
132
|
+
{
|
|
133
|
+
kind: 'file',
|
|
134
|
+
path: 'netlify.toml',
|
|
135
|
+
scope: 'project',
|
|
136
|
+
skipIfExists: true,
|
|
137
|
+
contents: projectNetlifyToml,
|
|
138
|
+
},
|
|
139
|
+
]),
|
|
47
140
|
],
|
|
48
141
|
};
|
|
49
142
|
},
|
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":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAkBtE;;;;;;GAMG;AACH,SAAS,oBAAoB;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDR,CAAA;AACD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAO,GAA0B,EAAE;IAChE,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CACb,kEAAkE,OAAO,OAAO,CAAC,YAAY,EAAE,CAChG,CAAA;IACH,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAA;IACzF,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;QACpD,KAAK,CAAC,GAAiB;YACrB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAA;YAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,GAAG,GAAG,CAAC,MAAM,oBAAoB,CAAA;YAE9E,wCAAwC;YACxC,MAAM,WAAW,GACf,+DAA+D;gBAC/D,wDAAwD;gBACxD,6DAA6D,CAAA;YAE/D,yDAAyD;YACzD,MAAM,kBAAkB,GACtB,WAAW;gBACX,+CAA+C;gBAC/C,gBAAgB,GAAG,CAAC,MAAM,4BAA4B;gBACtD,kBAAkB,GAAG,CAAC,MAAM,gCAAgC;gBAC5D,wDAAwD;gBACxD,6DAA6D,CAAA;YAE/D,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,SAAS;gBACnB,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,aAAa;gBACjC,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,SAAS;gBACjC,GAAG,iBAAiB,CAAC,GAAG,CAAC;gBACzB,YAAY;gBACZ,WAAW,EAAE,CAAC,cAAc,CAAC;gBAC7B,SAAS,EAAE;oBACT,sDAAsD;oBACtD,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,wBAAwB,EAAE;oBACvD,6BAA6B;oBAC7B;wBACE,IAAI,EAAE,UAAU;wBAChB,IAAI,EAAE,yCAAyC;wBAC/C,aAAa,EAAE,oBAAoB,EAAE;qBACtC;oBACD,0CAA0C;oBAC1C;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,6BAA6B;wBACnC,QAAQ,EAAE,WAAW;qBACtB;oBACD,GAAG,CAAC,OAAO,CAAC,aAAa,KAAK,KAAK;wBACjC,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC;4BACE;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,cAAc;gCACpB,KAAK,EAAE,SAAS;gCAChB,YAAY,EAAE,IAAI;gCAClB,QAAQ,EAAE,kBAAkB;6BACH;yBAC5B,CAAC;iBACP;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,eAAe,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvyxa/adapter-netlify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
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.17"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.json",
|