create-carlonicora-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/LICENSE +675 -0
- package/README.md +104 -0
- package/bin/cli.js +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +92 -0
- package/dist/cli.js.map +1 -0
- package/dist/git.d.ts +7 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +80 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +5 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +30 -0
- package/dist/prompts.js.map +1 -0
- package/dist/replacer.d.ts +9 -0
- package/dist/replacer.d.ts.map +1 -0
- package/dist/replacer.js +11 -0
- package/dist/replacer.js.map +1 -0
- package/dist/scaffold.d.ts +3 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +79 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/files.d.ts +6 -0
- package/dist/utils/files.d.ts.map +1 -0
- package/dist/utils/files.js +103 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +35 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/validation.d.ts +6 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +63 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +52 -0
- package/template/.env.example +159 -0
- package/template/.github/workflows/check-library-updates.yml +71 -0
- package/template/.github/workflows/dev.yml +63 -0
- package/template/.github/workflows/pull-request.yml +55 -0
- package/template/.gitmodules +6 -0
- package/template/.husky/pre-commit +1 -0
- package/template/.husky/pre-push +1 -0
- package/template/.prettierignore +1 -0
- package/template/.prettierrc +13 -0
- package/template/.releaserc +134 -0
- package/template/.vscode/settings.json +16 -0
- package/template/CHANGELOG.md +0 -0
- package/template/CLAUDE.md +34 -0
- package/template/DOCKER.md +1591 -0
- package/template/Dockerfile +228 -0
- package/template/README.md +1 -0
- package/template/apps/api/.prettierrc +12 -0
- package/template/apps/api/eslint.config.mjs +54 -0
- package/template/apps/api/jest.config.js +29 -0
- package/template/apps/api/nest-cli.json +15 -0
- package/template/apps/api/package.json +155 -0
- package/template/apps/api/src/config/config.ts +17 -0
- package/template/apps/api/src/config/enums/job.name.ts +6 -0
- package/template/apps/api/src/config/enums/queue.id.ts +3 -0
- package/template/apps/api/src/config/interfaces/config.interface.ts +3 -0
- package/template/apps/api/src/features/features.modules.ts +6 -0
- package/template/apps/api/src/i18n/en/notifications.json +3 -0
- package/template/apps/api/src/main.ts +23 -0
- package/template/apps/api/src/neo4j.migrations/20250901_001.ts +33 -0
- package/template/apps/api/src/neo4j.migrations/20250901_002.ts +90 -0
- package/template/apps/api/src/neo4j.migrations/20250901_003.ts +57 -0
- package/template/apps/api/src/neo4j.migrations/20250901_004.ts +32 -0
- package/template/apps/api/src/neo4j.migrations/queries/migration.queries.ts +49 -0
- package/template/apps/api/src/types/langchain.d.ts +56 -0
- package/template/apps/api/tsconfig.build.json +4 -0
- package/template/apps/api/tsconfig.json +38 -0
- package/template/apps/web/.swcrc +26 -0
- package/template/apps/web/components.json +21 -0
- package/template/apps/web/eslint.config.mjs +33 -0
- package/template/apps/web/global.d.ts +7 -0
- package/template/apps/web/messages/en.json +249 -0
- package/template/apps/web/next.config.js +50 -0
- package/template/apps/web/package.json +146 -0
- package/template/apps/web/playwright.config.ts +86 -0
- package/template/apps/web/postcss.config.mjs +5 -0
- package/template/apps/web/public/sw.js +32 -0
- package/template/apps/web/src/app/[locale]/(admin)/administration/companies/[id]/page.tsx +46 -0
- package/template/apps/web/src/app/[locale]/(admin)/administration/companies/page.tsx +23 -0
- package/template/apps/web/src/app/[locale]/(admin)/layout.tsx +49 -0
- package/template/apps/web/src/app/[locale]/(auth)/activation/[code]/page.tsx +13 -0
- package/template/apps/web/src/app/[locale]/(auth)/auth/page.tsx +11 -0
- package/template/apps/web/src/app/[locale]/(auth)/invitation/[code]/page.tsx +7 -0
- package/template/apps/web/src/app/[locale]/(auth)/layout.tsx +9 -0
- package/template/apps/web/src/app/[locale]/(auth)/login/page.tsx +6 -0
- package/template/apps/web/src/app/[locale]/(auth)/logout/page.tsx +5 -0
- package/template/apps/web/src/app/[locale]/(auth)/register/page.tsx +6 -0
- package/template/apps/web/src/app/[locale]/(auth)/reset/[code]/page.tsx +7 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/notifications/page.tsx +9 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/roles/[id]/page.tsx +23 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/roles/page.tsx +12 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/error.tsx +14 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/loading.tsx +21 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/page.tsx +46 -0
- package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/page.tsx +17 -0
- package/template/apps/web/src/app/[locale]/(main)/error.tsx +62 -0
- package/template/apps/web/src/app/[locale]/(main)/layout.tsx +40 -0
- package/template/apps/web/src/app/[locale]/(main)/page.tsx +41 -0
- package/template/apps/web/src/app/[locale]/layout.tsx +54 -0
- package/template/apps/web/src/app/globals.css +256 -0
- package/template/apps/web/src/config/BootstrapProvider.tsx +13 -0
- package/template/apps/web/src/config/Bootstrapper.ts +77 -0
- package/template/apps/web/src/config/env.ts +51 -0
- package/template/apps/web/src/config/middleware-env.ts +14 -0
- package/template/apps/web/src/enums/feature.ids.ts +3 -0
- package/template/apps/web/src/features/common/components/containers/IndexContainer.tsx +11 -0
- package/template/apps/web/src/features/common/components/details/LayoutDetails.tsx +33 -0
- package/template/apps/web/src/features/common/components/navigations/CommonSidebar.tsx +233 -0
- package/template/apps/web/src/features/common/components/navigations/CreationDropDown.tsx +117 -0
- package/template/apps/web/src/features/common/components/navigations/UserSidebarFooter.tsx +115 -0
- package/template/apps/web/src/features/common/components/navigations/VersionDisplay.tsx +18 -0
- package/template/apps/web/src/features/common/contexts/ErrorContext.tsx +62 -0
- package/template/apps/web/src/i18n/request.ts +13 -0
- package/template/apps/web/src/i18n/routing.ts +9 -0
- package/template/apps/web/src/i18n/useDateFnsLocale.ts +15 -0
- package/template/apps/web/src/proxy.ts +107 -0
- package/template/apps/web/src/server-actions/auth-cookies.ts +134 -0
- package/template/apps/web/src/types/modules.d.ts +10 -0
- package/template/apps/web/src/utils/metadata.ts +50 -0
- package/template/apps/web/src/utils/revalidation.ts +7 -0
- package/template/apps/web/tsconfig.json +51 -0
- package/template/docker-compose.yml +211 -0
- package/template/package.json +72 -0
- package/template/packages/nestjs-neo4jsonapi/.gitkeep +0 -0
- package/template/packages/nextjs-jsonapi/.gitkeep +0 -0
- package/template/packages/shared/package.json +23 -0
- package/template/packages/shared/src/const/roles.id.ts +5 -0
- package/template/packages/shared/src/const/system.roles.id.ts +4 -0
- package/template/packages/shared/src/index.ts +1 -0
- package/template/packages/shared/tsconfig.json +10 -0
- package/template/packages/shared/tsup.config.ts +16 -0
- package/template/pnpm-workspace.yaml +3 -0
- package/template/tsconfig.base.json +62 -0
- package/template/tsconfig.json +12 -0
- package/template/turbo.json +88 -0
- package/template/versions.production.json +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# create-carlonicora-app
|
|
2
|
+
|
|
3
|
+
CLI tool to scaffold a new NestJS + Next.js monorepo project with Neo4j and JSON:API.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### With npx (recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx create-carlonicora-app my-project
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### With global installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g create-carlonicora-app
|
|
17
|
+
create-carlonicora-app my-project
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Options
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
create-carlonicora-app [project-name] [options]
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
--skip-git Skip git initialization and submodules
|
|
27
|
+
--skip-install Skip dependency installation
|
|
28
|
+
-V, --version Output version number
|
|
29
|
+
-h, --help Display help
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## What's Included
|
|
33
|
+
|
|
34
|
+
The generated project includes:
|
|
35
|
+
|
|
36
|
+
- **apps/api** - NestJS 11 backend with:
|
|
37
|
+
- Fastify HTTP server
|
|
38
|
+
- Neo4j graph database integration
|
|
39
|
+
- BullMQ job processing
|
|
40
|
+
- JWT authentication
|
|
41
|
+
- JSON:API standard compliance
|
|
42
|
+
- OpenTelemetry observability
|
|
43
|
+
- LangChain AI integration
|
|
44
|
+
|
|
45
|
+
- **apps/web** - Next.js 16 frontend with:
|
|
46
|
+
- React 19
|
|
47
|
+
- Tailwind CSS 4
|
|
48
|
+
- shadcn/ui components
|
|
49
|
+
- next-intl internationalization
|
|
50
|
+
- JSON:API client
|
|
51
|
+
|
|
52
|
+
- **packages/shared** - Shared types and constants
|
|
53
|
+
|
|
54
|
+
- **Git submodules**:
|
|
55
|
+
- `@carlonicora/nestjs-neo4jsonapi`
|
|
56
|
+
- `@carlonicora/nextjs-jsonapi`
|
|
57
|
+
|
|
58
|
+
## Prerequisites
|
|
59
|
+
|
|
60
|
+
- Node.js 18+
|
|
61
|
+
- pnpm 10+
|
|
62
|
+
- Git
|
|
63
|
+
|
|
64
|
+
## After Scaffolding
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd my-project
|
|
68
|
+
cp .env.example .env
|
|
69
|
+
# Edit .env with your configuration
|
|
70
|
+
pnpm dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
### Building the CLI
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm install
|
|
79
|
+
pnpm build
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Syncing template from source
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm sync-template
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Testing locally
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Build first
|
|
92
|
+
pnpm build
|
|
93
|
+
|
|
94
|
+
# Test with node directly
|
|
95
|
+
node bin/cli.js test-project
|
|
96
|
+
|
|
97
|
+
# Or link globally
|
|
98
|
+
npm link
|
|
99
|
+
create-carlonicora-app test-project
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
GPL-3.0 - See [LICENSE](LICENSE) for details.
|
package/bin/cli.js
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { validateProjectName } from './utils/validation.js';
|
|
5
|
+
import { directoryExists, directoryIsEmpty } from './utils/files.js';
|
|
6
|
+
import { checkGitInstalled, checkPnpmInstalled } from './git.js';
|
|
7
|
+
import { promptProjectName, promptOverwrite, promptContinueWithoutGit, promptContinueWithoutPnpm, } from './prompts.js';
|
|
8
|
+
import { scaffold } from './scaffold.js';
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('create-carlonicora-app')
|
|
12
|
+
.description('Create a new NestJS + Next.js monorepo project with Neo4j and JSON:API')
|
|
13
|
+
.version('1.0.0')
|
|
14
|
+
.argument('[project-name]', 'Name of the project')
|
|
15
|
+
.option('--skip-git', 'Skip git initialization and submodules')
|
|
16
|
+
.option('--skip-install', 'Skip dependency installation')
|
|
17
|
+
.action(async (projectName, options) => {
|
|
18
|
+
console.log();
|
|
19
|
+
console.log(chalk.bold.cyan('create-carlonicora-app'));
|
|
20
|
+
console.log(chalk.gray('Creating a new NestJS + Next.js monorepo project'));
|
|
21
|
+
console.log();
|
|
22
|
+
try {
|
|
23
|
+
// 1. Get project name (from argument or prompt)
|
|
24
|
+
let name = projectName;
|
|
25
|
+
if (!name) {
|
|
26
|
+
name = await promptProjectName();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const validation = validateProjectName(name);
|
|
30
|
+
if (!validation.valid) {
|
|
31
|
+
console.error(chalk.red(`Error: ${validation.message}`));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 2. Determine target directory
|
|
36
|
+
const targetDir = path.resolve(process.cwd(), name);
|
|
37
|
+
// 3. Check if directory exists and is not empty
|
|
38
|
+
if (await directoryExists(targetDir)) {
|
|
39
|
+
if (!(await directoryIsEmpty(targetDir))) {
|
|
40
|
+
const overwrite = await promptOverwrite(name);
|
|
41
|
+
if (!overwrite) {
|
|
42
|
+
console.log(chalk.yellow('Aborted.'));
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// 4. Check prerequisites
|
|
48
|
+
let skipGit = options.skipGit ?? false;
|
|
49
|
+
let skipInstall = options.skipInstall ?? false;
|
|
50
|
+
if (!skipGit && !checkGitInstalled()) {
|
|
51
|
+
console.log(chalk.yellow('Warning: Git is not installed.'));
|
|
52
|
+
const continueWithoutGit = await promptContinueWithoutGit();
|
|
53
|
+
if (continueWithoutGit) {
|
|
54
|
+
skipGit = true;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.log(chalk.yellow('Aborted. Please install git first.'));
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!skipInstall && !checkPnpmInstalled()) {
|
|
62
|
+
console.log(chalk.yellow('Warning: pnpm is not installed.'));
|
|
63
|
+
const continueWithoutPnpm = await promptContinueWithoutPnpm();
|
|
64
|
+
if (continueWithoutPnpm) {
|
|
65
|
+
skipInstall = true;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.log(chalk.yellow('Aborted. Please install pnpm first.'));
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 5. Run scaffold
|
|
73
|
+
await scaffold({
|
|
74
|
+
projectName: name,
|
|
75
|
+
targetDir,
|
|
76
|
+
skipGit,
|
|
77
|
+
skipInstall,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error();
|
|
82
|
+
if (error instanceof Error) {
|
|
83
|
+
console.error(chalk.red('Error:'), error.message);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.error(chalk.red('An unexpected error occurred'));
|
|
87
|
+
}
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
program.parse();
|
|
92
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function initGit(targetDir: string): Promise<void>;
|
|
2
|
+
export declare function addSubmodules(targetDir: string): Promise<void>;
|
|
3
|
+
export declare function installDependencies(targetDir: string): Promise<void>;
|
|
4
|
+
export declare function checkGitInstalled(): boolean;
|
|
5
|
+
export declare function checkPnpmInstalled(): boolean;
|
|
6
|
+
export declare function createInitialCommit(targetDir: string): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAOA,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCpE;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1E;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAO5C;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU1E"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { execSync, exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
export async function initGit(targetDir) {
|
|
7
|
+
execSync('git init', { cwd: targetDir, stdio: 'pipe' });
|
|
8
|
+
}
|
|
9
|
+
export async function addSubmodules(targetDir) {
|
|
10
|
+
const submodules = [
|
|
11
|
+
{
|
|
12
|
+
path: 'packages/nestjs-neo4jsonapi',
|
|
13
|
+
url: 'https://github.com/carlonicora/nestjs-neo4jsonapi',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
path: 'packages/nextjs-jsonapi',
|
|
17
|
+
url: 'https://github.com/carlonicora/nextjs-jsonapi',
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
for (const submodule of submodules) {
|
|
21
|
+
// Remove placeholder directory if it exists (contains .gitkeep)
|
|
22
|
+
const submodulePath = path.join(targetDir, submodule.path);
|
|
23
|
+
if (await fs.pathExists(submodulePath)) {
|
|
24
|
+
await fs.remove(submodulePath);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
execSync(`git submodule add ${submodule.url} ${submodule.path}`, {
|
|
28
|
+
cwd: targetDir,
|
|
29
|
+
stdio: 'pipe',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
// If submodule already exists, continue
|
|
34
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
35
|
+
if (!errorMessage.includes('already exists')) {
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Initialize submodules
|
|
41
|
+
execSync('git submodule update --init --recursive', {
|
|
42
|
+
cwd: targetDir,
|
|
43
|
+
stdio: 'pipe',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export async function installDependencies(targetDir) {
|
|
47
|
+
// Use inherit for stdio so user can see the install progress
|
|
48
|
+
execSync('pnpm install', { cwd: targetDir, stdio: 'inherit' });
|
|
49
|
+
}
|
|
50
|
+
export function checkGitInstalled() {
|
|
51
|
+
try {
|
|
52
|
+
execSync('git --version', { stdio: 'pipe' });
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function checkPnpmInstalled() {
|
|
60
|
+
try {
|
|
61
|
+
execSync('pnpm --version', { stdio: 'pipe' });
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function createInitialCommit(targetDir) {
|
|
69
|
+
try {
|
|
70
|
+
execSync('git add .', { cwd: targetDir, stdio: 'pipe' });
|
|
71
|
+
execSync('git commit -m "Initial commit from create-carlonicora-app"', {
|
|
72
|
+
cwd: targetDir,
|
|
73
|
+
stdio: 'pipe',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Commit might fail if nothing to commit, which is fine
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { scaffold } from './scaffold.js';
|
|
2
|
+
export { validateProjectName, toKebabCase, toPascalCase } from './utils/validation.js';
|
|
3
|
+
export { applyReplacements } from './replacer.js';
|
|
4
|
+
export type { ScaffoldOptions, ReplacementConfig, ValidationResult } from './types/index.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Main entry point - re-exports for programmatic usage
|
|
2
|
+
export { scaffold } from './scaffold.js';
|
|
3
|
+
export { validateProjectName, toKebabCase, toPascalCase } from './utils/validation.js';
|
|
4
|
+
export { applyReplacements } from './replacer.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function promptProjectName(): Promise<string>;
|
|
2
|
+
export declare function promptOverwrite(dirName: string): Promise<boolean>;
|
|
3
|
+
export declare function promptContinueWithoutGit(): Promise<boolean>;
|
|
4
|
+
export declare function promptContinueWithoutPnpm(): Promise<boolean>;
|
|
5
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAGA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQzD;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CAKjE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,OAAO,CAAC,CAKlE"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { input, confirm } from '@inquirer/prompts';
|
|
2
|
+
import { validateProjectName } from './utils/validation.js';
|
|
3
|
+
export async function promptProjectName() {
|
|
4
|
+
return input({
|
|
5
|
+
message: 'What is your project name?',
|
|
6
|
+
validate: (value) => {
|
|
7
|
+
const result = validateProjectName(value);
|
|
8
|
+
return result.valid || result.message;
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export async function promptOverwrite(dirName) {
|
|
13
|
+
return confirm({
|
|
14
|
+
message: `Directory "${dirName}" already exists and is not empty. Overwrite?`,
|
|
15
|
+
default: false,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export async function promptContinueWithoutGit() {
|
|
19
|
+
return confirm({
|
|
20
|
+
message: 'Git is not installed. Continue without git initialization?',
|
|
21
|
+
default: true,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export async function promptContinueWithoutPnpm() {
|
|
25
|
+
return confirm({
|
|
26
|
+
message: 'pnpm is not installed. Continue without dependency installation?',
|
|
27
|
+
default: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,OAAO,KAAK,CAAC;QACX,OAAO,EAAE,4BAA4B;QACrC,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE;YAC1B,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC1C,OAAO,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAQ,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,cAAc,OAAO,+CAA+C;QAC7E,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,4DAA4D;QACrE,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,OAAO,OAAO,CAAC;QACb,OAAO,EAAE,kEAAkE;QAC3E,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReplacementConfig } from './types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Replaces {{name}} placeholders with the actual project name.
|
|
4
|
+
*
|
|
5
|
+
* The template files use {{name}} as a placeholder which gets replaced
|
|
6
|
+
* with the user's chosen project name during scaffolding.
|
|
7
|
+
*/
|
|
8
|
+
export declare function applyReplacements(content: string, config: ReplacementConfig): string;
|
|
9
|
+
//# sourceMappingURL=replacer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replacer.d.ts","sourceRoot":"","sources":["../src/replacer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAGpF"}
|
package/dist/replacer.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replaces {{name}} placeholders with the actual project name.
|
|
3
|
+
*
|
|
4
|
+
* The template files use {{name}} as a placeholder which gets replaced
|
|
5
|
+
* with the user's chosen project name during scaffolding.
|
|
6
|
+
*/
|
|
7
|
+
export function applyReplacements(content, config) {
|
|
8
|
+
// Simple replacement of {{name}} placeholder with project name
|
|
9
|
+
return content.split('{{name}}').join(config.projectNameKebab);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=replacer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replacer.js","sourceRoot":"","sources":["../src/replacer.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAyB;IAC1E,+DAA+D;IAC/D,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,kBAAkB,CAAC;AAS3E,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EtE"}
|
package/dist/scaffold.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { copyTemplate, ensureEmptyDir } from './utils/files.js';
|
|
6
|
+
import { toKebabCase, toPascalCase } from './utils/validation.js';
|
|
7
|
+
import { initGit, addSubmodules, installDependencies, createInitialCommit } from './git.js';
|
|
8
|
+
import { printSuccessMessage } from './utils/logger.js';
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
export async function scaffold(options) {
|
|
12
|
+
const { projectName, targetDir, skipGit, skipInstall } = options;
|
|
13
|
+
const config = {
|
|
14
|
+
projectName,
|
|
15
|
+
projectNameKebab: toKebabCase(projectName),
|
|
16
|
+
projectNamePascal: toPascalCase(projectName),
|
|
17
|
+
};
|
|
18
|
+
const spinner = ora();
|
|
19
|
+
try {
|
|
20
|
+
// Step 1: Create/clean target directory
|
|
21
|
+
spinner.start('Creating project directory...');
|
|
22
|
+
await ensureEmptyDir(targetDir);
|
|
23
|
+
spinner.succeed('Created project directory');
|
|
24
|
+
// Step 2: Copy template files with replacements
|
|
25
|
+
spinner.start('Copying template files...');
|
|
26
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
27
|
+
if (!(await fs.pathExists(templateDir))) {
|
|
28
|
+
spinner.fail('Template directory not found');
|
|
29
|
+
throw new Error(`Template directory not found at ${templateDir}. ` +
|
|
30
|
+
'Please run "npm run sync-template" first.');
|
|
31
|
+
}
|
|
32
|
+
await copyTemplate(templateDir, targetDir, config);
|
|
33
|
+
spinner.succeed('Copied template files');
|
|
34
|
+
// Step 3: Initialize git repository
|
|
35
|
+
if (!skipGit) {
|
|
36
|
+
spinner.start('Initializing git repository...');
|
|
37
|
+
try {
|
|
38
|
+
await initGit(targetDir);
|
|
39
|
+
spinner.succeed('Initialized git repository');
|
|
40
|
+
// Step 4: Add git submodules
|
|
41
|
+
spinner.start('Adding git submodules (this may take a moment)...');
|
|
42
|
+
await addSubmodules(targetDir);
|
|
43
|
+
spinner.succeed('Added git submodules');
|
|
44
|
+
// Create initial commit
|
|
45
|
+
spinner.start('Creating initial commit...');
|
|
46
|
+
await createInitialCommit(targetDir);
|
|
47
|
+
spinner.succeed('Created initial commit');
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
spinner.warn('Git initialization skipped (git may not be installed)');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
spinner.info('Skipped git initialization');
|
|
55
|
+
}
|
|
56
|
+
// Step 5: Install dependencies
|
|
57
|
+
if (!skipInstall) {
|
|
58
|
+
spinner.start('Installing dependencies (this may take a few minutes)...');
|
|
59
|
+
spinner.stopAndPersist({ symbol: '📦', text: 'Installing dependencies...' });
|
|
60
|
+
try {
|
|
61
|
+
await installDependencies(targetDir);
|
|
62
|
+
spinner.succeed('Installed dependencies');
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
spinner.warn('Dependency installation failed. Run "pnpm install" manually.');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
spinner.info('Skipped dependency installation');
|
|
70
|
+
}
|
|
71
|
+
// Step 6: Print success message
|
|
72
|
+
printSuccessMessage(projectName, targetDir);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
spinner.fail('Scaffold failed');
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ScaffoldOptions {
|
|
2
|
+
projectName: string;
|
|
3
|
+
targetDir: string;
|
|
4
|
+
skipGit?: boolean;
|
|
5
|
+
skipInstall?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ReplacementConfig {
|
|
8
|
+
projectName: string;
|
|
9
|
+
projectNameKebab: string;
|
|
10
|
+
projectNamePascal: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
message?: string;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ReplacementConfig } from '../types/index.js';
|
|
2
|
+
export declare function copyTemplate(srcDir: string, destDir: string, config: ReplacementConfig): Promise<void>;
|
|
3
|
+
export declare function ensureEmptyDir(dir: string): Promise<void>;
|
|
4
|
+
export declare function directoryExists(dir: string): Promise<boolean>;
|
|
5
|
+
export declare function directoryIsEmpty(dir: string): Promise<boolean>;
|
|
6
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA0C3D,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAcf;AAuBD,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/D;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { applyReplacements } from '../replacer.js';
|
|
4
|
+
const BINARY_EXTENSIONS = new Set([
|
|
5
|
+
// Images
|
|
6
|
+
'.png',
|
|
7
|
+
'.jpg',
|
|
8
|
+
'.jpeg',
|
|
9
|
+
'.gif',
|
|
10
|
+
'.webp',
|
|
11
|
+
'.ico',
|
|
12
|
+
'.svg',
|
|
13
|
+
'.bmp',
|
|
14
|
+
'.tiff',
|
|
15
|
+
// Fonts
|
|
16
|
+
'.woff',
|
|
17
|
+
'.woff2',
|
|
18
|
+
'.ttf',
|
|
19
|
+
'.eot',
|
|
20
|
+
'.otf',
|
|
21
|
+
// Archives
|
|
22
|
+
'.tar',
|
|
23
|
+
'.zip',
|
|
24
|
+
'.gz',
|
|
25
|
+
'.rar',
|
|
26
|
+
'.7z',
|
|
27
|
+
// Documents
|
|
28
|
+
'.pdf',
|
|
29
|
+
// Lock files (treat as binary to avoid corruption)
|
|
30
|
+
'.lock',
|
|
31
|
+
// Other binary formats
|
|
32
|
+
'.exe',
|
|
33
|
+
'.dll',
|
|
34
|
+
'.so',
|
|
35
|
+
'.dylib',
|
|
36
|
+
]);
|
|
37
|
+
function isBinaryFile(filePath) {
|
|
38
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
39
|
+
return BINARY_EXTENSIONS.has(ext);
|
|
40
|
+
}
|
|
41
|
+
export async function copyTemplate(srcDir, destDir, config) {
|
|
42
|
+
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
45
|
+
const destPath = path.join(destDir, entry.name);
|
|
46
|
+
if (entry.isDirectory()) {
|
|
47
|
+
await fs.ensureDir(destPath);
|
|
48
|
+
await copyTemplate(srcPath, destPath, config);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
await copyFile(srcPath, destPath, config);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function copyFile(srcPath, destPath, config) {
|
|
56
|
+
if (isBinaryFile(srcPath)) {
|
|
57
|
+
// Binary file - copy as-is
|
|
58
|
+
await fs.copy(srcPath, destPath);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Text file - apply replacements
|
|
62
|
+
try {
|
|
63
|
+
let content = await fs.readFile(srcPath, 'utf-8');
|
|
64
|
+
content = applyReplacements(content, config);
|
|
65
|
+
await fs.writeFile(destPath, content, 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// If reading as text fails, copy as binary
|
|
69
|
+
await fs.copy(srcPath, destPath);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export async function ensureEmptyDir(dir) {
|
|
74
|
+
if (await fs.pathExists(dir)) {
|
|
75
|
+
const files = await fs.readdir(dir);
|
|
76
|
+
if (files.length > 0) {
|
|
77
|
+
// Directory exists and is not empty
|
|
78
|
+
await fs.emptyDir(dir);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
await fs.ensureDir(dir);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function directoryExists(dir) {
|
|
86
|
+
try {
|
|
87
|
+
const stat = await fs.stat(dir);
|
|
88
|
+
return stat.isDirectory();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export async function directoryIsEmpty(dir) {
|
|
95
|
+
try {
|
|
96
|
+
const files = await fs.readdir(dir);
|
|
97
|
+
return files.length === 0;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=files.js.map
|