pob 38.11.0 → 38.12.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.
Files changed (50) hide show
  1. package/lib/generators/app/PobAppGenerator.js +24 -5
  2. package/lib/generators/app/vite/AppViteGenerator.js +50 -3
  3. package/lib/generators/app/vite/templates/index.html.ejs +11 -0
  4. package/lib/generators/app/vite/templates/index.ts.ejs +1 -0
  5. package/lib/generators/app/vite/templates/vite.config.js.ejs +8 -0
  6. package/lib/generators/common/babel/templates/app.rollup.config.mjs.ejs +1 -0
  7. package/lib/generators/common/babel/templates/lib.rollup.config.mjs.ejs +1 -0
  8. package/lib/generators/common/e2e/CommonE2eGenerator.js +6 -1
  9. package/lib/generators/common/format-lint/CommonLintGenerator.js +141 -85
  10. package/lib/generators/common/format-lint/templates/oxfmtrc.jsonc.ejs +1 -0
  11. package/lib/generators/common/husky/templates/lint-staged.config.js.txt +1 -0
  12. package/lib/generators/common/release/templates/workflow-release.yml.ejs +2 -1
  13. package/lib/generators/common/testing/templates/vite.config.js.ejs +1 -0
  14. package/lib/generators/common/transpiler/templates/app.rollup.config.mjs.ejs +1 -0
  15. package/lib/generators/common/transpiler/templates/lib.rollup.config.mjs.ejs +1 -0
  16. package/lib/generators/common/typescript/templates/tsconfig.check-js.json.ejs +1 -0
  17. package/lib/generators/common/typescript/templates/tsconfig.json.ejs +1 -0
  18. package/lib/generators/common/typescript/templates/tsconfig.tools.json.ejs +1 -0
  19. package/lib/generators/core/bun/templates/bunfig.toml.ejs +1 -0
  20. package/lib/generators/core/ci/templates/github-action-documentation-workflow.yml.ejs +2 -1
  21. package/lib/generators/core/ci/templates/github-action-push-workflow-split.yml.ejs +6 -5
  22. package/lib/generators/core/ci/templates/github-action-push-workflow.yml.ejs +2 -1
  23. package/lib/generators/core/claude/CoreClaudeGenerator.js +1 -1
  24. package/lib/generators/core/editorconfig/templates/editorconfig +1 -0
  25. package/lib/generators/core/git/CoreGitGenerator.js +72 -57
  26. package/lib/generators/core/git/generators/github/CoreGitGithubGenerator.js +192 -145
  27. package/lib/generators/core/gitignore/templates/gitignore.ejs +1 -0
  28. package/lib/generators/core/npm/templates/npmignore.ejs +1 -0
  29. package/lib/generators/core/package/CorePackageGenerator.js +21 -8
  30. package/lib/generators/core/pnpm/CorePnpmGenerator.js +30 -9
  31. package/lib/generators/core/vscode/templates/extensions.json.ejs +1 -0
  32. package/lib/generators/core/vscode/templates/settings.json.ejs +1 -0
  33. package/lib/generators/core/yarn/templates/yarn_gitignore.ejs +1 -0
  34. package/lib/generators/lib/doc/LibDocGenerator.js +3 -1
  35. package/lib/generators/lib/doc/templates/tsconfig.doc.json.ejs +1 -0
  36. package/lib/generators/lib/doc/templates/tsconfig.doc.json.lerna.ejs +1 -0
  37. package/lib/generators/monorepo/PobMonorepoGenerator.js +26 -5
  38. package/lib/generators/monorepo/templates/monorepo.rollup.config.mjs.ejs +1 -0
  39. package/lib/generators/monorepo/typescript/MonorepoTypescriptGenerator.js +21 -10
  40. package/lib/generators/monorepo/typescript/templates/tsconfig.json.ejs +1 -0
  41. package/lib/generators/monorepo/typescript/templates/tsconfig.tools.json.ejs +1 -0
  42. package/lib/generators/monorepo/workspaces/MonorepoWorkspacesGenerator.js +12 -4
  43. package/lib/generators/pob/PobBaseGenerator.js +1 -1
  44. package/lib/pob.js +49 -12
  45. package/lib/utils/git.js +34 -0
  46. package/lib/utils/git.test.js +71 -0
  47. package/lib/utils/workspaceUtils.js +10 -0
  48. package/lib/utils/workspaceUtils.test.js +15 -0
  49. package/package.json +13 -13
  50. package/lib/generators/common/format-lint/templates/eslint.config.js.ejs +0 -5
@@ -1,8 +1,15 @@
1
1
  import remoteUrl from "git-remote-url";
2
2
  import githubUsername from "github-username";
3
3
  import Generator from "yeoman-generator";
4
+ import { getRepoName, parseRepositoryUrl } from "../../../utils/git.js";
4
5
  import * as packageUtils from "../../../utils/package.js";
5
6
 
7
+ const gitHostDomains = {
8
+ github: "github.com",
9
+ gitlab: "gitlab.com",
10
+ bitbucket: "bitbucket.org",
11
+ };
12
+
6
13
  export default class CoreGitGenerator extends Generator {
7
14
  constructor(args, opts) {
8
15
  super(args, opts);
@@ -34,29 +41,29 @@ export default class CoreGitGenerator extends Generator {
34
41
  }
35
42
 
36
43
  async initializing() {
37
- let originUrl = await remoteUrl(this.destinationPath(), "origin").catch(
44
+ // the real remote, kept apart from the package.json fallback: only a real
45
+ // remote means the repository already exists
46
+ this.originUrl = await remoteUrl(this.destinationPath(), "origin").catch(
38
47
  () => "",
39
48
  );
40
49
 
41
- if (!originUrl) {
50
+ let repository = parseRepositoryUrl(this.originUrl);
51
+
52
+ if (!this.originUrl) {
42
53
  const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
43
- originUrl = pkg.repository;
54
+ repository = parseRepositoryUrl(pkg.repository);
55
+ if (pkg.repository && !repository) {
56
+ console.warn(
57
+ `git: ignoring invalid repository in package.json: ${JSON.stringify(pkg.repository)}`,
58
+ );
59
+ }
44
60
  }
45
61
 
46
- this.originUrl = originUrl;
47
- const match =
48
- originUrl &&
49
- typeof originUrl === "string" &&
50
- originUrl.match(
51
- /^(?:git@|https?:\/\/)(?:([^./:]+)(?:\.com)?[/:])?([^/:]+)\/([^./:]+)(?:.git)?/,
52
- );
53
- if (!match) return;
54
- const [, gitHost, gitAccount, repoName] = match;
55
- this.gitHost = gitHost || "github";
56
- this.gitHostAccount = gitAccount;
57
- if (repoName !== "undefined") {
58
- this.repoName = repoName;
59
- }
62
+ this.hasRepositoryUrl = !!(this.originUrl || repository);
63
+ if (!repository) return;
64
+ this.gitHost = repository.gitHost;
65
+ this.gitHostAccount = repository.gitAccount;
66
+ this.repoName = repository.repoName;
60
67
  }
61
68
 
62
69
  async prompting() {
@@ -72,9 +79,12 @@ export default class CoreGitGenerator extends Generator {
72
79
  type: "list",
73
80
  name: "gitHost",
74
81
  message: "Which git host service would you like ?",
75
- default: this.gitHost || (this.originUrl ? "none" : "github"),
82
+ default: this.gitHost || (this.hasRepositoryUrl ? "none" : "github"),
76
83
  choices: [
77
- { value: "none", name: !this.originUrl ? "none" : "don't change" },
84
+ {
85
+ value: "none",
86
+ name: !this.hasRepositoryUrl ? "none" : "don't change",
87
+ },
78
88
  "github",
79
89
  "bitbucket",
80
90
  "gitlab",
@@ -121,23 +131,35 @@ export default class CoreGitGenerator extends Generator {
121
131
  writing() {
122
132
  console.log("git: writing");
123
133
 
124
- if (this.gitHost === "none") {
134
+ if (this.gitHost === "none" || !this.gitHostAccount) {
125
135
  return;
126
136
  }
127
137
 
128
138
  const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
129
- const repoName = this.repoName || this.options.name || pkg.name;
130
-
131
- if (!pkg.homepage && this.gitHostAccount) {
132
- pkg.homepage = `https://${this.gitHost}.com/${this.gitHostAccount}/${repoName}`;
133
- }
134
- if (this.gitHostAccount) {
135
- pkg.bugs = {
136
- url: `https://${this.gitHost}.com/${this.gitHostAccount}/${repoName}/issues`,
137
- };
139
+ const repoName = this.repoName || getRepoName(pkg.name);
140
+ const repositoryUrl = `https://${this.gitHost}.com/${this.gitHostAccount}/${repoName}`;
141
+
142
+ // keep a custom homepage, but fix one pointing to another repository on the
143
+ // same host
144
+ const isHomepageInRepository = (homepage) => {
145
+ const lowerHomepage = homepage.toLowerCase();
146
+ const lowerRepositoryUrl = repositoryUrl.toLowerCase();
147
+ return (
148
+ lowerHomepage === lowerRepositoryUrl ||
149
+ lowerHomepage.startsWith(`${lowerRepositoryUrl}/`) ||
150
+ lowerHomepage.startsWith(`${lowerRepositoryUrl}#`)
151
+ );
152
+ };
153
+ if (
154
+ !pkg.homepage ||
155
+ (pkg.homepage.startsWith(`https://${this.gitHost}.com/`) &&
156
+ !isHomepageInRepository(pkg.homepage))
157
+ ) {
158
+ pkg.homepage = repositoryUrl;
138
159
  }
160
+ pkg.bugs = { url: `${repositoryUrl}/issues` };
139
161
 
140
- const repository = `https://${this.gitHost}.com/${this.gitHostAccount}/${repoName}.git`;
162
+ const repository = `${repositoryUrl}.git`;
141
163
 
142
164
  if (pkg.repository !== repository) {
143
165
  pkg.repository = repository;
@@ -147,37 +169,30 @@ export default class CoreGitGenerator extends Generator {
147
169
 
148
170
  const cwd = this.destinationPath();
149
171
 
150
- this.initGitRepository =
151
- this.spawnCommandSync("git status", {
172
+ const isGitRepository =
173
+ this.spawnSync("git", ["rev-parse", "--git-dir"], {
152
174
  cwd,
153
175
  stdio: "ignore",
154
176
  reject: false,
155
- }).status === 128;
156
- if (this.initGitRepository) {
157
- this.spawnCommandSync("git init", { cwd });
158
-
159
- if (!this.originUrl) {
160
- let repoSSH = pkg.repository;
161
- if (pkg.repository && !pkg.repository.includes(".git")) {
162
- /* this.spawnCommandSync('curl', [
163
- '--silent',
164
- '--write-out',
165
- '"%{http_code}"',
166
- '--output',
167
- '/dev/null',
168
- '-i',
169
- '-u',
170
- this.options.githubAccount,
171
- `-d "{"name": "${this.options.name}", "auto_init": true}`,
172
- 'https://api.github.com/user/repos',
173
- ], { cwd }); */
174
-
175
- repoSSH = pkg.repository;
176
- }
177
+ }).exitCode === 0;
178
+ if (!isGitRepository) {
179
+ this.spawnSync("git", ["init"], { cwd });
180
+ }
177
181
 
178
- this.spawnCommandSync(`git remote add origin ${repoSSH}`, {
179
- cwd,
180
- });
182
+ if (!this.originUrl) {
183
+ const remoteHost = gitHostDomains[this.gitHost];
184
+ if (remoteHost) {
185
+ const originSSH = `git@${remoteHost}:${this.gitHostAccount}/${repoName}.git`;
186
+ const { exitCode } = this.spawnSync(
187
+ "git",
188
+ ["remote", "add", "origin", originSSH],
189
+ { cwd, reject: false },
190
+ );
191
+ if (exitCode !== 0) {
192
+ console.warn(
193
+ `git: failed to add origin, run by hand: git remote add origin ${originSSH}`,
194
+ );
195
+ }
181
196
  }
182
197
  }
183
198
  }
@@ -1,10 +1,10 @@
1
- /* eslint-disable camelcase */
1
+ /* oxlint-disable eslint-js/camelcase */
2
2
 
3
3
  import { spawnSync } from "node:child_process";
4
4
  import * as os from "node:os";
5
5
  import Generator from "yeoman-generator";
6
+ import { getRepoName } from "../../../../../utils/git.js";
6
7
  import { ciContexts } from "../../../ci/CoreCIGenerator.js";
7
- // const packageUtils = require('../../../../../utils/package');
8
8
 
9
9
  const readTokenFromKeychain = () => {
10
10
  if (process.platform !== "darwin") return undefined;
@@ -26,71 +26,36 @@ const readTokenFromKeychain = () => {
26
26
 
27
27
  const GITHUB_TOKEN = process.env.POB_GITHUB_TOKEN || readTokenFromKeychain();
28
28
 
29
- const postJson = (url, jsonBody) =>
30
- fetch(`https://api.github.com/${url}`, {
31
- method: "POST",
32
- body: JSON.stringify(jsonBody),
33
- headers: {
34
- authorization: `token ${GITHUB_TOKEN}`,
35
- },
36
- }).then((res) => (res.ok ? res.json() : null));
29
+ const MISSING_TOKEN_HELP =
30
+ 'Create a token with https://github.com/settings/tokens/new?scopes=repo&description=POB%20Generator and set it in the POB_GITHUB_TOKEN env variable, or store it in the macOS keychain with: security add-generic-password -s pob-github-token -a "$USER" -w';
31
+
32
+ class GithubRequestError extends Error {
33
+ constructor(method, url, status, body) {
34
+ super(`${method} ${url} failed with status ${status}: ${body}`);
35
+ this.name = "GithubRequestError";
36
+ this.status = status;
37
+ }
38
+ }
37
39
 
38
- const putJson = (url, jsonBody) =>
39
- fetch(`https://api.github.com/${url}`, {
40
- method: "PUT",
41
- body: JSON.stringify(jsonBody),
40
+ const githubRequest = async (method, url, jsonBody) => {
41
+ const res = await fetch(`https://api.github.com/${url}`, {
42
+ method,
43
+ body: jsonBody === undefined ? undefined : JSON.stringify(jsonBody),
42
44
  headers: {
45
+ accept: "application/vnd.github+json",
43
46
  authorization: `token ${GITHUB_TOKEN}`,
44
47
  },
45
- }).then((res) => (res.ok ? res.json() : null));
46
-
47
- const configureProtectionRule = async (
48
- owner,
49
- repo,
50
- onlyLatestLTS,
51
- spawnCommandSync,
52
- ) => {
53
- if (!ciContexts || ciContexts.length === 0) {
54
- throw new Error("Invalid ciContexts: []");
48
+ });
49
+ if (!res.ok) {
50
+ const body = await res.text().catch(() => "");
51
+ throw new GithubRequestError(method, url, res.status, body);
55
52
  }
53
+ return res.json();
54
+ };
56
55
 
57
- for (const branch of ["main", "master"]) {
58
- try {
59
- const result = spawnCommandSync(
60
- "git",
61
- ["ls-remote", "--heads", `git@github.com:${owner}/${repo}.git`, branch],
62
- { stdio: "pipe" },
63
- );
64
-
65
- const isBranchExists =
66
- result.exitCode === 0 && result.stdout.toString().trim() !== "";
67
-
68
- if (isBranchExists) {
69
- await putJson(`repos/${owner}/${repo}/branches/${branch}/protection`, {
70
- required_status_checks: {
71
- strict: false,
72
- contexts: ciContexts,
73
- },
74
- enforce_admins: false, // true,
75
- required_pull_request_reviews: null,
76
- restrictions: null,
77
- required_linear_history: true,
78
- allow_force_pushes: true, // false
79
- allow_deletions: false,
80
- });
81
- if (branch === "master") {
82
- console.warn('You should rename your "master" branch to "main"');
83
- }
84
- } else if (branch === "main") {
85
- throw new Error(`Branch ${branch} does not exist`);
86
- }
87
- } catch (error) {
88
- if (branch === "main") {
89
- console.error(`Failed to configure ${branch} branch protection`);
90
- console.error(error.stack || error.message || error);
91
- }
92
- }
93
- }
56
+ const printError = (message, error) => {
57
+ console.error(message);
58
+ console.error(error.stack || error.message || error);
94
59
  };
95
60
 
96
61
  const githubRepoConfig = {
@@ -123,8 +88,8 @@ export default class CoreGitGithubGenerator extends Generator {
123
88
 
124
89
  this.option("repoName", {
125
90
  type: String,
126
- required: true,
127
- description: "repo name",
91
+ required: false,
92
+ description: "repo name, computed from the package name when missing",
128
93
  });
129
94
 
130
95
  this.option("onlyLatestLTS", {
@@ -139,107 +104,189 @@ export default class CoreGitGithubGenerator extends Generator {
139
104
  description: "split CI jobs for faster result",
140
105
  });
141
106
 
142
- if (!GITHUB_TOKEN && process.env.CI !== "true") {
143
- console.warn(
144
- 'Missing POB_GITHUB_TOKEN. Create one with https://github.com/settings/tokens/new?scopes=repo&description=POB%20Generator and add it in your env variables, or store it in the macOS keychain with: security add-generic-password -s pob-github-token -a "$USER" -w',
145
- );
146
- }
107
+ this.option("ciEnabled", {
108
+ type: Boolean,
109
+ required: true,
110
+ description: "ci enabled",
111
+ });
147
112
  }
148
113
 
149
- async end() {
150
- if (!GITHUB_TOKEN) return;
151
- const owner = this.options.gitHostAccount;
152
- const repo = this.options.repoName;
114
+ async configureProtectionRule(owner, repo) {
115
+ if (!this.options.ciEnabled) return;
116
+ if (ciContexts.length === 0) {
117
+ console.warn("No ci contexts: branch protection not configured");
118
+ return;
119
+ }
153
120
 
154
- const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
155
- const name = pkg.name.endsWith("-monorepo")
156
- ? pkg.name.slice(0, -"-monorepo".length)
157
- : pkg.name;
121
+ const cwd = this.destinationPath();
158
122
 
159
- if (this.options.shouldCreate) {
123
+ for (const branch of ["main", "master"]) {
160
124
  try {
161
- if (this.options.shouldCreate) {
162
- try {
163
- await postJson("user/repos", {
164
- name,
165
- description: pkg.description,
166
- homepage: null,
167
- private: false,
168
- auto_init: false,
169
- ...githubRepoConfig,
170
- });
171
- } catch (error) {
172
- console.error("Failed to create repository");
173
- console.error(error.stack || error.message || error);
125
+ const result = this.spawnSync(
126
+ "git",
127
+ ["ls-remote", "--heads", "origin", branch],
128
+ { cwd, stdio: "pipe", reject: false },
129
+ );
130
+
131
+ const isBranchExists =
132
+ result.exitCode === 0 && result.stdout.toString().trim() !== "";
133
+
134
+ if (isBranchExists) {
135
+ await githubRequest(
136
+ "PUT",
137
+ `repos/${owner}/${repo}/branches/${branch}/protection`,
138
+ {
139
+ required_status_checks: {
140
+ strict: false,
141
+ contexts: ciContexts,
142
+ },
143
+ enforce_admins: false, // true,
144
+ required_pull_request_reviews: null,
145
+ restrictions: null,
146
+ required_linear_history: true,
147
+ allow_force_pushes: true, // false
148
+ allow_deletions: false,
149
+ },
150
+ );
151
+ if (branch === "master") {
152
+ console.warn('You should rename your "master" branch to "main"');
174
153
  }
154
+ } else if (branch === "main") {
155
+ throw new Error(`Branch ${branch} does not exist`);
156
+ }
157
+ } catch (error) {
158
+ if (branch === "main") {
159
+ printError(`Failed to configure ${branch} branch protection`, error);
175
160
  }
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Runs a step of the repository setup, printing which step failed and what
167
+ * to run by hand instead of stopping the run.
168
+ */
169
+ runStep(description, manualCommand, fn) {
170
+ try {
171
+ fn();
172
+ return true;
173
+ } catch (error) {
174
+ printError(
175
+ `Failed to ${description}. Run by hand: ${manualCommand}`,
176
+ error,
177
+ );
178
+ return false;
179
+ }
180
+ }
181
+
182
+ async createRepository(owner, repo, pkg) {
183
+ const cwd = this.destinationPath();
176
184
 
177
- const cwd = this.destinationPath();
178
- try {
179
- this.spawnCommandSync("git", ["add", "--all", "."], { cwd });
180
- } catch (error) {
181
- this.spawnCommandSync("git", ["init"], { cwd });
182
- this.spawnCommandSync("git", ["add", "--all", "."], { cwd });
183
- this.spawnCommandSync(
185
+ try {
186
+ const user = await githubRequest("GET", "user");
187
+ const isOrganization = user.login.toLowerCase() !== owner.toLowerCase();
188
+ await githubRequest(
189
+ "POST",
190
+ isOrganization ? `orgs/${owner}/repos` : "user/repos",
191
+ {
192
+ name: repo,
193
+ description: pkg.description,
194
+ homepage: null,
195
+ // only projects with an open source license are public: making a
196
+ // pushed public repository private does not undo its exposure
197
+ private: !pkg.license || pkg.license === "UNLICENSED",
198
+ auto_init: false,
199
+ ...githubRepoConfig,
200
+ },
201
+ );
202
+ } catch (error) {
203
+ if (error.status !== 422) {
204
+ printError(
205
+ `Failed to create github repository ${owner}/${repo}: nothing was committed or pushed`,
206
+ error,
207
+ );
208
+ return;
209
+ }
210
+ console.warn(
211
+ `github repository ${owner}/${repo} already exists, syncing its settings`,
212
+ );
213
+ await this.syncRepository(owner, repo, pkg);
214
+ }
215
+
216
+ const hasCommit =
217
+ this.spawnSync("git", ["rev-parse", "--verify", "HEAD"], {
218
+ cwd,
219
+ stdio: "ignore",
220
+ reject: false,
221
+ }).exitCode === 0;
222
+
223
+ if (!hasCommit) {
224
+ const committed = this.runStep(
225
+ "create the initial commit",
226
+ 'git add --all . && git commit -m "chore: initial commit [skip ci]"',
227
+ () => {
228
+ this.spawnSync("git", ["add", "--all", "."], { cwd });
229
+ // generated files are already formatted by pob, and hooks may need
230
+ // tools not installed yet
231
+ this.spawnSync(
184
232
  "git",
185
- [
186
- "remote",
187
- "add",
188
- "origin",
189
- `git@github.com:christophehurpeau/${name}.git`,
190
- ],
191
- { cwd },
233
+ ["commit", "-m", "chore: initial commit [skip ci]"],
234
+ { cwd, env: { POB_GIT_HOOKS: "0" } },
192
235
  );
193
- console.error("Failed to create repository");
194
- console.error(error.stack || error.message || error);
195
- }
196
- this.spawnCommandSync(
197
- "git",
198
- ["commit", "-m", "chore: initial commit [skip ci]"],
199
- { cwd },
200
- );
201
- this.spawnCommandSync("git", ["branch", "-M", "main"], {
202
- cwd,
203
- });
204
- this.spawnCommandSync("git", ["push", "-u", "origin", "main"], {
205
- cwd,
206
- });
207
-
208
- await configureProtectionRule(
209
- owner,
210
- repo,
211
- this.options.onlyLatestLTS,
212
- this.spawnCommandSync.bind(this),
213
- );
236
+ },
237
+ );
238
+ if (!committed) return;
239
+ }
214
240
 
215
- // await gh.put(`/repos/${owner}/${repo}/topics`, {
216
- // names: pkg.keywords,
217
- // });
218
- } catch (error) {
219
- console.error("Failed to create github repository");
220
- console.error(error.stack || error.message || error);
221
- }
222
- } else {
223
- console.log("sync github info");
241
+ const pushed = this.runStep(
242
+ "push to github",
243
+ "git branch -M main && git push -u origin main",
244
+ () => {
245
+ this.spawnSync("git", ["branch", "-M", "main"], { cwd });
246
+ this.spawnSync("git", ["push", "-u", "origin", "main"], { cwd });
247
+ },
248
+ );
249
+ if (!pushed) return;
250
+
251
+ await this.configureProtectionRule(owner, repo);
252
+ }
224
253
 
225
- await postJson(`repos/${owner}/${repo}`, {
254
+ async syncRepository(owner, repo, pkg) {
255
+ try {
256
+ await githubRequest("PATCH", `repos/${owner}/${repo}`, {
226
257
  name: repo,
227
- /* pkg.name
228
- .replace(/-(lerna|monorepo)$/, '')
229
- .replace(/^@([^-]*)-/, '$1-') */
230
258
  description: pkg.description,
231
- // homepage: null,
232
259
  ...githubRepoConfig,
233
260
  });
261
+ } catch (error) {
262
+ printError(`Failed to sync github repository ${owner}/${repo}`, error);
263
+ }
264
+ }
234
265
 
235
- if (this.options.ci) {
236
- await configureProtectionRule(
237
- owner,
238
- repo,
239
- this.options.onlyLatestLTS,
240
- this.spawnCommandSync.bind(this),
266
+ async end() {
267
+ const pkg = this.fs.readJSON(this.destinationPath("package.json"), {});
268
+ const owner = this.options.gitHostAccount;
269
+ const repo = this.options.repoName || getRepoName(pkg.name);
270
+
271
+ if (!GITHUB_TOKEN) {
272
+ if (this.options.shouldCreate) {
273
+ console.warn(
274
+ `Missing POB_GITHUB_TOKEN: the github repository ${owner}/${repo} was not created, nothing was committed or pushed. ${MISSING_TOKEN_HELP}`,
275
+ );
276
+ } else if (process.env.CI !== "true") {
277
+ console.warn(
278
+ `Missing POB_GITHUB_TOKEN: github repository settings not synced. ${MISSING_TOKEN_HELP}`,
241
279
  );
242
280
  }
281
+ return;
282
+ }
283
+
284
+ if (this.options.shouldCreate) {
285
+ await this.createRepository(owner, repo, pkg);
286
+ } else {
287
+ console.log("sync github info");
288
+ await this.syncRepository(owner, repo, pkg);
289
+ await this.configureProtectionRule(owner, repo);
243
290
  }
244
291
  }
245
292
  }
@@ -1,3 +1,4 @@
1
+ # Generated by pob: do not edit, it is overwritten on each pob run.
1
2
  <% if (root) { -%>
2
3
  # dependencies
3
4
  node_modules
@@ -1 +1,2 @@
1
+ # Generated by pob: do not edit, it is overwritten on each pob run.
1
2
  # keep an empty file to avoid using gitignore.
@@ -121,6 +121,18 @@ export default class CorePackageGenerator extends Generator {
121
121
  pkg.type = this.options.packageType;
122
122
  }
123
123
 
124
+ // packages of a monorepo share the author, the license and the type of the
125
+ // root package.json
126
+ const rootPkg =
127
+ inMonorepo && !inMonorepo.root ? inMonorepo.rootMonorepoPkg : undefined;
128
+ if (rootPkg) {
129
+ if (!pkg.author && !pkg.authors && rootPkg.author) {
130
+ pkg.author = rootPkg.author;
131
+ }
132
+ if (!pkg.type && rootPkg.type) pkg.type = rootPkg.type;
133
+ }
134
+ const defaultLicense = rootPkg?.license;
135
+
124
136
  let author = packageUtils.parsePkgAuthor(pkg);
125
137
 
126
138
  const props = await this.prompt(
@@ -160,7 +172,7 @@ export default class CorePackageGenerator extends Generator {
160
172
  message: "License Type",
161
173
  type: "list",
162
174
  choices: ["MIT", "ISC", "UNLICENSED"],
163
- when: !pkg.license,
175
+ when: !pkg.license && !defaultLicense,
164
176
  },
165
177
  ].filter(Boolean),
166
178
  );
@@ -257,15 +269,16 @@ export default class CorePackageGenerator extends Generator {
257
269
  }
258
270
 
259
271
  if (!pkg.license) {
260
- pkg.license = props.license;
261
- this.fs.copyTpl(
262
- this.templatePath(`licenses/${props.license}.ejs`),
263
- this.destinationPath("LICENSE"),
264
- {
272
+ pkg.license = props.license || defaultLicense;
273
+ const licenseTemplatePath = this.templatePath(
274
+ `licenses/${pkg.license}.ejs`,
275
+ );
276
+ if (fs.existsSync(licenseTemplatePath)) {
277
+ this.fs.copyTpl(licenseTemplatePath, this.destinationPath("LICENSE"), {
265
278
  year: new Date().getFullYear(),
266
279
  author: pkg.author,
267
- },
268
- );
280
+ });
281
+ }
269
282
  }
270
283
 
271
284
  if (pkg.private) {