create-vitnode-app 0.0.9-canary.8 → 0.0.9
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 +9 -9
- package/dist/index.cjs +35 -34
- package/package.json +11 -11
- package/templates/basic/.env.template +16 -0
- package/templates/basic/.gitignore_template +0 -11
- package/templates/basic/README.md +42 -0
- package/templates/basic/apps/backend/drizzle.config.ts +1 -2
- package/templates/basic/apps/backend/src/app.module.ts +4 -7
- package/templates/basic/apps/backend/src/database/config.ts +4 -4
- package/templates/basic/apps/backend/src/database/database.module.ts +1 -1
- package/templates/basic/apps/backend/src/main.ts +4 -18
- package/templates/basic/apps/backend/src/plugins/plugins.module.ts +1 -1
- package/templates/basic/apps/backend/src/plugins/welcome/config.json +2 -2
- package/templates/basic/apps/{backend → frontend}/codegen.ts +2 -2
- package/templates/basic/apps/frontend/global.d.ts +3 -3
- package/templates/basic/apps/frontend/tailwind.config.ts +5 -5
- package/templates/basic/apps/frontend/tsconfig.json +1 -1
- package/templates/basic/turbo.json +2 -1
- package/templates/docker/docker-compose-dev.yml +1 -1
- package/templates/eslint/apps/backend/eslint.config.mjs +4 -0
- package/templates/eslint/apps/frontend/eslint.config.mjs +4 -0
- package/templates/basic/.env_template +0 -5
- package/templates/basic/apps/backend/src/plugins/welcome/admin/database/functions.ts +0 -6
- package/templates/basic/apps/frontend/app/[locale]/(main)/layout.tsx +0 -11
- package/templates/basic/apps/frontend/app/[locale]/error.tsx +0 -7
- package/templates/basic/apps/frontend/app/[locale]/layout.tsx +0 -13
- package/templates/basic/apps/frontend/app/global.css +0 -82
- package/templates/basic/apps/frontend/app/layout.tsx +0 -9
- package/templates/basic/apps/frontend/i18n.ts +0 -13
- package/templates/basic/apps/frontend/middleware.ts +0 -7
- package/templates/basic/apps/frontend/plugins/welcome/langs/en.json +0 -5
- package/templates/basic/apps/frontend/plugins/welcome/langs/pl.json +0 -5
- package/templates/basic/apps/frontend/plugins/welcome/templates/default-page.tsx +0 -38
- package/templates/basic/tsconfig.json +0 -4
- package/templates/eslint/apps/backend/.eslintrc.json +0 -5
- package/templates/eslint/apps/frontend/.eslintrc.json +0 -4
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-vitnode-app",
|
|
3
|
-
"version": "0.0.9
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Create a new VitNode app in seconds.",
|
|
5
5
|
"author": "VitNode Team",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://vitnode.com",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/
|
|
10
|
+
"url": "git+https://github.com/VitNode/vitnode.git",
|
|
11
11
|
"directory": "packages/create-vitnode-app"
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
@@ -26,23 +26,23 @@
|
|
|
26
26
|
"nest.js"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"figlet": "^1.
|
|
30
|
-
"picocolors": "^1.0
|
|
29
|
+
"figlet": "^1.8.0",
|
|
30
|
+
"picocolors": "^1.1.0",
|
|
31
31
|
"prompts": "^2.4.2",
|
|
32
|
-
"validate-npm-package-name": "^
|
|
32
|
+
"validate-npm-package-name": "^6.0.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/cross-spawn": "^6.0.6",
|
|
36
|
-
"@types/figlet": "^1.
|
|
37
|
-
"@types/node": "^22.
|
|
36
|
+
"@types/figlet": "^1.7.0",
|
|
37
|
+
"@types/node": "^22.7.5",
|
|
38
38
|
"@types/prompts": "^2.4.9",
|
|
39
39
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
40
40
|
"commander": "^12.1.0",
|
|
41
41
|
"cross-spawn": "^7.0.3",
|
|
42
|
-
"ora": "^8.0
|
|
43
|
-
"tsup": "^8.
|
|
44
|
-
"typescript": "^5.
|
|
45
|
-
"eslint-config-typescript-vitnode": "0.0.9
|
|
42
|
+
"ora": "^8.1.0",
|
|
43
|
+
"tsup": "^8.3.0",
|
|
44
|
+
"typescript": "^5.6.3",
|
|
45
|
+
"eslint-config-typescript-vitnode": "0.0.9"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"lint": "eslint .",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
NEXT_PUBLIC_BACKEND_URL=http://localhost:8080
|
|
2
|
+
NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000
|
|
3
|
+
|
|
4
|
+
# ! Database
|
|
5
|
+
DB_USER=root
|
|
6
|
+
DB_PASSWORD=root
|
|
7
|
+
# DB_HOST=database
|
|
8
|
+
# DB_DATABASE=vitnode
|
|
9
|
+
# DB_PORT=5432
|
|
10
|
+
# DB_SSL=false
|
|
11
|
+
|
|
12
|
+
# !!! SECIURE ENVIRONMENT VARIABLES !!!
|
|
13
|
+
# Automatically generated by create-vitnode-app
|
|
14
|
+
# Do not change this environment below, unless you know what you are doing
|
|
15
|
+
# Changing these values may break your session and other security features
|
|
16
|
+
LOGIN_TOKEN_SECRET=vitnode_secret
|
|
@@ -49,20 +49,9 @@ yarn-error.log*
|
|
|
49
49
|
!/apps/backend/uploads/public/index.html
|
|
50
50
|
!/apps/backend/uploads/private/index.html
|
|
51
51
|
!/apps/backend/uploads/temp/index.html
|
|
52
|
-
/apps/backend/schema.gql
|
|
53
52
|
|
|
54
53
|
## Configuration
|
|
55
|
-
/apps/backend/src/plugins/*/admin/database/migrations
|
|
56
54
|
/apps/backend/src/plugins/core/
|
|
57
55
|
|
|
58
56
|
## Frontend
|
|
59
|
-
/apps/frontend/app/not-found.tsx
|
|
60
|
-
/apps/frontend/app/\[\locale\]\/(main)/(vitnode)
|
|
61
|
-
/apps/frontend/app/\[\locale\]\/(main)/page.tsx
|
|
62
|
-
/apps/frontend/app/\[\locale\]\/admin/layout.tsx
|
|
63
|
-
/apps/frontend/app/\[\locale\]\/admin/(vitnode)
|
|
64
|
-
/apps/frontend/app/\[\locale\]\/admin/(auth)/(vitnode)
|
|
65
|
-
/apps/frontend/app/\[\locale\]\/admin/(auth)/layout.tsx
|
|
66
|
-
/apps/frontend/plugins/admin
|
|
67
|
-
/apps/frontend/plugins/core
|
|
68
57
|
/apps/frontend/next-env.d.ts
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<a href="https://vitnode.com/" target="_blank">
|
|
4
|
+
<picture>
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_dark.svg">
|
|
6
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg">
|
|
7
|
+
<img alt="VitNode Logo" src="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg" width="400">
|
|
8
|
+
</picture>
|
|
9
|
+
</a>
|
|
10
|
+
<br>
|
|
11
|
+
<br>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
# VitNode App
|
|
15
|
+
|
|
16
|
+
This is a basic template for a VitNode app.
|
|
17
|
+
|
|
18
|
+
## Getting Started
|
|
19
|
+
|
|
20
|
+
To get started, run the following commands:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm i
|
|
24
|
+
# or
|
|
25
|
+
npm i
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
To start the development server, you need to create a `.env` file in the root of the project from `.env.example`.
|
|
31
|
+
|
|
32
|
+
In the `development` environment, you can just copy and paste the content of `.env.example` to `.env`.
|
|
33
|
+
|
|
34
|
+
### Development server
|
|
35
|
+
|
|
36
|
+
To start the development server, run the following command:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm dev
|
|
40
|
+
# or
|
|
41
|
+
npm run dev
|
|
42
|
+
```
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
|
|
3
1
|
import { Module } from '@nestjs/common';
|
|
2
|
+
import { join } from 'path';
|
|
4
3
|
import { VitNodeCoreModule } from 'vitnode-backend';
|
|
5
4
|
|
|
6
|
-
import {
|
|
7
|
-
import { DATABASE_ENVS, schemaDatabase } from './database';
|
|
5
|
+
import { DATABASE_ENVS, schemaDatabase } from './database/config';
|
|
8
6
|
import { DatabaseModule } from './database/database.module';
|
|
7
|
+
import { PluginsModule } from './plugins/plugins.module';
|
|
9
8
|
|
|
10
9
|
@Module({
|
|
11
10
|
imports: [
|
|
12
11
|
VitNodeCoreModule.register({
|
|
13
|
-
|
|
14
|
-
envFile: join(process.cwd(), '..', '..', '.env'),
|
|
15
|
-
},
|
|
12
|
+
pathToEnvFile: join(process.cwd(), '..', '..', '.env'),
|
|
16
13
|
database: {
|
|
17
14
|
config: DATABASE_ENVS,
|
|
18
15
|
schemaDatabase,
|
|
@@ -10,10 +10,10 @@ export const schemaDatabase = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export const DATABASE_ENVS = {
|
|
13
|
-
host: process.env.DB_HOST
|
|
13
|
+
host: process.env.DB_HOST ?? 'localhost',
|
|
14
14
|
port: process.env.DB_PORT ? +process.env.DB_PORT : 5432,
|
|
15
|
-
user: process.env.DB_USER
|
|
16
|
-
password: process.env.DB_PASSWORD
|
|
17
|
-
database: process.env.DB_DATABASE
|
|
15
|
+
user: process.env.DB_USER ?? 'root',
|
|
16
|
+
password: process.env.DB_PASSWORD ?? 'root',
|
|
17
|
+
database: process.env.DB_DATABASE ?? 'vitnode',
|
|
18
18
|
ssl: process.env.DB_SSL ? process.env.DB_SSL === 'true' : false,
|
|
19
19
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import { NestFactory } from '@nestjs/core';
|
|
3
1
|
import { INestApplication } from '@nestjs/common';
|
|
2
|
+
import { NestFactory } from '@nestjs/core';
|
|
4
3
|
import { nestjsMainApp } from 'vitnode-backend';
|
|
5
4
|
|
|
6
5
|
import { AppModule } from './app.module';
|
|
@@ -8,20 +7,7 @@ import { AppModule } from './app.module';
|
|
|
8
7
|
async function bootstrap() {
|
|
9
8
|
const app: INestApplication = await NestFactory.create(AppModule);
|
|
10
9
|
|
|
11
|
-
nestjsMainApp(app, {
|
|
12
|
-
cors: {
|
|
13
|
-
origin: [
|
|
14
|
-
process.env.NEXT_PUBLIC_FRONTEND_URL
|
|
15
|
-
? process.env.NEXT_PUBLIC_FRONTEND_URL
|
|
16
|
-
: 'http://localhost:3000',
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
await app.listen(process.env.PORT ?? '8080', '', () => {
|
|
22
|
-
console.log(
|
|
23
|
-
`Application is running on: http://localhost:${process.env.PORT ?? 8080}/graphql`,
|
|
24
|
-
);
|
|
25
|
-
});
|
|
10
|
+
void nestjsMainApp(app, {});
|
|
26
11
|
}
|
|
27
|
-
|
|
12
|
+
|
|
13
|
+
void bootstrap();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
|
|
3
|
-
import { codegenConfig } from 'vitnode-
|
|
3
|
+
import { codegenConfig } from 'vitnode-frontend/codegen';
|
|
4
4
|
import { CodegenConfig } from '@graphql-codegen/cli';
|
|
5
5
|
|
|
6
6
|
const config: CodegenConfig = codegenConfig({
|
|
7
|
-
pathOutGql: join(process.cwd(), '..', 'frontend', 'graphql'),
|
|
7
|
+
pathOutGql: join(process.cwd(), '..', 'frontend', 'src', 'graphql'),
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
export default config;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import core from '@/plugins/core/langs/en.json';
|
|
2
|
+
import admin from '@/plugins/admin/langs/en.json';
|
|
3
|
+
import welcome from '@/plugins/welcome/langs/en.json';
|
|
4
4
|
// ! === IMPORT ===
|
|
5
5
|
|
|
6
6
|
type Messages = typeof core & typeof admin & typeof welcome; // ! === MODULE ===
|
|
@@ -4,11 +4,11 @@ import vitnodeConfig from 'vitnode-frontend/tailwind.config';
|
|
|
4
4
|
const config = {
|
|
5
5
|
presets: [vitnodeConfig],
|
|
6
6
|
content: [
|
|
7
|
-
'
|
|
8
|
-
'
|
|
9
|
-
'./components/**/*.
|
|
10
|
-
'./app/**/*.
|
|
11
|
-
'./plugins/**/templates/**/*.
|
|
7
|
+
'./node_modules/vitnode-frontend/src/components/**/*.tsx',
|
|
8
|
+
'./node_modules/vitnode-frontend/src/views/**/*.tsx',
|
|
9
|
+
'./src/components/**/*.tsx',
|
|
10
|
+
'./src/app/**/*.tsx',
|
|
11
|
+
'./src/plugins/**/templates/**/*.tsx',
|
|
12
12
|
],
|
|
13
13
|
} satisfies Config;
|
|
14
14
|
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# !!! SECIURE ENVIRONMENT VARIABLES !!!
|
|
2
|
-
# Automatically generated by create-vitnode-app
|
|
3
|
-
# Do not change this environment below, unless you know what you are doing
|
|
4
|
-
# Changing these values may break your session and other security features
|
|
5
|
-
LOGIN_TOKEN_SECRET=vitnode_secret
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { AuthLayout } from 'vitnode-frontend/views/layout/auth/auth-layout';
|
|
3
|
-
import { ThemeLayout } from 'vitnode-frontend/views/theme/layout/theme-layout';
|
|
4
|
-
|
|
5
|
-
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
6
|
-
return (
|
|
7
|
-
<AuthLayout>
|
|
8
|
-
<ThemeLayout>{children}</ThemeLayout>
|
|
9
|
-
</AuthLayout>
|
|
10
|
-
);
|
|
11
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { GeistSans } from 'geist/font/sans';
|
|
3
|
-
import {
|
|
4
|
-
RootLayout,
|
|
5
|
-
RootLayoutProps,
|
|
6
|
-
generateMetadataRootLayout,
|
|
7
|
-
} from 'vitnode-frontend/views/layout/root-layout';
|
|
8
|
-
|
|
9
|
-
export const generateMetadata = generateMetadataRootLayout;
|
|
10
|
-
|
|
11
|
-
export default function Layout(props: RootLayoutProps) {
|
|
12
|
-
return <RootLayout className={GeistSans.className} {...props} />;
|
|
13
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
@tailwind components;
|
|
2
|
-
@tailwind utilities;
|
|
3
|
-
@tailwind base;
|
|
4
|
-
|
|
5
|
-
@layer base {
|
|
6
|
-
* {
|
|
7
|
-
@apply border-border;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
body {
|
|
11
|
-
@apply bg-background text-foreground;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
a {
|
|
15
|
-
@apply text-primary;
|
|
16
|
-
@apply cursor-pointer;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
:root {
|
|
20
|
-
--background: 220 40% 98%;
|
|
21
|
-
--foreground: 213deg 5% 8%;
|
|
22
|
-
--card: 220 40% 100%;
|
|
23
|
-
--card-foreground: 213deg 26% 7%;
|
|
24
|
-
--popover: var(--card);
|
|
25
|
-
--popover-foreground: var(--card-foreground);
|
|
26
|
-
--primary: 220 58% 47%;
|
|
27
|
-
--primary-foreground: 220 40% 98%;
|
|
28
|
-
--secondary: 220 42% 94%;
|
|
29
|
-
--secondary-foreground: 210 40% 2%;
|
|
30
|
-
--muted: 220 40% 96%;
|
|
31
|
-
--muted-foreground: 220 8% 44%;
|
|
32
|
-
--accent: 220 40% 92%;
|
|
33
|
-
--accent-foreground: 222 47% 11%;
|
|
34
|
-
--destructive: 0 57% 43%;
|
|
35
|
-
--destructive-foreground: 210 40% 98%;
|
|
36
|
-
--border: 220 20% 90%;
|
|
37
|
-
--input: var(--border);
|
|
38
|
-
--ring: var(--primary);
|
|
39
|
-
--radius: 0.5rem;
|
|
40
|
-
--cover: 220 80% 67%;
|
|
41
|
-
--cover-foreground: 210 40% 98%;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.dark {
|
|
45
|
-
--background: 216 32% 7%;
|
|
46
|
-
--foreground: 0 0% 98%;
|
|
47
|
-
--card: 216 32% 10%;
|
|
48
|
-
--card-foreground: 0 0% 98%;
|
|
49
|
-
/* --popover: var(--card); */
|
|
50
|
-
/* --popover-foreground: var(--card-foreground); */
|
|
51
|
-
--primary: 220 83% 60%;
|
|
52
|
-
--primary-foreground: 220 40% 98%;
|
|
53
|
-
--secondary: 222 25% 18%;
|
|
54
|
-
--secondary-foreground: 0 0% 98%;
|
|
55
|
-
--muted: 216 32% 11%;
|
|
56
|
-
--muted-foreground: 216 18% 64%;
|
|
57
|
-
--accent: 216 32% 14%;
|
|
58
|
-
--accent-foreground: 0 0% 98%;
|
|
59
|
-
--destructive: 359 78% 55%;
|
|
60
|
-
--destructive-foreground: 210 40% 98%;
|
|
61
|
-
--border: 216 25% 16%;
|
|
62
|
-
/* --input: var(--border); */
|
|
63
|
-
/* --ring: var(--primary); */
|
|
64
|
-
--cover: 216 64% 39%;
|
|
65
|
-
--cover-foreground: 210 40% 98%;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
@layer utilities {
|
|
70
|
-
.underline-strike-through {
|
|
71
|
-
text-decoration: underline line-through;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.no-scrollbar {
|
|
75
|
-
-ms-overflow-style: none;
|
|
76
|
-
scrollbar-width: none;
|
|
77
|
-
|
|
78
|
-
&::-webkit-scrollbar {
|
|
79
|
-
display: none;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { getRequestConfig } from 'next-intl/server';
|
|
2
|
-
import { i18nConfig } from 'vitnode-frontend/i18n';
|
|
3
|
-
|
|
4
|
-
export default getRequestConfig(async args => {
|
|
5
|
-
const config = await i18nConfig({
|
|
6
|
-
...args,
|
|
7
|
-
pathsToMessagesFromPlugins: async ({ plugin, locale }) => {
|
|
8
|
-
return import(`./plugins/${plugin}/langs/${locale}.json`);
|
|
9
|
-
},
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
return config;
|
|
13
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { LogoVitNode } from 'vitnode-frontend/components/logo-vitnode';
|
|
2
|
-
import { buttonVariants } from 'vitnode-frontend/components/ui/button';
|
|
3
|
-
import { Link } from 'vitnode-frontend/navigation';
|
|
4
|
-
import { BookIcon, KeyRoundIcon } from 'lucide-react';
|
|
5
|
-
|
|
6
|
-
export default function DefaultPage() {
|
|
7
|
-
return (
|
|
8
|
-
<main className="container mt-10 flex max-w-lg flex-col items-center justify-center gap-8 text-center">
|
|
9
|
-
<LogoVitNode className="w-48" />
|
|
10
|
-
|
|
11
|
-
<div className="space-y-1">
|
|
12
|
-
<h1 className="text-3xl font-bold">Ready to build?</h1>
|
|
13
|
-
|
|
14
|
-
<p className="text-muted-foreground">
|
|
15
|
-
Dive in and install your first plugin! Or, if you're feeling
|
|
16
|
-
adventurous, create your own masterpiece.
|
|
17
|
-
</p>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
<div className="flex flex-wrap items-center justify-center gap-4">
|
|
21
|
-
<Link href="/admin" target="_blank" className={buttonVariants()}>
|
|
22
|
-
<KeyRoundIcon /> Go to AdminCP
|
|
23
|
-
</Link>
|
|
24
|
-
|
|
25
|
-
<Link
|
|
26
|
-
href="https://vitnode.com/"
|
|
27
|
-
target="_blank"
|
|
28
|
-
rel="noopener noreferrer"
|
|
29
|
-
className={buttonVariants({
|
|
30
|
-
variant: 'ghost',
|
|
31
|
-
})}
|
|
32
|
-
>
|
|
33
|
-
<BookIcon /> Read our Docs
|
|
34
|
-
</Link>
|
|
35
|
-
</div>
|
|
36
|
-
</main>
|
|
37
|
-
);
|
|
38
|
-
}
|