vyriy 0.4.4 → 0.4.6
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 +11 -16
- package/commands/create/plan/plan.d.ts +1 -1
- package/commands/create/preset/index.d.ts +5 -0
- package/commands/create/preset/index.js +6 -0
- package/commands/create/preset/rest.js +337 -7
- package/commands/create/preset/spa.js +41 -41
- package/commands/create/preset/ssg.js +69 -69
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -78,22 +78,17 @@ Prepares every package inside the `dist/` directory for npm publishing:
|
|
|
78
78
|
|
|
79
79
|
Registered presets:
|
|
80
80
|
|
|
81
|
-
| Key | Description
|
|
82
|
-
| --------- |
|
|
83
|
-
| `base` |
|
|
84
|
-
| `library` |
|
|
85
|
-
| `api` |
|
|
86
|
-
| `ssr` |
|
|
87
|
-
| `ssg` | Static site generation
|
|
88
|
-
| `spa` | Single-page application
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
| Key | Direction |
|
|
93
|
-
| ------ | ---------------------- |
|
|
94
|
-
| `rest` | REST API project |
|
|
95
|
-
| `gql` | GraphQL API project |
|
|
96
|
-
| `mfe` | Micro-frontend project |
|
|
81
|
+
| Key | Description |
|
|
82
|
+
| --------- | ------------------------------------------------- |
|
|
83
|
+
| `base` | Preset to create minimal monorepo with configs |
|
|
84
|
+
| `library` | Preset to create js/react library |
|
|
85
|
+
| `api` | Preset to create simple API |
|
|
86
|
+
| `ssr` | Preset to create Server Side Rendering (SSR) API |
|
|
87
|
+
| `ssg` | Preset to create Static site generation (SSG) |
|
|
88
|
+
| `spa` | Preset to create Single-page application (SPA) |
|
|
89
|
+
| `rest` | Preset to create simple REST API |
|
|
90
|
+
| `gql` | Preset to create GraphQL API |
|
|
91
|
+
| `mfe` | Preset to create Micro-frontend (MFE) application |
|
|
97
92
|
|
|
98
93
|
Registered presets are selectable by the wizard. In-progress presets exist as
|
|
99
94
|
source modules and are expected to become selectable as their generated project
|
|
@@ -2,7 +2,7 @@ export declare const plan: (dirName: string, appPath: string) => Promise<{
|
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
4
|
target: string;
|
|
5
|
-
preset: "ssr" | "base" | "api" | "library" | "ssg" | "spa";
|
|
5
|
+
preset: "ssr" | "base" | "rest" | "api" | "library" | "ssg" | "spa";
|
|
6
6
|
scope: string | undefined;
|
|
7
7
|
ci: import("../preset/types.js").CiProvider | undefined;
|
|
8
8
|
deploy: import("../preset/types.js").DeployProvider | undefined;
|
|
@@ -4,6 +4,7 @@ import { api } from './api.js';
|
|
|
4
4
|
import { ssr } from './ssr.js';
|
|
5
5
|
import { ssg } from './ssg.js';
|
|
6
6
|
import { spa } from './spa.js';
|
|
7
|
+
import { rest } from './rest.js';
|
|
7
8
|
export const presets = {
|
|
8
9
|
base: {
|
|
9
10
|
name: 'Base',
|
|
@@ -35,4 +36,9 @@ export const presets = {
|
|
|
35
36
|
description: 'Preset for Single Page Application (SPA)',
|
|
36
37
|
preset: spa,
|
|
37
38
|
},
|
|
39
|
+
rest: {
|
|
40
|
+
name: 'REST',
|
|
41
|
+
description: 'Preset for simple REST API',
|
|
42
|
+
preset: rest,
|
|
43
|
+
},
|
|
38
44
|
};
|
|
@@ -1,16 +1,346 @@
|
|
|
1
|
+
import packageJson from '../../../package.json' with { type: 'json' };
|
|
1
2
|
import { base } from './base.js';
|
|
2
3
|
export const rest = {
|
|
3
4
|
files: (options) => ({
|
|
4
5
|
...base.files(options),
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
'package.json': JSON.stringify({
|
|
7
|
+
name: options.name,
|
|
8
|
+
version: '0.0.0',
|
|
9
|
+
description: options.description,
|
|
10
|
+
private: true,
|
|
11
|
+
type: 'module',
|
|
12
|
+
agents: './AGENTS.md',
|
|
13
|
+
packageManager: packageJson.packageManager,
|
|
14
|
+
engines: {
|
|
15
|
+
node: packageJson.engines.node,
|
|
16
|
+
},
|
|
17
|
+
workspaces: [
|
|
18
|
+
'workspaces/*',
|
|
19
|
+
],
|
|
20
|
+
scripts: {
|
|
21
|
+
storybook: 'cross-env STORYBOOK_DISABLE_TELEMETRY=1 storybook dev -p 6006 --disable-telemetry',
|
|
22
|
+
check: 'run-s lint build test',
|
|
23
|
+
fix: "run-s 'fix:*'",
|
|
24
|
+
start: "run-p 'start:*'",
|
|
25
|
+
lint: "run-s 'lint:*'",
|
|
26
|
+
build: "run-s 'build:*'",
|
|
27
|
+
test: "run-s 'test:*'",
|
|
28
|
+
'fix:prettier': 'prettier . --write',
|
|
29
|
+
'fix:eslint': 'eslint . --fix',
|
|
30
|
+
'start:api': 'sh workspaces/api/bin/start.sh',
|
|
31
|
+
'lint:ts': 'tsc',
|
|
32
|
+
'lint:prettier': 'prettier . --check',
|
|
33
|
+
'lint:eslint': 'eslint .',
|
|
34
|
+
'build:api': 'rimraf dist && sh workspaces/api/bin/build.sh',
|
|
35
|
+
'build:storybook': 'cross-env STORYBOOK_DISABLE_TELEMETRY=1 storybook build --quiet --disable-telemetry',
|
|
36
|
+
'test:jest': 'jest',
|
|
37
|
+
postinstall: 'husky',
|
|
38
|
+
},
|
|
39
|
+
dependencies: {
|
|
40
|
+
'@vyriy/typescript-config': `^${packageJson.version}`,
|
|
41
|
+
typescript: packageJson.peerDependencies.typescript,
|
|
42
|
+
'@vyriy/prettier-config': `^${packageJson.version}`,
|
|
43
|
+
prettier: packageJson.peerDependencies.prettier,
|
|
44
|
+
'@vyriy/eslint-config': `^${packageJson.version}`,
|
|
45
|
+
eslint: packageJson.peerDependencies.eslint,
|
|
46
|
+
'@vyriy/jest-config': `^${packageJson.version}`,
|
|
47
|
+
jest: packageJson.peerDependencies.jest,
|
|
48
|
+
'@vyriy/storybook-config': `^${packageJson.version}`,
|
|
49
|
+
storybook: packageJson.peerDependencies.storybook,
|
|
50
|
+
'@vyriy/path': `^${packageJson.version}`,
|
|
51
|
+
vyriy: `^${packageJson.version}`,
|
|
52
|
+
husky: packageJson.peerDependencies.husky,
|
|
53
|
+
'npm-run-all2': packageJson.peerDependencies['npm-run-all2'],
|
|
54
|
+
'cross-env': packageJson.peerDependencies['cross-env'],
|
|
55
|
+
rimraf: packageJson.peerDependencies.rimraf,
|
|
56
|
+
'@vyriy/webpack-config': `^${packageJson.version}`,
|
|
57
|
+
'@vyriy/handler': `^${packageJson.version}`,
|
|
58
|
+
'@vyriy/server': `^${packageJson.version}`,
|
|
59
|
+
tsx: packageJson.peerDependencies.tsx,
|
|
60
|
+
webpack: packageJson.peerDependencies.webpack,
|
|
61
|
+
'webpack-cli': packageJson.peerDependencies['webpack-cli'],
|
|
62
|
+
'@vyriy/router': `^${packageJson.version}`,
|
|
63
|
+
'@vyriy/html': `^${packageJson.version}`,
|
|
64
|
+
},
|
|
65
|
+
}, null, 2) + '\n',
|
|
66
|
+
'workspaces/api/bin/build.sh': `#!/usr/bin/env sh
|
|
67
|
+
|
|
68
|
+
set -e
|
|
69
|
+
|
|
70
|
+
scriptdir="$PWD/workspaces/api";
|
|
71
|
+
|
|
72
|
+
NODE_ENV=production npx webpack --config $scriptdir/webpack.config.ts
|
|
73
|
+
|
|
74
|
+
cp $scriptdir/package.json dist/api/package.json
|
|
75
|
+
npm pkg delete "type" --prefix dist/api
|
|
76
|
+
npm pkg delete "private" --prefix dist/api
|
|
77
|
+
`,
|
|
78
|
+
'workspaces/api/bin/start.sh': `#!/usr/bin/env sh
|
|
79
|
+
|
|
80
|
+
set -e
|
|
81
|
+
|
|
82
|
+
scriptdir="$PWD/workspaces/api";
|
|
83
|
+
|
|
84
|
+
NODE_ENV=production LOG_LEVEL=info tsx $scriptdir/index.ts
|
|
85
|
+
`,
|
|
86
|
+
'workspaces/api/doc.mdx': `import { Meta, Markdown } from '@storybook/addon-docs/blocks';
|
|
87
|
+
import ReadMe from './README.md?raw';
|
|
88
|
+
|
|
89
|
+
<Meta title="Workspaces/API" />
|
|
90
|
+
|
|
91
|
+
<Markdown>{ReadMe}</Markdown>
|
|
92
|
+
`,
|
|
93
|
+
'workspaces/api/README.md': `# ${options.name} API\n\n${options.description}\n`,
|
|
94
|
+
'workspaces/api/webpack.config.ts': `import { path } from '@vyriy/path';
|
|
95
|
+
import { ssr, external } from '@vyriy/webpack-config';
|
|
96
|
+
|
|
97
|
+
export default ssr(
|
|
98
|
+
'@w/api',
|
|
99
|
+
{
|
|
100
|
+
path: path('dist', 'api'),
|
|
101
|
+
filename: 'index.js',
|
|
102
|
+
library: { type: 'commonjs2' },
|
|
103
|
+
},
|
|
104
|
+
(config) => ({
|
|
105
|
+
...config,
|
|
106
|
+
externals: [external({ allowlist: [/^@p/, /^@w/, /^@vyriy/] })],
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
109
|
+
`,
|
|
110
|
+
'workspaces/api/package.json': JSON.stringify({
|
|
111
|
+
name: '@w/api',
|
|
112
|
+
type: 'module',
|
|
113
|
+
private: true,
|
|
114
|
+
}, null, 2) + '\n',
|
|
115
|
+
'workspaces/api/index.ts': `import { server } from '@vyriy/server';
|
|
116
|
+
import { api } from '@vyriy/handler';
|
|
117
|
+
import { createRouter } from '@vyriy/router';
|
|
118
|
+
import { html, minify } from '@vyriy/html';
|
|
119
|
+
|
|
120
|
+
const router = createRouter();
|
|
121
|
+
|
|
122
|
+
router.get('/api/test', async () => {
|
|
123
|
+
return Promise.resolve({
|
|
124
|
+
headers: {
|
|
125
|
+
'content-type': 'application/json',
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify({ test: 'ok' }),
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
router.get('/openapi.json', async () => {
|
|
132
|
+
return Promise.resolve({
|
|
133
|
+
headers: {
|
|
134
|
+
'content-type': 'application/json',
|
|
135
|
+
},
|
|
136
|
+
body: JSON.stringify({
|
|
137
|
+
openapi: '3.0.0',
|
|
138
|
+
info: {
|
|
139
|
+
title: 'REST API',
|
|
140
|
+
description: 'A minimal example of an OpenAPI definition in JSON format.',
|
|
141
|
+
version: '1.0.0',
|
|
142
|
+
},
|
|
143
|
+
servers: [
|
|
144
|
+
{
|
|
145
|
+
url: 'http://localhost:3000',
|
|
146
|
+
description: 'Local server',
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
paths: {
|
|
150
|
+
'/api/test': {
|
|
151
|
+
get: {
|
|
152
|
+
summary: 'Test endpoint',
|
|
153
|
+
operationId: 'getTest',
|
|
154
|
+
responses: {
|
|
155
|
+
'200': {
|
|
156
|
+
description: 'A successful test response',
|
|
157
|
+
content: {
|
|
158
|
+
'application/json': {
|
|
159
|
+
schema: {
|
|
160
|
+
$ref: '#/components/schemas/TestResponse',
|
|
161
|
+
},
|
|
162
|
+
example: {
|
|
163
|
+
test: 'ok',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
components: {
|
|
173
|
+
schemas: {
|
|
174
|
+
TestResponse: {
|
|
175
|
+
type: 'object',
|
|
176
|
+
required: ['test'],
|
|
177
|
+
properties: {
|
|
178
|
+
test: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
example: 'ok',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
9
184
|
},
|
|
185
|
+
},
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
router.get('/', async () => {
|
|
191
|
+
return Promise.resolve({
|
|
192
|
+
headers: {
|
|
193
|
+
'content-type': 'text/html; charset=utf-8',
|
|
10
194
|
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
195
|
+
body: minify(
|
|
196
|
+
html({
|
|
197
|
+
title: '<title>REST API</title>',
|
|
198
|
+
meta: '<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
199
|
+
body: [
|
|
200
|
+
'<div id="app"></div>',
|
|
201
|
+
'<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>',
|
|
202
|
+
"<script>Scalar.createApiReference('#app', { url: '/openapi.json' })</script>",
|
|
203
|
+
].join(''),
|
|
204
|
+
}),
|
|
205
|
+
),
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
server(api(async (event) => router.route(event)));
|
|
210
|
+
`,
|
|
211
|
+
'workspaces/api/index.test.ts': `import { describe, expect, it, jest } from '@jest/globals';
|
|
212
|
+
import type { APIGatewayProxyEvent } from '@vyriy/router';
|
|
213
|
+
|
|
214
|
+
const apiMock = jest.fn((handler) => ({
|
|
215
|
+
handler,
|
|
216
|
+
}));
|
|
217
|
+
const serverMock = jest.fn();
|
|
218
|
+
|
|
219
|
+
jest.mock('@vyriy/handler', () => ({
|
|
220
|
+
api: apiMock,
|
|
221
|
+
}));
|
|
222
|
+
|
|
223
|
+
jest.mock('@vyriy/server', () => ({
|
|
224
|
+
server: serverMock,
|
|
225
|
+
}));
|
|
226
|
+
|
|
227
|
+
describe('workspaces/api/index.ts', () => {
|
|
228
|
+
const getEvent = (path: string): APIGatewayProxyEvent =>
|
|
229
|
+
({
|
|
230
|
+
body: null,
|
|
231
|
+
headers: {},
|
|
232
|
+
httpMethod: 'GET',
|
|
233
|
+
path,
|
|
234
|
+
pathParameters: null,
|
|
235
|
+
queryStringParameters: null,
|
|
236
|
+
}) as APIGatewayProxyEvent;
|
|
237
|
+
|
|
238
|
+
it('starts the server with the API router handler', async () => {
|
|
239
|
+
await import('./index.js');
|
|
240
|
+
|
|
241
|
+
expect(apiMock).toHaveBeenCalledTimes(1);
|
|
242
|
+
expect(serverMock).toHaveBeenCalledTimes(1);
|
|
243
|
+
expect(serverMock).toHaveBeenCalledWith(apiMock.mock.results[0]?.value);
|
|
244
|
+
|
|
245
|
+
const handler = apiMock.mock.calls[0]?.[0] as (event: APIGatewayProxyEvent) => Promise<{
|
|
246
|
+
body: string;
|
|
247
|
+
headers?: Record<string, string>;
|
|
248
|
+
statusCode: number;
|
|
249
|
+
}>;
|
|
250
|
+
|
|
251
|
+
await expect(handler(getEvent('/api/test'))).resolves.toEqual({
|
|
252
|
+
body: JSON.stringify({
|
|
253
|
+
test: 'ok',
|
|
254
|
+
}),
|
|
255
|
+
headers: {
|
|
256
|
+
'content-type': 'application/json',
|
|
257
|
+
},
|
|
258
|
+
statusCode: 200,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const openApiResponse = await handler(getEvent('/openapi.json'));
|
|
262
|
+
|
|
263
|
+
expect(openApiResponse).toEqual({
|
|
264
|
+
body: expect.any(String),
|
|
265
|
+
headers: {
|
|
266
|
+
'content-type': 'application/json',
|
|
267
|
+
},
|
|
268
|
+
statusCode: 200,
|
|
269
|
+
});
|
|
270
|
+
expect(JSON.parse(openApiResponse.body)).toEqual({
|
|
271
|
+
components: {
|
|
272
|
+
schemas: {
|
|
273
|
+
TestResponse: {
|
|
274
|
+
properties: {
|
|
275
|
+
test: {
|
|
276
|
+
example: 'ok',
|
|
277
|
+
type: 'string',
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
required: ['test'],
|
|
281
|
+
type: 'object',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
info: {
|
|
286
|
+
description: 'A minimal example of an OpenAPI definition in JSON format.',
|
|
287
|
+
title: 'REST API',
|
|
288
|
+
version: '1.0.0',
|
|
289
|
+
},
|
|
290
|
+
openapi: '3.0.0',
|
|
291
|
+
paths: {
|
|
292
|
+
'/api/test': {
|
|
293
|
+
get: {
|
|
294
|
+
operationId: 'getTest',
|
|
295
|
+
responses: {
|
|
296
|
+
'200': {
|
|
297
|
+
content: {
|
|
298
|
+
'application/json': {
|
|
299
|
+
example: {
|
|
300
|
+
test: 'ok',
|
|
301
|
+
},
|
|
302
|
+
schema: {
|
|
303
|
+
$ref: '#/components/schemas/TestResponse',
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
description: 'A successful test response',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
summary: 'Test endpoint',
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
servers: [
|
|
315
|
+
{
|
|
316
|
+
description: 'Local server',
|
|
317
|
+
url: 'http://localhost:3000',
|
|
14
318
|
},
|
|
319
|
+
],
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const docsResponse = await handler(getEvent('/'));
|
|
323
|
+
|
|
324
|
+
expect(docsResponse).toEqual({
|
|
325
|
+
body: expect.stringContaining("Scalar.createApiReference('#app', { url: '/openapi.json' })"),
|
|
326
|
+
headers: {
|
|
327
|
+
'content-type': 'text/html; charset=utf-8',
|
|
328
|
+
},
|
|
329
|
+
statusCode: 200,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
await expect(handler(getEvent('/healthcheck'))).resolves.toEqual({
|
|
333
|
+
body: JSON.stringify({
|
|
334
|
+
message: 'Not Found',
|
|
335
|
+
}),
|
|
336
|
+
statusCode: 404,
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
`,
|
|
341
|
+
}),
|
|
342
|
+
ci: {
|
|
343
|
+
...base.ci,
|
|
15
344
|
},
|
|
345
|
+
deploy: {},
|
|
16
346
|
};
|
|
@@ -93,56 +93,56 @@ extends @vyriy/browserslist-config
|
|
|
93
93
|
'packages/components/index.ts': "export * from './page/index.js';\n",
|
|
94
94
|
'packages/components/index.test.tsx': `import { describe, expect, it } from '@jest/globals';
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
import { Page } from './index.js';
|
|
97
|
+
import { Page as PageImplementation } from './page/index.js';
|
|
98
|
+
|
|
99
|
+
describe('packages/components/page', () => {
|
|
100
|
+
it('re-exports the page component', () => {
|
|
101
|
+
expect(Page).toBe(PageImplementation);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
`,
|
|
105
105
|
'packages/components/page/index.ts': `export * from './page.js';
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
export type * from './types.js';
|
|
107
|
+
`,
|
|
108
108
|
'packages/components/page/index.test.ts': `import { describe, expect, it } from '@jest/globals';
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
import { Page } from './index.js';
|
|
111
|
+
import { Page as PageImplementation } from './page.js';
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
describe('packages/components/page', () => {
|
|
114
|
+
it('re-exports the page component', () => {
|
|
115
|
+
expect(Page).toBe(PageImplementation);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
`,
|
|
119
119
|
'packages/components/page/types.ts': `import { FC } from 'react';
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
export type PageProps = {
|
|
122
|
+
content: string;
|
|
123
|
+
};
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
export type PageType = FC<PageProps>;
|
|
126
|
+
`,
|
|
127
127
|
'packages/components/page/page.tsx': `import type { PageType } from './types.js';
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
export const Page: PageType = ({ content }) => <div className="content">{content}</div>;
|
|
130
|
+
`,
|
|
131
131
|
'packages/components/page/styles.scss': `.content {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
display: block;
|
|
133
|
+
}
|
|
134
|
+
`,
|
|
135
135
|
'packages/components/page/page.test.tsx': `import { renderToStaticMarkup } from 'react-dom/server';
|
|
136
|
-
|
|
136
|
+
import { describe, expect, it } from '@jest/globals';
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
import { Page } from './page.js';
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
describe('packages/components/page/page', () => {
|
|
141
|
+
it('renders content inside the page content container', () => {
|
|
142
|
+
expect(renderToStaticMarkup(<Page content="Page body" />)).toBe('<div class="content">Page body</div>');
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
`,
|
|
146
146
|
'workspaces/spa/bin/build.sh': `#!/usr/bin/env sh
|
|
147
147
|
|
|
148
148
|
set -e
|
|
@@ -160,12 +160,12 @@ scriptdir="$PWD/workspaces/spa";
|
|
|
160
160
|
npx webpack serve --open --config $scriptdir/webpack.config.ts
|
|
161
161
|
`,
|
|
162
162
|
'workspaces/spa/doc.mdx': `import { Meta, Markdown } from '@storybook/addon-docs/blocks';
|
|
163
|
-
|
|
163
|
+
import ReadMe from './README.md?raw';
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
<Meta title="Workspaces/SPA" />
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
<Markdown>{ReadMe}</Markdown>
|
|
168
|
+
`,
|
|
169
169
|
'workspaces/spa/README.md': `# ${options.name} SPA\n\n${options.description}\n`,
|
|
170
170
|
'workspaces/spa/webpack.config.ts': `import { csr, html } from '@vyriy/webpack-config';
|
|
171
171
|
import { path } from '@vyriy/path';
|
|
@@ -82,84 +82,84 @@ export const ssg = {
|
|
|
82
82
|
'packages/components/index.ts': "export * from './page/index.js';\n",
|
|
83
83
|
'packages/components/index.test.tsx': `import { describe, expect, it } from '@jest/globals';
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
import { Page } from './index.js';
|
|
86
|
+
import { Page as PageImplementation } from './page/index.js';
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
});
|
|
88
|
+
describe('packages/components/page', () => {
|
|
89
|
+
it('re-exports the page component', () => {
|
|
90
|
+
expect(Page).toBe(PageImplementation);
|
|
92
91
|
});
|
|
93
|
-
|
|
92
|
+
});
|
|
93
|
+
`,
|
|
94
94
|
'packages/components/page/index.ts': `export * from './page.js';
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
export type * from './types.js';
|
|
96
|
+
`,
|
|
97
97
|
'packages/components/page/index.test.ts': `import { describe, expect, it } from '@jest/globals';
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
import { Page } from './index.js';
|
|
100
|
+
import { Page as PageImplementation } from './page.js';
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
102
|
+
describe('packages/components/page', () => {
|
|
103
|
+
it('re-exports the page component', () => {
|
|
104
|
+
expect(Page).toBe(PageImplementation);
|
|
106
105
|
});
|
|
107
|
-
|
|
106
|
+
});
|
|
107
|
+
`,
|
|
108
108
|
'packages/components/page/types.ts': `import { FC } from 'react';
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
export type PageProps = {
|
|
111
|
+
content: string;
|
|
112
|
+
};
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
export type PageType = FC<PageProps>;
|
|
115
|
+
`,
|
|
116
116
|
'packages/components/page/page.tsx': `import type { PageType } from './types.js';
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
export const Page: PageType = ({ content }) => <div className="content">{content}</div>;
|
|
119
|
+
`,
|
|
120
120
|
'packages/components/page/styles.scss': `.content {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
display: block;
|
|
122
|
+
}
|
|
123
|
+
`,
|
|
124
124
|
'packages/components/page/page.test.tsx': `import { renderToStaticMarkup } from 'react-dom/server';
|
|
125
|
-
|
|
125
|
+
import { describe, expect, it } from '@jest/globals';
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
import { Page } from './page.js';
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
129
|
+
describe('packages/components/page/page', () => {
|
|
130
|
+
it('renders content inside the page content container', () => {
|
|
131
|
+
expect(renderToStaticMarkup(<Page content="Page body" />)).toBe('<div class="content">Page body</div>');
|
|
133
132
|
});
|
|
134
|
-
|
|
133
|
+
});
|
|
134
|
+
`,
|
|
135
135
|
'packages/services/package.json': JSON.stringify({
|
|
136
136
|
name: '@p/services',
|
|
137
137
|
private: true,
|
|
138
138
|
type: 'module',
|
|
139
139
|
}, null, 2) + '\n',
|
|
140
140
|
'packages/services/cms/index.ts': `export const cms = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
getContent: async () => {
|
|
142
|
+
// Placeholder for fetching content from a CMS
|
|
143
|
+
return Promise.resolve({
|
|
144
|
+
title: 'Sample Content',
|
|
145
|
+
body: 'This is a sample content fetched from the CMS.',
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
`,
|
|
150
150
|
'packages/services/cms/index.test.ts': `import { describe, expect, it } from '@jest/globals';
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
import { cms } from './index.js';
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
154
|
+
describe('packages/services/cms', () => {
|
|
155
|
+
it('returns content for rendering a page', async () => {
|
|
156
|
+
await expect(cms.getContent()).resolves.toEqual({
|
|
157
|
+
title: 'Sample Content',
|
|
158
|
+
body: 'This is a sample content fetched from the CMS.',
|
|
160
159
|
});
|
|
161
160
|
});
|
|
162
|
-
|
|
161
|
+
});
|
|
162
|
+
`,
|
|
163
163
|
'workspaces/ssg/bin/build.sh': `#!/usr/bin/env sh
|
|
164
164
|
|
|
165
165
|
set -e
|
|
@@ -187,29 +187,29 @@ yarn exec sass packages/components/page/styles.scss "$distdir/styles.css" --no-s
|
|
|
187
187
|
PROJECT_CWD="$distdir" NODE_ENV=production LOG_LEVEL=info "$PWD/node_modules/.bin/tsx" $scriptdir/index.tsx
|
|
188
188
|
`,
|
|
189
189
|
'workspaces/ssg/doc.mdx': `import { Meta, Markdown } from '@storybook/addon-docs/blocks';
|
|
190
|
-
|
|
190
|
+
import ReadMe from './README.md?raw';
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
<Meta title="Workspaces/SSG" />
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
<Markdown>{ReadMe}</Markdown>
|
|
195
|
+
`,
|
|
196
196
|
'workspaces/ssg/README.md': `# ${options.name} SSG\n\n${options.description}\n`,
|
|
197
197
|
'workspaces/ssg/webpack.config.ts': `import { path } from '@vyriy/path';
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
198
|
+
import { ssr, external } from '@vyriy/webpack-config';
|
|
199
|
+
|
|
200
|
+
export default ssr(
|
|
201
|
+
'@w/ssg',
|
|
202
|
+
{
|
|
203
|
+
path: path('dist', 'ssg'),
|
|
204
|
+
filename: 'index.js',
|
|
205
|
+
library: { type: 'commonjs2' },
|
|
206
|
+
},
|
|
207
|
+
(config) => ({
|
|
208
|
+
...config,
|
|
209
|
+
externals: [external({ allowlist: [/^@p/, /^@w/, /^@vyriy/] })],
|
|
210
|
+
}),
|
|
211
|
+
);
|
|
212
|
+
`,
|
|
213
213
|
'workspaces/ssg/package.json': JSON.stringify({
|
|
214
214
|
name: '@w/ssg',
|
|
215
215
|
type: 'module',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vyriy",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Interactive project master for calm cloud-ready applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./bin/vyriy.js",
|
|
@@ -29,9 +29,6 @@
|
|
|
29
29
|
"webpack-cli": "^7.0.2"
|
|
30
30
|
},
|
|
31
31
|
"peerDependenciesMeta": {
|
|
32
|
-
"@storybook/react-webpack5": {
|
|
33
|
-
"optional": true
|
|
34
|
-
},
|
|
35
32
|
"@types/react": {
|
|
36
33
|
"optional": true
|
|
37
34
|
},
|