create-appraise 0.1.0 → 0.1.2
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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.e2e.test.d.ts +2 -0
- package/dist/cli.e2e.test.d.ts.map +1 -0
- package/dist/cli.e2e.test.js +34 -0
- package/dist/cli.e2e.test.js.map +1 -0
- package/dist/cli.js +82 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +30 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +65 -0
- package/dist/config.test.js.map +1 -0
- package/dist/copy-template.d.ts +4 -0
- package/dist/copy-template.d.ts.map +1 -0
- package/dist/copy-template.js +99 -0
- package/dist/copy-template.js.map +1 -0
- package/dist/copy-template.test.d.ts +2 -0
- package/dist/copy-template.test.d.ts.map +1 -0
- package/dist/copy-template.test.js +52 -0
- package/dist/copy-template.test.js.map +1 -0
- package/dist/download-repo.d.ts +5 -0
- package/dist/download-repo.d.ts.map +1 -0
- package/dist/download-repo.js +104 -0
- package/dist/download-repo.js.map +1 -0
- package/dist/download-repo.test.d.ts +2 -0
- package/dist/download-repo.test.d.ts.map +1 -0
- package/dist/download-repo.test.js +14 -0
- package/dist/download-repo.test.js.map +1 -0
- package/dist/install.d.ts +7 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +34 -0
- package/dist/install.js.map +1 -0
- package/dist/install.test.d.ts +2 -0
- package/dist/install.test.d.ts.map +1 -0
- package/dist/install.test.js +21 -0
- package/dist/install.test.js.map +1 -0
- package/dist/prompts.d.ts +8 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +57 -0
- package/dist/prompts.js.map +1 -0
- package/dist/prompts.test.d.ts +2 -0
- package/dist/prompts.test.d.ts.map +1 -0
- package/dist/prompts.test.js +58 -0
- package/dist/prompts.test.js.map +1 -0
- package/package.json +2 -1
- package/templates/default/.env +2 -0
- package/templates/default/next-env.d.ts +1 -1
- package/templates/default/package.json +1 -1
- package/templates/default/prisma/prisma/dev.db +0 -0
- package/templates/default/scripts/sync-appraise-base-template.ts +106 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.e2e.test.d.ts","sourceRoot":"","sources":["../src/cli.e2e.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { getTemplatePath } from './copy-template.js';
|
|
6
|
+
describe('CLI E2E', () => {
|
|
7
|
+
let tempDir;
|
|
8
|
+
let destDir;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'create-appraise-e2e-'));
|
|
11
|
+
destDir = path.join(tempDir, 'my-app');
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await fs.remove(tempDir).catch(() => { });
|
|
15
|
+
});
|
|
16
|
+
it('scaffolds app when run with non-interactive input (manual run required for full E2E)', async () => {
|
|
17
|
+
const templatePath = getTemplatePath();
|
|
18
|
+
if (!(await fs.pathExists(templatePath))) {
|
|
19
|
+
console.warn('Skipping E2E: template not found (run npm run build first)');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
await fs.ensureDir(destDir);
|
|
23
|
+
const pkgJsonPath = path.join(destDir, 'package.json');
|
|
24
|
+
const srcPath = path.join(destDir, 'src');
|
|
25
|
+
const { copyTemplate } = await import('./copy-template.js');
|
|
26
|
+
await copyTemplate(destDir);
|
|
27
|
+
expect(await fs.pathExists(pkgJsonPath)).toBe(true);
|
|
28
|
+
expect(await fs.pathExists(srcPath)).toBe(true);
|
|
29
|
+
const pkg = await fs.readJson(pkgJsonPath);
|
|
30
|
+
expect(pkg.name).toBe('appraise');
|
|
31
|
+
expect(pkg.scripts?.dev).toBeDefined();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=cli.e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.e2e.test.js","sourceRoot":"","sources":["../src/cli.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,OAAe,CAAC;IACpB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAC3E,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;QACvC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAE1C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC5D,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;QAE5B,MAAM,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import { runPrompts } from './prompts.js';
|
|
5
|
+
import { copyTemplate } from './copy-template.js';
|
|
6
|
+
import { runInstall, getInstallCommand } from './install.js';
|
|
7
|
+
import { getConfig } from './config.js';
|
|
8
|
+
import { downloadRepo } from './download-repo.js';
|
|
9
|
+
function printSuccessMessage(targetDir, packageManager, didInstall) {
|
|
10
|
+
const relativePath = path.relative(process.cwd(), targetDir);
|
|
11
|
+
const cdPath = relativePath.startsWith('..') ? targetDir : `./${relativePath}`;
|
|
12
|
+
console.log('\n\u2713 Appraise app created successfully!\n');
|
|
13
|
+
console.log(` Location: ${targetDir}\n`);
|
|
14
|
+
console.log(' Next steps:\n');
|
|
15
|
+
if (!didInstall) {
|
|
16
|
+
const { command, args } = getInstallCommand(packageManager);
|
|
17
|
+
console.log(` 1. cd ${cdPath}`);
|
|
18
|
+
console.log(` 2. ${command} ${args.join(' ')}`);
|
|
19
|
+
console.log(' 3. npm run setup');
|
|
20
|
+
console.log(' 4. npm run dev\n');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.log(` 1. cd ${cdPath}`);
|
|
24
|
+
console.log(' 2. npm run setup');
|
|
25
|
+
console.log(' 3. npm run dev\n');
|
|
26
|
+
}
|
|
27
|
+
console.log(' See README.md in the project for more details.\n');
|
|
28
|
+
}
|
|
29
|
+
async function main() {
|
|
30
|
+
console.log('\n Create Appraise\n');
|
|
31
|
+
const cwd = process.cwd();
|
|
32
|
+
let answers;
|
|
33
|
+
try {
|
|
34
|
+
answers = await runPrompts(cwd);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
38
|
+
console.error('\n\u2717', message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
const { directory, packageManager, runInstall: shouldRunInstall } = answers;
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
try {
|
|
44
|
+
console.log('\n Validating target directory...');
|
|
45
|
+
console.log(` Creating project at: ${directory}\n`);
|
|
46
|
+
if (config.useBundled) {
|
|
47
|
+
console.log(' Copying template files...');
|
|
48
|
+
await copyTemplate(directory);
|
|
49
|
+
console.log(' Template files copied.\n');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
let cleanupDir = null;
|
|
53
|
+
try {
|
|
54
|
+
console.log(' Downloading template from', config.repoBase, '...');
|
|
55
|
+
const { repoRoot, cleanupDir: dir } = await downloadRepo(config.repoBase, config.branch, config.templateSubpath);
|
|
56
|
+
cleanupDir = dir;
|
|
57
|
+
const templatePathOverride = path.join(repoRoot, config.templateSubpath);
|
|
58
|
+
console.log(' Copying template files...');
|
|
59
|
+
await copyTemplate(directory, undefined, templatePathOverride);
|
|
60
|
+
console.log(' Template files copied.\n');
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (cleanupDir) {
|
|
64
|
+
await fs.remove(cleanupDir).catch(() => { });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (shouldRunInstall) {
|
|
69
|
+
console.log(' Installing dependencies...');
|
|
70
|
+
await runInstall(directory, packageManager);
|
|
71
|
+
console.log(' Dependencies installed.\n');
|
|
72
|
+
}
|
|
73
|
+
printSuccessMessage(directory, packageManager, shouldRunInstall);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
77
|
+
console.error('\n\u2717', message);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
main();
|
|
82
|
+
//# 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/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;CACrB;AAWD,wBAAgB,SAAS,IAAI,MAAM,CAqBlC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const DEFAULT_REPO_BASE = 'https://github.com/jamil2018/appraisejs-core.git';
|
|
2
|
+
const DEFAULT_BRANCH = 'main';
|
|
3
|
+
const DEFAULT_TEMPLATE_SUBPATH = 'templates/default';
|
|
4
|
+
function normalizeRepoBase(value) {
|
|
5
|
+
let s = value.trim();
|
|
6
|
+
while (s.endsWith('/') || s.endsWith('.git')) {
|
|
7
|
+
if (s.endsWith('.git'))
|
|
8
|
+
s = s.slice(0, -4);
|
|
9
|
+
else if (s.endsWith('/'))
|
|
10
|
+
s = s.slice(0, -1);
|
|
11
|
+
}
|
|
12
|
+
return s;
|
|
13
|
+
}
|
|
14
|
+
export function getConfig() {
|
|
15
|
+
const repoBaseRaw = process.env.CREATE_APPRAISE_REPO_URL ?? DEFAULT_REPO_BASE;
|
|
16
|
+
const repoBase = repoBaseRaw ? normalizeRepoBase(repoBaseRaw) : DEFAULT_REPO_BASE;
|
|
17
|
+
const branch = process.env.CREATE_APPRAISE_BRANCH?.trim() ?? DEFAULT_BRANCH;
|
|
18
|
+
const templateSubpath = process.env.CREATE_APPRAISE_TEMPLATE_SUBPATH?.trim() ?? DEFAULT_TEMPLATE_SUBPATH;
|
|
19
|
+
const useBundledRaw = process.env.CREATE_APPRAISE_USE_BUNDLED;
|
|
20
|
+
const useBundled = useBundledRaw !== undefined &&
|
|
21
|
+
useBundledRaw !== '' &&
|
|
22
|
+
['1', 'true', 'yes'].includes(String(useBundledRaw).toLowerCase());
|
|
23
|
+
return {
|
|
24
|
+
repoBase: repoBase || DEFAULT_REPO_BASE,
|
|
25
|
+
branch,
|
|
26
|
+
templateSubpath,
|
|
27
|
+
useBundled,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAAG,kDAAkD,CAAC;AAC7E,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AASrD,SAAS,iBAAiB,CAAC,KAAa;IACtC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aACtC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,iBAAiB,CAAC;IAC9E,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAElF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE,IAAI,cAAc,CAAC;IAE5E,MAAM,eAAe,GACnB,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,IAAI,EAAE,IAAI,wBAAwB,CAAC;IAEnF,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAC9D,MAAM,UAAU,GACd,aAAa,KAAK,SAAS;QAC3B,aAAa,KAAK,EAAE;QACpB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAErE,OAAO;QACL,QAAQ,EAAE,QAAQ,IAAI,iBAAiB;QACvC,MAAM;QACN,eAAe;QACf,UAAU;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { getConfig } from './config.js';
|
|
3
|
+
describe('getConfig', () => {
|
|
4
|
+
const originalEnv = process.env;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
process.env = { ...originalEnv };
|
|
7
|
+
delete process.env.CREATE_APPRAISE_REPO_URL;
|
|
8
|
+
delete process.env.CREATE_APPRAISE_BRANCH;
|
|
9
|
+
delete process.env.CREATE_APPRAISE_TEMPLATE_SUBPATH;
|
|
10
|
+
delete process.env.CREATE_APPRAISE_USE_BUNDLED;
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
process.env = originalEnv;
|
|
14
|
+
});
|
|
15
|
+
it('returns default repo base, branch, template subpath, and useBundled false when no env set', () => {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
expect(config.repoBase).toContain('github.com');
|
|
18
|
+
expect(config.repoBase).toContain('appraise');
|
|
19
|
+
expect(config.branch).toBe('main');
|
|
20
|
+
expect(config.templateSubpath).toBe('templates/default');
|
|
21
|
+
expect(config.useBundled).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it('uses CREATE_APPRAISE_REPO_URL when set', () => {
|
|
24
|
+
process.env.CREATE_APPRAISE_REPO_URL = 'https://example.com/repo';
|
|
25
|
+
const config = getConfig();
|
|
26
|
+
expect(config.repoBase).toBe('https://example.com/repo');
|
|
27
|
+
});
|
|
28
|
+
it('normalizes repo base: trims, removes trailing slash and .git', () => {
|
|
29
|
+
process.env.CREATE_APPRAISE_REPO_URL = ' https://example.com/repo/.git/ ';
|
|
30
|
+
const config = getConfig();
|
|
31
|
+
expect(config.repoBase).toBe('https://example.com/repo');
|
|
32
|
+
});
|
|
33
|
+
it('uses CREATE_APPRAISE_BRANCH when set', () => {
|
|
34
|
+
process.env.CREATE_APPRAISE_BRANCH = 'dev';
|
|
35
|
+
const config = getConfig();
|
|
36
|
+
expect(config.branch).toBe('dev');
|
|
37
|
+
});
|
|
38
|
+
it('uses CREATE_APPRAISE_TEMPLATE_SUBPATH when set', () => {
|
|
39
|
+
process.env.CREATE_APPRAISE_TEMPLATE_SUBPATH = 'templates/custom';
|
|
40
|
+
const config = getConfig();
|
|
41
|
+
expect(config.templateSubpath).toBe('templates/custom');
|
|
42
|
+
});
|
|
43
|
+
it('sets useBundled true when CREATE_APPRAISE_USE_BUNDLED is 1', () => {
|
|
44
|
+
process.env.CREATE_APPRAISE_USE_BUNDLED = '1';
|
|
45
|
+
const config = getConfig();
|
|
46
|
+
expect(config.useBundled).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it('sets useBundled true when CREATE_APPRAISE_USE_BUNDLED is true', () => {
|
|
49
|
+
process.env.CREATE_APPRAISE_USE_BUNDLED = 'true';
|
|
50
|
+
const config = getConfig();
|
|
51
|
+
expect(config.useBundled).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
it('sets useBundled true when CREATE_APPRAISE_USE_BUNDLED is yes', () => {
|
|
54
|
+
process.env.CREATE_APPRAISE_USE_BUNDLED = 'yes';
|
|
55
|
+
const config = getConfig();
|
|
56
|
+
expect(config.useBundled).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
it('sets useBundled false when CREATE_APPRAISE_USE_BUNDLED is empty or 0', () => {
|
|
59
|
+
process.env.CREATE_APPRAISE_USE_BUNDLED = '';
|
|
60
|
+
expect(getConfig().useBundled).toBe(false);
|
|
61
|
+
process.env.CREATE_APPRAISE_USE_BUNDLED = '0';
|
|
62
|
+
expect(getConfig().useBundled).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getCollectedFilesForTest(src: string): string[];
|
|
2
|
+
export declare function getTemplatePath(): string;
|
|
3
|
+
export declare function copyTemplate(destDir: string, onProgress?: (current: number, total: number, filename: string) => void, templatePathOverride?: string): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=copy-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-template.d.ts","sourceRoot":"","sources":["../src/copy-template.ts"],"names":[],"mappings":"AA8DA,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9D;AAED,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvE,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import cliProgress from 'cli-progress';
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const EXCLUDED_DIRS = new Set(['node_modules', '.next', '.git']);
|
|
7
|
+
const EXCLUDED_FILES = new Set([
|
|
8
|
+
'.env',
|
|
9
|
+
'.env.local',
|
|
10
|
+
'.env.*.local',
|
|
11
|
+
'package-lock.json',
|
|
12
|
+
'yarn.lock',
|
|
13
|
+
'pnpm-lock.yaml',
|
|
14
|
+
'bun.lockb',
|
|
15
|
+
]);
|
|
16
|
+
const EXCLUDED_EXTENSIONS = new Set(['.db', '.sqlite', '.sqlite3']);
|
|
17
|
+
function shouldExclude(relativePath, name, stat) {
|
|
18
|
+
if (EXCLUDED_DIRS.has(name))
|
|
19
|
+
return true;
|
|
20
|
+
if (stat.isFile()) {
|
|
21
|
+
if (EXCLUDED_FILES.has(name))
|
|
22
|
+
return true;
|
|
23
|
+
const ext = path.extname(name);
|
|
24
|
+
if (EXCLUDED_EXTENSIONS.has(ext))
|
|
25
|
+
return true;
|
|
26
|
+
if (name.startsWith('.env') && name !== '.env.example')
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
function collectFiles(src, base = '') {
|
|
32
|
+
const resolvedSrc = path.resolve(src);
|
|
33
|
+
let entries;
|
|
34
|
+
try {
|
|
35
|
+
entries = fs.readdirSync(resolvedSrc, { withFileTypes: true });
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const files = [];
|
|
41
|
+
for (const ent of entries) {
|
|
42
|
+
const rel = base ? path.join(base, ent.name) : ent.name;
|
|
43
|
+
const full = path.resolve(resolvedSrc, ent.name);
|
|
44
|
+
let stat;
|
|
45
|
+
try {
|
|
46
|
+
stat = fs.lstatSync(full);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (shouldExclude(rel, ent.name, stat))
|
|
52
|
+
continue;
|
|
53
|
+
if (stat.isSymbolicLink()) {
|
|
54
|
+
files.push(rel);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (stat.isDirectory()) {
|
|
58
|
+
files.push(...collectFiles(full, rel));
|
|
59
|
+
}
|
|
60
|
+
else if (stat.isFile()) {
|
|
61
|
+
files.push(rel);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return files;
|
|
65
|
+
}
|
|
66
|
+
export function getCollectedFilesForTest(src) {
|
|
67
|
+
return collectFiles(src, '');
|
|
68
|
+
}
|
|
69
|
+
export function getTemplatePath() {
|
|
70
|
+
const packageDir = path.resolve(__dirname, '..');
|
|
71
|
+
return path.join(packageDir, 'templates', 'default');
|
|
72
|
+
}
|
|
73
|
+
export async function copyTemplate(destDir, onProgress, templatePathOverride) {
|
|
74
|
+
const templatePath = templatePathOverride ?? getTemplatePath();
|
|
75
|
+
if (!(await fs.pathExists(templatePath))) {
|
|
76
|
+
throw new Error(`Template not found at: ${templatePath}`);
|
|
77
|
+
}
|
|
78
|
+
await fs.ensureDir(destDir);
|
|
79
|
+
const files = collectFiles(templatePath);
|
|
80
|
+
const total = files.length;
|
|
81
|
+
const progressBar = new cliProgress.SingleBar({
|
|
82
|
+
format: 'Copying template files | {bar} | {percentage}% | {value}/{total} files',
|
|
83
|
+
barCompleteChar: '\u2588',
|
|
84
|
+
barIncompleteChar: '\u2591',
|
|
85
|
+
hideCursor: true,
|
|
86
|
+
}, cliProgress.Presets.shades_classic);
|
|
87
|
+
progressBar.start(total, 0);
|
|
88
|
+
for (let i = 0; i < files.length; i++) {
|
|
89
|
+
const rel = files[i];
|
|
90
|
+
const srcFile = path.join(templatePath, rel);
|
|
91
|
+
const destFile = path.join(destDir, rel);
|
|
92
|
+
await fs.ensureDir(path.dirname(destFile));
|
|
93
|
+
await fs.copy(srcFile, destFile);
|
|
94
|
+
progressBar.update(i + 1, { filename: rel });
|
|
95
|
+
onProgress?.(i + 1, total, rel);
|
|
96
|
+
}
|
|
97
|
+
progressBar.stop();
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=copy-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-template.js","sourceRoot":"","sources":["../src/copy-template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-template.test.d.ts","sourceRoot":"","sources":["../src/copy-template.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { copyTemplate, getTemplatePath } from './copy-template.js';
|
|
6
|
+
describe('copy-template', () => {
|
|
7
|
+
let tempDir;
|
|
8
|
+
let destDir;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'create-appraise-test-'));
|
|
11
|
+
destDir = path.join(tempDir, 'output');
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await fs.remove(tempDir).catch(() => { });
|
|
15
|
+
});
|
|
16
|
+
describe('getTemplatePath', () => {
|
|
17
|
+
it('returns a path ending with templates/default', () => {
|
|
18
|
+
const templatePath = getTemplatePath();
|
|
19
|
+
expect(templatePath).toMatch(/[\\/]templates[\\/]default$/);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe('copyTemplate', () => {
|
|
23
|
+
it('copies template files and excludes node_modules, .env, and lockfiles', async () => {
|
|
24
|
+
const fixtureDir = path.join(tempDir, 'fixture');
|
|
25
|
+
await fs.ensureDir(path.join(fixtureDir, 'src', 'app'));
|
|
26
|
+
await fs.ensureDir(path.join(fixtureDir, 'node_modules', 'pkg'));
|
|
27
|
+
await fs.writeJson(path.join(fixtureDir, 'package.json'), { name: 'test' });
|
|
28
|
+
await fs.writeFile(path.join(fixtureDir, '.env'), 'SECRET=1');
|
|
29
|
+
await fs.writeFile(path.join(fixtureDir, 'package-lock.json'), '{}');
|
|
30
|
+
await fs.writeFile(path.join(fixtureDir, 'src', 'app', 'page.tsx'), 'export default function Page() {}');
|
|
31
|
+
const { getCollectedFilesForTest } = await import('./copy-template.js');
|
|
32
|
+
const files = getCollectedFilesForTest(fixtureDir);
|
|
33
|
+
expect(files).toContain('package.json');
|
|
34
|
+
expect(files.some((f) => f.includes('node_modules'))).toBe(false);
|
|
35
|
+
expect(files.some((f) => f.includes('.env'))).toBe(false);
|
|
36
|
+
expect(files.some((f) => f.includes('package-lock'))).toBe(false);
|
|
37
|
+
const srcFiles = files.filter((f) => f.includes('src'));
|
|
38
|
+
expect(srcFiles.length).toBeGreaterThan(0);
|
|
39
|
+
await copyTemplate(destDir, undefined, fixtureDir);
|
|
40
|
+
expect(await fs.pathExists(path.join(destDir, 'package.json'))).toBe(true);
|
|
41
|
+
expect(await fs.pathExists(path.join(destDir, 'src'))).toBe(true);
|
|
42
|
+
expect(await fs.pathExists(path.join(destDir, 'src', 'app', 'page.tsx'))).toBe(true);
|
|
43
|
+
const hasNodeModules = await fs.pathExists(path.join(destDir, 'node_modules'));
|
|
44
|
+
const hasEnv = await fs.pathExists(path.join(destDir, '.env'));
|
|
45
|
+
const hasLock = await fs.pathExists(path.join(destDir, 'package-lock.json'));
|
|
46
|
+
expect(hasNodeModules).toBe(false);
|
|
47
|
+
expect(hasEnv).toBe(false);
|
|
48
|
+
expect(hasLock).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=copy-template.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-template.test.js","sourceRoot":"","sources":["../src/copy-template.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-repo.d.ts","sourceRoot":"","sources":["../src/download-repo.ts"],"names":[],"mappings":"AA+GA,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBnD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
import { x as extractTar } from 'tar';
|
|
6
|
+
const TEMP_PREFIX = 'create-appraise-';
|
|
7
|
+
function getTarballUrl(repoBase, branch) {
|
|
8
|
+
const base = repoBase.replace(/\/$/, '').replace(/\.git$/, '');
|
|
9
|
+
return `${base}/archive/refs/heads/${encodeURIComponent(branch)}.tar.gz`;
|
|
10
|
+
}
|
|
11
|
+
function getCloneUrl(repoBase) {
|
|
12
|
+
return repoBase.replace(/\/$/, '').replace(/\.git$/, '');
|
|
13
|
+
}
|
|
14
|
+
async function tryTarball(repoBase, branch, templateSubpath) {
|
|
15
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), TEMP_PREFIX));
|
|
16
|
+
const archivePath = path.join(tempDir, 'archive.tar.gz');
|
|
17
|
+
try {
|
|
18
|
+
const tarballUrl = getTarballUrl(repoBase, branch);
|
|
19
|
+
const response = await fetch(tarballUrl);
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
return {
|
|
22
|
+
error: `Tarball download failed: ${response.status} ${response.statusText}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
26
|
+
await fs.writeFile(archivePath, Buffer.from(arrayBuffer));
|
|
27
|
+
await extractTar({ file: archivePath, cwd: tempDir });
|
|
28
|
+
const entries = await fs.readdir(tempDir, { withFileTypes: true });
|
|
29
|
+
const topLevelDirs = entries.filter((e) => e.isDirectory());
|
|
30
|
+
if (topLevelDirs.length !== 1) {
|
|
31
|
+
const dirNames = topLevelDirs.map((d) => d.name).join(', ') || 'none';
|
|
32
|
+
return {
|
|
33
|
+
error: `Tarball extract failed: expected exactly one top-level directory, got ${topLevelDirs.length} (${dirNames})`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const repoRoot = path.join(tempDir, topLevelDirs[0].name);
|
|
37
|
+
const templatePath = path.join(repoRoot, templateSubpath);
|
|
38
|
+
const templateExists = await fs.pathExists(templatePath);
|
|
39
|
+
const templateIsDir = templateExists && (await fs.stat(templatePath)).isDirectory();
|
|
40
|
+
if (!templateExists || !templateIsDir) {
|
|
41
|
+
return {
|
|
42
|
+
error: `Template not found at ${templatePath}. The repository may not contain this path.`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return { repoRoot, cleanupDir: tempDir };
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
49
|
+
return { error: `Tarball download failed: ${message}` };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function runGitClone(cloneUrl, branch, tempDir) {
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const child = spawn('git', ['clone', '--depth', '1', '--branch', branch, cloneUrl, tempDir], {
|
|
55
|
+
stdio: 'pipe',
|
|
56
|
+
});
|
|
57
|
+
let stderr = '';
|
|
58
|
+
child.stderr?.on('data', (chunk) => {
|
|
59
|
+
stderr += chunk;
|
|
60
|
+
});
|
|
61
|
+
child.on('error', reject);
|
|
62
|
+
child.on('close', (code) => {
|
|
63
|
+
if (code === 0)
|
|
64
|
+
resolve();
|
|
65
|
+
else
|
|
66
|
+
reject(new Error(`Git clone failed (exit ${code}): ${stderr.trim() || 'unknown'}`));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function tryClone(repoBase, branch, templateSubpath) {
|
|
71
|
+
const cloneUrl = getCloneUrl(repoBase);
|
|
72
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), TEMP_PREFIX));
|
|
73
|
+
try {
|
|
74
|
+
await runGitClone(cloneUrl, branch, tempDir);
|
|
75
|
+
const repoRoot = tempDir;
|
|
76
|
+
const templatePath = path.join(repoRoot, templateSubpath);
|
|
77
|
+
const templateExists = await fs.pathExists(templatePath);
|
|
78
|
+
const templateIsDir = templateExists && (await fs.stat(templatePath)).isDirectory();
|
|
79
|
+
if (!templateExists || !templateIsDir) {
|
|
80
|
+
return {
|
|
81
|
+
error: `Template not found at ${templatePath}. The repository may not contain this path.`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return { repoRoot, cleanupDir: tempDir };
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
88
|
+
return { error: `Git clone failed: ${message}` };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function downloadRepo(repoBase, branch, templateSubpath) {
|
|
92
|
+
const tarballResult = await tryTarball(repoBase, branch, templateSubpath);
|
|
93
|
+
if ('repoRoot' in tarballResult) {
|
|
94
|
+
return { repoRoot: tarballResult.repoRoot, cleanupDir: tarballResult.cleanupDir };
|
|
95
|
+
}
|
|
96
|
+
const cloneResult = await tryClone(repoBase, branch, templateSubpath);
|
|
97
|
+
if ('repoRoot' in cloneResult) {
|
|
98
|
+
return { repoRoot: cloneResult.repoRoot, cleanupDir: cloneResult.cleanupDir };
|
|
99
|
+
}
|
|
100
|
+
const tarballError = tarballResult.error;
|
|
101
|
+
const cloneError = cloneResult.error;
|
|
102
|
+
throw new Error(`Could not download the template. Tarball download failed: ${tarballError}. Git clone failed: ${cloneError}. Set CREATE_APPRAISE_USE_BUNDLED=1 to use the bundled template instead.`);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=download-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-repo.js","sourceRoot":"","sources":["../src/download-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-repo.test.d.ts","sourceRoot":"","sources":["../src/download-repo.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
|
+
import { downloadRepo } from './download-repo.js';
|
|
3
|
+
describe('downloadRepo', () => {
|
|
4
|
+
const originalFetch = globalThis.fetch;
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
globalThis.fetch = originalFetch;
|
|
8
|
+
});
|
|
9
|
+
it('throws with message including both attempts and CREATE_APPRAISE_USE_BUNDLED when both tarball and clone fail', async () => {
|
|
10
|
+
globalThis.fetch = vi.fn().mockResolvedValue({ ok: false, status: 404, statusText: 'Not Found' });
|
|
11
|
+
await expect(downloadRepo('https://github.com/invalid/repo', 'main', 'templates/default')).rejects.toThrow(/CREATE_APPRAISE_USE_BUNDLED/);
|
|
12
|
+
}, 15000);
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=download-repo.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-repo.test.js","sourceRoot":"","sources":["../src/download-repo.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,eAAe,EAAE,CAAC;QACrB,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8GAA8G,EAAE,KAAK,IAAI,EAAE;QAC5H,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;QAElG,MAAM,MAAM,CACV,YAAY,CAAC,iCAAiC,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAC7E,CAAC,OAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACnD,CAAC,EAAE,KAAK,CAAC,CAAC;AACZ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PackageManager } from './prompts.js';
|
|
2
|
+
export declare function getInstallCommand(pm: PackageManager): {
|
|
3
|
+
command: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function runInstall(targetDir: string, pm: PackageManager): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAazF;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAc/E"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export function getInstallCommand(pm) {
|
|
4
|
+
switch (pm) {
|
|
5
|
+
case 'npm':
|
|
6
|
+
return { command: 'npm', args: ['install', '--legacy-peer-deps'] };
|
|
7
|
+
case 'pnpm':
|
|
8
|
+
return { command: 'pnpm', args: ['install'] };
|
|
9
|
+
case 'yarn':
|
|
10
|
+
return { command: 'yarn', args: ['install'] };
|
|
11
|
+
case 'bun':
|
|
12
|
+
return { command: 'bun', args: ['install'] };
|
|
13
|
+
default:
|
|
14
|
+
return { command: 'npm', args: ['install', '--legacy-peer-deps'] };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function runInstall(targetDir, pm) {
|
|
18
|
+
const { command, args } = getInstallCommand(pm);
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const child = spawn(command, args, {
|
|
21
|
+
cwd: path.resolve(targetDir),
|
|
22
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
23
|
+
shell: true,
|
|
24
|
+
});
|
|
25
|
+
child.on('error', reject);
|
|
26
|
+
child.on('close', (code) => {
|
|
27
|
+
if (code === 0)
|
|
28
|
+
resolve();
|
|
29
|
+
else
|
|
30
|
+
reject(new Error(`${command} ${args.join(' ')} exited with code ${code}`));
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,UAAU,iBAAiB,CAAC,EAAkB;IAClD,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,KAAK;YACR,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC;QACrE,KAAK,MAAM;YACT,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,KAAK,MAAM;YACT,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,KAAK,KAAK;YACR,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C;YACE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC;IACvE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,EAAkB;IAC9D,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAChD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAC5B,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;YACvC,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.test.d.ts","sourceRoot":"","sources":["../src/install.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { getInstallCommand } from './install.js';
|
|
3
|
+
describe('getInstallCommand', () => {
|
|
4
|
+
it('returns npm install with legacy-peer-deps for npm', () => {
|
|
5
|
+
const result = getInstallCommand('npm');
|
|
6
|
+
expect(result).toEqual({ command: 'npm', args: ['install', '--legacy-peer-deps'] });
|
|
7
|
+
});
|
|
8
|
+
it('returns pnpm install for pnpm', () => {
|
|
9
|
+
const result = getInstallCommand('pnpm');
|
|
10
|
+
expect(result).toEqual({ command: 'pnpm', args: ['install'] });
|
|
11
|
+
});
|
|
12
|
+
it('returns yarn install for yarn', () => {
|
|
13
|
+
const result = getInstallCommand('yarn');
|
|
14
|
+
expect(result).toEqual({ command: 'yarn', args: ['install'] });
|
|
15
|
+
});
|
|
16
|
+
it('returns bun install for bun', () => {
|
|
17
|
+
const result = getInstallCommand('bun');
|
|
18
|
+
expect(result).toEqual({ command: 'bun', args: ['install'] });
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=install.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.test.js","sourceRoot":"","sources":["../src/install.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
2
|
+
export interface PromptAnswers {
|
|
3
|
+
directory: string;
|
|
4
|
+
packageManager: PackageManager;
|
|
5
|
+
runInstall: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function runPrompts(cwd: string): Promise<PromptAnswers>;
|
|
8
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,OAAO,CAAC;CACrB;AAuBD,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqCpE"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { input, select, confirm } from '@inquirer/prompts';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
const DEFAULT_DIR = './my-appraise-app';
|
|
5
|
+
function isDirEmpty(dirPath) {
|
|
6
|
+
if (!fs.existsSync(dirPath))
|
|
7
|
+
return true;
|
|
8
|
+
const entries = fs.readdirSync(dirPath);
|
|
9
|
+
return entries.length === 0;
|
|
10
|
+
}
|
|
11
|
+
function validateTargetDirectory(resolved) {
|
|
12
|
+
if (!fs.existsSync(resolved))
|
|
13
|
+
return;
|
|
14
|
+
const stat = fs.statSync(resolved);
|
|
15
|
+
if (!stat.isDirectory()) {
|
|
16
|
+
throw new Error(`Path exists and is not a directory: ${resolved}`);
|
|
17
|
+
}
|
|
18
|
+
if (!isDirEmpty(resolved)) {
|
|
19
|
+
throw new Error(`Directory must be empty: ${resolved}\nPlease choose an empty directory or a new path.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function runPrompts(cwd) {
|
|
23
|
+
const rawDir = await input({
|
|
24
|
+
message: 'Where should we create your app?',
|
|
25
|
+
default: DEFAULT_DIR,
|
|
26
|
+
validate: (value) => {
|
|
27
|
+
if (!value?.trim())
|
|
28
|
+
return 'Please enter a directory path.';
|
|
29
|
+
return true;
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const directory = rawDir.trim() || DEFAULT_DIR;
|
|
33
|
+
const resolved = path.resolve(cwd, directory);
|
|
34
|
+
try {
|
|
35
|
+
validateTargetDirectory(resolved);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
throw new Error(message);
|
|
40
|
+
}
|
|
41
|
+
const packageManager = await select({
|
|
42
|
+
message: 'Which package manager do you want to use?',
|
|
43
|
+
choices: [
|
|
44
|
+
{ name: 'npm', value: 'npm' },
|
|
45
|
+
{ name: 'pnpm', value: 'pnpm' },
|
|
46
|
+
{ name: 'yarn', value: 'yarn' },
|
|
47
|
+
{ name: 'bun', value: 'bun' },
|
|
48
|
+
],
|
|
49
|
+
default: 'npm',
|
|
50
|
+
});
|
|
51
|
+
const runInstall = await confirm({
|
|
52
|
+
message: 'Would you like to run the package installation now?',
|
|
53
|
+
default: true,
|
|
54
|
+
});
|
|
55
|
+
return { directory: resolved, packageManager, runInstall };
|
|
56
|
+
}
|
|
57
|
+
//# 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,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAUpB,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,SAAS,UAAU,CAAC,OAAe;IACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO;IACrC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,4BAA4B,QAAQ,mDAAmD,CACxF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QACzB,OAAO,EAAE,kCAAkC;QAC3C,OAAO,EAAE,WAAW;QACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;gBAAE,OAAO,gCAAgC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,WAAW,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,MAAM,CAAiB;QAClD,OAAO,EAAE,2CAA2C;QACpD,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;YAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC/B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC/B,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;SAC9B;QACD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;QAC/B,OAAO,EAAE,qDAAqD;QAC9D,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.test.d.ts","sourceRoot":"","sources":["../src/prompts.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { runPrompts } from './prompts.js';
|
|
6
|
+
vi.mock('@inquirer/prompts', () => ({
|
|
7
|
+
input: vi.fn(),
|
|
8
|
+
select: vi.fn(),
|
|
9
|
+
confirm: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
async function getMocks() {
|
|
12
|
+
const { input, select, confirm } = await import('@inquirer/prompts');
|
|
13
|
+
return { input: input, select: select, confirm: confirm };
|
|
14
|
+
}
|
|
15
|
+
describe('runPrompts', () => {
|
|
16
|
+
let cwd;
|
|
17
|
+
let tempDir;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
cwd = process.cwd();
|
|
20
|
+
tempDir = path.join(os.tmpdir(), `create-appraise-prompts-${Date.now()}`);
|
|
21
|
+
});
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
24
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
25
|
+
}
|
|
26
|
+
vi.clearAllMocks();
|
|
27
|
+
});
|
|
28
|
+
it('returns directory, packageManager, and runInstall from mocked prompts', async () => {
|
|
29
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
30
|
+
const { input, select, confirm } = await getMocks();
|
|
31
|
+
input.mockResolvedValue(tempDir);
|
|
32
|
+
select.mockResolvedValue('pnpm');
|
|
33
|
+
confirm.mockResolvedValue(false);
|
|
34
|
+
const result = await runPrompts(cwd);
|
|
35
|
+
expect(result.directory).toBe(path.resolve(cwd, tempDir));
|
|
36
|
+
expect(result.packageManager).toBe('pnpm');
|
|
37
|
+
expect(result.runInstall).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it('throws when target directory exists and is non-empty', async () => {
|
|
40
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
41
|
+
fs.writeFileSync(path.join(tempDir, 'file.txt'), 'x');
|
|
42
|
+
const { input } = await getMocks();
|
|
43
|
+
input.mockResolvedValue(tempDir);
|
|
44
|
+
await expect(runPrompts(cwd)).rejects.toThrow(/Directory must be empty/);
|
|
45
|
+
});
|
|
46
|
+
it('accepts when target directory does not exist', async () => {
|
|
47
|
+
const newPath = path.join(tempDir, 'new-app');
|
|
48
|
+
const { input, select, confirm } = await getMocks();
|
|
49
|
+
input.mockResolvedValue(newPath);
|
|
50
|
+
select.mockResolvedValue('npm');
|
|
51
|
+
confirm.mockResolvedValue(true);
|
|
52
|
+
const result = await runPrompts(cwd);
|
|
53
|
+
expect(result.directory).toBe(path.resolve(cwd, newPath));
|
|
54
|
+
expect(result.packageManager).toBe('npm');
|
|
55
|
+
expect(result.runInstall).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=prompts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.test.js","sourceRoot":"","sources":["../src/prompts.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IAClC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;IACd,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;IACf,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;CACjB,CAAC,CAAC,CAAC;AAEJ,KAAK,UAAU,QAAQ;IACrB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACrE,OAAO,EAAE,KAAK,EAAE,KAAiC,EAAE,MAAM,EAAE,MAAkC,EAAE,OAAO,EAAE,OAAmC,EAAE,CAAC;AAChJ,CAAC;AAED,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,GAAW,CAAC;IAChB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,GAAG,EAAE;QACd,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACpB,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,2BAA2B,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,IAAI,OAAO,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACpD,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEjC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QAErC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;QACtD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACnC,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAEjC,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC9C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACpD,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAChC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QAErC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-appraise",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Scaffold a new Appraise app in your directory",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Hasnat Jamil",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"templates"
|
|
36
36
|
],
|
|
37
37
|
"scripts": {
|
|
38
|
+
"prepublishOnly": "npm run build",
|
|
38
39
|
"build": "npm run sync-templates && tsc",
|
|
39
40
|
"sync-templates": "tsx scripts/sync-templates.ts",
|
|
40
41
|
"test": "vitest run",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"sync-template-step-groups": "npx tsx scripts/sync-template-step-groups.ts",
|
|
26
26
|
"sync-template-steps": "npx tsx scripts/sync-template-steps.ts",
|
|
27
27
|
"sync-all": "npx tsx scripts/sync-all.ts",
|
|
28
|
-
"sync-template": "
|
|
28
|
+
"sync-template": "npx tsx scripts/sync-appraise-base-template.ts",
|
|
29
29
|
"test": "cucumber-js",
|
|
30
30
|
"appraise:setup": "npm run setup",
|
|
31
31
|
"appraise:sync": "npm run sync-all"
|
|
Binary file
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sync the default template from the base app (repo root).
|
|
4
|
+
* Copies src/, prisma/, public/, scripts/, and root config files into templates/default/,
|
|
5
|
+
* preserves template-only README.md and appraise.config.json, and merges package.json scripts.
|
|
6
|
+
*
|
|
7
|
+
* Usage: npx tsx scripts/sync-appraise-base-template.ts
|
|
8
|
+
* Or: npm run sync-template
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { cpSync, readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
12
|
+
import { dirname, join } from 'path';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const repoRoot = join(__dirname, '..');
|
|
17
|
+
const target = join(repoRoot, 'templates', 'default');
|
|
18
|
+
|
|
19
|
+
const EXCLUDED_DIRS = new Set(['node_modules', '.next', '.git']);
|
|
20
|
+
const EXCLUDED_EXTENSIONS = new Set(['.db', '.sqlite', '.sqlite3']);
|
|
21
|
+
|
|
22
|
+
function shouldExclude(relativePath: string): boolean {
|
|
23
|
+
const parts = relativePath.split(/[/\\]/);
|
|
24
|
+
if (parts.some((p) => EXCLUDED_DIRS.has(p))) return true;
|
|
25
|
+
const ext = relativePath.endsWith('.sqlite3')
|
|
26
|
+
? '.sqlite3'
|
|
27
|
+
: relativePath.endsWith('.sqlite')
|
|
28
|
+
? '.sqlite'
|
|
29
|
+
: relativePath.slice(relativePath.lastIndexOf('.'));
|
|
30
|
+
if (EXCLUDED_EXTENSIONS.has(ext)) return true;
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function copyDirWithFilter(src: string, dest: string): void {
|
|
35
|
+
cpSync(src, dest, {
|
|
36
|
+
recursive: true,
|
|
37
|
+
force: true,
|
|
38
|
+
filter: (source: string) => {
|
|
39
|
+
const rel = source.slice(src.length).replace(/^[/\\]/, '') || '';
|
|
40
|
+
return !shouldExclude(rel);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function copyFile(src: string, dest: string): void {
|
|
46
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
47
|
+
cpSync(src, dest, { force: true });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 1. Preserve template-only files
|
|
51
|
+
const readmePath = join(target, 'README.md');
|
|
52
|
+
const appraiseConfigPath = join(target, 'appraise.config.json');
|
|
53
|
+
const savedReadme = existsSync(readmePath) ? readFileSync(readmePath, 'utf8') : null;
|
|
54
|
+
const savedAppraiseConfig = existsSync(appraiseConfigPath)
|
|
55
|
+
? readFileSync(appraiseConfigPath, 'utf8')
|
|
56
|
+
: null;
|
|
57
|
+
|
|
58
|
+
// 2. Copy directories
|
|
59
|
+
console.log('Copying src/...');
|
|
60
|
+
copyDirWithFilter(join(repoRoot, 'src'), join(target, 'src'));
|
|
61
|
+
console.log('Copying prisma/...');
|
|
62
|
+
copyDirWithFilter(join(repoRoot, 'prisma'), join(target, 'prisma'));
|
|
63
|
+
console.log('Copying public/...');
|
|
64
|
+
copyDirWithFilter(join(repoRoot, 'public'), join(target, 'public'));
|
|
65
|
+
console.log('Copying scripts/...');
|
|
66
|
+
copyDirWithFilter(join(repoRoot, 'scripts'), join(target, 'scripts'));
|
|
67
|
+
|
|
68
|
+
// 3. Copy root config files
|
|
69
|
+
const configFiles = [
|
|
70
|
+
'eslint.config.mjs',
|
|
71
|
+
'tailwind.config.ts',
|
|
72
|
+
'tsconfig.json',
|
|
73
|
+
'postcss.config.mjs',
|
|
74
|
+
'components.json',
|
|
75
|
+
'next.config.ts',
|
|
76
|
+
'.env.example',
|
|
77
|
+
];
|
|
78
|
+
console.log('Copying config files...');
|
|
79
|
+
for (const name of configFiles) {
|
|
80
|
+
const src = join(repoRoot, name);
|
|
81
|
+
if (existsSync(src)) {
|
|
82
|
+
copyFile(src, join(target, name));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 4. package.json: base + template-only scripts
|
|
87
|
+
const rootPkg = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8')) as {
|
|
88
|
+
scripts: Record<string, string>;
|
|
89
|
+
[key: string]: unknown;
|
|
90
|
+
};
|
|
91
|
+
rootPkg.scripts['appraise:setup'] = 'npm run setup';
|
|
92
|
+
rootPkg.scripts['appraise:sync'] = 'npm run sync-all';
|
|
93
|
+
writeFileSync(join(target, 'package.json'), JSON.stringify(rootPkg, null, 2) + '\n');
|
|
94
|
+
console.log('Wrote package.json with appraise:setup and appraise:sync.');
|
|
95
|
+
|
|
96
|
+
// 5. Restore template-only files
|
|
97
|
+
if (savedReadme) {
|
|
98
|
+
writeFileSync(readmePath, savedReadme);
|
|
99
|
+
console.log('Restored README.md');
|
|
100
|
+
}
|
|
101
|
+
if (savedAppraiseConfig) {
|
|
102
|
+
writeFileSync(appraiseConfigPath, savedAppraiseConfig);
|
|
103
|
+
console.log('Restored appraise.config.json');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('Synced base app to templates/default.');
|