@stopnetic/js 0.0.6-pilot → 0.1.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.
- package/README.md +48 -48
- package/dist/client-guide.md +6 -3
- package/dist/server.d.ts +17 -17
- package/dist/server.js +125 -123
- package/dist/setup.js +126 -125
- package/examples/frontend/angular/app/app.config.ts +8 -8
- package/examples/frontend/angular/app/app.routes.ts +20 -20
- package/examples/frontend/angular/app/app.ts +21 -21
- package/examples/frontend/angular/app/members.page.ts +21 -21
- package/examples/frontend/angular/app/stopnetic-access.service.ts +27 -27
- package/examples/frontend/angular/main.ts +4 -4
- package/examples/frontend/load-private-data.d.ts +1 -1
- package/examples/frontend/load-private-data.js +9 -9
- package/examples/frontend/react/App.tsx +48 -48
- package/examples/frontend/react/main.tsx +3 -3
- package/examples/frontend/solid/App.tsx +54 -54
- package/examples/frontend/solid/main.tsx +3 -3
- package/examples/frontend/svelte/App.svelte +56 -56
- package/examples/frontend/svelte/main.js +4 -4
- package/examples/frontend/vanilla/main.js +46 -46
- package/examples/frontend/vue/App.vue +17 -17
- package/examples/frontend/vue/Members.vue +14 -14
- package/examples/frontend/vue/main.js +4 -4
- package/examples/frontend/vue/router.js +40 -40
- package/examples/ssr/angular/app.routes.server.ts +5 -5
- package/examples/ssr/angular/server.ts +12 -12
- package/examples/ssr/astro/middleware.js +11 -11
- package/examples/ssr/astro/page.astro +4 -4
- package/examples/ssr/node/fetch.mjs +9 -9
- package/examples/ssr/node/install.mjs +9 -9
- package/examples/ssr/nuxt/middleware.mjs +10 -10
- package/examples/ssr/react/install.mjs +10 -10
- package/examples/ssr/react-router/install.mjs +22 -22
- package/examples/ssr/solidstart/middleware-v1.js +19 -19
- package/examples/ssr/solidstart/middleware-v2.js +25 -25
- package/examples/ssr/sveltekit/hooks.server.js +16 -16
- package/examples/ssr/sveltekit/page.server.js +3 -3
- package/examples/ssr/vue/install.mjs +10 -10
- package/package.json +35 -9
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Existing custom React SSR server: call before assets, APIs and React rendering.
|
|
2
|
-
// Keep renderToPipeableStream/renderToReadableStream and hydration unchanged.
|
|
3
|
-
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
-
export function installStopneticReactSSR(app) {
|
|
5
|
-
let server;
|
|
6
|
-
app.use((req, res, next) => {
|
|
7
|
-
server ??= createStopneticServer();
|
|
8
|
-
return server.access(req, res, () => server.guard(req, res, next));
|
|
9
|
-
});
|
|
10
|
-
}
|
|
1
|
+
// Existing custom React SSR server: call before assets, APIs and React rendering.
|
|
2
|
+
// Keep renderToPipeableStream/renderToReadableStream and hydration unchanged.
|
|
3
|
+
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
+
export function installStopneticReactSSR(app) {
|
|
5
|
+
let server;
|
|
6
|
+
app.use((req, res, next) => {
|
|
7
|
+
server ??= createStopneticServer();
|
|
8
|
+
return server.access(req, res, () => server.guard(req, res, next));
|
|
9
|
+
});
|
|
10
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
// Call installStopneticReactRouter(app) before parsers, assets and the existing
|
|
2
|
-
// @react-router/express createRequestHandler. Keep that handler/context intact.
|
|
3
|
-
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
-
|
|
5
|
-
export function installStopneticReactRouter(app) {
|
|
6
|
-
let server;
|
|
7
|
-
app.use((req, res, next) => {
|
|
8
|
-
server ??= createStopneticServer();
|
|
9
|
-
return server.access(req, res, () => {
|
|
10
|
-
// React Router 7 single-fetch data URLs must use the page's policy.
|
|
11
|
-
// The renderer still receives the original request and unread body.
|
|
12
|
-
const url = new URL(req.originalUrl || req.url, 'https://example.invalid');
|
|
13
|
-
let checked = req;
|
|
14
|
-
if (url.pathname.endsWith('.data')) {
|
|
15
|
-
url.pathname = url.pathname === '/_root.data' ? '/' : url.pathname.slice(0, -5);
|
|
16
|
-
checked = Object.create(req);
|
|
17
|
-
checked.originalUrl = url.pathname + url.search;
|
|
18
|
-
}
|
|
19
|
-
return server.guard(checked, res, next);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
1
|
+
// Call installStopneticReactRouter(app) before parsers, assets and the existing
|
|
2
|
+
// @react-router/express createRequestHandler. Keep that handler/context intact.
|
|
3
|
+
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
+
|
|
5
|
+
export function installStopneticReactRouter(app) {
|
|
6
|
+
let server;
|
|
7
|
+
app.use((req, res, next) => {
|
|
8
|
+
server ??= createStopneticServer();
|
|
9
|
+
return server.access(req, res, () => {
|
|
10
|
+
// React Router 7 single-fetch data URLs must use the page's policy.
|
|
11
|
+
// The renderer still receives the original request and unread body.
|
|
12
|
+
const url = new URL(req.originalUrl || req.url, 'https://example.invalid');
|
|
13
|
+
let checked = req;
|
|
14
|
+
if (url.pathname.endsWith('.data')) {
|
|
15
|
+
url.pathname = url.pathname === '/_root.data' ? '/' : url.pathname.slice(0, -5);
|
|
16
|
+
checked = Object.create(req);
|
|
17
|
+
checked.originalUrl = url.pathname + url.search;
|
|
18
|
+
}
|
|
19
|
+
return server.guard(checked, res, next);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
// SolidStart 1: register using defineConfig({ middleware: './src/middleware.js' }).
|
|
2
|
-
// Keep the existing entry-server.tsx renderer. This is NOT SolidStart 2 config.
|
|
3
|
-
import { createMiddleware } from '@solidjs/start/middleware';
|
|
4
|
-
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
5
|
-
|
|
6
|
-
let check;
|
|
7
|
-
export default createMiddleware({
|
|
8
|
-
onRequest: async event => {
|
|
9
|
-
check ??= createStopneticAppHandler((_request, state) => {
|
|
10
|
-
state.allowed = true;
|
|
11
|
-
return new Response(null, { status: 204 });
|
|
12
|
-
});
|
|
13
|
-
const state = { allowed: false };
|
|
14
|
-
const response = await check(event.request, state);
|
|
15
|
-
if (!state.allowed) return response;
|
|
16
|
-
event.response.headers.set('cache-control', 'private, no-store');
|
|
17
|
-
// undefined continues to SolidStart; preserve its rendering and API handling.
|
|
18
|
-
},
|
|
19
|
-
});
|
|
1
|
+
// SolidStart 1: register using defineConfig({ middleware: './src/middleware.js' }).
|
|
2
|
+
// Keep the existing entry-server.tsx renderer. This is NOT SolidStart 2 config.
|
|
3
|
+
import { createMiddleware } from '@solidjs/start/middleware';
|
|
4
|
+
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
5
|
+
|
|
6
|
+
let check;
|
|
7
|
+
export default createMiddleware({
|
|
8
|
+
onRequest: async event => {
|
|
9
|
+
check ??= createStopneticAppHandler((_request, state) => {
|
|
10
|
+
state.allowed = true;
|
|
11
|
+
return new Response(null, { status: 204 });
|
|
12
|
+
});
|
|
13
|
+
const state = { allowed: false };
|
|
14
|
+
const response = await check(event.request, state);
|
|
15
|
+
if (!state.allowed) return response;
|
|
16
|
+
event.response.headers.set('cache-control', 'private, no-store');
|
|
17
|
+
// undefined continues to SolidStart; preserve its rendering and API handling.
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
// SolidStart 2: register this module using solidStart({ middleware: ... }).
|
|
2
|
-
import { createMiddleware } from '@solidjs/start/middleware';
|
|
3
|
-
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
4
|
-
|
|
5
|
-
let check;
|
|
6
|
-
export default createMiddleware([
|
|
7
|
-
async (event, next) => {
|
|
8
|
-
check ??= createStopneticAppHandler((_request, state) => {
|
|
9
|
-
state.allowed = true;
|
|
10
|
-
return new Response(null, { status: 204 });
|
|
11
|
-
});
|
|
12
|
-
// Per-request state: a verification 204 must NEVER be mistaken for permission.
|
|
13
|
-
const state = { allowed: false };
|
|
14
|
-
const response = await check(event.req, state);
|
|
15
|
-
if (!state.allowed) return response;
|
|
16
|
-
event.res.headers.set('cache-control', 'private, no-store');
|
|
17
|
-
const result = await next(); // Preserve H3/SolidStart context and raw results.
|
|
18
|
-
if (!(result instanceof Response)) return result;
|
|
19
|
-
const headers = new Headers(result.headers);
|
|
20
|
-
headers.set('cache-control', 'private, no-store');
|
|
21
|
-
return new Response(result.body, {
|
|
22
|
-
status: result.status, statusText: result.statusText, headers,
|
|
23
|
-
});
|
|
24
|
-
},
|
|
25
|
-
]);
|
|
1
|
+
// SolidStart 2: register this module using solidStart({ middleware: ... }).
|
|
2
|
+
import { createMiddleware } from '@solidjs/start/middleware';
|
|
3
|
+
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
4
|
+
|
|
5
|
+
let check;
|
|
6
|
+
export default createMiddleware([
|
|
7
|
+
async (event, next) => {
|
|
8
|
+
check ??= createStopneticAppHandler((_request, state) => {
|
|
9
|
+
state.allowed = true;
|
|
10
|
+
return new Response(null, { status: 204 });
|
|
11
|
+
});
|
|
12
|
+
// Per-request state: a verification 204 must NEVER be mistaken for permission.
|
|
13
|
+
const state = { allowed: false };
|
|
14
|
+
const response = await check(event.req, state);
|
|
15
|
+
if (!state.allowed) return response;
|
|
16
|
+
event.res.headers.set('cache-control', 'private, no-store');
|
|
17
|
+
const result = await next(); // Preserve H3/SolidStart context and raw results.
|
|
18
|
+
if (!(result instanceof Response)) return result;
|
|
19
|
+
const headers = new Headers(result.headers);
|
|
20
|
+
headers.set('cache-control', 'private, no-store');
|
|
21
|
+
return new Response(result.body, {
|
|
22
|
+
status: result.status, statusText: result.statusText, headers,
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { building } from '$app/environment';
|
|
2
|
-
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
3
|
-
|
|
4
|
-
let guarded;
|
|
5
|
-
// When merging existing hooks, run this first and put them in the continuation.
|
|
6
|
-
export async function handle({ event, resolve }) {
|
|
7
|
-
// Build-time public prerendering only. Protected routes must have prerender=false.
|
|
8
|
-
if (building) return resolve(event);
|
|
9
|
-
guarded ??= createStopneticAppHandler((_request, run) => run());
|
|
10
|
-
// SvelteKit exposes the canonical page URL on data requests. Check that page
|
|
11
|
-
// rather than allowing an unmatched /members/__data.json alias through.
|
|
12
|
-
const checked = event.isDataRequest
|
|
13
|
-
? new Request(event.url, { method: event.request.method, headers: event.request.headers })
|
|
14
|
-
: event.request;
|
|
15
|
-
return guarded(checked, () => resolve(event));
|
|
16
|
-
}
|
|
1
|
+
import { building } from '$app/environment';
|
|
2
|
+
import { createStopneticAppHandler } from '@stopnetic/js/server';
|
|
3
|
+
|
|
4
|
+
let guarded;
|
|
5
|
+
// When merging existing hooks, run this first and put them in the continuation.
|
|
6
|
+
export async function handle({ event, resolve }) {
|
|
7
|
+
// Build-time public prerendering only. Protected routes must have prerender=false.
|
|
8
|
+
if (building) return resolve(event);
|
|
9
|
+
guarded ??= createStopneticAppHandler((_request, run) => run());
|
|
10
|
+
// SvelteKit exposes the canonical page URL on data requests. Check that page
|
|
11
|
+
// rather than allowing an unmatched /members/__data.json alias through.
|
|
12
|
+
const checked = event.isDataRequest
|
|
13
|
+
? new Request(event.url, { method: event.request.method, headers: event.request.headers })
|
|
14
|
+
: event.request;
|
|
15
|
+
return guarded(checked, () => resolve(event));
|
|
16
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
// Merge into the PROTECTED route's +page.server.js, retaining loads/actions.
|
|
2
|
-
export const prerender = false;
|
|
3
|
-
export const ssr = true;
|
|
1
|
+
// Merge into the PROTECTED route's +page.server.js, retaining loads/actions.
|
|
2
|
+
export const prerender = false;
|
|
3
|
+
export const ssr = true;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Existing custom Vue SSR server: call before assets, APIs and Vue rendering.
|
|
2
|
-
// Keep createSSRApp/renderToString and client hydration unchanged.
|
|
3
|
-
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
-
export function installStopneticVueSSR(app) {
|
|
5
|
-
let server;
|
|
6
|
-
app.use((req, res, next) => {
|
|
7
|
-
server ??= createStopneticServer();
|
|
8
|
-
return server.access(req, res, () => server.guard(req, res, next));
|
|
9
|
-
});
|
|
10
|
-
}
|
|
1
|
+
// Existing custom Vue SSR server: call before assets, APIs and Vue rendering.
|
|
2
|
+
// Keep createSSRApp/renderToString and client hydration unchanged.
|
|
3
|
+
import { createStopneticServer } from '@stopnetic/js/server';
|
|
4
|
+
export function installStopneticVueSSR(app) {
|
|
5
|
+
let server;
|
|
6
|
+
app.use((req, res, next) => {
|
|
7
|
+
server ??= createStopneticServer();
|
|
8
|
+
return server.access(req, res, () => server.guard(req, res, next));
|
|
9
|
+
});
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stopnetic/js",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Server-side Stopnetic guard for JavaScript websites, Node.js and Express-compatible servers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Stopnetic",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/KlimentSidorov/
|
|
10
|
+
"url": "git+https://github.com/KlimentSidorov/stopnetic.git",
|
|
11
11
|
"directory": "integrations/javascript"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"stopnetic",
|
|
15
15
|
"javascript",
|
|
16
|
+
"typescript",
|
|
16
17
|
"nodejs",
|
|
17
18
|
"express",
|
|
19
|
+
"react",
|
|
20
|
+
"angular",
|
|
21
|
+
"vue",
|
|
22
|
+
"svelte",
|
|
18
23
|
"access-control"
|
|
19
24
|
],
|
|
20
25
|
"files": [
|
|
@@ -23,24 +28,41 @@
|
|
|
23
28
|
"examples/frontend",
|
|
24
29
|
"examples/ssr"
|
|
25
30
|
],
|
|
26
|
-
"bin": {
|
|
31
|
+
"bin": {
|
|
32
|
+
"stopnetic-js": "./bin/stopnetic-js.js"
|
|
33
|
+
},
|
|
27
34
|
"exports": {
|
|
28
35
|
".": {
|
|
29
36
|
"types": "./dist/index.d.ts",
|
|
30
37
|
"default": "./dist/index.js"
|
|
31
38
|
},
|
|
32
|
-
"./server": {
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
"./server": {
|
|
40
|
+
"types": "./dist/server.d.ts",
|
|
41
|
+
"default": "./dist/server.js"
|
|
42
|
+
},
|
|
43
|
+
"./browser": {
|
|
44
|
+
"types": "./dist/browser.d.ts",
|
|
45
|
+
"default": "./dist/browser.js"
|
|
46
|
+
},
|
|
47
|
+
"./react": {
|
|
48
|
+
"types": "./dist/react.d.ts",
|
|
49
|
+
"default": "./dist/react.js"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"react": "*"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"react": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
35
59
|
},
|
|
36
|
-
"peerDependencies": { "react": "*" },
|
|
37
|
-
"peerDependenciesMeta": { "react": { "optional": true } },
|
|
38
60
|
"engines": {
|
|
39
61
|
"node": ">=22"
|
|
40
62
|
},
|
|
41
63
|
"publishConfig": {
|
|
42
64
|
"access": "public",
|
|
43
|
-
"tag": "
|
|
65
|
+
"tag": "latest",
|
|
44
66
|
"registry": "https://registry.npmjs.org/"
|
|
45
67
|
},
|
|
46
68
|
"scripts": {
|
|
@@ -52,5 +74,9 @@
|
|
|
52
74
|
"devDependencies": {
|
|
53
75
|
"express": "^4.22.3",
|
|
54
76
|
"express5": "npm:express@^5.2.1"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/KlimentSidorov/stopnetic/tree/main/integrations/javascript#readme",
|
|
79
|
+
"bugs": {
|
|
80
|
+
"url": "https://github.com/KlimentSidorov/stopnetic/issues"
|
|
55
81
|
}
|
|
56
82
|
}
|