@undp/create-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/bin/generateFiles.js +65 -0
- package/bin/generateTemplates/copyTemplate.js +18 -0
- package/bin/generateTemplates/generateIndexHtml.js +15 -0
- package/bin/generateTemplates/generatePackageJson.js +105 -0
- package/bin/generateTemplates/generateReadme.js +143 -0
- package/bin/generateTemplates/generateStyleCss.js +6 -0
- package/bin/generateTemplates/index.js +6 -0
- package/bin/generateTemplates/templates/basic/App.txt +32 -0
- package/bin/generateTemplates/templates/basic/AppWithContainer.txt +32 -0
- package/bin/generateTemplates/templates/basic/main.txt +10 -0
- package/bin/generateTemplates/templates/configFiles/.prettierrc +10 -0
- package/bin/generateTemplates/templates/configFiles/eslint.config.js +97 -0
- package/bin/generateTemplates/templates/configFiles/icon.txt +1 -0
- package/bin/generateTemplates/templates/configFiles/staticwebapp.config.json +44 -0
- package/bin/generateTemplates/templates/configFiles/tailwind.config.js +7 -0
- package/bin/generateTemplates/templates/configFiles/tsconfig.json +29 -0
- package/bin/generateTemplates/templates/configFiles/tsconfig.node.json +9 -0
- package/bin/generateTemplates/templates/configFiles/vite-env.txt +1 -0
- package/bin/generateTemplates/templates/configFiles/vite.config.ts.txt +109 -0
- package/bin/generateTemplates/templates/configFiles/viteWithoutPostCss.config.ts.txt +58 -0
- package/bin/generateTemplates/templates/css/fonts.css +213 -0
- package/bin/generateTemplates/templates/query/App.txt +57 -0
- package/bin/generateTemplates/templates/query/AppWithContainer.txt +67 -0
- package/bin/generateTemplates/templates/query/main.txt +29 -0
- package/bin/generateTemplates/templates/router/App.txt +30 -0
- package/bin/generateTemplates/templates/router/components/Footer.txt +20 -0
- package/bin/generateTemplates/templates/router/components/Header.txt +29 -0
- package/bin/generateTemplates/templates/router/main.txt +60 -0
- package/bin/generateTemplates/templates/router/routes/About.txt +28 -0
- package/bin/generateTemplates/templates/router+query/App.txt +30 -0
- package/bin/generateTemplates/templates/router+query/components/Footer.txt +20 -0
- package/bin/generateTemplates/templates/router+query/components/Header.txt +29 -0
- package/bin/generateTemplates/templates/router+query/integration/tanstack-query.txt +27 -0
- package/bin/generateTemplates/templates/router+query/main.txt +69 -0
- package/bin/generateTemplates/templates/router+query/routes/queryDemo.txt +56 -0
- package/bin/index.js +57 -0
- package/bin/promptUser.js +96 -0
- package/bin/utils/createFolders.js +11 -0
- package/bin/utils/index.js +2 -0
- package/bin/utils/printSuccess.js +23 -0
- package/package.json +32 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createRoute } from '@tanstack/react-router';
|
|
2
|
+
import type { RootRoute } from '@tanstack/react-router';
|
|
3
|
+
|
|
4
|
+
function About() {
|
|
5
|
+
return (
|
|
6
|
+
<div className='m-5'>
|
|
7
|
+
<div>
|
|
8
|
+
<img
|
|
9
|
+
src={undpLogo}
|
|
10
|
+
className='logo react mb-8'
|
|
11
|
+
alt='React logo'
|
|
12
|
+
width='72px'
|
|
13
|
+
style={{ marginLeft: 'auto', marginRight: 'auto' }}
|
|
14
|
+
/>
|
|
15
|
+
</div>
|
|
16
|
+
<H3 className='text-center'>
|
|
17
|
+
This is an about page
|
|
18
|
+
</H3>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default (parentRoute: RootRoute) =>
|
|
24
|
+
createRoute({
|
|
25
|
+
path: '/about',
|
|
26
|
+
component: About,
|
|
27
|
+
getParentRoute: () => parentRoute,
|
|
28
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { H3 } from '@undp/design-system-react';
|
|
2
|
+
|
|
3
|
+
import '@/styles/fonts.css';
|
|
4
|
+
import '@/styles/style.css';
|
|
5
|
+
import undpLogo from './assets/undp-logo-blue.svg';
|
|
6
|
+
|
|
7
|
+
function App() {
|
|
8
|
+
return (
|
|
9
|
+
<div className='m-5'>
|
|
10
|
+
<div>
|
|
11
|
+
<img
|
|
12
|
+
src={undpLogo}
|
|
13
|
+
className='logo react mb-8'
|
|
14
|
+
alt='React logo'
|
|
15
|
+
width='72px'
|
|
16
|
+
style={{ marginLeft: 'auto', marginRight: 'auto' }}
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
<H3 className='text-center'>
|
|
20
|
+
This is template for building visualization and frontend project
|
|
21
|
+
maintained by UNDP's DAI Hub.
|
|
22
|
+
<br />
|
|
23
|
+
<br />
|
|
24
|
+
Contact us at data@undp.org if you have any feedback or questions.
|
|
25
|
+
</H3>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default App;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Footer,
|
|
3
|
+
FooterLogoUnit,
|
|
4
|
+
FooterCopyrightUnit,
|
|
5
|
+
} from '@undp/design-system-react/Footer';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export default function Header() {
|
|
10
|
+
return (
|
|
11
|
+
<Footer>
|
|
12
|
+
<FooterLogoUnit>
|
|
13
|
+
subscribe to email
|
|
14
|
+
</FooterLogoUnit>
|
|
15
|
+
<FooterCopyrightUnit>
|
|
16
|
+
Footnote can be added here
|
|
17
|
+
</FooterCopyrightUnit>
|
|
18
|
+
</Footer>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Header,
|
|
3
|
+
HeaderLogoUnit,
|
|
4
|
+
HeaderMainNavUnit,
|
|
5
|
+
HeaderMenuUnit,
|
|
6
|
+
} from '@undp/design-system-react/Header';
|
|
7
|
+
import { Link } from '@tanstack/react-router';
|
|
8
|
+
|
|
9
|
+
export default function Header() {
|
|
10
|
+
return (
|
|
11
|
+
<Header>
|
|
12
|
+
<HeaderLogoUnit
|
|
13
|
+
hyperlink="./"
|
|
14
|
+
siteName="Site name"
|
|
15
|
+
siteSubName="Sub-site name"
|
|
16
|
+
/>
|
|
17
|
+
<HeaderMainNavUnit>
|
|
18
|
+
<HeaderMenuUnit>
|
|
19
|
+
<Link to='/'>
|
|
20
|
+
Home
|
|
21
|
+
</Link>
|
|
22
|
+
<Link to='/query-demo'>
|
|
23
|
+
Query Demo
|
|
24
|
+
</Link>
|
|
25
|
+
</HeaderMenuUnit>
|
|
26
|
+
</HeaderMainNavUnit>
|
|
27
|
+
</Header>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
|
|
3
|
+
export function getContext() {
|
|
4
|
+
const queryClient = new QueryClient({
|
|
5
|
+
defaultOptions: {
|
|
6
|
+
queries: {
|
|
7
|
+
staleTime: 1000 * 60 * 60 * 24, // how long fetched data is considered āfreshā before it becomes āstaleā š”¢ 24 hrs
|
|
8
|
+
gcTime: 1000 * 60 * 60 * 24, // how long inactive (unused) query data stays in memory before being deleted 𔢠24 hrs
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
queryClient,
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function Provider({
|
|
18
|
+
children,
|
|
19
|
+
queryClient,
|
|
20
|
+
}: {
|
|
21
|
+
children: React.ReactNode
|
|
22
|
+
queryClient: QueryClient
|
|
23
|
+
}) {
|
|
24
|
+
return (
|
|
25
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { StrictMode } from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom/client';
|
|
3
|
+
import {
|
|
4
|
+
Outlet,
|
|
5
|
+
RouterProvider,
|
|
6
|
+
createRootRoute,
|
|
7
|
+
createRoute,
|
|
8
|
+
createRouter,
|
|
9
|
+
} from '@tanstack/react-router';
|
|
10
|
+
|
|
11
|
+
import Header from './components/Header';
|
|
12
|
+
import Footer from './components/Footer';
|
|
13
|
+
import * as TanStackQueryProvider from './integration/tanstack-query';
|
|
14
|
+
|
|
15
|
+
import './styles/fonts.css';
|
|
16
|
+
import './styles/style.css';
|
|
17
|
+
|
|
18
|
+
import App from './App';
|
|
19
|
+
|
|
20
|
+
const rootRoute = createRootRoute({
|
|
21
|
+
component: () => (
|
|
22
|
+
<>
|
|
23
|
+
<Header />
|
|
24
|
+
<Outlet />
|
|
25
|
+
<Footer />
|
|
26
|
+
</>
|
|
27
|
+
),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const indexRoute = createRoute({
|
|
31
|
+
getParentRoute: () => rootRoute,
|
|
32
|
+
path: '/',
|
|
33
|
+
component: App,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const routeTree = rootRoute.addChildren([
|
|
37
|
+
indexRoute,
|
|
38
|
+
TanStackQueryDemo(rootRoute),
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const TanStackQueryProviderContext = TanStackQueryProvider.getContext();
|
|
42
|
+
const router = createRouter({
|
|
43
|
+
routeTree,
|
|
44
|
+
context: {
|
|
45
|
+
...TanStackQueryProviderContext,
|
|
46
|
+
},
|
|
47
|
+
defaultPreload: 'intent',
|
|
48
|
+
scrollRestoration: true,
|
|
49
|
+
defaultStructuralSharing: true,
|
|
50
|
+
defaultPreloadStaleTime: 0,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
declare module '@tanstack/react-router' {
|
|
54
|
+
interface Register {
|
|
55
|
+
router: typeof router;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const rootElement = document.getElementById('app');
|
|
60
|
+
if (rootElement && !rootElement.innerHTML) {
|
|
61
|
+
const root = ReactDOM.createRoot(rootElement);
|
|
62
|
+
root.render(
|
|
63
|
+
<StrictMode>
|
|
64
|
+
<TanStackQueryProvider.Provider {...TanStackQueryProviderContext}>
|
|
65
|
+
<RouterProvider router={router} />
|
|
66
|
+
</TanStackQueryProvider.Provider>
|
|
67
|
+
</StrictMode>,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createRoute } from '@tanstack/react-router';
|
|
2
|
+
import { useQuery } from '@tanstack/react-query';
|
|
3
|
+
import type { RootRoute } from '@tanstack/react-router';
|
|
4
|
+
import { Spinner } from '@undp/design-system-react/Spinner';
|
|
5
|
+
|
|
6
|
+
function useTodoData() {
|
|
7
|
+
return useQuery({
|
|
8
|
+
queryKey: ['todos'],
|
|
9
|
+
queryFn: () =>
|
|
10
|
+
Promise.resolve([
|
|
11
|
+
{ id: 1, name: 'Alice' },
|
|
12
|
+
{ id: 2, name: 'Bob' },
|
|
13
|
+
{ id: 3, name: 'Charlie' },
|
|
14
|
+
]),
|
|
15
|
+
initialData: [],
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function TanStackQueryDemo() {
|
|
20
|
+
const { data, isLoading, isError } = useTodoData();
|
|
21
|
+
|
|
22
|
+
if (isLoading) return <Spinner size='lg' className='my-20 m-auto' />;
|
|
23
|
+
|
|
24
|
+
if (isError)
|
|
25
|
+
return (
|
|
26
|
+
<div className='px-4 mx-auto'>
|
|
27
|
+
<div>Error</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
return (
|
|
31
|
+
<div className='m-5'>
|
|
32
|
+
<div>
|
|
33
|
+
<img
|
|
34
|
+
src={undpLogo}
|
|
35
|
+
className='logo react mb-8'
|
|
36
|
+
alt='React logo'
|
|
37
|
+
width='72px'
|
|
38
|
+
style={{ marginLeft: 'auto', marginRight: 'auto' }}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
<H3 className='text-center'>
|
|
42
|
+
Data loaded successfully
|
|
43
|
+
<br />
|
|
44
|
+
<br />
|
|
45
|
+
{data.length} elements in the query
|
|
46
|
+
</H3>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default (parentRoute: RootRoute) =>
|
|
52
|
+
createRoute({
|
|
53
|
+
path: '/query-demo',
|
|
54
|
+
component: TanStackQueryDemo,
|
|
55
|
+
getParentRoute: () => parentRoute,
|
|
56
|
+
});
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { promptUser } from './promptUser.js';
|
|
7
|
+
import { generateFiles } from './generateFiles.js';
|
|
8
|
+
import { printSuccess, createFolders } from './utils/index.js';
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
// Get user configuration
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const projectName = args[0];
|
|
14
|
+
const config = await promptUser(projectName);
|
|
15
|
+
|
|
16
|
+
const projectPath = path.resolve(process.cwd(), config.projectName);
|
|
17
|
+
console.log(chalk.gray('\n' + 'ā'.repeat(60)));
|
|
18
|
+
console.log(chalk.bold.green(`\nš Creating project at: ${chalk.cyan(projectPath)}\n`));
|
|
19
|
+
|
|
20
|
+
createFolders(projectPath, true);
|
|
21
|
+
|
|
22
|
+
process.chdir(projectPath);
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
createFolders(path.join(projectPath, 'public'), false);
|
|
26
|
+
createFolders(path.join(projectPath, 'src'), false);
|
|
27
|
+
createFolders(path.join(projectPath, 'src', 'styles'), false);
|
|
28
|
+
createFolders(path.join(projectPath, 'src', 'assets'), false);
|
|
29
|
+
|
|
30
|
+
if(config.installRouter) {
|
|
31
|
+
createFolders(path.join(projectPath, 'src', 'routes'), false);
|
|
32
|
+
createFolders(path.join(projectPath, 'src', 'components'), false);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if(config.installRouter && config.installQuery) {
|
|
36
|
+
createFolders(path.join(projectPath, 'src', 'integration'), false);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
generateFiles(config);
|
|
40
|
+
|
|
41
|
+
const { installNow } = await inquirer.prompt([
|
|
42
|
+
{
|
|
43
|
+
type: 'confirm',
|
|
44
|
+
name: 'installNow',
|
|
45
|
+
message: 'Would you like to install dependencies now?',
|
|
46
|
+
default: true,
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
console.log(chalk.bold.yellow('\nš¦ Installing dependencies (this might take some time)...'));
|
|
51
|
+
if (installNow) execSync('npm install', { stdio: 'inherit' })
|
|
52
|
+
console.log(chalk.green(' ā All dependencies installed'));
|
|
53
|
+
|
|
54
|
+
printSuccess(config, installNow);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
const rl = readline.createInterface({
|
|
6
|
+
input: process.stdin,
|
|
7
|
+
output: process.stdout,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const question = (query) =>
|
|
11
|
+
new Promise(resolve => rl.question(query, resolve));
|
|
12
|
+
|
|
13
|
+
export async function promptUser(name) {
|
|
14
|
+
console.log(
|
|
15
|
+
chalk.bold.cyan("\nš UNDP Frontend Starter Kit | Let's configure your application") +
|
|
16
|
+
chalk.gray('\nš§ Powered by React, Vite, TypeScript, ESLint, Prettier, Tailwind, and React Compiler\n')
|
|
17
|
+
);
|
|
18
|
+
console.log(chalk.gray('ā'.repeat(60)) + '\n');
|
|
19
|
+
|
|
20
|
+
const projectName = name ? name : (await question(chalk.yellow('š Enter project name: '))) || 'my-undp-react-app';
|
|
21
|
+
|
|
22
|
+
const { libraries } = await inquirer.prompt([
|
|
23
|
+
{
|
|
24
|
+
type: 'checkbox',
|
|
25
|
+
name: 'libraries',
|
|
26
|
+
message: chalk.yellow('š¦ Select the libraries you want to install:'),
|
|
27
|
+
choices: [
|
|
28
|
+
{ name: '@undp/data-viz (for visualizations)', value: '@undp/data-viz' },
|
|
29
|
+
{ name: 'lucide-react (for icons)', value: 'lucide-react' },
|
|
30
|
+
{ name: '@tanstack/react-router (for routing)', value: '@tanstack/react-router' },
|
|
31
|
+
{ name: '@tanstack/react-query (for state management and fetching data from api)', value: '@tanstack/react-query' },
|
|
32
|
+
],
|
|
33
|
+
default: ['@undp/data-viz', 'lucide-react'], // optional default selection
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
36
|
+
const installLucide = libraries.includes('lucide-react');
|
|
37
|
+
const installDataViz = libraries.includes('@undp/data-viz');
|
|
38
|
+
const installRouter = libraries.includes('@tanstack/react-router');
|
|
39
|
+
const installQuery = libraries.includes('@tanstack/react-query');
|
|
40
|
+
|
|
41
|
+
let installDataVizPeerDeps = false;
|
|
42
|
+
if (installDataViz) {
|
|
43
|
+
const { peerDeps } = await inquirer.prompt([
|
|
44
|
+
{
|
|
45
|
+
type: 'list',
|
|
46
|
+
name: 'peerDeps',
|
|
47
|
+
message: chalk.yellow('š¦ Add peer dependencies for @undp/data-viz?'),
|
|
48
|
+
choices: ['Yes', 'No'],
|
|
49
|
+
default: 'Yes',
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
installDataVizPeerDeps = peerDeps === 'Yes'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let addPostCSSScripts = false;
|
|
56
|
+
|
|
57
|
+
if(!installRouter) {
|
|
58
|
+
const { postCSS } = await inquirer.prompt([
|
|
59
|
+
{
|
|
60
|
+
type: 'list',
|
|
61
|
+
name: 'postCSS',
|
|
62
|
+
message: chalk.yellow(
|
|
63
|
+
'āļø Add PostCSS script to flatten layers, wrap all classes in `.undp-container`, and reorder media queries (recommended if embedding in another app)?'
|
|
64
|
+
),
|
|
65
|
+
choices: ['Yes', 'No'],
|
|
66
|
+
default: 'Yes',
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
addPostCSSScripts = postCSS === 'Yes';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { staticWebApp } = await inquirer.prompt([
|
|
73
|
+
{
|
|
74
|
+
type: 'list',
|
|
75
|
+
name: 'staticWebApp',
|
|
76
|
+
message: chalk.yellow('āļø Add Azure Static Web App Config file?'),
|
|
77
|
+
choices: ['Yes', 'No'],
|
|
78
|
+
default: 'No',
|
|
79
|
+
},
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
// Convert string responses to booleans for convenience
|
|
83
|
+
const addStaticWebAppConfig = staticWebApp === 'Yes';
|
|
84
|
+
|
|
85
|
+
rl.close();
|
|
86
|
+
return {
|
|
87
|
+
projectName,
|
|
88
|
+
installLucide,
|
|
89
|
+
installDataViz,
|
|
90
|
+
installDataVizPeerDeps,
|
|
91
|
+
addStaticWebAppConfig,
|
|
92
|
+
addPostCSSScripts,
|
|
93
|
+
installRouter,
|
|
94
|
+
installQuery
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export function createFolders(dir, showError){
|
|
5
|
+
if (!fs.existsSync(dir)) {
|
|
6
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
7
|
+
} else if(showError) {
|
|
8
|
+
console.error(chalk.red(`ā Error: Folder "${config.projectName}" already exists.`));
|
|
9
|
+
throw new Error(`Project folder already exists at ${projectPath}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export function printSuccess(config, installNow){
|
|
5
|
+
console.log(chalk.bold.green('\nā
Project created successfully!\n'));
|
|
6
|
+
|
|
7
|
+
console.log(chalk.cyan('š¦ Added packages:'));
|
|
8
|
+
console.log(chalk.gray(' ⢠React + TypeScript + Vite'));
|
|
9
|
+
console.log(chalk.gray(' ⢠Tailwind CSS'));
|
|
10
|
+
console.log(chalk.gray(' ⢠ESLint + Prettier'));
|
|
11
|
+
console.log(chalk.gray(' ⢠@undp/design-system-react'));
|
|
12
|
+
if (config.installLucide) console.log(chalk.gray(' ⢠lucide-react'));
|
|
13
|
+
if (config.installDataViz) console.log(chalk.gray(' ⢠@undp/data-viz'));
|
|
14
|
+
if (config.installQuery) console.log(chalk.gray(' ⢠@tanstack/react-query'));
|
|
15
|
+
if (config.installRouter) console.log(chalk.gray(' ⢠@tanstack/react-router'));
|
|
16
|
+
|
|
17
|
+
console.log(chalk.cyan('\nš Next steps:'));
|
|
18
|
+
console.log(chalk.white(` cd ${chalk.bold(config.projectName)}`));
|
|
19
|
+
if(!installNow) console.log(chalk.white(` ${chalk.bold('npm install')}`));
|
|
20
|
+
console.log(chalk.white(` ${chalk.bold('npm run dev')}`));
|
|
21
|
+
|
|
22
|
+
console.log(chalk.dim('\nHappy coding! š\n'));
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@undp/create-app",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "UNDP's project scaffolding tool",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-undp-app": "./bin/index.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "node ./bin/index.js"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"files": ["bin", "dist", "templates"],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"UNDP",
|
|
17
|
+
"scaffold",
|
|
18
|
+
"generator",
|
|
19
|
+
"cli"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"chalk": "^4.1.2",
|
|
23
|
+
"fs-extra": "^11.1.0",
|
|
24
|
+
"inquirer": "^8.2.7"
|
|
25
|
+
},
|
|
26
|
+
"author": "UNDP",
|
|
27
|
+
"license": "ISC",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^24.10.0"
|
|
31
|
+
}
|
|
32
|
+
}
|