@akinon/projectzero 2.0.20-rc.0 → 2.0.21-beta.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.
@@ -12,8 +12,10 @@
12
12
  * 7. Run sentry-9 codemod (only when @sentry/nextjs is present)
13
13
  * 8. Run migrate-eslint codemod (ESLint v9 flat config)
14
14
  * 9. Run migrate-page-types codemod (PageProps -> Async/Resolved)
15
- * 10. yarn build (validation)
16
- * 11. Summary report
15
+ * 10. Run fix-template-currenturl codemod (template.tsx JSON-LD url)
16
+ * 11. Run fix-login-form-action codemod (login form React 19 hardening)
17
+ * 12. yarn build (validation)
18
+ * 13. Summary report
17
19
  *
18
20
  * Out of scope in this first version:
19
21
  * - Tailwind v3 -> v4 migration (run manually with @tailwindcss/upgrade)
@@ -34,6 +36,8 @@
34
36
  * --skip-sentry Do not run sentry-9 (auto-skipped if not needed)
35
37
  * --skip-eslint Do not run migrate-eslint
36
38
  * --skip-page-types Do not run migrate-page-types
39
+ * --skip-template-url Do not run fix-template-currenturl
40
+ * --skip-login-action Do not run fix-login-form-action
37
41
  * --skip-install Do not run yarn install
38
42
  * --skip-build Do not run yarn build
39
43
  * --interactive Pause for confirmation after each step
@@ -49,6 +53,8 @@ const AUTH_CODEMOD = path.resolve(__dirname, '..', 'migrate-auth-v5');
49
53
  const SENTRY_CODEMOD = path.resolve(__dirname, '..', 'sentry-9');
50
54
  const ESLINT_CODEMOD = path.resolve(__dirname, '..', 'migrate-eslint');
51
55
  const PAGE_TYPES_CODEMOD = path.resolve(__dirname, '..', 'migrate-page-types');
56
+ const TEMPLATE_URL_CODEMOD = path.resolve(__dirname, '..', 'fix-template-currenturl');
57
+ const LOGIN_ACTION_CODEMOD = path.resolve(__dirname, '..', 'fix-login-form-action');
52
58
 
53
59
  const TARGET_MATRIX = {
54
60
  dependencies: {
@@ -56,7 +62,11 @@ const TARGET_MATRIX = {
56
62
  react: '19.2.5',
57
63
  'react-dom': '19.2.5',
58
64
  'next-auth': '5.0.0-beta.25',
59
- '@akinon/next': 'latest'
65
+ '@akinon/next': 'latest',
66
+ // 2.17.1 declared React peer as ^16-^18 and reads the old
67
+ // ReactSharedInternals shape, throwing on the checkout shipping address
68
+ // step under React 19. 2.20.8 is same-major and declares React 19.
69
+ '@react-google-maps/api': '2.20.8'
60
70
  },
61
71
  devDependencies: {
62
72
  '@types/react': '19.2.14',
@@ -138,6 +148,8 @@ function parseArgs(argv) {
138
148
  skipSentry: argv.includes('--skip-sentry'),
139
149
  skipEslint: argv.includes('--skip-eslint'),
140
150
  skipPageTypes: argv.includes('--skip-page-types'),
151
+ skipTemplateUrl: argv.includes('--skip-template-url'),
152
+ skipLoginAction: argv.includes('--skip-login-action'),
141
153
  skipInstall: argv.includes('--skip-install'),
142
154
  skipBuild: argv.includes('--skip-build'),
143
155
  interactive: argv.includes('--interactive'),
@@ -158,7 +170,7 @@ function writePackageJson(cwd, pkg) {
158
170
  }
159
171
 
160
172
  function stepPreflight(cwd, flags) {
161
- logStep('[1/11] Preflight', 'starting');
173
+ logStep('[1/13] Preflight', 'starting');
162
174
 
163
175
  const pkg = readPackageJson(cwd);
164
176
  if (!pkg) {
@@ -192,19 +204,19 @@ function stepPreflight(cwd, flags) {
192
204
  log(` Current: next@${currentNext} react@${currentReact} next-auth@${currentAuth} @akinon/next@${currentAkinon}`);
193
205
  log(` Target: next@${TARGET_MATRIX.dependencies.next} react@${TARGET_MATRIX.dependencies.react} next-auth@${TARGET_MATRIX.dependencies['next-auth']} @akinon/next@${TARGET_MATRIX.dependencies['@akinon/next']}`);
194
206
 
195
- logStep('[1/11] Preflight', 'ok');
207
+ logStep('[1/13] Preflight', 'ok');
196
208
  }
197
209
 
198
210
  function stepBackup(cwd, flags) {
199
211
  if (flags.skipBackup) {
200
- logStep('[2/11] Backup branch', 'skipped');
212
+ logStep('[2/13] Backup branch', 'skipped');
201
213
  return null;
202
214
  }
203
215
  const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
204
216
  const branchName = `pre-upgrade-2-${today}`;
205
217
 
206
218
  if (flags.dryRun) {
207
- logStep('[2/11] Backup branch', `[DRY] git branch ${branchName}`);
219
+ logStep('[2/13] Backup branch', `[DRY] git branch ${branchName}`);
208
220
  return branchName;
209
221
  }
210
222
 
@@ -214,7 +226,7 @@ function stepBackup(cwd, flags) {
214
226
  { cwd, encoding: 'utf-8' }
215
227
  );
216
228
  if (existing.status === 0) {
217
- logStep('[2/11] Backup branch', `already exists: ${branchName}`);
229
+ logStep('[2/13] Backup branch', `already exists: ${branchName}`);
218
230
  return branchName;
219
231
  }
220
232
 
@@ -225,7 +237,7 @@ function stepBackup(cwd, flags) {
225
237
  if (result.status !== 0) {
226
238
  throw new Error(`Failed to create backup branch ${branchName}`);
227
239
  }
228
- logStep('[2/11] Backup branch', `created ${branchName}`);
240
+ logStep('[2/13] Backup branch', `created ${branchName}`);
229
241
  return branchName;
230
242
  }
231
243
 
@@ -323,7 +335,7 @@ function pinNextScriptsToWebpack(pkg) {
323
335
 
324
336
  function stepBump(cwd, flags) {
325
337
  if (flags.skipBump) {
326
- logStep('[3/11] Bump deps', 'skipped');
338
+ logStep('[3/13] Bump deps', 'skipped');
327
339
  return { hasSentry: false, changes: [] };
328
340
  }
329
341
 
@@ -371,16 +383,16 @@ function stepBump(cwd, flags) {
371
383
  allChanges.push(...scriptChanges);
372
384
 
373
385
  if (allChanges.length === 0) {
374
- logStep('[3/11] Bump deps', 'already at target, no changes');
386
+ logStep('[3/13] Bump deps', 'already at target, no changes');
375
387
  return { hasSentry, changes: [] };
376
388
  }
377
389
 
378
390
  if (flags.dryRun) {
379
- logStep('[3/11] Bump deps', `[DRY] ${allChanges.length} changes`);
391
+ logStep('[3/13] Bump deps', `[DRY] ${allChanges.length} changes`);
380
392
  allChanges.forEach((c) => log(` - ${c}`));
381
393
  } else {
382
394
  writePackageJson(cwd, pkg);
383
- logStep('[3/11] Bump deps', `${allChanges.length} changes applied`);
395
+ logStep('[3/13] Bump deps', `${allChanges.length} changes applied`);
384
396
  if (flags.verbose) allChanges.forEach((c) => log(` - ${c}`));
385
397
  }
386
398
 
@@ -389,28 +401,28 @@ function stepBump(cwd, flags) {
389
401
 
390
402
  function stepNextCodemod(cwd, flags) {
391
403
  if (flags.skipNextCodemod) {
392
- logStep('[5/11] Next codemod', 'skipped');
404
+ logStep('[5/13] Next codemod', 'skipped');
393
405
  return { ok: true };
394
406
  }
395
407
  const cmd = flags.dryRun
396
408
  ? 'npx --yes @next/codemod@latest upgrade latest --verbose'
397
409
  : 'npx --yes @next/codemod@latest upgrade latest';
398
- logStep('[5/11] Next codemod', `running ${cmd}`);
410
+ logStep('[5/13] Next codemod', `running ${cmd}`);
399
411
  const result = runCommand(cmd, { cwd, dryRun: false, verbose: flags.verbose });
400
412
  if (result.status !== 0) {
401
- logStep('[5/11] Next codemod', `FAILED (exit ${result.status})`);
413
+ logStep('[5/13] Next codemod', `FAILED (exit ${result.status})`);
402
414
  return { ok: false };
403
415
  }
404
- logStep('[5/11] Next codemod', 'ok');
416
+ logStep('[5/13] Next codemod', 'ok');
405
417
  return { ok: true };
406
418
  }
407
419
 
408
420
  function stepAuthCodemod(cwd, flags) {
409
421
  if (flags.skipAuth) {
410
- logStep('[6/11] Auth codemod', 'skipped');
422
+ logStep('[6/13] Auth codemod', 'skipped');
411
423
  return { ok: true };
412
424
  }
413
- logStep('[6/11] Auth codemod', 'running migrate-auth-v5');
425
+ logStep('[6/13] Auth codemod', 'running migrate-auth-v5');
414
426
  try {
415
427
  const prevArgv = process.argv;
416
428
  process.argv = [
@@ -430,21 +442,21 @@ function stepAuthCodemod(cwd, flags) {
430
442
  return result.then(
431
443
  () => {
432
444
  finish();
433
- logStep('[6/11] Auth codemod', 'ok');
445
+ logStep('[6/13] Auth codemod', 'ok');
434
446
  return { ok: true };
435
447
  },
436
448
  (err) => {
437
449
  finish();
438
- logStep('[6/11] Auth codemod', `FAILED: ${err.message}`);
450
+ logStep('[6/13] Auth codemod', `FAILED: ${err.message}`);
439
451
  return { ok: false };
440
452
  }
441
453
  );
442
454
  }
443
455
  finish();
444
- logStep('[6/11] Auth codemod', 'ok');
456
+ logStep('[6/13] Auth codemod', 'ok');
445
457
  return { ok: true };
446
458
  } catch (err) {
447
- logStep('[6/11] Auth codemod', `FAILED: ${err.message}`);
459
+ logStep('[6/13] Auth codemod', `FAILED: ${err.message}`);
448
460
  return { ok: false };
449
461
  }
450
462
  }
@@ -452,34 +464,34 @@ function stepAuthCodemod(cwd, flags) {
452
464
  function stepSentryCodemod(cwd, flags, hasSentry) {
453
465
  if (flags.skipSentry || !hasSentry) {
454
466
  const reason = flags.skipSentry ? 'skipped' : 'no @sentry/nextjs, skipping';
455
- logStep('[7/11] Sentry codemod', reason);
467
+ logStep('[7/13] Sentry codemod', reason);
456
468
  return { ok: true };
457
469
  }
458
470
  if (flags.dryRun) {
459
- logStep('[7/11] Sentry codemod', '[DRY] would run sentry-9');
471
+ logStep('[7/13] Sentry codemod', '[DRY] would run sentry-9');
460
472
  return { ok: true };
461
473
  }
462
- logStep('[7/11] Sentry codemod', 'running sentry-9');
474
+ logStep('[7/13] Sentry codemod', 'running sentry-9');
463
475
  try {
464
476
  const savedCwd = process.cwd();
465
477
  process.chdir(cwd);
466
478
  const codemod = require(SENTRY_CODEMOD);
467
479
  codemod.transform();
468
480
  process.chdir(savedCwd);
469
- logStep('[7/11] Sentry codemod', 'ok');
481
+ logStep('[7/13] Sentry codemod', 'ok');
470
482
  return { ok: true };
471
483
  } catch (err) {
472
- logStep('[7/11] Sentry codemod', `FAILED: ${err.message}`);
484
+ logStep('[7/13] Sentry codemod', `FAILED: ${err.message}`);
473
485
  return { ok: false };
474
486
  }
475
487
  }
476
488
 
477
489
  function stepEslintCodemod(cwd, flags) {
478
490
  if (flags.skipEslint) {
479
- logStep('[8/11] ESLint codemod', 'skipped');
491
+ logStep('[8/13] ESLint codemod', 'skipped');
480
492
  return { ok: true };
481
493
  }
482
- logStep('[8/11] ESLint codemod', 'running migrate-eslint');
494
+ logStep('[8/13] ESLint codemod', 'running migrate-eslint');
483
495
  try {
484
496
  const prevArgv = process.argv;
485
497
  process.argv = [
@@ -493,20 +505,20 @@ function stepEslintCodemod(cwd, flags) {
493
505
  codemod.transform();
494
506
  process.chdir(savedCwd);
495
507
  process.argv = prevArgv;
496
- logStep('[8/11] ESLint codemod', 'ok');
508
+ logStep('[8/13] ESLint codemod', 'ok');
497
509
  return { ok: true };
498
510
  } catch (err) {
499
- logStep('[8/11] ESLint codemod', `FAILED: ${err.message}`);
511
+ logStep('[8/13] ESLint codemod', `FAILED: ${err.message}`);
500
512
  return { ok: false };
501
513
  }
502
514
  }
503
515
 
504
516
  function stepPageTypesCodemod(cwd, flags) {
505
517
  if (flags.skipPageTypes) {
506
- logStep('[9/11] Page types codemod', 'skipped');
518
+ logStep('[9/13] Page types codemod', 'skipped');
507
519
  return { ok: true };
508
520
  }
509
- logStep('[9/11] Page types codemod', 'running migrate-page-types');
521
+ logStep('[9/13] Page types codemod', 'running migrate-page-types');
510
522
  try {
511
523
  const prevArgv = process.argv;
512
524
  process.argv = [
@@ -526,35 +538,123 @@ function stepPageTypesCodemod(cwd, flags) {
526
538
  return result.then(
527
539
  () => {
528
540
  finish();
529
- logStep('[9/11] Page types codemod', 'ok');
541
+ logStep('[9/13] Page types codemod', 'ok');
530
542
  return { ok: true };
531
543
  },
532
544
  (err) => {
533
545
  finish();
534
- logStep('[9/11] Page types codemod', `FAILED: ${err.message}`);
546
+ logStep('[9/13] Page types codemod', `FAILED: ${err.message}`);
535
547
  return { ok: false };
536
548
  }
537
549
  );
538
550
  }
539
551
  finish();
540
- logStep('[9/11] Page types codemod', 'ok');
552
+ logStep('[9/13] Page types codemod', 'ok');
541
553
  return { ok: true };
542
554
  } catch (err) {
543
- logStep('[9/11] Page types codemod', `FAILED: ${err.message}`);
555
+ logStep('[9/13] Page types codemod', `FAILED: ${err.message}`);
556
+ return { ok: false };
557
+ }
558
+ }
559
+
560
+ function stepTemplateUrlCodemod(cwd, flags) {
561
+ if (flags.skipTemplateUrl) {
562
+ logStep('[10/13] Template currentUrl codemod', 'skipped');
563
+ return { ok: true };
564
+ }
565
+ logStep('[10/13] Template currentUrl codemod', 'running fix-template-currenturl');
566
+ try {
567
+ const prevArgv = process.argv;
568
+ process.argv = [
569
+ process.argv[0],
570
+ process.argv[1],
571
+ ...(flags.dryRun ? ['--dry-run'] : [])
572
+ ];
573
+ const savedCwd = process.cwd();
574
+ process.chdir(cwd);
575
+ const codemod = require(TEMPLATE_URL_CODEMOD);
576
+ const result = codemod.transform();
577
+ const finish = () => {
578
+ process.chdir(savedCwd);
579
+ process.argv = prevArgv;
580
+ };
581
+ if (result && typeof result.then === 'function') {
582
+ return result.then(
583
+ () => {
584
+ finish();
585
+ logStep('[10/13] Template currentUrl codemod', 'ok');
586
+ return { ok: true };
587
+ },
588
+ (err) => {
589
+ finish();
590
+ logStep('[10/13] Template currentUrl codemod', `FAILED: ${err.message}`);
591
+ return { ok: false };
592
+ }
593
+ );
594
+ }
595
+ finish();
596
+ logStep('[10/13] Template currentUrl codemod', 'ok');
597
+ return { ok: true };
598
+ } catch (err) {
599
+ logStep('[10/13] Template currentUrl codemod', `FAILED: ${err.message}`);
600
+ return { ok: false };
601
+ }
602
+ }
603
+
604
+ function stepLoginActionCodemod(cwd, flags) {
605
+ if (flags.skipLoginAction) {
606
+ logStep('[11/13] Login form action codemod', 'skipped');
607
+ return { ok: true };
608
+ }
609
+ logStep('[11/13] Login form action codemod', 'running fix-login-form-action');
610
+ try {
611
+ const prevArgv = process.argv;
612
+ process.argv = [
613
+ process.argv[0],
614
+ process.argv[1],
615
+ ...(flags.dryRun ? ['--dry-run'] : [])
616
+ ];
617
+ const savedCwd = process.cwd();
618
+ process.chdir(cwd);
619
+ const codemod = require(LOGIN_ACTION_CODEMOD);
620
+ const result = codemod.transform();
621
+ const finish = () => {
622
+ process.chdir(savedCwd);
623
+ process.argv = prevArgv;
624
+ };
625
+ if (result && typeof result.then === 'function') {
626
+ return result.then(
627
+ () => {
628
+ finish();
629
+ logStep('[11/13] Login form action codemod', 'ok');
630
+ return { ok: true };
631
+ },
632
+ (err) => {
633
+ finish();
634
+ logStep('[11/13] Login form action codemod', `FAILED: ${err.message}`);
635
+ return { ok: false };
636
+ }
637
+ );
638
+ }
639
+ finish();
640
+ logStep('[11/13] Login form action codemod', 'ok');
641
+ return { ok: true };
642
+ } catch (err) {
643
+ logStep('[11/13] Login form action codemod', `FAILED: ${err.message}`);
544
644
  return { ok: false };
545
645
  }
546
646
  }
547
647
 
548
648
  function stepInstall(cwd, flags) {
549
649
  if (flags.skipInstall) {
550
- logStep('[4/11] yarn install', 'skipped');
650
+ logStep('[4/13] yarn install', 'skipped');
551
651
  return { ok: true };
552
652
  }
553
653
  if (flags.dryRun) {
554
- logStep('[4/11] yarn install', '[DRY] yarn clean && yarn');
654
+ logStep('[4/13] yarn install', '[DRY] yarn clean && yarn');
555
655
  return { ok: true };
556
656
  }
557
- logStep('[4/11] yarn install', 'running yarn clean && yarn');
657
+ logStep('[4/13] yarn install', 'running yarn clean && yarn');
558
658
  const clean = runCommand('yarn clean', {
559
659
  cwd,
560
660
  dryRun: false,
@@ -569,33 +669,33 @@ function stepInstall(cwd, flags) {
569
669
  verbose: flags.verbose
570
670
  });
571
671
  if (install.status !== 0) {
572
- logStep('[4/11] yarn install', `FAILED (exit ${install.status})`);
672
+ logStep('[4/13] yarn install', `FAILED (exit ${install.status})`);
573
673
  return { ok: false };
574
674
  }
575
- logStep('[4/11] yarn install', 'ok');
675
+ logStep('[4/13] yarn install', 'ok');
576
676
  return { ok: true };
577
677
  }
578
678
 
579
679
  function stepBuild(cwd, flags) {
580
680
  if (flags.skipBuild) {
581
- logStep('[10/11] yarn build', 'skipped');
681
+ logStep('[12/13] yarn build', 'skipped');
582
682
  return { ok: true };
583
683
  }
584
684
  if (flags.dryRun) {
585
- logStep('[10/11] yarn build', '[DRY] yarn build');
685
+ logStep('[12/13] yarn build', '[DRY] yarn build');
586
686
  return { ok: true };
587
687
  }
588
- logStep('[10/11] yarn build', 'running');
688
+ logStep('[12/13] yarn build', 'running');
589
689
  const result = runCommand('yarn build', {
590
690
  cwd,
591
691
  dryRun: false,
592
692
  verbose: flags.verbose
593
693
  });
594
694
  if (result.status !== 0) {
595
- logStep('[10/11] yarn build', `FAILED (exit ${result.status})`);
695
+ logStep('[12/13] yarn build', `FAILED (exit ${result.status})`);
596
696
  return { ok: false };
597
697
  }
598
- logStep('[10/11] yarn build', 'ok');
698
+ logStep('[12/13] yarn build', 'ok');
599
699
  return { ok: true };
600
700
  }
601
701
 
@@ -607,7 +707,7 @@ function countTodoMarkers(cwd) {
607
707
  }
608
708
 
609
709
  function stepReport(cwd, results) {
610
- logStep('[11/11] Report', 'summary');
710
+ logStep('[13/13] Report', 'summary');
611
711
  const pkg = readPackageJson(cwd) || {};
612
712
  const todoCount = countTodoMarkers(cwd);
613
713
 
@@ -667,7 +767,7 @@ async function transform() {
667
767
  results.preflight = true;
668
768
  await maybePause(flags, 'preflight');
669
769
  } else {
670
- logStep('[1/11] Preflight', 'skipped');
770
+ logStep('[1/13] Preflight', 'skipped');
671
771
  results.preflight = true;
672
772
  }
673
773
 
@@ -709,6 +809,22 @@ async function transform() {
709
809
  results.pageTypesCodemod = pageTypesAwaited.ok;
710
810
  await maybePause(flags, 'page-types-codemod');
711
811
 
812
+ const templateUrlResult = stepTemplateUrlCodemod(cwd, flags);
813
+ const templateUrlAwaited =
814
+ templateUrlResult && typeof templateUrlResult.then === 'function'
815
+ ? await templateUrlResult
816
+ : templateUrlResult;
817
+ results.templateUrlCodemod = templateUrlAwaited.ok;
818
+ await maybePause(flags, 'template-url-codemod');
819
+
820
+ const loginActionResult = stepLoginActionCodemod(cwd, flags);
821
+ const loginActionAwaited =
822
+ loginActionResult && typeof loginActionResult.then === 'function'
823
+ ? await loginActionResult
824
+ : loginActionResult;
825
+ results.loginActionCodemod = loginActionAwaited.ok;
826
+ await maybePause(flags, 'login-action-codemod');
827
+
712
828
  results.build = stepBuild(cwd, flags).ok;
713
829
  } catch (err) {
714
830
  log(`FATAL: ${err.message}`);
@@ -164,10 +164,6 @@ export default async () => {
164
164
  name: 'Tamara Payment Extension',
165
165
  value: 'pz-tamara-extension'
166
166
  },
167
- {
168
- name: 'Similar Products',
169
- value: 'pz-similar-products'
170
- },
171
167
  {
172
168
  name: 'Hepsipay',
173
169
  value: 'pz-hepsipay'
@@ -183,10 +183,6 @@ exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
183
183
  name: 'Tamara Payment Extension',
184
184
  value: 'pz-tamara-extension'
185
185
  },
186
- {
187
- name: 'Similar Products',
188
- value: 'pz-similar-products'
189
- },
190
186
  {
191
187
  name: 'Hepsipay',
192
188
  value: 'pz-hepsipay'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/projectzero",
3
- "version": "2.0.20-rc.0",
3
+ "version": "2.0.21-beta.0",
4
4
  "private": false,
5
5
  "description": "CLI tool to manage your Project Zero Next project",
6
6
  "bin": {
@@ -1,22 +0,0 @@
1
- 'use client';
2
-
3
- import { useSentryUncaughtErrors } from '@akinon/next/hooks';
4
-
5
- export default function GlobalError({
6
- error,
7
- reset
8
- }: {
9
- error: Error & { digest?: string };
10
- reset: () => void;
11
- }) {
12
- useSentryUncaughtErrors(error);
13
-
14
- return (
15
- <html>
16
- <body>
17
- <h2>Something went wrong!</h2>
18
- <button onClick={() => reset()}>Try again</button>
19
- </body>
20
- </html>
21
- );
22
- }