@epicabdou/create-linkrjs-app 0.0.1
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 +33 -0
- package/dist/index.js +43 -0
- package/package.json +31 -0
- package/template/index.html +12 -0
- package/template/package.json +24 -0
- package/template/src/config/protect.tsx +11 -0
- package/template/src/main.tsx +15 -0
- package/template/src/pages/404.tsx +14 -0
- package/template/src/pages/index.tsx +8 -0
- package/template/src/vite-env.d.ts +1 -0
- package/template/tsconfig.json +20 -0
- package/template/vite.config.ts +7 -0
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# create-linkrjs-app
|
|
2
|
+
|
|
3
|
+
Scaffold a new **linkr.js** app (Vite + React + React Router + file-based routing).
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @epicabdou/create-linkrjs-app my-app
|
|
9
|
+
cd my-app
|
|
10
|
+
pnpm install
|
|
11
|
+
pnpm dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
(Or `npx create-linkrjs-app my-app` if you have the package installed globally.)
|
|
15
|
+
|
|
16
|
+
This creates a folder `my-app` with:
|
|
17
|
+
|
|
18
|
+
- Vite + React + TypeScript
|
|
19
|
+
- React Router v7
|
|
20
|
+
- **@epicabdou/linkr** for file-based routes from `src/pages/`
|
|
21
|
+
- `index.tsx` (home) and `404.tsx` (not found)
|
|
22
|
+
|
|
23
|
+
Dev server runs at http://localhost:8000.
|
|
24
|
+
|
|
25
|
+
## What gets created
|
|
26
|
+
|
|
27
|
+
- `package.json` — name set to your project name
|
|
28
|
+
- `vite.config.ts` — React plugin, port 8000
|
|
29
|
+
- `src/main.tsx` — router using `createRoutes` + `import.meta.glob("./pages/**/*.tsx")`
|
|
30
|
+
- `src/pages/index.tsx` — home page
|
|
31
|
+
- `src/pages/404.tsx` — 404 page
|
|
32
|
+
|
|
33
|
+
Add more routes by adding files under `src/pages/` (e.g. `about.tsx` → `/about`).
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cpSync, mkdirSync, existsSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { dirname, join } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const templateDir = join(__dirname, "..", "template");
|
|
9
|
+
|
|
10
|
+
const projectName = process.argv[2];
|
|
11
|
+
if (!projectName) {
|
|
12
|
+
console.log(`
|
|
13
|
+
Create a new linkr.js app
|
|
14
|
+
|
|
15
|
+
Usage: npx create-linkrjs-app <project-name>
|
|
16
|
+
|
|
17
|
+
Example: npx create-linkrjs-app my-app
|
|
18
|
+
`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const targetDir = join(process.cwd(), projectName);
|
|
23
|
+
if (existsSync(targetDir)) {
|
|
24
|
+
console.error(`Error: "${projectName}" already exists. Choose another name.`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
mkdirSync(targetDir, { recursive: true });
|
|
29
|
+
cpSync(templateDir, targetDir, { recursive: true });
|
|
30
|
+
|
|
31
|
+
const pkgPath = join(targetDir, "package.json");
|
|
32
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
33
|
+
pkg.name = projectName.replace(/^[^a-zA-Z]|[^a-zA-Z0-9-_]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g) || "linkrjs-app";
|
|
34
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
35
|
+
|
|
36
|
+
console.log(`
|
|
37
|
+
Done! Your linkr.js app is in ./${projectName}
|
|
38
|
+
|
|
39
|
+
Next steps:
|
|
40
|
+
cd ${projectName}
|
|
41
|
+
pnpm install
|
|
42
|
+
pnpm dev
|
|
43
|
+
`);
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@epicabdou/create-linkrjs-app",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Scaffold a new linkr.js app (Vite + React + React Router + file-based routing)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-linkrjs-app": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/epicabdou/linkrjs.git"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"linkr",
|
|
20
|
+
"linkrjs",
|
|
21
|
+
"create-app",
|
|
22
|
+
"scaffold",
|
|
23
|
+
"vite",
|
|
24
|
+
"react",
|
|
25
|
+
"react-router"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {}
|
|
31
|
+
}
|
|
@@ -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>linkr.js App</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": "my-linkrjs-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc -b && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@epicabdou/linkr": "^1.0.0",
|
|
13
|
+
"react": "^18.2.0",
|
|
14
|
+
"react-dom": "^18.2.0",
|
|
15
|
+
"react-router": "^7.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/react": "^18.2.0",
|
|
19
|
+
"@types/react-dom": "^18.2.0",
|
|
20
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
21
|
+
"typescript": "^5.3.0",
|
|
22
|
+
"vite": "^5.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProtectConfig } from "@epicabdou/linkr";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Predefined auth protection: redirect to /login when there is no token.
|
|
5
|
+
* Use in any layout or page: <Protect {...authProtect}><Outlet /></Protect>
|
|
6
|
+
*/
|
|
7
|
+
export const authProtect: ProtectConfig = {
|
|
8
|
+
condition: () => !!localStorage.getItem("token"),
|
|
9
|
+
redirectTo: "/login",
|
|
10
|
+
fallback: <div>Checking access…</div>,
|
|
11
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StrictMode } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
import { createBrowserRouter, RouterProvider } from "react-router";
|
|
4
|
+
import { createRoutes } from "@epicabdou/linkr";
|
|
5
|
+
|
|
6
|
+
const pages = import.meta.glob("./pages/**/*.tsx");
|
|
7
|
+
const routes = createRoutes({ pagesGlob: pages, pagesDir: "pages" });
|
|
8
|
+
const router = createBrowserRouter(routes);
|
|
9
|
+
|
|
10
|
+
const root = createRoot(document.getElementById("root")!);
|
|
11
|
+
root.render(
|
|
12
|
+
<StrictMode>
|
|
13
|
+
<RouterProvider router={router} />
|
|
14
|
+
</StrictMode>
|
|
15
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useNavigate } from "react-router";
|
|
2
|
+
|
|
3
|
+
export default function NotFound() {
|
|
4
|
+
const navigate = useNavigate();
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<h1>404</h1>
|
|
8
|
+
<p>Page not found.</p>
|
|
9
|
+
<button type="button" onClick={() => navigate("/")}>
|
|
10
|
+
Go home
|
|
11
|
+
</button>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"jsx": "react-jsx",
|
|
14
|
+
"strict": true,
|
|
15
|
+
"noUnusedLocals": true,
|
|
16
|
+
"noUnusedParameters": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"]
|
|
20
|
+
}
|