@varlabs/create-solidstep 0.1.5 → 0.1.7
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/generate/app/layout.tsx +2 -2
- package/generate/app/middleware.ts +16 -5
- package/generate/app/page.tsx +1 -1
- package/generate/app.config.ts +2 -68
- package/generate/package.json +3 -4
- package/package.json +1 -1
- package/generate/client.ts +0 -105
- package/generate/server.ts +0 -784
- package/generate/utils/cache.ts +0 -106
- package/generate/utils/cookies.ts +0 -25
- package/generate/utils/cors.ts +0 -16
- package/generate/utils/csp.ts +0 -27
- package/generate/utils/csrf.ts +0 -62
- package/generate/utils/loader.ts +0 -35
- package/generate/utils/redirect.ts +0 -16
- package/generate/utils/router.ts +0 -272
- package/generate/utils/server-only.ts +0 -5
- package/generate/utils/types.ts +0 -8
package/generate/app/layout.tsx
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import { defineMiddleware } from 'vinxi/http';
|
|
2
|
-
import {
|
|
3
|
-
import { cors } from '
|
|
4
|
-
import { csrf } from '
|
|
2
|
+
import { createBasePolicy, serializePolicy, withNonce } from 'solidstep/utils/csp';
|
|
3
|
+
import { cors } from 'solidstep/utils/cors';
|
|
4
|
+
import { csrf } from 'solidstep/utils/csrf';
|
|
5
|
+
import { randomBytes } from 'node:crypto';
|
|
5
6
|
|
|
6
7
|
const trustedOrigins = ['https://example.com', 'https://another-example.com'];
|
|
7
8
|
|
|
8
9
|
const corsMiddleware = cors(trustedOrigins);
|
|
9
10
|
const csrfMiddleware = csrf(trustedOrigins);
|
|
11
|
+
let cspPolicy = createBasePolicy();
|
|
10
12
|
|
|
11
13
|
const middleware = defineMiddleware({
|
|
12
14
|
onRequest: async (event) => {
|
|
13
|
-
|
|
15
|
+
const nonce = randomBytes(16).toString('base64');
|
|
16
|
+
|
|
17
|
+
(event as any).locals = {
|
|
18
|
+
cspNonce: nonce,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
cspPolicy = withNonce(cspPolicy, nonce);
|
|
22
|
+
|
|
23
|
+
event.node.res.setHeader('Content-Security-Policy', serializePolicy(cspPolicy));
|
|
14
24
|
event.node.res.setHeader('Vary', 'Origin, Access-Control-Request-Method');
|
|
15
25
|
|
|
16
26
|
const origin = event.node.req.headers.origin || '';
|
|
17
|
-
const
|
|
27
|
+
const protocol = origin.startsWith('https') ? 'https' : 'http';
|
|
28
|
+
const requestUrl = new URL(event.node.req.url, `${protocol}://${event.node.req.headers.host || 'localhost'}`);
|
|
18
29
|
|
|
19
30
|
const csrfResult = csrfMiddleware(
|
|
20
31
|
event.node.req.method,
|
package/generate/app/page.tsx
CHANGED
package/generate/app.config.ts
CHANGED
|
@@ -1,69 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import solid from 'vite-plugin-solid';
|
|
3
|
-
import { serverFunctions } from '@vinxi/server-functions/plugin';
|
|
4
|
-
import { ServerRouter, ClientRouter } from './utils/router';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { dirname } from 'node:path';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
1
|
+
import { defineConfig } from 'solidstep';
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export default createApp({
|
|
12
|
-
server: {
|
|
13
|
-
experimental: {
|
|
14
|
-
asyncContext: true,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
routers: [
|
|
18
|
-
{
|
|
19
|
-
name: 'public',
|
|
20
|
-
type: 'static',
|
|
21
|
-
dir: './public',
|
|
22
|
-
base: '/',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: 'client',
|
|
26
|
-
type: 'client',
|
|
27
|
-
target: 'browser',
|
|
28
|
-
handler: './client.ts',
|
|
29
|
-
plugins: () => [serverFunctions.client(), solid({ ssr: true })],
|
|
30
|
-
base: '/_build',
|
|
31
|
-
routes: (router, app) => {
|
|
32
|
-
return new ClientRouter(
|
|
33
|
-
{
|
|
34
|
-
dir: path.join(__dirname, 'app'),
|
|
35
|
-
extensions: ['jsx', 'js', 'tsx', 'ts'],
|
|
36
|
-
},
|
|
37
|
-
router,
|
|
38
|
-
app
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'ssr',
|
|
44
|
-
type: 'http',
|
|
45
|
-
base: '/',
|
|
46
|
-
handler: './server.ts',
|
|
47
|
-
target: 'server',
|
|
48
|
-
plugins: () => [
|
|
49
|
-
serverFunctions.server(),
|
|
50
|
-
solid({ ssr: true })
|
|
51
|
-
],
|
|
52
|
-
// link: {
|
|
53
|
-
// client: 'client',
|
|
54
|
-
// },
|
|
55
|
-
middleware: './app/middleware.ts',
|
|
56
|
-
routes: (router, app) => {
|
|
57
|
-
return new ServerRouter(
|
|
58
|
-
{
|
|
59
|
-
dir: path.join(__dirname, 'app'),
|
|
60
|
-
extensions: ['jsx', 'js', 'tsx', 'ts'],
|
|
61
|
-
},
|
|
62
|
-
router,
|
|
63
|
-
app
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
// serverFunctions.router(),
|
|
68
|
-
],
|
|
69
|
-
});
|
|
3
|
+
export default defineConfig({});
|
package/generate/package.json
CHANGED
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
"keywords": [],
|
|
12
12
|
"author": "",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
14
|
+
"solid-js": "^1.9.9",
|
|
15
|
+
"solidstep": "^0.1.1",
|
|
16
16
|
"vinxi": "^0.5.8"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"typescript": "^5.8.3"
|
|
20
|
-
"vite-plugin-solid": "^2.11.7"
|
|
19
|
+
"typescript": "^5.8.3"
|
|
21
20
|
}
|
|
22
21
|
}
|
package/package.json
CHANGED
package/generate/client.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { hydrate } from 'solid-js/web';
|
|
2
|
-
import 'vinxi/client';
|
|
3
|
-
import fileRoutes from 'vinxi/routes';
|
|
4
|
-
import { getManifest } from 'vinxi/manifest';
|
|
5
|
-
|
|
6
|
-
const importModule = async (routeModule: any) => {
|
|
7
|
-
const manifest = getManifest('client');
|
|
8
|
-
if ((import.meta as any).env.DEV) {
|
|
9
|
-
return await manifest.inputs[routeModule.src].import();
|
|
10
|
-
}
|
|
11
|
-
return await routeModule.import();
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const main = async (
|
|
15
|
-
modulePath: string,
|
|
16
|
-
routeParams: Record<string, string> = {},
|
|
17
|
-
searchParams: Record<string, string> = {},
|
|
18
|
-
loaderDataManifest: Record<string, any> = {}
|
|
19
|
-
) => {
|
|
20
|
-
// find the route that matches the path
|
|
21
|
-
const pageModule = fileRoutes.find((route) => route.path === modulePath);
|
|
22
|
-
if (!pageModule) {
|
|
23
|
-
console.error(`No route found for path: ${modulePath}`);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const pageLoaderData = loaderDataManifest[modulePath];
|
|
27
|
-
|
|
28
|
-
const segments = modulePath.split('/').slice(2);
|
|
29
|
-
if (segments.at(0)) {
|
|
30
|
-
segments.unshift('');
|
|
31
|
-
}
|
|
32
|
-
const layouts: any[] = [];
|
|
33
|
-
const layoutLoaderData: any[] = [];
|
|
34
|
-
const groups: Record<string, any> = {};
|
|
35
|
-
for (let i = 0; i < segments.length; i++) {
|
|
36
|
-
const path = '/' + segments.slice(1, segments.length - i).join('/');
|
|
37
|
-
const loaderData = loaderDataManifest[`/layout${path}`];
|
|
38
|
-
const layoutModule = fileRoutes.find((route) => {
|
|
39
|
-
const routePath = '/' + route.path.split('/').slice(2).join('/');
|
|
40
|
-
return routePath === path && (route as any).type === 'layout';
|
|
41
|
-
});
|
|
42
|
-
if (layoutModule) {
|
|
43
|
-
layouts.unshift(layoutModule);
|
|
44
|
-
}
|
|
45
|
-
if (loaderData) {
|
|
46
|
-
layoutLoaderData.unshift(loaderData);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const groupModules = fileRoutes.filter((route) => {
|
|
50
|
-
const parentPath = (route as any).parent || '';
|
|
51
|
-
return parentPath === segments.join('/') && (route as any).type === 'group';
|
|
52
|
-
});
|
|
53
|
-
if (groupModules && groupModules.length > 0) {
|
|
54
|
-
for (const groupModule of groupModules) {
|
|
55
|
-
const groupName = groupModule.path.split('/').at(-1).replace('@', '');
|
|
56
|
-
groups[groupName] = groupModule;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const compose = layouts.reduceRight(
|
|
60
|
-
(children, layout, index) => async () => {
|
|
61
|
-
const { default: layoutModule } = await importModule(layout.$component);
|
|
62
|
-
const loaderData = layoutLoaderData[index] || {};
|
|
63
|
-
const slots: Record<string, any> = {};
|
|
64
|
-
const slotPromises: Promise<any>[] = [children()];
|
|
65
|
-
if (index === layouts.length - 1) {
|
|
66
|
-
// last layout, we can render slots
|
|
67
|
-
for (const [groupName, group] of Object.entries(groups)) {
|
|
68
|
-
slotPromises.push(
|
|
69
|
-
(async () => {
|
|
70
|
-
const { default: groupPage } = await importModule(group.$component);
|
|
71
|
-
const groupLoaderData = loaderDataManifest[group.path] || {};
|
|
72
|
-
slots[groupName] = () => groupPage({
|
|
73
|
-
routeParams,
|
|
74
|
-
searchParams,
|
|
75
|
-
loaderData: groupLoaderData,
|
|
76
|
-
});
|
|
77
|
-
})()
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
const [childrenRendered] = await Promise.all(slotPromises);
|
|
82
|
-
return () => layoutModule({
|
|
83
|
-
children: childrenRendered,
|
|
84
|
-
routeParams,
|
|
85
|
-
searchParams,
|
|
86
|
-
slots: slots,
|
|
87
|
-
loaderData,
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
async () => {
|
|
91
|
-
const { default: page } = await importModule(pageModule.$component);
|
|
92
|
-
return () => page({
|
|
93
|
-
routeParams,
|
|
94
|
-
searchParams,
|
|
95
|
-
loaderData: pageLoaderData || {},
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const composed = await compose();
|
|
101
|
-
|
|
102
|
-
hydrate(() => composed(), document);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export default main;
|