create-nscope-app 1.0.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/bin/create-nscope-app.mjs +186 -0
- package/package.json +22 -0
- package/templates/next/.env.local.example +3 -0
- package/templates/next/README.md +21 -0
- package/templates/next/app/globals.css +30 -0
- package/templates/next/app/layout.tsx +22 -0
- package/templates/next/app/page.tsx +5 -0
- package/templates/next/components/home-page.tsx +40 -0
- package/templates/next/components/providers.tsx +8 -0
- package/templates/next/lib/nscope.ts +10 -0
- package/templates/next/next-env.d.ts +2 -0
- package/templates/next/next.config.ts +5 -0
- package/templates/next/package.json +23 -0
- package/templates/next/tsconfig.json +23 -0
- package/templates/vite/.env.example +3 -0
- package/templates/vite/README.md +20 -0
- package/templates/vite/index.html +12 -0
- package/templates/vite/package.json +24 -0
- package/templates/vite/src/App.tsx +31 -0
- package/templates/vite/src/index.css +30 -0
- package/templates/vite/src/main.tsx +14 -0
- package/templates/vite/src/nscope.ts +10 -0
- package/templates/vite/tsconfig.json +21 -0
- package/templates/vite/vite.config.ts +6 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cp, mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const TEMPLATES_DIR = join(__dirname, "..", "templates");
|
|
10
|
+
|
|
11
|
+
const TEMPLATE_CHOICES = ["vite", "next"];
|
|
12
|
+
|
|
13
|
+
function parseArgs(argv) {
|
|
14
|
+
const result = {
|
|
15
|
+
projectName: "",
|
|
16
|
+
template: "",
|
|
17
|
+
apiKey: "",
|
|
18
|
+
baseUrl: "http://localhost:3333",
|
|
19
|
+
redirectUri: "http://localhost:5173",
|
|
20
|
+
help: false,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
24
|
+
const arg = argv[index];
|
|
25
|
+
|
|
26
|
+
if (arg === "--help" || arg === "-h") {
|
|
27
|
+
result.help = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (arg === "--template" || arg === "-t") {
|
|
32
|
+
result.template = argv[index + 1] ?? "";
|
|
33
|
+
index += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (arg === "--api-key") {
|
|
38
|
+
result.apiKey = argv[index + 1] ?? "";
|
|
39
|
+
index += 1;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (arg === "--base-url") {
|
|
44
|
+
result.baseUrl = argv[index + 1] ?? result.baseUrl;
|
|
45
|
+
index += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (arg === "--redirect-uri") {
|
|
50
|
+
result.redirectUri = argv[index + 1] ?? result.redirectUri;
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!arg.startsWith("-") && !result.projectName) {
|
|
56
|
+
result.projectName = arg;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function printHelp() {
|
|
64
|
+
console.log(`
|
|
65
|
+
create-nscope-app — scaffold a Nscope client app
|
|
66
|
+
|
|
67
|
+
Usage:
|
|
68
|
+
npx create-nscope-app <project-name> [options]
|
|
69
|
+
|
|
70
|
+
Options:
|
|
71
|
+
-t, --template <vite|next> Template (default: vite)
|
|
72
|
+
--api-key <key> Nscope API key (pk_live_...)
|
|
73
|
+
--base-url <url> API base URL (default: http://localhost:3333)
|
|
74
|
+
--redirect-uri <url> OAuth return URL (default: http://localhost:5173)
|
|
75
|
+
-h, --help Show this help
|
|
76
|
+
|
|
77
|
+
Examples:
|
|
78
|
+
npx create-nscope-app my-saas --template vite
|
|
79
|
+
npx create-nscope-app my-saas -t next --api-key pk_live_xxx
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function prompt(question, defaultValue = "") {
|
|
84
|
+
const rl = createInterface({ input, output });
|
|
85
|
+
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
86
|
+
const answer = (await rl.question(`${question}${suffix}: `)).trim();
|
|
87
|
+
rl.close();
|
|
88
|
+
return answer || defaultValue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function copyDir(source, destination, replacements) {
|
|
92
|
+
await mkdir(destination, { recursive: true });
|
|
93
|
+
const entries = await readdir(source, { withFileTypes: true });
|
|
94
|
+
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const sourcePath = join(source, entry.name);
|
|
97
|
+
const destPath = join(destination, entry.name);
|
|
98
|
+
|
|
99
|
+
if (entry.isDirectory()) {
|
|
100
|
+
await copyDir(sourcePath, destPath, replacements);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let content = await readFile(sourcePath, "utf8");
|
|
105
|
+
|
|
106
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
107
|
+
content = content.replaceAll(`{{${key}}}`, value);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await writeFile(destPath, content, "utf8");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function main() {
|
|
115
|
+
const args = parseArgs(process.argv.slice(2));
|
|
116
|
+
|
|
117
|
+
if (args.help) {
|
|
118
|
+
printHelp();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const projectName =
|
|
123
|
+
args.projectName || (await prompt("Project name", "my-nscope-app"));
|
|
124
|
+
const template =
|
|
125
|
+
args.template ||
|
|
126
|
+
(await prompt(`Template (${TEMPLATE_CHOICES.join("|")})`, "vite"));
|
|
127
|
+
|
|
128
|
+
if (!TEMPLATE_CHOICES.includes(template)) {
|
|
129
|
+
console.error(`Invalid template "${template}". Use: ${TEMPLATE_CHOICES.join(", ")}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const apiKey =
|
|
134
|
+
args.apiKey || (await prompt("API key (pk_live_...)", "pk_live_YOUR_KEY"));
|
|
135
|
+
const baseUrl =
|
|
136
|
+
args.baseUrl || (await prompt("API base URL", "http://localhost:3333"));
|
|
137
|
+
const redirectUri =
|
|
138
|
+
args.redirectUri ||
|
|
139
|
+
(await prompt(
|
|
140
|
+
"Redirect URI",
|
|
141
|
+
template === "next" ? "http://localhost:3000" : "http://localhost:5173",
|
|
142
|
+
));
|
|
143
|
+
|
|
144
|
+
const targetDir = resolve(process.cwd(), projectName);
|
|
145
|
+
const templateDir = join(TEMPLATES_DIR, template);
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
await stat(templateDir);
|
|
149
|
+
} catch {
|
|
150
|
+
console.error(`Template not found: ${template}`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
await stat(targetDir);
|
|
156
|
+
console.error(`Directory already exists: ${targetDir}`);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
} catch {
|
|
159
|
+
// ok
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const replacements = {
|
|
163
|
+
PROJECT_NAME: projectName,
|
|
164
|
+
API_KEY: apiKey,
|
|
165
|
+
BASE_URL: baseUrl,
|
|
166
|
+
REDIRECT_URI: redirectUri,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
await copyDir(templateDir, targetDir, replacements);
|
|
170
|
+
|
|
171
|
+
console.log(`
|
|
172
|
+
✓ Created ${projectName} (${template})
|
|
173
|
+
|
|
174
|
+
Next steps:
|
|
175
|
+
cd ${projectName}
|
|
176
|
+
pnpm install
|
|
177
|
+
pnpm dev
|
|
178
|
+
|
|
179
|
+
Docs: https://github.com/tratondigital/nscope-app — /docs/sdk
|
|
180
|
+
`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
main().catch((error) => {
|
|
184
|
+
console.error(error instanceof Error ? error.message : error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-nscope-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold a Nscope client app (Vite or Next.js)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-nscope-app": "./bin/create-nscope-app.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"templates"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"nscope",
|
|
15
|
+
"auth",
|
|
16
|
+
"scaffold",
|
|
17
|
+
"vite",
|
|
18
|
+
"next"
|
|
19
|
+
],
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"author": "Traton Digital"
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Starter Next.js App Router with [@nscope/react](https://www.npmjs.com/package/@nscope/react).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. Copy `.env.local.example` to `.env.local` and fill in your API key.
|
|
8
|
+
2. Add `{{REDIRECT_URI}}` to **allowed domains** and as default return URL in Nscope.
|
|
9
|
+
3. Run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm install
|
|
13
|
+
pnpm dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Open [http://localhost:3000](http://localhost:3000).
|
|
17
|
+
|
|
18
|
+
## Next steps
|
|
19
|
+
|
|
20
|
+
- Wrap protected pages with `<GuardedRoute>`
|
|
21
|
+
- See `/docs/sdk` in your Nscope dashboard
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
color: #18181b;
|
|
5
|
+
background: #fafafa;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
* {
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
body {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.page {
|
|
17
|
+
max-width: 640px;
|
|
18
|
+
margin: 4rem auto;
|
|
19
|
+
padding: 0 1rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
button {
|
|
23
|
+
border: none;
|
|
24
|
+
border-radius: 8px;
|
|
25
|
+
background: #18181b;
|
|
26
|
+
color: white;
|
|
27
|
+
padding: 0.65rem 1rem;
|
|
28
|
+
font: inherit;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Providers } from "@/components/providers";
|
|
3
|
+
import { HomePage } from "@/components/home-page";
|
|
4
|
+
import "./globals.css";
|
|
5
|
+
|
|
6
|
+
export const metadata: Metadata = {
|
|
7
|
+
title: "{{PROJECT_NAME}}",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({
|
|
11
|
+
children,
|
|
12
|
+
}: Readonly<{
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}>) {
|
|
15
|
+
return (
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<body>
|
|
18
|
+
<Providers>{children}</Providers>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Can, useNscope } from "@nscope/react";
|
|
4
|
+
|
|
5
|
+
export function HomePage() {
|
|
6
|
+
const { user, isAuthenticated, isLoading, login, logout } = useNscope();
|
|
7
|
+
|
|
8
|
+
if (isLoading) {
|
|
9
|
+
return <main className="page">Loading…</main>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<main className="page">
|
|
14
|
+
<h1>{{PROJECT_NAME}}</h1>
|
|
15
|
+
|
|
16
|
+
{isAuthenticated && user ? (
|
|
17
|
+
<>
|
|
18
|
+
<p>Signed in as {user.name ?? user.email}</p>
|
|
19
|
+
<Can subject="users" action="LIST">
|
|
20
|
+
<p>You can list users.</p>
|
|
21
|
+
</Can>
|
|
22
|
+
<button type="button" onClick={() => logout()}>
|
|
23
|
+
Sign out
|
|
24
|
+
</button>
|
|
25
|
+
</>
|
|
26
|
+
) : (
|
|
27
|
+
<button
|
|
28
|
+
type="button"
|
|
29
|
+
onClick={() =>
|
|
30
|
+
login({
|
|
31
|
+
redirectUri: process.env.NEXT_PUBLIC_NSCOPE_REDIRECT_URI,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
>
|
|
35
|
+
Sign in with Nscope
|
|
36
|
+
</button>
|
|
37
|
+
)}
|
|
38
|
+
</main>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@nscope/react": "^1.0.0",
|
|
12
|
+
"@nscope/sdk": "^1.3.0",
|
|
13
|
+
"next": "^15.3.0",
|
|
14
|
+
"react": "^19.0.0",
|
|
15
|
+
"react-dom": "^19.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^22.0.0",
|
|
19
|
+
"@types/react": "^19.0.0",
|
|
20
|
+
"@types/react-dom": "^19.0.0",
|
|
21
|
+
"typescript": "^5.9.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [{ "name": "next" }],
|
|
17
|
+
"paths": {
|
|
18
|
+
"@/*": ["./*"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
22
|
+
"exclude": ["node_modules"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Starter Vite + React with [@nscope/react](https://www.npmjs.com/package/@nscope/react).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. Copy `.env.example` to `.env` and fill in your API key from the Nscope dashboard.
|
|
8
|
+
2. Add `{{REDIRECT_URI}}` to **allowed domains** and set it as the default return URL in project settings.
|
|
9
|
+
3. Run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm install
|
|
13
|
+
pnpm dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Next steps
|
|
17
|
+
|
|
18
|
+
- Customize login redirect in `src/App.tsx`
|
|
19
|
+
- Protect routes with `<GuardedRoute>` from `@nscope/react`
|
|
20
|
+
- Read the SDK docs in your Nscope panel at `/docs/sdk`
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>{{PROJECT_NAME}}</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc -b && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@nscope/react": "^1.0.0",
|
|
13
|
+
"@nscope/sdk": "^1.3.0",
|
|
14
|
+
"react": "^19.0.0",
|
|
15
|
+
"react-dom": "^19.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/react": "^19.0.0",
|
|
19
|
+
"@types/react-dom": "^19.0.0",
|
|
20
|
+
"@vitejs/plugin-react": "^4.4.0",
|
|
21
|
+
"typescript": "^5.9.0",
|
|
22
|
+
"vite": "^6.3.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Can, useNscope } from "@nscope/react";
|
|
2
|
+
|
|
3
|
+
export default function App() {
|
|
4
|
+
const { user, isAuthenticated, isLoading, login, logout } = useNscope();
|
|
5
|
+
|
|
6
|
+
if (isLoading) {
|
|
7
|
+
return <main className="page">Loading…</main>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<main className="page">
|
|
12
|
+
<h1>{{PROJECT_NAME}}</h1>
|
|
13
|
+
|
|
14
|
+
{isAuthenticated && user ? (
|
|
15
|
+
<>
|
|
16
|
+
<p>Signed in as {user.name ?? user.email}</p>
|
|
17
|
+
<Can subject="users" action="LIST">
|
|
18
|
+
<p>You can list users.</p>
|
|
19
|
+
</Can>
|
|
20
|
+
<button type="button" onClick={() => logout()}>
|
|
21
|
+
Sign out
|
|
22
|
+
</button>
|
|
23
|
+
</>
|
|
24
|
+
) : (
|
|
25
|
+
<button type="button" onClick={() => login({ redirectUri: import.meta.env.VITE_NSCOPE_REDIRECT_URI })}>
|
|
26
|
+
Sign in with Nscope
|
|
27
|
+
</button>
|
|
28
|
+
)}
|
|
29
|
+
</main>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
color: #18181b;
|
|
5
|
+
background: #fafafa;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
* {
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
body {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.page {
|
|
17
|
+
max-width: 640px;
|
|
18
|
+
margin: 4rem auto;
|
|
19
|
+
padding: 0 1rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
button {
|
|
23
|
+
border: none;
|
|
24
|
+
border-radius: 8px;
|
|
25
|
+
background: #18181b;
|
|
26
|
+
color: white;
|
|
27
|
+
padding: 0.65rem 1rem;
|
|
28
|
+
font: inherit;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StrictMode } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
import { NscopeProvider } from "@nscope/react";
|
|
4
|
+
import App from "./App";
|
|
5
|
+
import { nscope } from "./nscope";
|
|
6
|
+
import "./index.css";
|
|
7
|
+
|
|
8
|
+
createRoot(document.getElementById("root")!).render(
|
|
9
|
+
<StrictMode>
|
|
10
|
+
<NscopeProvider config={nscope}>
|
|
11
|
+
<App />
|
|
12
|
+
</NscopeProvider>
|
|
13
|
+
</StrictMode>,
|
|
14
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"moduleDetection": "force",
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"jsx": "react-jsx",
|
|
14
|
+
"strict": true,
|
|
15
|
+
"noUnusedLocals": true,
|
|
16
|
+
"noUnusedParameters": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noUncheckedSideEffectImports": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src"]
|
|
21
|
+
}
|