@pie-element/cli 0.1.1 → 0.1.2-next.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 (281) hide show
  1. package/README.md +48 -10
  2. package/dist/commands/dev/demo/index.d.ts +1 -1
  3. package/dist/commands/dev/demo/index.js +21 -0
  4. package/dist/commands/dev/demo/index.js.map +1 -1
  5. package/dist/commands/dev/test-bundler.d.ts +0 -1
  6. package/dist/commands/dev/test-bundler.js +2 -10
  7. package/dist/commands/dev/test-bundler.js.map +1 -1
  8. package/dist/commands/docs/generate.d.ts +16 -0
  9. package/dist/commands/docs/generate.js +150 -0
  10. package/dist/commands/docs/generate.js.map +1 -0
  11. package/dist/commands/docs/verify.d.ts +12 -0
  12. package/dist/commands/docs/verify.js +40 -0
  13. package/dist/commands/docs/verify.js.map +1 -0
  14. package/dist/commands/packages/create-controllers.d.ts +0 -1
  15. package/dist/commands/packages/create-controllers.js.map +1 -1
  16. package/dist/commands/packages/create-lib-react.d.ts +0 -1
  17. package/dist/commands/packages/create-lib-react.js +1 -3
  18. package/dist/commands/packages/create-lib-react.js.map +1 -1
  19. package/dist/commands/packages/create-react-elements.d.ts +0 -1
  20. package/dist/commands/packages/create-react-elements.js +2 -3
  21. package/dist/commands/packages/create-react-elements.js.map +1 -1
  22. package/dist/commands/packages/enable-publishing.d.ts +0 -1
  23. package/dist/commands/packages/enable-publishing.js +26 -23
  24. package/dist/commands/packages/enable-publishing.js.map +1 -1
  25. package/dist/commands/packages/init-synced-elements.d.ts +0 -1
  26. package/dist/commands/packages/init-synced-elements.js +1 -1
  27. package/dist/commands/packages/init-synced-elements.js.map +1 -1
  28. package/dist/commands/upstream/analyze-esm.d.ts +0 -1
  29. package/dist/commands/upstream/analyze-esm.js +5 -1
  30. package/dist/commands/upstream/analyze-esm.js.map +1 -1
  31. package/dist/commands/upstream/check.d.ts +0 -1
  32. package/dist/commands/upstream/check.js.map +1 -1
  33. package/dist/commands/upstream/deps.d.ts +0 -1
  34. package/dist/commands/upstream/deps.js.map +1 -1
  35. package/dist/commands/upstream/sync.d.ts +11 -2
  36. package/dist/commands/upstream/sync.js +364 -25
  37. package/dist/commands/upstream/sync.js.map +1 -1
  38. package/dist/commands/upstream/track.d.ts +0 -1
  39. package/dist/commands/upstream/track.js.map +1 -1
  40. package/dist/commands/upstream/update.d.ts +0 -1
  41. package/dist/commands/upstream/update.js +37 -7
  42. package/dist/commands/upstream/update.js.map +1 -1
  43. package/dist/commands/verify/controllers.d.ts +0 -1
  44. package/dist/commands/verify/controllers.js +213 -59
  45. package/dist/commands/verify/controllers.js.map +1 -1
  46. package/dist/commands/verify/dependency-integrity.d.ts +18 -0
  47. package/dist/commands/verify/dependency-integrity.js +147 -0
  48. package/dist/commands/verify/dependency-integrity.js.map +1 -0
  49. package/dist/commands/verify/react-build.d.ts +0 -1
  50. package/dist/commands/verify/react-build.js.map +1 -1
  51. package/dist/index.d.ts +0 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/lib/docs/contract-validator.d.ts +12 -0
  54. package/dist/lib/docs/contract-validator.js +38 -0
  55. package/dist/lib/docs/contract-validator.js.map +1 -0
  56. package/dist/lib/docs/contracts.d.ts +11 -0
  57. package/dist/lib/docs/contracts.js +241 -0
  58. package/dist/lib/docs/contracts.js.map +1 -0
  59. package/dist/lib/docs/discovery.d.ts +10 -0
  60. package/dist/lib/docs/discovery.js +91 -0
  61. package/dist/lib/docs/discovery.js.map +1 -0
  62. package/dist/lib/docs/generator.d.ts +14 -0
  63. package/dist/lib/docs/generator.js +450 -0
  64. package/dist/lib/docs/generator.js.map +1 -0
  65. package/dist/lib/docs/source-extractor.d.ts +2 -0
  66. package/dist/lib/docs/source-extractor.js +209 -0
  67. package/dist/lib/docs/source-extractor.js.map +1 -0
  68. package/dist/lib/docs/types.d.ts +77 -0
  69. package/dist/lib/docs/types.js +2 -0
  70. package/dist/lib/docs/types.js.map +1 -0
  71. package/dist/lib/upstream/repo-utils.d.ts +0 -1
  72. package/dist/lib/upstream/repo-utils.js.map +1 -1
  73. package/dist/lib/upstream/sync-compatibility.d.ts +0 -1
  74. package/dist/lib/upstream/sync-compatibility.js.map +1 -1
  75. package/dist/lib/upstream/sync-constants.d.ts +35 -7
  76. package/dist/lib/upstream/sync-constants.js +40 -11
  77. package/dist/lib/upstream/sync-constants.js.map +1 -1
  78. package/dist/lib/upstream/sync-controllers-strategy.d.ts +0 -1
  79. package/dist/lib/upstream/sync-controllers-strategy.js +14 -4
  80. package/dist/lib/upstream/sync-controllers-strategy.js.map +1 -1
  81. package/dist/lib/upstream/sync-demo-metadata.d.ts +0 -1
  82. package/dist/lib/upstream/sync-demo-metadata.js +1 -1
  83. package/dist/lib/upstream/sync-demo-metadata.js.map +1 -1
  84. package/dist/lib/upstream/sync-entry-discovery.d.ts +3 -0
  85. package/dist/lib/upstream/sync-entry-discovery.js +23 -0
  86. package/dist/lib/upstream/sync-entry-discovery.js.map +1 -0
  87. package/dist/lib/upstream/sync-externals.d.ts +7 -7
  88. package/dist/lib/upstream/sync-externals.js +51 -35
  89. package/dist/lib/upstream/sync-externals.js.map +1 -1
  90. package/dist/lib/upstream/sync-filesystem.d.ts +0 -1
  91. package/dist/lib/upstream/sync-filesystem.js.map +1 -1
  92. package/dist/lib/upstream/sync-imports.d.ts +82 -62
  93. package/dist/lib/upstream/sync-imports.js +658 -185
  94. package/dist/lib/upstream/sync-imports.js.map +1 -1
  95. package/dist/lib/upstream/sync-package-json.d.ts +0 -1
  96. package/dist/lib/upstream/sync-package-json.js +7 -0
  97. package/dist/lib/upstream/sync-package-json.js.map +1 -1
  98. package/dist/lib/upstream/sync-package-manager.d.ts +14 -4
  99. package/dist/lib/upstream/sync-package-manager.js +405 -72
  100. package/dist/lib/upstream/sync-package-manager.js.map +1 -1
  101. package/dist/lib/upstream/sync-pielib-strategy.d.ts +2 -1
  102. package/dist/lib/upstream/sync-pielib-strategy.js +228 -110
  103. package/dist/lib/upstream/sync-pielib-strategy.js.map +1 -1
  104. package/dist/lib/upstream/sync-presets.d.ts +52 -0
  105. package/dist/lib/upstream/sync-presets.js +175 -0
  106. package/dist/lib/upstream/sync-presets.js.map +1 -0
  107. package/dist/lib/upstream/sync-react-strategy.d.ts +6 -1
  108. package/dist/lib/upstream/sync-react-strategy.js +342 -134
  109. package/dist/lib/upstream/sync-react-strategy.js.map +1 -1
  110. package/dist/lib/upstream/sync-source-edit.d.ts +14 -0
  111. package/dist/lib/upstream/sync-source-edit.js +89 -0
  112. package/dist/lib/upstream/sync-source-edit.js.map +1 -0
  113. package/dist/lib/upstream/sync-source-tree.d.ts +22 -0
  114. package/dist/lib/upstream/sync-source-tree.js +99 -0
  115. package/dist/lib/upstream/sync-source-tree.js.map +1 -0
  116. package/dist/lib/upstream/sync-strategy.d.ts +1 -1
  117. package/dist/lib/upstream/sync-strategy.js.map +1 -1
  118. package/dist/lib/upstream/sync-summary.d.ts +0 -1
  119. package/dist/lib/upstream/sync-summary.js.map +1 -1
  120. package/dist/lib/upstream/sync-transforms.d.ts +13 -11
  121. package/dist/lib/upstream/sync-transforms.js +23 -17
  122. package/dist/lib/upstream/sync-transforms.js.map +1 -1
  123. package/dist/lib/upstream/sync-vite-config.d.ts +13 -1
  124. package/dist/lib/upstream/sync-vite-config.js +65 -46
  125. package/dist/lib/upstream/sync-vite-config.js.map +1 -1
  126. package/dist/utils/compatibility.d.ts +13 -1
  127. package/dist/utils/compatibility.js +143 -2
  128. package/dist/utils/compatibility.js.map +1 -1
  129. package/dist/utils/conversion.d.ts +0 -1
  130. package/dist/utils/conversion.js.map +1 -1
  131. package/dist/utils/dependency-integrity.d.ts +37 -0
  132. package/dist/utils/dependency-integrity.js +557 -0
  133. package/dist/utils/dependency-integrity.js.map +1 -0
  134. package/dist/utils/git.d.ts +0 -1
  135. package/dist/utils/git.js.map +1 -1
  136. package/dist/utils/logger.d.ts +0 -1
  137. package/dist/utils/logger.js.map +1 -1
  138. package/dist/utils/package-json.d.ts +0 -1
  139. package/dist/utils/package-json.js.map +1 -1
  140. package/package.json +25 -8
  141. package/.compatibility/report.json +0 -2491
  142. package/.turbo/turbo-build.log +0 -1
  143. package/CHANGELOG.md +0 -8
  144. package/REFACTORING.md +0 -131
  145. package/bin/dev.js +0 -5
  146. package/dist/commands/dev/demo/index.d.ts.map +0 -1
  147. package/dist/commands/dev/test-bundler.d.ts.map +0 -1
  148. package/dist/commands/mathquill/migrate.d.ts +0 -20
  149. package/dist/commands/mathquill/migrate.d.ts.map +0 -1
  150. package/dist/commands/mathquill/migrate.js +0 -240
  151. package/dist/commands/mathquill/migrate.js.map +0 -1
  152. package/dist/commands/mathquill/status.d.ts +0 -20
  153. package/dist/commands/mathquill/status.d.ts.map +0 -1
  154. package/dist/commands/mathquill/status.js +0 -231
  155. package/dist/commands/mathquill/status.js.map +0 -1
  156. package/dist/commands/packages/create-controllers.d.ts.map +0 -1
  157. package/dist/commands/packages/create-lib-react.d.ts.map +0 -1
  158. package/dist/commands/packages/create-react-elements.d.ts.map +0 -1
  159. package/dist/commands/packages/enable-publishing.d.ts.map +0 -1
  160. package/dist/commands/packages/init-synced-elements.d.ts.map +0 -1
  161. package/dist/commands/upstream/analyze-esm.d.ts.map +0 -1
  162. package/dist/commands/upstream/check.d.ts.map +0 -1
  163. package/dist/commands/upstream/deps.d.ts.map +0 -1
  164. package/dist/commands/upstream/sync-mathquill.d.ts +0 -12
  165. package/dist/commands/upstream/sync-mathquill.d.ts.map +0 -1
  166. package/dist/commands/upstream/sync-mathquill.js +0 -97
  167. package/dist/commands/upstream/sync-mathquill.js.map +0 -1
  168. package/dist/commands/upstream/sync.d.ts.map +0 -1
  169. package/dist/commands/upstream/track.d.ts.map +0 -1
  170. package/dist/commands/upstream/update.d.ts.map +0 -1
  171. package/dist/commands/verify/controllers.d.ts.map +0 -1
  172. package/dist/commands/verify/react-build.d.ts.map +0 -1
  173. package/dist/index.d.ts.map +0 -1
  174. package/dist/lib/mathquill/extension-generator.d.ts +0 -9
  175. package/dist/lib/mathquill/extension-generator.d.ts.map +0 -1
  176. package/dist/lib/mathquill/extension-generator.js +0 -107
  177. package/dist/lib/mathquill/extension-generator.js.map +0 -1
  178. package/dist/lib/mathquill/khan-extractor.d.ts +0 -16
  179. package/dist/lib/mathquill/khan-extractor.d.ts.map +0 -1
  180. package/dist/lib/mathquill/khan-extractor.js +0 -148
  181. package/dist/lib/mathquill/khan-extractor.js.map +0 -1
  182. package/dist/lib/mathquill/learnosity-extractor.d.ts +0 -15
  183. package/dist/lib/mathquill/learnosity-extractor.d.ts.map +0 -1
  184. package/dist/lib/mathquill/learnosity-extractor.js +0 -170
  185. package/dist/lib/mathquill/learnosity-extractor.js.map +0 -1
  186. package/dist/lib/mathquill/migration-orchestrator.d.ts +0 -77
  187. package/dist/lib/mathquill/migration-orchestrator.d.ts.map +0 -1
  188. package/dist/lib/mathquill/migration-orchestrator.js +0 -391
  189. package/dist/lib/mathquill/migration-orchestrator.js.map +0 -1
  190. package/dist/lib/mathquill/package-updater.d.ts +0 -9
  191. package/dist/lib/mathquill/package-updater.d.ts.map +0 -1
  192. package/dist/lib/mathquill/package-updater.js +0 -103
  193. package/dist/lib/mathquill/package-updater.js.map +0 -1
  194. package/dist/lib/mathquill/pie-extractor.d.ts +0 -14
  195. package/dist/lib/mathquill/pie-extractor.d.ts.map +0 -1
  196. package/dist/lib/mathquill/pie-extractor.js +0 -167
  197. package/dist/lib/mathquill/pie-extractor.js.map +0 -1
  198. package/dist/lib/upstream/repo-utils.d.ts.map +0 -1
  199. package/dist/lib/upstream/sync-compatibility.d.ts.map +0 -1
  200. package/dist/lib/upstream/sync-constants.d.ts.map +0 -1
  201. package/dist/lib/upstream/sync-controllers-strategy.d.ts.map +0 -1
  202. package/dist/lib/upstream/sync-demo-metadata.d.ts.map +0 -1
  203. package/dist/lib/upstream/sync-dev-exports.d.ts +0 -13
  204. package/dist/lib/upstream/sync-dev-exports.d.ts.map +0 -1
  205. package/dist/lib/upstream/sync-dev-exports.js +0 -115
  206. package/dist/lib/upstream/sync-dev-exports.js.map +0 -1
  207. package/dist/lib/upstream/sync-externals.d.ts.map +0 -1
  208. package/dist/lib/upstream/sync-filesystem.d.ts.map +0 -1
  209. package/dist/lib/upstream/sync-imports.d.ts.map +0 -1
  210. package/dist/lib/upstream/sync-mathquill.d.ts +0 -19
  211. package/dist/lib/upstream/sync-mathquill.d.ts.map +0 -1
  212. package/dist/lib/upstream/sync-mathquill.js +0 -160
  213. package/dist/lib/upstream/sync-mathquill.js.map +0 -1
  214. package/dist/lib/upstream/sync-package-json.d.ts.map +0 -1
  215. package/dist/lib/upstream/sync-package-manager.d.ts.map +0 -1
  216. package/dist/lib/upstream/sync-pielib-strategy.d.ts.map +0 -1
  217. package/dist/lib/upstream/sync-react-strategy.d.ts.map +0 -1
  218. package/dist/lib/upstream/sync-strategy.d.ts.map +0 -1
  219. package/dist/lib/upstream/sync-summary.d.ts.map +0 -1
  220. package/dist/lib/upstream/sync-transforms.d.ts.map +0 -1
  221. package/dist/lib/upstream/sync-vite-config.d.ts.map +0 -1
  222. package/dist/utils/compatibility.d.ts.map +0 -1
  223. package/dist/utils/conversion.d.ts.map +0 -1
  224. package/dist/utils/git.d.ts.map +0 -1
  225. package/dist/utils/logger.d.ts.map +0 -1
  226. package/dist/utils/package-json.d.ts.map +0 -1
  227. package/packages/cli/bin/dev.js +0 -5
  228. package/packages/cli/bin/run.js +0 -5
  229. package/src/commands/dev/demo/index.ts +0 -313
  230. package/src/commands/dev/test-bundler.ts +0 -345
  231. package/src/commands/mathquill/migrate.ts +0 -269
  232. package/src/commands/mathquill/status.ts +0 -267
  233. package/src/commands/packages/create-controllers.ts +0 -127
  234. package/src/commands/packages/create-lib-react.ts +0 -279
  235. package/src/commands/packages/create-react-elements.ts +0 -306
  236. package/src/commands/packages/enable-publishing.ts +0 -161
  237. package/src/commands/packages/init-synced-elements.ts +0 -259
  238. package/src/commands/upstream/README.md +0 -444
  239. package/src/commands/upstream/analyze-esm.ts +0 -1973
  240. package/src/commands/upstream/check.ts +0 -228
  241. package/src/commands/upstream/deps.ts +0 -222
  242. package/src/commands/upstream/sync-mathquill.ts +0 -108
  243. package/src/commands/upstream/sync.ts +0 -687
  244. package/src/commands/upstream/track.ts +0 -145
  245. package/src/commands/upstream/update.ts +0 -110
  246. package/src/commands/verify/controllers.ts +0 -166
  247. package/src/commands/verify/react-build.ts +0 -171
  248. package/src/index.ts +0 -1
  249. package/src/lib/mathquill/extension-generator.ts +0 -111
  250. package/src/lib/mathquill/khan-extractor.ts +0 -175
  251. package/src/lib/mathquill/learnosity-extractor.ts +0 -198
  252. package/src/lib/mathquill/migration-orchestrator.ts +0 -513
  253. package/src/lib/mathquill/package-updater.ts +0 -120
  254. package/src/lib/mathquill/pie-extractor.ts +0 -194
  255. package/src/lib/upstream/repo-utils.ts +0 -18
  256. package/src/lib/upstream/sync-compatibility.ts +0 -89
  257. package/src/lib/upstream/sync-constants.ts +0 -77
  258. package/src/lib/upstream/sync-controllers-strategy.ts +0 -291
  259. package/src/lib/upstream/sync-demo-metadata.ts +0 -199
  260. package/src/lib/upstream/sync-dev-exports.ts +0 -151
  261. package/src/lib/upstream/sync-externals.ts +0 -159
  262. package/src/lib/upstream/sync-filesystem.ts +0 -87
  263. package/src/lib/upstream/sync-imports.ts +0 -992
  264. package/src/lib/upstream/sync-mathquill.ts +0 -194
  265. package/src/lib/upstream/sync-package-json.ts +0 -86
  266. package/src/lib/upstream/sync-package-manager.ts +0 -694
  267. package/src/lib/upstream/sync-pielib-strategy.ts +0 -441
  268. package/src/lib/upstream/sync-react-strategy.ts +0 -945
  269. package/src/lib/upstream/sync-strategy.ts +0 -61
  270. package/src/lib/upstream/sync-summary.ts +0 -194
  271. package/src/lib/upstream/sync-transforms.ts +0 -154
  272. package/src/lib/upstream/sync-vite-config.ts +0 -243
  273. package/src/types/es-module-lexer.d.ts +0 -4
  274. package/src/utils/compatibility.ts +0 -182
  275. package/src/utils/conversion.ts +0 -153
  276. package/src/utils/git.ts +0 -63
  277. package/src/utils/logger.ts +0 -69
  278. package/src/utils/package-json.ts +0 -43
  279. package/tests/sync-package-manager.test.ts +0 -112
  280. package/tests/transform-assign-props.test.ts +0 -101
  281. package/tsconfig.json +0 -15
@@ -1,11 +1,12 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import { Logger } from '../../utils/logger.js';
3
- import { loadCompatibilityReport } from '../../utils/compatibility.js';
3
+ import { formatCompatibilityReportLastAnalyzed, loadCompatibilityReport, } from '../../utils/compatibility.js';
4
4
  import { getCurrentCommit } from '../../utils/git.js';
5
5
  import { printSyncSummary, createEmptySummary } from '../../lib/upstream/sync-summary.js';
6
- import { loadPackageJson } from '../../utils/package-json.js';
6
+ import { loadPackageJson, writePackageJson } from '../../utils/package-json.js';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { existsSync } from 'node:fs';
9
+ import { readFile, stat as fsStat, writeFile } from 'node:fs/promises';
9
10
  import { join } from 'node:path';
10
11
  import { readdir } from '../../lib/upstream/sync-filesystem.js';
11
12
  import { getAllDeps } from '../../lib/upstream/sync-package-json.js';
@@ -14,7 +15,9 @@ import { ReactComponentsStrategy } from '../../lib/upstream/sync-react-strategy.
14
15
  import { PieLibStrategy } from '../../lib/upstream/sync-pielib-strategy.js';
15
16
  import { DEFAULT_PATHS, COMPATIBILITY_FILE, WORKSPACE } from '../../lib/upstream/sync-constants.js';
16
17
  import { assertReposExist } from '../../lib/upstream/repo-utils.js';
17
- import { addDevelopmentExports } from '../../lib/upstream/sync-dev-exports.js';
18
+ import { rewriteRelativeSpecifiersForNodeEsm } from '../../lib/upstream/sync-imports.js';
19
+ import { analyzePackageDependencyIntegrity, collectWorkspacePackageDirs, } from '../../utils/dependency-integrity.js';
20
+ import { getPostSyncTextPatches } from '../../lib/upstream/sync-presets.js';
18
21
  export default class Sync extends Command {
19
22
  static description = 'Synchronize code from upstream pie-elements repository';
20
23
  static examples = [
@@ -39,6 +42,7 @@ export default class Sync extends Command {
39
42
  logger = new Logger();
40
43
  touchedElementPackages = new Set();
41
44
  touchedPieLibPackages = new Set();
45
+ preSyncProblemIntegrityByImport = new Map();
42
46
  async run() {
43
47
  const { flags } = await this.parse(Sync);
44
48
  this.logger = new Logger(flags.verbose);
@@ -78,6 +82,7 @@ export default class Sync extends Command {
78
82
  // Reset touched packages for this run
79
83
  this.touchedElementPackages = new Set();
80
84
  this.touchedPieLibPackages = new Set();
85
+ this.preSyncProblemIntegrityByImport = new Map();
81
86
  this.logger.section('🔄 Syncing from upstream');
82
87
  this.logger.info(` Source: ${config.pieElements}`);
83
88
  this.logger.info(` Destination: ${config.pieElementsNg}/packages/`);
@@ -128,6 +133,31 @@ export default class Sync extends Command {
128
133
  this.logger.error(error instanceof Error ? error.message : String(error));
129
134
  this.error('Sync failed', { exit: 1 });
130
135
  }
136
+ if (config.dryRun) {
137
+ this.logger.section('🧪 Dry run');
138
+ this.logger.info(' No files will be modified.');
139
+ const elementsPlanned = config.syncReactComponents
140
+ ? await this.listElementPackages(config)
141
+ : [];
142
+ const pieLibPlanned = config.syncPieLibPackages && config.pieLibPackages ? [...config.pieLibPackages] : [];
143
+ syncSummary.controllersSync = config.syncControllers ? elementsPlanned.length : 0;
144
+ syncSummary.reactComponentsSynced = elementsPlanned.length;
145
+ syncSummary.pieLibPackagesSynced = pieLibPlanned.length;
146
+ syncSummary.totalPackagesSynced = elementsPlanned.length + pieLibPlanned.length;
147
+ syncSummary.syncedPackageNames = [
148
+ ...elementsPlanned,
149
+ ...pieLibPlanned.map((pkg) => `@pie-lib/${pkg}`),
150
+ ];
151
+ if (compatibilityReport) {
152
+ syncSummary.blockedElements = Object.keys(compatibilityReport.blockedElements).length;
153
+ syncSummary.blockedPieLib = Object.values(compatibilityReport.pieLibDetails).filter((d) => !d.compatible).length;
154
+ }
155
+ printSyncSummary(syncSummary, compatibilityReport, config.pieElementsNg, this.logger);
156
+ return;
157
+ }
158
+ // Capture current dependency integrity gaps before sync so we only fail on new regressions.
159
+ this.preSyncProblemIntegrityByImport =
160
+ await this.captureCurrentProblemIntegrityBaseline(config);
131
161
  // Clean target directories first (ensures a clean slate for full syncs)
132
162
  await this.cleanTargetDirectories(config);
133
163
  // Execute sync strategies
@@ -146,6 +176,7 @@ export default class Sync extends Command {
146
176
  syncPieLib: config.syncPieLibPackages,
147
177
  pieLibPackages: config.pieLibPackages,
148
178
  skipDemos: true,
179
+ dryRun: config.dryRun,
149
180
  upstreamCommit: getCurrentCommit(config.pieElements),
150
181
  },
151
182
  logger: this.logger,
@@ -194,12 +225,36 @@ export default class Sync extends Command {
194
225
  if (!config.dryRun) {
195
226
  await this.rewriteWorkspaceDependencies(config);
196
227
  }
197
- // Add development export conditions for HMR support
198
- if (!config.dryRun && this.touchedElementPackages.size > 0) {
199
- await this.addDevelopmentExportsToPackages(config);
228
+ // Auto-fix missing direct dependency declarations in touched package manifests.
229
+ // This makes sync resilient to upstream package.json drift.
230
+ {
231
+ const autoFix = await this.autoFixTouchedPackageDependencyDeclarations(config);
232
+ if (autoFix.unresolved.length > 0) {
233
+ for (const unresolved of autoFix.unresolved) {
234
+ result.warnings.push(`Could not infer version for ${unresolved.dependency} in ${unresolved.packageName}`);
235
+ }
236
+ }
237
+ }
238
+ // Apply targeted post-sync source patches for known declaration-emit issues.
239
+ if (!config.dryRun) {
240
+ await this.applyPostSyncBuildStabilizers(config);
241
+ }
242
+ // Normalize relative ESM specifiers to explicit .js paths for NodeNext.
243
+ if (!config.dryRun) {
244
+ await this.applyNodeEsmSpecifierRewrites(config);
245
+ }
246
+ // Verify synced packages for dependency integrity regressions (broken/hoist-reliant imports).
247
+ // This catches runtime failures like unresolved "prop-types" and newly introduced hoist reliance.
248
+ {
249
+ const integrityRegressions = await this.verifyTouchedPackageDependencyIntegrity(config);
250
+ if (integrityRegressions.length > 0) {
251
+ for (const issue of integrityRegressions) {
252
+ result.errors.push(`${issue.packageName} (${issue.packagePath}) has new ${issue.status} dependency: ${issue.dependency}`);
253
+ }
254
+ }
200
255
  }
201
256
  // Build by default (unless dry-run or explicitly skipped)
202
- if (!config.dryRun && !config.skipBuild) {
257
+ if (!config.dryRun && !config.skipBuild && result.errors.length === 0) {
203
258
  await this.buildTouchedPackages(config, result);
204
259
  }
205
260
  // Add blocked package counts from compatibility report
@@ -211,6 +266,13 @@ export default class Sync extends Command {
211
266
  // and managed directly in this repository (not synced from upstream)
212
267
  // Print summary and handle errors
213
268
  printSyncSummary(syncSummary, compatibilityReport, config.pieElementsNg, this.logger);
269
+ if (result.warnings.length > 0) {
270
+ this.logger.warn('Sync completed with warnings:');
271
+ for (const warning of result.warnings) {
272
+ this.logger.warn(` - ${warning}`);
273
+ }
274
+ this.log('');
275
+ }
214
276
  if (result.errors.length > 0) {
215
277
  this.error('Sync completed with errors', { exit: 1 });
216
278
  }
@@ -233,7 +295,7 @@ export default class Sync extends Command {
233
295
  return null;
234
296
  }
235
297
  this.logger.info(`📋 Using ESM compatibility filter from ${config.compatibilityFile}`);
236
- this.logger.info(` Last analyzed: ${new Date(report.lastAnalyzed).toLocaleString()}`);
298
+ this.logger.info(` Last analyzed: ${formatCompatibilityReportLastAnalyzed(report)}`);
237
299
  this.logger.info(` Compatible elements: ${report.elements.length}`);
238
300
  this.logger.info(` Compatible pie-lib packages: ${report.pieLibPackages.length}`);
239
301
  if (Object.keys(report.blockedElements).length > 0) {
@@ -346,6 +408,299 @@ export default class Sync extends Command {
346
408
  });
347
409
  });
348
410
  }
411
+ async verifyTouchedPackageDependencyIntegrity(config) {
412
+ this.logger.section('🔎 Verifying dependency integrity regressions');
413
+ const packageDirs = [];
414
+ for (const element of this.touchedElementPackages) {
415
+ packageDirs.push(join(config.pieElementsNg, 'packages/elements-react', element));
416
+ }
417
+ for (const pieLib of this.touchedPieLibPackages) {
418
+ packageDirs.push(join(config.pieElementsNg, 'packages/lib-react', pieLib));
419
+ }
420
+ if (packageDirs.length === 0) {
421
+ this.logger.info(' No touched packages to verify\n');
422
+ return [];
423
+ }
424
+ const regressions = [];
425
+ let existingIssuesIgnored = 0;
426
+ for (const packageDir of packageDirs) {
427
+ const analysis = await analyzePackageDependencyIntegrity(packageDir);
428
+ if (!analysis) {
429
+ continue;
430
+ }
431
+ for (const issue of analysis.issues) {
432
+ if (issue.status !== 'broken' && issue.status !== 'hoist') {
433
+ continue;
434
+ }
435
+ const key = this.integrityIssueKey(analysis.packageName, issue.dependency);
436
+ const previous = this.preSyncProblemIntegrityByImport.get(key);
437
+ if (previous === issue.status) {
438
+ existingIssuesIgnored++;
439
+ continue;
440
+ }
441
+ regressions.push({
442
+ packageName: analysis.packageName,
443
+ packagePath: analysis.packagePath,
444
+ dependency: issue.dependency,
445
+ status: issue.status,
446
+ });
447
+ }
448
+ }
449
+ if (regressions.length === 0) {
450
+ if (existingIssuesIgnored > 0) {
451
+ this.logger.info(` ✓ No new broken/hoist regressions (ignored ${existingIssuesIgnored} pre-existing issue(s))\n`);
452
+ }
453
+ else {
454
+ this.logger.info(` ✓ No broken/hoist dependency integrity regressions\n`);
455
+ }
456
+ return [];
457
+ }
458
+ this.logger.error(` Found ${regressions.length} new dependency integrity regression(s):\n`);
459
+ for (const regression of regressions) {
460
+ this.logger.error(` - ${regression.packageName}: ${regression.status} -> ${regression.dependency}`);
461
+ }
462
+ this.log('');
463
+ return regressions;
464
+ }
465
+ async captureCurrentProblemIntegrityBaseline(config) {
466
+ const baseline = new Map();
467
+ const packageDirs = await collectWorkspacePackageDirs(config.pieElementsNg);
468
+ for (const packageDir of packageDirs) {
469
+ const analysis = await analyzePackageDependencyIntegrity(packageDir);
470
+ if (!analysis) {
471
+ continue;
472
+ }
473
+ for (const issue of analysis.issues) {
474
+ if (issue.status === 'broken' || issue.status === 'hoist') {
475
+ baseline.set(this.integrityIssueKey(analysis.packageName, issue.dependency), issue.status);
476
+ }
477
+ }
478
+ }
479
+ return baseline;
480
+ }
481
+ integrityIssueKey(packageName, dependency) {
482
+ return `${packageName}::${dependency}`;
483
+ }
484
+ async autoFixTouchedPackageDependencyDeclarations(config) {
485
+ this.logger.section('🛠️ Auto-fixing dependency declarations');
486
+ const packageDirs = this.getTouchedPackageDirs(config);
487
+ if (packageDirs.length === 0) {
488
+ this.logger.info(' No touched packages to auto-fix\n');
489
+ return { packagesUpdated: 0, dependenciesAdded: 0, unresolved: [] };
490
+ }
491
+ const catalog = await this.buildDependencyVersionCatalog(config.pieElementsNg);
492
+ let packagesUpdated = 0;
493
+ let dependenciesAdded = 0;
494
+ const unresolved = [];
495
+ for (const packageDir of packageDirs) {
496
+ const analysis = await analyzePackageDependencyIntegrity(packageDir);
497
+ if (!analysis)
498
+ continue;
499
+ const pkgJsonPath = join(packageDir, 'package.json');
500
+ const pkgJson = (await loadPackageJson(pkgJsonPath));
501
+ if (!pkgJson)
502
+ continue;
503
+ const declared = new Set([
504
+ ...Object.keys(pkgJson.dependencies || {}),
505
+ ...Object.keys(pkgJson.devDependencies || {}),
506
+ ...Object.keys(pkgJson.peerDependencies || {}),
507
+ ...Object.keys(pkgJson.optionalDependencies || {}),
508
+ ]);
509
+ let modified = false;
510
+ if (!pkgJson.dependencies) {
511
+ pkgJson.dependencies = {};
512
+ }
513
+ for (const issue of analysis.issues) {
514
+ const dep = issue.dependency;
515
+ if (declared.has(dep)) {
516
+ continue;
517
+ }
518
+ const version = this.resolveDependencyVersion(config, dep, catalog);
519
+ if (!version) {
520
+ unresolved.push({ packageName: analysis.packageName, dependency: dep });
521
+ continue;
522
+ }
523
+ pkgJson.dependencies[dep] = version;
524
+ declared.add(dep);
525
+ modified = true;
526
+ dependenciesAdded++;
527
+ }
528
+ if (modified) {
529
+ await writePackageJson(pkgJsonPath, pkgJson);
530
+ packagesUpdated++;
531
+ }
532
+ }
533
+ if (dependenciesAdded === 0 && unresolved.length === 0) {
534
+ this.logger.info(' ✓ No missing declarations detected in touched packages\n');
535
+ return { packagesUpdated, dependenciesAdded, unresolved };
536
+ }
537
+ if (dependenciesAdded > 0) {
538
+ this.logger.info(` ✓ Added ${dependenciesAdded} dependency declaration(s) in ${packagesUpdated} package(s)`);
539
+ }
540
+ if (unresolved.length > 0) {
541
+ this.logger.warn(` Could not infer ${unresolved.length} dependency version(s)`);
542
+ }
543
+ this.log('');
544
+ return { packagesUpdated, dependenciesAdded, unresolved };
545
+ }
546
+ getTouchedPackageDirs(config) {
547
+ const dirs = [];
548
+ for (const element of this.touchedElementPackages) {
549
+ dirs.push(join(config.pieElementsNg, 'packages/elements-react', element));
550
+ }
551
+ for (const pieLib of this.touchedPieLibPackages) {
552
+ dirs.push(join(config.pieElementsNg, 'packages/lib-react', pieLib));
553
+ }
554
+ return dirs.sort();
555
+ }
556
+ async buildDependencyVersionCatalog(rootDir) {
557
+ const catalog = new Map();
558
+ const addVersions = (record) => {
559
+ if (!record)
560
+ return;
561
+ for (const [name, version] of Object.entries(record)) {
562
+ if (!catalog.has(name)) {
563
+ catalog.set(name, version);
564
+ }
565
+ }
566
+ };
567
+ // Root package.json has the canonical versions we prefer.
568
+ const rootPkgPath = join(rootDir, 'package.json');
569
+ if (existsSync(rootPkgPath)) {
570
+ const rootPkg = (await loadPackageJson(rootPkgPath));
571
+ if (rootPkg) {
572
+ addVersions(rootPkg.dependencies);
573
+ addVersions(rootPkg.devDependencies);
574
+ }
575
+ }
576
+ // Add versions seen across workspace package manifests as fallback.
577
+ const workspacePackageDirs = await collectWorkspacePackageDirs(rootDir);
578
+ for (const packageDir of workspacePackageDirs) {
579
+ const pkgPath = join(packageDir, 'package.json');
580
+ if (!existsSync(pkgPath))
581
+ continue;
582
+ const pkg = (await loadPackageJson(pkgPath));
583
+ if (!pkg)
584
+ continue;
585
+ addVersions(pkg.dependencies);
586
+ addVersions(pkg.devDependencies);
587
+ addVersions(pkg.peerDependencies);
588
+ addVersions(pkg.optionalDependencies);
589
+ }
590
+ return catalog;
591
+ }
592
+ resolveDependencyVersion(config, dep, catalog) {
593
+ const fallbackVersions = {
594
+ 'js-combinatorics': '^2.1.2',
595
+ '@testing-library/react': '^16.3.0',
596
+ '@testing-library/dom': '^10.4.1',
597
+ '@tiptap/extensions': '^3.20.0',
598
+ '@tiptap/extension-list': '^3.20.0',
599
+ '@tiptap/extension-code-block': '^3.20.0',
600
+ 'nested-property': '^4.0.0',
601
+ 'prosemirror-state': '^1.4.4',
602
+ 'react-is': '^19.2.0',
603
+ pluralize: '^8.0.0',
604
+ };
605
+ // Internal workspace packages should stay workspace-linked.
606
+ if (dep.startsWith('@pie-lib/')) {
607
+ const libName = dep.replace('@pie-lib/', '');
608
+ const localPath = join(config.pieElementsNg, 'packages/lib-react', libName, 'package.json');
609
+ if (existsSync(localPath)) {
610
+ return 'workspace:*';
611
+ }
612
+ }
613
+ if (dep.startsWith('@pie-element/')) {
614
+ const elementName = dep.replace('@pie-element/', '');
615
+ const elementPath = join(config.pieElementsNg, 'packages/elements-react', elementName, 'package.json');
616
+ if (existsSync(elementPath)) {
617
+ return 'workspace:*';
618
+ }
619
+ // Shared packages map @pie-element/shared-foo -> packages/shared/foo.
620
+ if (elementName.startsWith('shared-')) {
621
+ const sharedName = elementName.replace('shared-', '');
622
+ const sharedPath = join(config.pieElementsNg, 'packages/shared', sharedName, 'package.json');
623
+ if (existsSync(sharedPath)) {
624
+ return 'workspace:*';
625
+ }
626
+ }
627
+ }
628
+ return catalog.get(dep) || fallbackVersions[dep] || null;
629
+ }
630
+ async applyPostSyncBuildStabilizers(config) {
631
+ let appliedPatches = 0;
632
+ const patchFile = async (filePath, replacements, label) => {
633
+ if (!existsSync(filePath)) {
634
+ return false;
635
+ }
636
+ let content = await readFile(filePath, 'utf-8');
637
+ let changed = false;
638
+ for (const replacement of replacements) {
639
+ if (content.includes(replacement.from)) {
640
+ content = content.replace(replacement.from, replacement.to);
641
+ changed = true;
642
+ }
643
+ }
644
+ if (changed) {
645
+ await writeFile(filePath, content, 'utf-8');
646
+ this.logger.info(` ✓ Applied post-sync patch: ${label}`);
647
+ }
648
+ return changed;
649
+ };
650
+ const patches = getPostSyncTextPatches(config.pieElementsNg);
651
+ for (const patch of patches) {
652
+ if (await patchFile(patch.file, patch.replacements, patch.label)) {
653
+ appliedPatches++;
654
+ }
655
+ }
656
+ if (appliedPatches === 0) {
657
+ this.logger.info(' ✓ No post-sync stabilizer patches needed');
658
+ }
659
+ }
660
+ async applyNodeEsmSpecifierRewrites(config) {
661
+ this.logger.section('🔧 Rewriting relative ESM specifiers');
662
+ const packageDirs = this.getTouchedPackageDirs(config);
663
+ if (packageDirs.length === 0) {
664
+ this.logger.info(' No touched packages to rewrite\n');
665
+ return;
666
+ }
667
+ let checkedFiles = 0;
668
+ let rewrittenFiles = 0;
669
+ for (const packageDir of packageDirs) {
670
+ const sourceDir = join(packageDir, 'src');
671
+ const sourceFiles = await this.collectTypeScriptSourceFiles(sourceDir);
672
+ for (const filePath of sourceFiles) {
673
+ checkedFiles++;
674
+ if (await rewriteRelativeSpecifiersForNodeEsm(filePath)) {
675
+ rewrittenFiles++;
676
+ }
677
+ }
678
+ }
679
+ if (rewrittenFiles === 0) {
680
+ this.logger.info(` ✓ Specifiers already normalized (${checkedFiles} file(s) checked)\n`);
681
+ return;
682
+ }
683
+ this.logger.info(` ✓ Rewrote ${rewrittenFiles} file(s) out of ${checkedFiles} checked\n`);
684
+ }
685
+ async collectTypeScriptSourceFiles(dir) {
686
+ if (!existsSync(dir)) {
687
+ return [];
688
+ }
689
+ const files = [];
690
+ const items = await readdir(dir);
691
+ for (const item of items) {
692
+ const fullPath = join(dir, item);
693
+ const stats = await fsStat(fullPath);
694
+ if (stats.isDirectory()) {
695
+ files.push(...(await this.collectTypeScriptSourceFiles(fullPath)));
696
+ continue;
697
+ }
698
+ if (item.endsWith('.ts') || item.endsWith('.tsx')) {
699
+ files.push(fullPath);
700
+ }
701
+ }
702
+ return files;
703
+ }
349
704
  async rewriteWorkspaceDependencies(config) {
350
705
  this.logger.section('🔧 Rewriting workspace dependencies');
351
706
  // Discover available packages in the workspace
@@ -405,7 +760,7 @@ export default class Sync extends Command {
405
760
  for (const pkgPath of packagesToCheck) {
406
761
  const pkgJsonPath = join(pkgPath, 'package.json');
407
762
  const pkgJson = (await loadPackageJson(pkgJsonPath));
408
- if (!pkgJson || !pkgJson.dependencies) {
763
+ if (!pkgJson?.dependencies) {
409
764
  continue;
410
765
  }
411
766
  const pkgName = pkgJson.name || pkgPath;
@@ -474,22 +829,6 @@ export default class Sync extends Command {
474
829
  this.logger.info(' ✓ bun install completed successfully\n');
475
830
  }
476
831
  }
477
- async addDevelopmentExportsToPackages(config) {
478
- this.logger.section('🔧 Adding development export conditions');
479
- const elementsDir = join(config.pieElementsNg, 'packages/elements-react');
480
- const packageNames = Array.from(this.touchedElementPackages);
481
- if (packageNames.length === 0) {
482
- this.logger.debug(' No element packages to process');
483
- return;
484
- }
485
- const updated = await addDevelopmentExports(elementsDir, packageNames, this.logger);
486
- if (updated > 0) {
487
- this.logger.info(` ✓ Added development exports to ${updated} package(s)\n`);
488
- }
489
- else {
490
- this.logger.debug(' → No changes needed\n');
491
- }
492
- }
493
832
  async buildTouchedPackages(config, result) {
494
833
  const rootPkgPath = join(config.pieElementsNg, 'package.json');
495
834
  const rootPkg = (await loadPackageJson(rootPkgPath));