fabrica-e-commerce 0.1.3 → 0.1.4
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/package.json +1 -1
- package/src/github.js +94 -17
package/package.json
CHANGED
package/src/github.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import { commandExists, runCommand, runCommandCapture } from './system.js';
|
|
3
|
+
import { choose } from './prompt.js';
|
|
3
4
|
import { kv, section, spinner } from './ui.js';
|
|
4
5
|
|
|
5
6
|
export async function isGithubCliInstalled() {
|
|
@@ -11,6 +12,11 @@ export async function isLoggedInToGithub() {
|
|
|
11
12
|
return result.code === 0;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
async function setupGithubGitCredentials() {
|
|
16
|
+
const result = await runCommandCapture('gh', ['auth', 'setup-git']);
|
|
17
|
+
return result.code === 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
export async function ensureGithubLogin() {
|
|
15
21
|
section('GitHub login');
|
|
16
22
|
if (!(await isGithubCliInstalled())) {
|
|
@@ -19,15 +25,23 @@ export async function ensureGithubLogin() {
|
|
|
19
25
|
const spin = spinner('Checking GitHub CLI login');
|
|
20
26
|
if (await isLoggedInToGithub()) {
|
|
21
27
|
spin.succeed('Already logged in to GitHub');
|
|
22
|
-
|
|
28
|
+
} else {
|
|
29
|
+
spin.fail('Not logged in to GitHub');
|
|
30
|
+
console.log('A browser/device flow will open so you can log in with "gh auth login"...');
|
|
31
|
+
await runCommand('gh', ['auth', 'login', '--hostname', 'github.com', '--git-protocol', 'https', '--web']);
|
|
32
|
+
if (!(await isLoggedInToGithub())) {
|
|
33
|
+
throw new Error('GitHub login was not completed. Run "fabrica build" again after logging in with "gh auth login".');
|
|
34
|
+
}
|
|
35
|
+
kv('GitHub', 'Logged in');
|
|
23
36
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
|
|
38
|
+
const gitSpin = spinner('Configuring GitHub credentials for git push');
|
|
39
|
+
if (await setupGithubGitCredentials()) {
|
|
40
|
+
gitSpin.succeed('GitHub credentials ready for git push');
|
|
41
|
+
} else {
|
|
42
|
+
gitSpin.fail('Could not configure GitHub git credentials automatically');
|
|
43
|
+
console.log('If git push asks for credentials, complete the prompt or run: gh auth setup-git');
|
|
29
44
|
}
|
|
30
|
-
kv('GitHub', 'Logged in');
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
async function getGithubLogin() {
|
|
@@ -36,6 +50,72 @@ async function getGithubLogin() {
|
|
|
36
50
|
return result.stdout.trim();
|
|
37
51
|
}
|
|
38
52
|
|
|
53
|
+
async function githubRepoExists(owner, repoName) {
|
|
54
|
+
const result = await runCommandCapture('gh', ['repo', 'view', `${owner}/${repoName}`, '--json', 'name']);
|
|
55
|
+
return result.code === 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function ensureGithubRepo(owner, repoName) {
|
|
59
|
+
const fullName = `${owner}/${repoName}`;
|
|
60
|
+
if (await githubRepoExists(owner, repoName)) {
|
|
61
|
+
const action = await choose(`GitHub repo ${fullName} already exists. What should Fabrica do?`, [
|
|
62
|
+
{ name: 'Use the existing repo and push this storefront to it', value: 'use' },
|
|
63
|
+
{ name: 'Stop so I can choose a different Vercel project/repo name', value: 'stop' }
|
|
64
|
+
]);
|
|
65
|
+
if (action === 'stop') throw new Error(`GitHub repo ${fullName} already exists. Re-run build with a different project name.`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const spin = spinner(`Creating GitHub repo ${fullName}`);
|
|
70
|
+
const create = await runCommandCapture('gh', ['repo', 'create', fullName, '--private']);
|
|
71
|
+
if (create.code !== 0) {
|
|
72
|
+
spin.fail('Could not create GitHub repository');
|
|
73
|
+
throw new Error(create.stderr || 'gh repo create failed');
|
|
74
|
+
}
|
|
75
|
+
spin.succeed(`Created GitHub repo ${fullName}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function setOrigin(project, repoUrl) {
|
|
79
|
+
const existing = await runCommandCapture('git', ['remote', 'get-url', 'origin'], { cwd: project.target });
|
|
80
|
+
if (existing.code === 0) {
|
|
81
|
+
await runCommand('git', ['remote', 'set-url', 'origin', repoUrl], { cwd: project.target });
|
|
82
|
+
} else {
|
|
83
|
+
await runCommand('git', ['remote', 'add', 'origin', repoUrl], { cwd: project.target });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function pushWithCredentialFallback(project) {
|
|
88
|
+
const spin = spinner('Pushing storefront to GitHub');
|
|
89
|
+
let push = await runCommandCapture('git', ['push', '-u', 'origin', 'main'], { cwd: project.target });
|
|
90
|
+
if (push.code === 0) {
|
|
91
|
+
spin.succeed('Pushed storefront to GitHub');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
spin.fail('Initial git push failed');
|
|
96
|
+
console.log('GitHub rejected the push credentials. Re-configuring GitHub CLI credentials and retrying...');
|
|
97
|
+
await setupGithubGitCredentials();
|
|
98
|
+
push = await runCommandCapture('git', ['push', '-u', 'origin', 'main'], { cwd: project.target });
|
|
99
|
+
if (push.code === 0) {
|
|
100
|
+
kv('GitHub push', 'Succeeded after refreshing credentials');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log(push.stderr || push.stdout || 'git push failed');
|
|
105
|
+
const action = await choose('GitHub push still needs authentication. What should Fabrica do?', [
|
|
106
|
+
{ name: 'Open GitHub login again, then retry push', value: 'login' },
|
|
107
|
+
{ name: 'Stop so I can fix GitHub credentials manually', value: 'stop' }
|
|
108
|
+
]);
|
|
109
|
+
if (action === 'login') {
|
|
110
|
+
await runCommand('gh', ['auth', 'login', '--hostname', 'github.com', '--git-protocol', 'https', '--web']);
|
|
111
|
+
await setupGithubGitCredentials();
|
|
112
|
+
await runCommand('git', ['push', '-u', 'origin', 'main'], { cwd: project.target });
|
|
113
|
+
kv('GitHub push', 'Succeeded after login');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
throw new Error('GitHub push failed. Run "gh auth setup-git" or "gh auth login", then rerun build.');
|
|
117
|
+
}
|
|
118
|
+
|
|
39
119
|
// Re-homes the cloned storefront code into a brand new GitHub repository
|
|
40
120
|
// owned by the logged-in user, so the deployed Vercel project can stay
|
|
41
121
|
// connected to that repo (git push -> auto deploy) instead of the original
|
|
@@ -45,6 +125,7 @@ export async function createGithubRepoFromClone(project) {
|
|
|
45
125
|
await ensureGithubLogin();
|
|
46
126
|
const owner = await getGithubLogin();
|
|
47
127
|
const repoName = project.projectName;
|
|
128
|
+
const repoUrl = `https://github.com/${owner}/${repoName}.git`;
|
|
48
129
|
|
|
49
130
|
// Detach from the template's git history and start a clean repo so we
|
|
50
131
|
// don't try to push into someone else's repository history.
|
|
@@ -57,15 +138,11 @@ export async function createGithubRepoFromClone(project) {
|
|
|
57
138
|
await runCommand('git', ['add', '-A'], { cwd: project.target });
|
|
58
139
|
await runCommand('git', ['-c', 'user.email=fabrica-cli@local', '-c', 'user.name=Fabrica CLI', 'commit', '-m', 'Initial commit from Fabrica storefront'], { cwd: project.target });
|
|
59
140
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
spin.fail('Could not create GitHub repository');
|
|
64
|
-
throw new Error(create.stderr || 'gh repo create failed');
|
|
65
|
-
}
|
|
66
|
-
spin.succeed(`Pushed code to ${owner}/${repoName}`);
|
|
141
|
+
await ensureGithubRepo(owner, repoName);
|
|
142
|
+
await setOrigin(project, repoUrl);
|
|
143
|
+
await pushWithCredentialFallback(project);
|
|
67
144
|
|
|
68
|
-
const
|
|
69
|
-
kv('GitHub repo',
|
|
70
|
-
return { owner, repoName, repoUrl };
|
|
145
|
+
const browserUrl = `https://github.com/${owner}/${repoName}`;
|
|
146
|
+
kv('GitHub repo', browserUrl);
|
|
147
|
+
return { owner, repoName, repoUrl: browserUrl };
|
|
71
148
|
}
|