create-react-on-rails-app 16.5.1 → 16.6.0-rc.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/lib/create-app.js CHANGED
@@ -10,6 +10,94 @@ const path_1 = __importDefault(require("path"));
10
10
  const fs_1 = __importDefault(require("fs"));
11
11
  const utils_js_1 = require("./utils.js");
12
12
  const DOCS_URL = 'https://reactonrails.com/docs/';
13
+ const DEFAULT_GIT_AUTHOR_NAME = 'React on Rails Generator';
14
+ const DEFAULT_GIT_AUTHOR_EMAIL = 'generator@reactonrails.invalid';
15
+ const SUPPORTED_RAILTIES_MAJORS = [7, 8];
16
+ // Keep this renderer intentionally minimal. It renders Rails' installed
17
+ // gitignore/gitattributes templates and falls back to bundled defaults when:
18
+ // - railties is unavailable in the current Ruby environment, or
19
+ // - railties major version is outside SUPPORTED_RAILTIES_MAJORS.
20
+ const RAILS_GIT_TEMPLATE_RENDERER = `
21
+ require "erb"
22
+
23
+ class ReactOnRailsGitTemplateOptions
24
+ def api? = false
25
+
26
+ def [](key)
27
+ key == :skip_active_record ? false : nil
28
+ end
29
+ end
30
+
31
+ class ReactOnRailsGitTemplateContext
32
+ def keeps? = true
33
+
34
+ def skip_storage? = false
35
+
36
+ def options = ReactOnRailsGitTemplateOptions.new
37
+
38
+ def get_binding
39
+ binding
40
+ end
41
+ end
42
+
43
+ spec = Gem::Specification.find_by_name("railties")
44
+ railties_major = spec.version.segments.first
45
+ unless [${SUPPORTED_RAILTIES_MAJORS.join(', ')}].include?(railties_major)
46
+ warn "Unsupported railties major version for git template rendering: #{spec.version}"
47
+ exit 1
48
+ end
49
+ template_path = File.join(spec.gem_dir, "lib/rails/generators/rails/app/templates", ARGV[0])
50
+ template = File.read(template_path)
51
+ print ERB.new(template, trim_mode: "-").result(ReactOnRailsGitTemplateContext.new.get_binding)
52
+ `;
53
+ // Fallback copy of the Rails git scaffold (validated against Rails 7.2 templates)
54
+ // for environments where rendering the installed railties templates is unavailable.
55
+ const RAILS_GITIGNORE_FALLBACK = `# See https://help.github.com/articles/ignoring-files for more about ignoring files.
56
+ #
57
+ # Temporary files generated by your text editor or operating system
58
+ # belong in git's global ignore instead:
59
+ # \`$XDG_CONFIG_HOME/git/ignore\` or \`~/.config/git/ignore\`
60
+
61
+ # Ignore bundler config.
62
+ /.bundle
63
+
64
+ # Ignore all environment files.
65
+ /.env*
66
+
67
+ # Ignore all logfiles and tempfiles.
68
+ /log/*
69
+ /tmp/*
70
+ !/log/.keep
71
+ !/tmp/.keep
72
+
73
+ # Ignore node modules.
74
+ /node_modules
75
+
76
+ # Ignore pidfiles, but keep the directory.
77
+ /tmp/pids/*
78
+ !/tmp/pids/
79
+ !/tmp/pids/.keep
80
+
81
+ # Ignore storage (uploaded files in development and any SQLite databases).
82
+ /storage/*
83
+ !/storage/.keep
84
+ /tmp/storage/*
85
+ !/tmp/storage/
86
+ !/tmp/storage/.keep
87
+
88
+ /public/assets
89
+
90
+ # Ignore key files for decrypting credentials and more.
91
+ /config/*.key
92
+ `;
93
+ const RAILS_GITATTRIBUTES_FALLBACK = `# See https://git-scm.com/docs/gitattributes for more about git attribute files.
94
+
95
+ # Mark the database schema as having been generated.
96
+ db/schema.rb linguist-generated
97
+
98
+ # Mark any vendored files as having been vendored.
99
+ vendor/* linguist-vendored
100
+ `;
13
101
  function cleanupAppDirectory(appPath, appName, cleanupSuccessMessage, cleanupFallbackMessage) {
14
102
  if (!fs_1.default.existsSync(appPath)) {
15
103
  return;
@@ -46,7 +134,7 @@ function bundleAddArgs(gemName, localPath, strict = true) {
46
134
  return args;
47
135
  }
48
136
  function buildGeneratorArgs(options) {
49
- const args = [];
137
+ const args = ['--new-app'];
50
138
  if (options.template === 'typescript') {
51
139
  args.push('--typescript');
52
140
  }
@@ -63,10 +151,9 @@ function buildGeneratorArgs(options) {
63
151
  // --force makes the generator overwrite conflicting files without prompting,
64
152
  // which is safe for a freshly scaffolded app with no custom content yet.
65
153
  args.push('--force');
66
- // The newly created app directory is not a git repo yet, so the generator's
67
- // uncommitted-changes check would always warn. --ignore-warnings bypasses all
68
- // generator validation warnings (git, Node version, package manager) which is
69
- // acceptable for a fresh app where prerequisites were already checked above.
154
+ // Keep the create-app flow non-interactive. --ignore-warnings bypasses generator
155
+ // validation warnings (git, Node version, package manager) because the CLI
156
+ // already checked prerequisites and is driving a fresh-app automation path.
70
157
  args.push('--ignore-warnings');
71
158
  return args;
72
159
  }
@@ -102,6 +189,30 @@ function rewriteFileIfPresent(filePath, transform) {
102
189
  fs_1.default.writeFileSync(filePath, updated, 'utf8');
103
190
  }
104
191
  }
192
+ function readInstalledRailsGitTemplate(appPath, templateName) {
193
+ try {
194
+ const renderedTemplate = (0, utils_js_1.execCaptureArgs)('ruby', ['-e', RAILS_GIT_TEMPLATE_RENDERER, templateName], appPath);
195
+ return renderedTemplate.length > 0 ? `${renderedTemplate}\n` : null;
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ }
201
+ function railsGitScaffold(appPath) {
202
+ const renderedGitignore = readInstalledRailsGitTemplate(appPath, 'gitignore.tt');
203
+ const renderedGitattributes = readInstalledRailsGitTemplate(appPath, 'gitattributes.tt');
204
+ return {
205
+ gitignore: renderedGitignore ?? RAILS_GITIGNORE_FALLBACK,
206
+ gitattributes: renderedGitattributes ?? RAILS_GITATTRIBUTES_FALLBACK,
207
+ };
208
+ }
209
+ function restoreRailsGitScaffold(appPath) {
210
+ // Rails omits .gitignore/.gitattributes when rails new runs with --skip-git.
211
+ // Recreate the defaults so the educational commit history stays clean.
212
+ const scaffold = railsGitScaffold(appPath);
213
+ fs_1.default.writeFileSync(path_1.default.join(appPath, '.gitignore'), scaffold.gitignore, 'utf8');
214
+ fs_1.default.writeFileSync(path_1.default.join(appPath, '.gitattributes'), scaffold.gitattributes, 'utf8');
215
+ }
105
216
  function normalizeGeneratedPackageManager(appPath, packageManager) {
106
217
  if (packageManager !== 'pnpm') {
107
218
  return;
@@ -133,7 +244,95 @@ function normalizeGeneratedPackageManager(appPath, packageManager) {
133
244
  });
134
245
  (0, utils_js_1.logStepDone)('pnpm configuration applied');
135
246
  }
136
- function printSuccessMessage(appName, route) {
247
+ function ensureGitRepository(appPath) {
248
+ if (fs_1.default.existsSync(path_1.default.join(appPath, '.git'))) {
249
+ return;
250
+ }
251
+ (0, utils_js_1.execLiveArgs)('git', ['init'], appPath);
252
+ }
253
+ function readGitConfig(appPath, key) {
254
+ try {
255
+ const value = (0, utils_js_1.execCaptureArgs)('git', ['config', '--get', key], appPath);
256
+ return value === '' ? null : value;
257
+ }
258
+ catch {
259
+ return null;
260
+ }
261
+ }
262
+ function educationalGitEnv(appPath) {
263
+ const userName = readGitConfig(appPath, 'user.name') ?? DEFAULT_GIT_AUTHOR_NAME;
264
+ const userEmail = readGitConfig(appPath, 'user.email') ?? DEFAULT_GIT_AUTHOR_EMAIL;
265
+ return {
266
+ ...process.env,
267
+ GIT_AUTHOR_NAME: userName,
268
+ GIT_AUTHOR_EMAIL: userEmail,
269
+ GIT_COMMITTER_NAME: userName,
270
+ GIT_COMMITTER_EMAIL: userEmail,
271
+ };
272
+ }
273
+ function gitHasPendingChanges(appPath) {
274
+ try {
275
+ return (0, utils_js_1.execCaptureArgs)('git', ['status', '--porcelain'], appPath) !== '';
276
+ }
277
+ catch {
278
+ return false;
279
+ }
280
+ }
281
+ function createEducationalCommit(appPath, subject, body, educationalGitEnvForCommit) {
282
+ ensureGitRepository(appPath);
283
+ if (!gitHasPendingChanges(appPath)) {
284
+ return false;
285
+ }
286
+ // The educational history intentionally snapshots each full scaffold step.
287
+ (0, utils_js_1.execLiveArgs)('git', ['add', '-A'], appPath);
288
+ (0, utils_js_1.execLiveArgs)('git', ['-c', 'commit.gpgsign=false', 'commit', '-m', subject, '-m', body], appPath, educationalGitEnvForCommit());
289
+ return true;
290
+ }
291
+ function railsBaselineCommitMessage() {
292
+ return {
293
+ subject: 'Create Rails app with PostgreSQL',
294
+ body: 'Generate the fresh Rails baseline before adding React on Rails.',
295
+ };
296
+ }
297
+ function reactOnRailsGemCommitMessage() {
298
+ return {
299
+ subject: 'Add react_on_rails gem',
300
+ body: 'Install the OSS gem so the next commit can run the React on Rails generator.',
301
+ };
302
+ }
303
+ function reactOnRailsProCommitMessage(modeFlag) {
304
+ return {
305
+ subject: 'Add react_on_rails_pro gem',
306
+ body: `Install the Pro gem required by ${modeFlag} before running the generator.`,
307
+ };
308
+ }
309
+ function generatorCommitMessage(options) {
310
+ const language = options.template === 'typescript' ? 'TypeScript' : 'JavaScript';
311
+ const bundler = options.rspack ? 'Rspack' : 'Webpack';
312
+ if (options.rsc) {
313
+ return {
314
+ subject: `Install React Server Components with ${language} and ${bundler}`,
315
+ body: 'Run react_on_rails:install --rsc to add the generated home page, HelloServer example, and Pro RSC wiring.',
316
+ };
317
+ }
318
+ if (options.pro) {
319
+ return {
320
+ subject: `Install React on Rails Pro with ${language} and ${bundler}`,
321
+ body: 'Run react_on_rails:install --pro to add the generated home page, SSR example, and Pro Node renderer wiring.',
322
+ };
323
+ }
324
+ return {
325
+ subject: `Install React on Rails with ${language} and ${bundler}`,
326
+ body: 'Run react_on_rails:install to add the generated home page, SSR example, and development workflow.',
327
+ };
328
+ }
329
+ function pnpmCommitMessage() {
330
+ return {
331
+ subject: 'Normalize the generated app for pnpm',
332
+ body: 'Convert npm artifacts to pnpm, remove package-lock.json, and update bin/setup to use pnpm install.',
333
+ };
334
+ }
335
+ function printSuccessMessage(appName, educationalCommitsEnabled) {
137
336
  console.log('');
138
337
  (0, utils_js_1.logSuccess)(`Created ${appName} with React on Rails!`);
139
338
  console.log('');
@@ -144,7 +343,16 @@ function printSuccessMessage(appName, route) {
144
343
  console.log('');
145
344
  (0, utils_js_1.logInfo)('Note: The generated app uses PostgreSQL by default. Start PostgreSQL before running bin/rails db:prepare.');
146
345
  console.log('');
147
- (0, utils_js_1.logInfo)(`Then visit http://localhost:3000/${route}`);
346
+ (0, utils_js_1.logInfo)('Then visit http://localhost:3000');
347
+ (0, utils_js_1.logInfo)('bin/dev will try to open the generated home page on first successful boot.');
348
+ console.log('');
349
+ if (educationalCommitsEnabled) {
350
+ (0, utils_js_1.logInfo)('Educational commits skip GPG signing so scaffold automation does not block on local signer prompts.');
351
+ (0, utils_js_1.logInfo)('Educational git history: git log --oneline --reverse');
352
+ }
353
+ else {
354
+ (0, utils_js_1.logInfo)('Educational git history is partial because git commit automation was skipped after an earlier failure.');
355
+ }
148
356
  console.log('');
149
357
  (0, utils_js_1.logInfo)(`Documentation: ${DOCS_URL}`);
150
358
  console.log('');
@@ -175,24 +383,49 @@ function validateAppName(name) {
175
383
  function createApp(appName, options) {
176
384
  const appPath = path_1.default.resolve(process.cwd(), appName);
177
385
  const proRequested = options.pro || options.rsc;
386
+ let educationalCommitsEnabled = true;
387
+ let cachedEducationalGitEnv = null;
178
388
  let proModeLabel = null;
179
- if (options.rsc) {
180
- proModeLabel = '--rsc';
181
- }
182
- else if (options.pro) {
183
- proModeLabel = '--pro';
389
+ if (proRequested) {
390
+ proModeLabel = options.rsc ? '--rsc' : '--pro';
184
391
  }
185
392
  const baseSteps = 3; // rails new + add react_on_rails + run generator
186
393
  const totalSteps = baseSteps + (proRequested ? 1 : 0);
187
394
  let currentStep = 1;
188
395
  const reactOnRailsGemPath = localGemPath('REACT_ON_RAILS_GEM_PATH');
189
396
  const reactOnRailsProGemPath = proRequested ? localGemPath('REACT_ON_RAILS_PRO_GEM_PATH') : null;
397
+ function educationalGitEnvForCommits() {
398
+ if (!cachedEducationalGitEnv) {
399
+ // The baseline commit happens before git init; in that case git config falls back
400
+ // to the user's global identity, which is the behavior we want here.
401
+ cachedEducationalGitEnv = educationalGitEnv(appPath);
402
+ }
403
+ return cachedEducationalGitEnv;
404
+ }
405
+ function recordEducationalCommit(subject, body) {
406
+ if (!educationalCommitsEnabled) {
407
+ return;
408
+ }
409
+ try {
410
+ createEducationalCommit(appPath, subject, body, educationalGitEnvForCommits);
411
+ }
412
+ catch (error) {
413
+ educationalCommitsEnabled = false;
414
+ (0, utils_js_1.logInfo)(`Educational git history paused after "${subject}" because git commit automation failed. The app scaffold will continue.`);
415
+ if (error instanceof Error && error.message) {
416
+ console.error(`Git debug info: ${error.message}`);
417
+ }
418
+ }
419
+ }
190
420
  // Step 1: Create Rails application
191
421
  // appName is validated by validateAppName() to be ^[a-zA-Z][a-zA-Z0-9]*([_-][a-zA-Z0-9]+)*$ only,
192
422
  // so it's always a simple directory name safe to use with rails new.
193
423
  (0, utils_js_1.logStep)(currentStep, totalSteps, 'Creating Rails application...');
194
424
  try {
195
- (0, utils_js_1.execLiveArgs)('rails', ['new', appName, '--database=postgresql', '--skip-javascript']);
425
+ (0, utils_js_1.execLiveArgs)('rails', ['new', appName, '--database=postgresql', '--skip-javascript', '--skip-git']);
426
+ restoreRailsGitScaffold(appPath);
427
+ const { subject, body } = railsBaselineCommitMessage();
428
+ recordEducationalCommit(subject, body);
196
429
  (0, utils_js_1.logStepDone)('Rails application created');
197
430
  }
198
431
  catch (error) {
@@ -212,6 +445,8 @@ function createApp(appName, options) {
212
445
  (0, utils_js_1.logInfo)(`Using local react_on_rails gem path: ${reactOnRailsGemPath}`);
213
446
  }
214
447
  (0, utils_js_1.execLiveArgs)('bundle', reactOnRailsArgs, appPath);
448
+ const { subject, body } = reactOnRailsGemCommitMessage();
449
+ recordEducationalCommit(subject, body);
215
450
  (0, utils_js_1.logStepDone)('react_on_rails gem added');
216
451
  }
217
452
  catch (error) {
@@ -231,6 +466,8 @@ function createApp(appName, options) {
231
466
  (0, utils_js_1.logInfo)(`Using local react_on_rails_pro gem path: ${reactOnRailsProGemPath}`);
232
467
  }
233
468
  (0, utils_js_1.execLiveArgs)('bundle', reactOnRailsProArgs, appPath);
469
+ const { subject, body } = reactOnRailsProCommitMessage(proModeLabel ?? '--pro');
470
+ recordEducationalCommit(subject, body);
234
471
  (0, utils_js_1.logStepDone)('react_on_rails_pro gem added');
235
472
  }
236
473
  catch (error) {
@@ -251,6 +488,8 @@ function createApp(appName, options) {
251
488
  ...process.env,
252
489
  REACT_ON_RAILS_PACKAGE_MANAGER: options.packageManager,
253
490
  });
491
+ const { subject, body } = generatorCommitMessage(options);
492
+ recordEducationalCommit(subject, body);
254
493
  (0, utils_js_1.logStepDone)('React on Rails setup complete');
255
494
  }
256
495
  catch (error) {
@@ -263,6 +502,10 @@ function createApp(appName, options) {
263
502
  }
264
503
  try {
265
504
  normalizeGeneratedPackageManager(appPath, options.packageManager);
505
+ if (options.packageManager === 'pnpm') {
506
+ const { subject, body } = pnpmCommitMessage();
507
+ recordEducationalCommit(subject, body);
508
+ }
266
509
  }
267
510
  catch (error) {
268
511
  (0, utils_js_1.logError)(`Failed to finish ${options.packageManager} setup. The app was created, but package manager normalization did not complete.`);
@@ -280,6 +523,6 @@ function createApp(appName, options) {
280
523
  }
281
524
  // Final success
282
525
  (0, utils_js_1.logStepDone)('Done!');
283
- printSuccessMessage(appName, options.rsc ? 'hello_server' : 'hello_world');
526
+ printSuccessMessage(appName, educationalCommitsEnabled);
284
527
  }
285
528
  //# sourceMappingURL=create-app.js.map
package/lib/index.js CHANGED
@@ -110,11 +110,18 @@ What it does:
110
110
  1. Creates a new Rails app with PostgreSQL
111
111
  2. Adds required gem(s) (react_on_rails, plus react_on_rails_pro for --pro/--rsc)
112
112
  3. Runs the React on Rails generator (Shakapacker, components, webpack config)
113
+ 4. Creates educational git commits for each major scaffold step
113
114
 
114
115
  After setup, run bin/dev and visit:
115
- - http://localhost:3000/hello_world (default and --pro)
116
- - http://localhost:3000/hello_server (--rsc)
116
+ - http://localhost:3000 (generated home page)
117
+ - /hello_world (default and --pro example page)
118
+ - /hello_server (--rsc example page)
117
119
 
120
+ Inspect the generated setup history with:
121
+ - git log --oneline --reverse
122
+
123
+ The generated app includes one git commit per logical setup step.`)
124
+ .addHelpText('after', `
118
125
  --pro and --rsc support both JavaScript and TypeScript templates.
119
126
 
120
127
  Documentation: https://reactonrails.com/docs/`)
package/lib/utils.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * - Callers must still ensure `command` and `args` come from trusted/validated values.
7
7
  */
8
8
  export declare function execLiveArgs(command: string, args: string[], cwd?: string, env?: NodeJS.ProcessEnv): void;
9
+ export declare function execCaptureArgs(command: string, args: string[], cwd?: string, env?: NodeJS.ProcessEnv): string;
9
10
  export declare function getCommandVersion(command: string): string | null;
10
11
  export declare function detectPackageManager(): 'npm' | 'pnpm' | null;
11
12
  export declare function logStep(current: number, total: number, message: string): void;
package/lib/utils.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.execLiveArgs = execLiveArgs;
7
+ exports.execCaptureArgs = execCaptureArgs;
7
8
  exports.getCommandVersion = getCommandVersion;
8
9
  exports.detectPackageManager = detectPackageManager;
9
10
  exports.logStep = logStep;
@@ -13,6 +14,10 @@ exports.logSuccess = logSuccess;
13
14
  exports.logInfo = logInfo;
14
15
  const child_process_1 = require("child_process");
15
16
  const chalk_1 = __importDefault(require("chalk"));
17
+ function childEnv(env) {
18
+ // Always inherit PATH, HOME, and the rest of process.env; callers only add/override keys.
19
+ return env ? { ...process.env, ...env } : process.env;
20
+ }
16
21
  /**
17
22
  * Execute a command and stream output to the current terminal.
18
23
  *
@@ -24,15 +29,39 @@ function execLiveArgs(command, args, cwd, env) {
24
29
  const result = (0, child_process_1.spawnSync)(command, args, {
25
30
  stdio: 'inherit',
26
31
  cwd,
27
- ...(env ? { env } : {}),
32
+ env: childEnv(env),
28
33
  });
29
34
  if (result.error) {
30
35
  throw result.error;
31
36
  }
37
+ if (result.status === null) {
38
+ throw new Error(`Command "${command}" was terminated by ${result.signal ?? 'unknown signal'}`);
39
+ }
32
40
  if (result.status !== 0) {
33
41
  throw new Error(`Command "${command}" exited with code ${result.status}`);
34
42
  }
35
43
  }
44
+ function execCaptureArgs(command, args, cwd, env) {
45
+ const result = (0, child_process_1.spawnSync)(command, args, {
46
+ stdio: 'pipe',
47
+ encoding: 'utf8',
48
+ cwd,
49
+ env: childEnv(env),
50
+ });
51
+ if (result.error) {
52
+ throw result.error;
53
+ }
54
+ if (result.status === null) {
55
+ throw new Error(`Command "${command}" was terminated by ${result.signal ?? 'unknown signal'}`);
56
+ }
57
+ if (result.status !== 0) {
58
+ const stderr = result.stderr?.trim();
59
+ throw new Error(stderr && stderr.length > 0
60
+ ? `Command "${command}" exited with code ${result.status}: ${stderr}`
61
+ : `Command "${command}" exited with code ${result.status}`);
62
+ }
63
+ return result.stdout?.trim() ?? '';
64
+ }
36
65
  function getCommandVersion(command) {
37
66
  try {
38
67
  return (0, child_process_1.execFileSync)(command, ['--version'], { encoding: 'utf8', stdio: 'pipe' }).trim();
@@ -2,6 +2,7 @@ import { ValidationResult } from './types.js';
2
2
  export declare function validateNode(): ValidationResult;
3
3
  export declare function validateRuby(): ValidationResult;
4
4
  export declare function validateRails(): ValidationResult;
5
+ export declare function validateGit(): ValidationResult;
5
6
  export declare function validatePackageManager(pm: 'npm' | 'pnpm'): ValidationResult;
6
7
  export interface PrerequisiteResults {
7
8
  allValid: boolean;
package/lib/validators.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateNode = validateNode;
4
4
  exports.validateRuby = validateRuby;
5
5
  exports.validateRails = validateRails;
6
+ exports.validateGit = validateGit;
6
7
  exports.validatePackageManager = validatePackageManager;
7
8
  exports.validateAll = validateAll;
8
9
  const utils_js_1 = require("./utils.js");
@@ -85,6 +86,19 @@ function validateRails() {
85
86
  }
86
87
  return { valid: true, message: firstLine };
87
88
  }
89
+ function validateGit() {
90
+ const gitVersion = (0, utils_js_1.getCommandVersion)('git');
91
+ if (!gitVersion) {
92
+ return {
93
+ valid: false,
94
+ message: 'git is not installed or not found in PATH.\n\n' +
95
+ 'create-react-on-rails-app now records the generated app as a step-by-step git history.\n' +
96
+ 'Install git, then try again:\n' +
97
+ ' https://git-scm.com/downloads',
98
+ };
99
+ }
100
+ return { valid: true, message: gitVersion.split('\n')[0].trim() };
101
+ }
88
102
  function validatePackageManager(pm) {
89
103
  const version = (0, utils_js_1.getCommandVersion)(pm);
90
104
  if (!version) {
@@ -100,6 +114,7 @@ function validateAll(packageManager) {
100
114
  { name: 'Node.js', result: validateNode() },
101
115
  { name: 'Ruby', result: validateRuby() },
102
116
  { name: 'Rails', result: validateRails() },
117
+ { name: 'git', result: validateGit() },
103
118
  { name: 'Package Manager', result: validatePackageManager(packageManager) },
104
119
  ];
105
120
  const allValid = results.every((r) => r.result.valid);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-react-on-rails-app",
3
- "version": "16.5.1",
3
+ "version": "16.6.0-rc.0",
4
4
  "description": "Create React on Rails applications with a single command",
5
5
  "bin": {
6
6
  "create-react-on-rails-app": "./bin/create-react-on-rails-app.js"