@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
@@ -4,13 +4,41 @@
4
4
  * This module consolidates all package.json generation and management logic
5
5
  * to eliminate the massive duplication between controllers-strategy and react-strategy.
6
6
  */
7
- import { existsSync } from 'node:fs';
8
- import { readFile, writeFile } from 'node:fs/promises';
9
- import { dirname, join } from 'node:path';
7
+ import { existsSync, readFileSync } from 'node:fs';
8
+ import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
9
+ import { dirname, join, resolve } from 'node:path';
10
10
  import { loadPackageJson } from '../../utils/package-json.js';
11
11
  import { existsAny } from './sync-filesystem.js';
12
12
  import { applyPackageJsonTransforms } from './sync-transforms.js';
13
- import { BUILD_TOOLS, REACT, PACKAGE_DEFAULTS, SCRIPTS, WORKSPACE } from './sync-constants.js';
13
+ import { BUILD_TOOLS, PACKAGE_DEFAULTS, REACT, SCRIPTS, WORKSPACE, composeElementBuildScript, } from './sync-constants.js';
14
+ import { getPieLibDependencyAugmentations, getPieLibDependencyOverride, shouldGenerateConfigUiFractionHelper, shouldGenerateAutosizeInputComponent, } from './sync-presets.js';
15
+ function getLegacyConfigureEntry(entryPoints) {
16
+ if (entryPoints.hasConfigure) {
17
+ return 'configure';
18
+ }
19
+ if (entryPoints.hasAuthor) {
20
+ return 'author';
21
+ }
22
+ return null;
23
+ }
24
+ function distEntryExport(entry) {
25
+ return {
26
+ types: `./dist/${entry}/index.d.ts`,
27
+ default: `./dist/${entry}/index.js`,
28
+ };
29
+ }
30
+ function readBrowserEsmPolicy(rootDir) {
31
+ const policyPath = join(rootDir, 'tools/vite/browser-esm-policy.json');
32
+ if (!existsSync(policyPath)) {
33
+ return {};
34
+ }
35
+ try {
36
+ return JSON.parse(readFileSync(policyPath, 'utf-8'));
37
+ }
38
+ catch {
39
+ return {};
40
+ }
41
+ }
14
42
  /**
15
43
  * Detect available entry points in an element package
16
44
  */
@@ -52,6 +80,12 @@ export function detectEntryPoints(elementDir) {
52
80
  join(elementDir, 'src/print/index.js'),
53
81
  join(elementDir, 'src/print/index.jsx'),
54
82
  ]),
83
+ hasRuntimeSupport: existsAny([
84
+ join(elementDir, 'src/runtime-support.ts'),
85
+ join(elementDir, 'src/runtime-support.tsx'),
86
+ join(elementDir, 'src/runtime-support.js'),
87
+ join(elementDir, 'src/runtime-support.jsx'),
88
+ ]),
55
89
  hasTypes: existsAny([
56
90
  join(elementDir, 'src/types/index.ts'),
57
91
  join(elementDir, 'src/types/index.tsx'),
@@ -63,7 +97,8 @@ export function detectEntryPoints(elementDir) {
63
97
  /**
64
98
  * Generate exports object based on available entry points
65
99
  */
66
- export function generateExportsObject(entryPoints) {
100
+ export function generateExportsObject(entryPoints, options = {}) {
101
+ const includeBrowserExports = options.includeBrowserExports ?? false;
67
102
  const exports = {
68
103
  '.': {
69
104
  types: './dist/index.d.ts',
@@ -75,30 +110,56 @@ export function generateExportsObject(entryPoints) {
75
110
  types: './dist/delivery/index.d.ts',
76
111
  default: './dist/delivery/index.js',
77
112
  };
113
+ if (includeBrowserExports) {
114
+ exports['./browser/delivery'] = {
115
+ default: './dist/browser/delivery/index.js',
116
+ };
117
+ }
78
118
  }
79
119
  if (entryPoints.hasAuthor) {
80
120
  exports['./author'] = {
81
121
  types: './dist/author/index.d.ts',
82
122
  default: './dist/author/index.js',
83
123
  };
124
+ if (includeBrowserExports) {
125
+ exports['./browser/author'] = {
126
+ default: './dist/browser/author/index.js',
127
+ };
128
+ }
129
+ }
130
+ const legacyConfigureEntry = getLegacyConfigureEntry(entryPoints);
131
+ if (legacyConfigureEntry) {
132
+ exports['./configure'] = distEntryExport(legacyConfigureEntry);
84
133
  }
85
134
  if (entryPoints.hasController) {
86
135
  exports['./controller'] = {
87
136
  types: './dist/controller/index.d.ts',
88
137
  default: './dist/controller/index.js',
89
138
  };
90
- }
91
- if (entryPoints.hasConfigure) {
92
- exports['./configure'] = {
93
- types: './dist/configure/index.d.ts',
94
- default: './dist/configure/index.js',
139
+ exports['./controller.js'] = {
140
+ types: './dist/controller/index.d.ts',
141
+ default: './dist/controller/index.js',
95
142
  };
143
+ if (includeBrowserExports) {
144
+ exports['./browser/controller'] = {
145
+ default: './dist/browser/controller/index.js',
146
+ };
147
+ }
96
148
  }
97
149
  if (entryPoints.hasPrint) {
98
150
  exports['./print'] = {
99
151
  types: './dist/print/index.d.ts',
100
152
  default: './dist/print/index.js',
101
153
  };
154
+ exports['./print.js'] = {
155
+ types: './dist/print/index.d.ts',
156
+ default: './dist/print/index.js',
157
+ };
158
+ if (includeBrowserExports) {
159
+ exports['./browser/print'] = {
160
+ default: './dist/browser/print/index.js',
161
+ };
162
+ }
102
163
  }
103
164
  if (entryPoints.hasTypes) {
104
165
  exports['./types'] = {
@@ -106,8 +167,44 @@ export function generateExportsObject(entryPoints) {
106
167
  default: './dist/types/index.js',
107
168
  };
108
169
  }
170
+ if (entryPoints.hasRuntimeSupport) {
171
+ exports['./runtime-support'] = {
172
+ types: './dist/runtime-support.d.ts',
173
+ default: './dist/runtime-support.js',
174
+ };
175
+ }
109
176
  return exports;
110
177
  }
178
+ function generateRuntimeSupportSource(elementName, entryPoints) {
179
+ const packageName = `${WORKSPACE.PIE_ELEMENT_PREFIX}${elementName}`;
180
+ return `export const runtimeSupport = {
181
+ schemaVersion: 1,
182
+ packageName: '${packageName}',
183
+ supports: {
184
+ esm: {
185
+ delivery: ${entryPoints.hasDelivery},
186
+ author: ${entryPoints.hasAuthor},
187
+ print: ${entryPoints.hasPrint},
188
+ },
189
+ },
190
+ };
191
+
192
+ export default runtimeSupport;
193
+ `;
194
+ }
195
+ async function ensureBrowserRuntimeSupportSource(elementName, elementDir, entryPoints) {
196
+ const runtimeSupportPath = join(elementDir, 'src', 'runtime-support.ts');
197
+ const nextContent = generateRuntimeSupportSource(elementName, entryPoints);
198
+ const currentContent = existsSync(runtimeSupportPath)
199
+ ? await readFile(runtimeSupportPath, 'utf-8').catch(() => null)
200
+ : null;
201
+ if (currentContent === nextContent) {
202
+ return false;
203
+ }
204
+ await mkdir(dirname(runtimeSupportPath), { recursive: true });
205
+ await writeFile(runtimeSupportPath, nextContent, 'utf-8');
206
+ return true;
207
+ }
111
208
  /**
112
209
  * Extract imports from source files to determine runtime dependencies
113
210
  */
@@ -139,7 +236,9 @@ export async function extractImportsFromSources(elementDir) {
139
236
  const importPath = match[1];
140
237
  // Only track package imports (not relative imports)
141
238
  if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
142
- imports.add(importPath);
239
+ const normalized = normalizePackageImport(importPath);
240
+ if (normalized)
241
+ imports.add(normalized);
143
242
  }
144
243
  match = importRegex.exec(content);
145
244
  }
@@ -147,7 +246,9 @@ export async function extractImportsFromSources(elementDir) {
147
246
  while (match !== null) {
148
247
  const importPath = match[1];
149
248
  if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
150
- imports.add(importPath);
249
+ const normalized = normalizePackageImport(importPath);
250
+ if (normalized)
251
+ imports.add(normalized);
151
252
  }
152
253
  match = dynamicImportRegex.exec(content);
153
254
  }
@@ -165,10 +266,21 @@ export async function extractImportsFromSources(elementDir) {
165
266
  await scanDirectory(srcDir);
166
267
  return imports;
167
268
  }
269
+ function normalizePackageImport(specifier) {
270
+ if (!specifier || specifier.startsWith('.') || specifier.startsWith('/')) {
271
+ return null;
272
+ }
273
+ if (specifier.startsWith('@')) {
274
+ const parts = specifier.split('/');
275
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;
276
+ }
277
+ return specifier.split('/')[0] || null;
278
+ }
279
+ const LEGACY_PEERS_TO_SKIP = new Set(['@emotion/core']);
168
280
  async function findInstalledPackageJson(packageName, fromDir) {
169
281
  try {
170
282
  const { createRequire } = await import('node:module');
171
- const req = createRequire(join(fromDir, 'package.json'));
283
+ const req = createRequire(resolve(fromDir, 'package.json'));
172
284
  const resolvedEntry = req.resolve(packageName);
173
285
  let currentDir = dirname(resolvedEntry);
174
286
  while (true) {
@@ -191,7 +303,7 @@ async function findInstalledPackageJson(packageName, fromDir) {
191
303
  }
192
304
  return null;
193
305
  }
194
- async function addTransitivePeerDependencies(deps, fromDir) {
306
+ async function addTransitivePeerDependencies(deps, fromDir, declaredPeerDeps = new Set()) {
195
307
  const depNames = Object.keys(deps);
196
308
  for (const depName of depNames) {
197
309
  if (depName.startsWith(WORKSPACE.PIE_LIB_PREFIX) ||
@@ -201,8 +313,14 @@ async function addTransitivePeerDependencies(deps, fromDir) {
201
313
  }
202
314
  const installedPkg = await findInstalledPackageJson(depName, fromDir);
203
315
  const peerDeps = installedPkg?.peerDependencies ?? {};
316
+ const optionalPeers = new Set(Object.entries(installedPkg?.peerDependenciesMeta ?? {})
317
+ .filter(([, meta]) => meta?.optional)
318
+ .map(([peerName]) => peerName));
204
319
  for (const [peerName, peerVersion] of Object.entries(peerDeps)) {
205
- if (deps[peerName]) {
320
+ if (deps[peerName] ||
321
+ declaredPeerDeps.has(peerName) ||
322
+ optionalPeers.has(peerName) ||
323
+ LEGACY_PEERS_TO_SKIP.has(peerName)) {
206
324
  continue;
207
325
  }
208
326
  if (peerName.startsWith(WORKSPACE.PIE_LIB_PREFIX) ||
@@ -231,6 +349,26 @@ async function inferPeerVersionFromDeclaredDeps(targetDep, deps, fromDir) {
231
349
  }
232
350
  return null;
233
351
  }
352
+ function addKnownPeerFallbacks(deps) {
353
+ // Some widely used packages rely on peers that upstream metadata can omit
354
+ // or that may not be inferable from local resolution during sync.
355
+ if ((deps.recharts || deps['styled-components']) && !deps['react-is']) {
356
+ deps['react-is'] = '^18.3.1';
357
+ }
358
+ if (deps['@tiptap/extension-character-count'] && !deps['@tiptap/extensions']) {
359
+ deps['@tiptap/extensions'] = '^3.20.0';
360
+ }
361
+ if (deps['@tiptap/extension-list-item'] && !deps['@tiptap/extension-list']) {
362
+ const tiptapVersion = deps['@tiptap/extension-list-item'];
363
+ deps['@tiptap/extension-list'] = tiptapVersion;
364
+ }
365
+ if (deps['@testing-library/user-event'] && !deps['@testing-library/dom']) {
366
+ deps['@testing-library/dom'] = '^10.4.1';
367
+ }
368
+ if (deps['@visx/curve'] && !deps['d3-shape']) {
369
+ deps['d3-shape'] = '^3.2.0';
370
+ }
371
+ }
234
372
  /**
235
373
  * Extract and normalize dependencies from upstream package.json
236
374
  */
@@ -238,7 +376,7 @@ export function extractUpstreamDependencies(upstreamPkg) {
238
376
  if (!upstreamPkg)
239
377
  return {};
240
378
  const upstreamDeps = upstreamPkg.dependencies ?? {};
241
- const expectedDeps = {};
379
+ let expectedDeps = {};
242
380
  for (const [name, version] of Object.entries(upstreamDeps)) {
243
381
  if (name.startsWith(WORKSPACE.PIE_LIB_PREFIX)) {
244
382
  expectedDeps[name] = WORKSPACE.VERSION;
@@ -249,31 +387,38 @@ export function extractUpstreamDependencies(upstreamPkg) {
249
387
  }
250
388
  return expectedDeps;
251
389
  }
390
+ function resolveSyncedVersion(upstreamPkg, existingPkg) {
391
+ const existingVersion = typeof existingPkg?.version === 'string' ? existingPkg.version : null;
392
+ if (existingVersion) {
393
+ return existingVersion;
394
+ }
395
+ const upstreamVersion = typeof upstreamPkg?.version === 'string' ? upstreamPkg.version : null;
396
+ return upstreamVersion || '0.1.0';
397
+ }
252
398
  /**
253
- * Ensure devDependencies include all required build tools
399
+ * Ensure devDependencies include all required build tools.
400
+ *
401
+ * The pinned versions in BUILD_TOOLS / REACT are the source of truth for the
402
+ * monorepo's toolchain, so we overwrite any existing entries instead of only
403
+ * filling in missing ones. This prevents an upstream package.json from
404
+ * silently downgrading vite / @vitejs/plugin-react / typescript across the
405
+ * pie-lib packages during `upstream:update`.
254
406
  */
255
407
  export function ensureBuildToolDependencies(pkg) {
256
408
  if (!pkg.devDependencies || typeof pkg.devDependencies !== 'object') {
257
409
  pkg.devDependencies = {};
258
410
  }
259
411
  const devDeps = pkg.devDependencies;
260
- if (!devDeps.vite)
261
- devDeps.vite = BUILD_TOOLS.VITE;
262
- if (!devDeps.typescript)
263
- devDeps.typescript = BUILD_TOOLS.TYPESCRIPT;
264
- if (!devDeps['@vitejs/plugin-react'])
265
- devDeps['@vitejs/plugin-react'] = BUILD_TOOLS.VITE_REACT_PLUGIN;
266
- if (!devDeps['@types/react'])
267
- devDeps['@types/react'] = REACT.TYPES_VERSION;
268
- if (!devDeps['@types/react-dom'])
269
- devDeps['@types/react-dom'] = REACT.TYPES_VERSION;
412
+ devDeps.vite = BUILD_TOOLS.VITE;
413
+ devDeps.typescript = BUILD_TOOLS.TYPESCRIPT;
414
+ devDeps['@vitejs/plugin-react'] = BUILD_TOOLS.VITE_REACT_PLUGIN;
415
+ devDeps['@types/react'] = REACT.TYPES_VERSION;
416
+ devDeps['@types/react-dom'] = REACT.TYPES_VERSION;
270
417
  }
271
418
  /**
272
419
  * Check if a @pie-framework or @pie-element/shared- package exists in the workspace
273
420
  *
274
- * Supports both legacy @pie-framework naming and new @pie-element/shared- naming:
275
- * - @pie-framework/mathquill → packages/shared/mathquill (legacy, should migrate)
276
- * - @pie-element/shared-mathquill → packages/shared/mathquill (new convention)
421
+ * Supports both legacy @pie-framework naming and new @pie-element/shared- naming.
277
422
  */
278
423
  function isPieFrameworkWorkspacePackage(packageName, config) {
279
424
  let pkgName;
@@ -297,12 +442,13 @@ function isPieFrameworkWorkspacePackage(packageName, config) {
297
442
  * This function consolidates the ~400 lines of duplicated package.json management
298
443
  * logic from controllers-strategy and react-strategy into a single, maintainable function.
299
444
  */
300
- export async function ensureElementPackageJson(elementName, elementDir, config) {
445
+ export async function ensureElementPackageJson(elementName, elementDir, config, options = {}) {
301
446
  if (!existsSync(elementDir)) {
302
447
  return false;
303
448
  }
304
449
  const pkgPath = join(elementDir, 'package.json');
305
450
  const upstreamPkgPath = join(config.pieElements, 'packages', elementName, 'package.json');
451
+ const includeBrowserExports = options.includeBrowserExports ?? false;
306
452
  // Load existing package.json
307
453
  let pkg = null;
308
454
  if (existsSync(pkgPath)) {
@@ -314,6 +460,11 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
314
460
  : null;
315
461
  // Extract and normalize upstream dependencies
316
462
  const expectedDeps = extractUpstreamDependencies(upstreamPkg);
463
+ const declaredPeerDeps = new Set([
464
+ ...Object.keys(pkg?.peerDependencies ?? {}),
465
+ 'react',
466
+ 'react-dom',
467
+ ]);
317
468
  // Scan source files for actual imports to catch dependencies from skipped directories
318
469
  const importedPackages = await extractImportsFromSources(elementDir);
319
470
  // Add workspace dependencies found in imports
@@ -323,6 +474,9 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
323
474
  if (imported === currentPackageName) {
324
475
  continue;
325
476
  }
477
+ if (imported === 'react' || imported === 'react-dom') {
478
+ continue;
479
+ }
326
480
  if (imported.startsWith(WORKSPACE.PIE_LIB_PREFIX)) {
327
481
  expectedDeps[imported] = WORKSPACE.VERSION;
328
482
  }
@@ -341,14 +495,29 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
341
495
  }
342
496
  }
343
497
  }
498
+ else if (!expectedDeps[imported]) {
499
+ // Keep element package.json aligned with actual runtime imports from src/.
500
+ // Upstream package.json can miss third-party deps after source transforms.
501
+ const installedPkg = await findInstalledPackageJson(imported, elementDir);
502
+ if (installedPkg?.version) {
503
+ expectedDeps[imported] = `^${installedPkg.version}`;
504
+ }
505
+ else {
506
+ const inferredPeerVersion = await inferPeerVersionFromDeclaredDeps(imported, expectedDeps, elementDir);
507
+ if (inferredPeerVersion) {
508
+ expectedDeps[imported] = inferredPeerVersion;
509
+ }
510
+ }
511
+ }
344
512
  }
345
- await addTransitivePeerDependencies(expectedDeps, elementDir);
513
+ await addTransitivePeerDependencies(expectedDeps, elementDir, declaredPeerDeps);
514
+ addKnownPeerFallbacks(expectedDeps);
346
515
  // Create minimal package.json if missing
347
516
  if (!pkg) {
348
517
  pkg = {
349
518
  name: `${WORKSPACE.PIE_ELEMENT_PREFIX}${elementName}`,
350
519
  private: true,
351
- version: '0.1.0',
520
+ version: resolveSyncedVersion(upstreamPkg, null),
352
521
  description: upstreamPkg?.description ??
353
522
  `React implementation of ${elementName} element synced from pie-elements`,
354
523
  dependencies: expectedDeps,
@@ -362,19 +531,90 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
362
531
  if (Object.keys(expectedDeps).length > 0) {
363
532
  pkg.dependencies = expectedDeps;
364
533
  }
534
+ pkg.peerDependencies = {
535
+ ...(pkg.peerDependencies ?? {}),
536
+ react: REACT.VERSION,
537
+ 'react-dom': REACT.VERSION,
538
+ };
365
539
  // Preserve pie metadata (if present upstream or locally)
366
540
  const pieMetadata = (upstreamPkg?.pie ??
367
541
  pkg?.pie ??
368
542
  undefined);
369
543
  // Apply all standard transformations
370
544
  pkg = applyPackageJsonTransforms(pkg);
371
- if (pieMetadata) {
372
- pkg.pie = pieMetadata;
545
+ // React must also be a real dependency, not only a peer. Legacy webpack
546
+ // bundlers (builder.pie-api.com) install `dependencies` and never install
547
+ // peers, so peer-only React leaves node_modules/react absent in the build
548
+ // snapshot and every @mui / @emotion / @dnd-kit peer fails with
549
+ // "Module not found: Can't resolve 'react'".
550
+ //
551
+ // This must run AFTER applyPackageJsonTransforms: transformPackageJsonBrowserEsmDependencies
552
+ // unconditionally deletes react/react-dom from dependencies to drop whatever
553
+ // arbitrary range upstream declared. We re-add them here as the final word,
554
+ // pinned to the policy version.
555
+ //
556
+ // Install metadata only. The browser runtime singleton contract stays governed
557
+ // by pie.browserSharedDependencies plus the player import map, and isExternal()
558
+ // in sync-externals.ts keeps React external in every bundle regardless of what
559
+ // is declared here, so bundle output is unaffected.
560
+ //
561
+ // Versions come from tools/vite/browser-esm-policy.json - the same source as
562
+ // pie.browserSharedDependencies below.
563
+ //
564
+ // Declared as a caret range, NOT an exact pin. An exact pin resolves to its own
565
+ // copy alongside the root's `^`-resolved one, and two React instances break
566
+ // hooks at runtime ("Invalid hook call", useRef of null). The installed version
567
+ // only has to resolve for the legacy webpack path, so a range is sufficient.
568
+ const sharedRuntimeDeps = readBrowserEsmPolicy(config.pieElementsNg).sharedDependencyVersions;
569
+ if (sharedRuntimeDeps && Object.keys(sharedRuntimeDeps).length > 0) {
570
+ const rangedRuntimeDeps = Object.fromEntries(Object.entries(sharedRuntimeDeps).map(([name, version]) => [name, `^${version}`]));
571
+ pkg.dependencies = {
572
+ ...(pkg.dependencies ?? {}),
573
+ ...rangedRuntimeDeps,
574
+ };
373
575
  }
374
576
  // Detect available entry points
375
577
  const entryPoints = detectEntryPoints(elementDir);
376
- // Generate exports based on entry points
377
- pkg.exports = generateExportsObject(entryPoints);
578
+ const wroteRuntimeSupport = includeBrowserExports && !entryPoints.hasRuntimeSupport
579
+ ? await ensureBrowserRuntimeSupportSource(elementName, elementDir, entryPoints)
580
+ : false;
581
+ if (includeBrowserExports) {
582
+ entryPoints.hasRuntimeSupport = true;
583
+ }
584
+ // Generate dist-only exports based on entry points. Do not preserve
585
+ // source-backed `development` conditions; PIE-605 makes raw source paths a
586
+ // private implementation detail and keeps public package surfaces dist-only.
587
+ const nextPieMetadata = pieMetadata ? { ...pieMetadata } : {};
588
+ if (entryPoints.hasController) {
589
+ nextPieMetadata.controller = `${WORKSPACE.PIE_ELEMENT_PREFIX}${elementName}/controller`;
590
+ }
591
+ else {
592
+ delete nextPieMetadata.controller;
593
+ }
594
+ const legacyConfigureEntry = getLegacyConfigureEntry(entryPoints);
595
+ if (legacyConfigureEntry) {
596
+ nextPieMetadata.configure = `${WORKSPACE.PIE_ELEMENT_PREFIX}${elementName}/configure`;
597
+ }
598
+ else {
599
+ delete nextPieMetadata.configure;
600
+ }
601
+ if (includeBrowserExports) {
602
+ const browserEsmPolicy = readBrowserEsmPolicy(config.pieElementsNg);
603
+ if (browserEsmPolicy.sharedDependencyVersions) {
604
+ nextPieMetadata.browserSharedDependencies = browserEsmPolicy.sharedDependencyVersions;
605
+ }
606
+ }
607
+ else {
608
+ delete nextPieMetadata.browserSharedDependencies;
609
+ }
610
+ if (Object.keys(nextPieMetadata).length > 0) {
611
+ pkg.pie = nextPieMetadata;
612
+ }
613
+ else {
614
+ delete pkg.pie;
615
+ }
616
+ const hasBrowserBuild = includeBrowserExports;
617
+ pkg.exports = generateExportsObject(entryPoints, { includeBrowserExports: hasBrowserBuild });
378
618
  // Warn when metadata/structure disagree for core capabilities
379
619
  const metadataCapabilities = Array.isArray(pieMetadata?.capabilities)
380
620
  ? new Set(pieMetadata.capabilities)
@@ -402,14 +642,35 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
402
642
  }
403
643
  // Set core package.json fields
404
644
  pkg.name = `${WORKSPACE.PIE_ELEMENT_PREFIX}${elementName}`;
645
+ pkg.version = resolveSyncedVersion(upstreamPkg, pkg);
405
646
  pkg.type = PACKAGE_DEFAULTS.TYPE;
406
647
  pkg.main = './dist/index.js';
407
648
  pkg.types = './dist/index.d.ts';
408
- // Ensure files array
649
+ // Ensure publish surface is dist-only. Source remains available in the repo,
650
+ // but must not be published as a public package API. Controller-bearing
651
+ // elements additionally publish the root shim required by legacy builders.
409
652
  const files = Array.isArray(pkg.files) ? pkg.files : [];
410
653
  const normalizedFiles = new Set(files.filter((v) => typeof v === 'string'));
411
654
  normalizedFiles.add('dist');
412
- normalizedFiles.add('src');
655
+ normalizedFiles.delete('src');
656
+ if (entryPoints.hasController) {
657
+ normalizedFiles.add('controller.js');
658
+ }
659
+ else {
660
+ normalizedFiles.delete('controller.js');
661
+ }
662
+ if (legacyConfigureEntry) {
663
+ normalizedFiles.add('configure.js');
664
+ }
665
+ else {
666
+ normalizedFiles.delete('configure.js');
667
+ }
668
+ if (entryPoints.hasPrint) {
669
+ normalizedFiles.add('print.js');
670
+ }
671
+ else {
672
+ normalizedFiles.delete('print.js');
673
+ }
413
674
  pkg.files = Array.from(normalizedFiles).sort();
414
675
  // Set sideEffects
415
676
  if (typeof pkg.sideEffects === 'undefined') {
@@ -424,20 +685,85 @@ export async function ensureElementPackageJson(elementName, elementDir, config)
424
685
  const scripts = pkg.scripts;
425
686
  const hasIifeEntry = existsSync(join(elementDir, 'src/index.iife.ts')) ||
426
687
  existsSync(join(elementDir, 'vite.config.iife.ts'));
427
- scripts.build = hasIifeEntry ? SCRIPTS.BUILD_WITH_IIFE : SCRIPTS.BUILD;
688
+ // A print entry point means this package also needs the legacy print lane, so
689
+ // module/print.js is emitted for the current @pie-framework/pie-print loader.
690
+ scripts.build = composeElementBuildScript({
691
+ browser: hasBrowserBuild,
692
+ legacyPrint: entryPoints.hasPrint,
693
+ iife: hasIifeEntry,
694
+ });
428
695
  scripts.dev = SCRIPTS.DEV;
429
696
  scripts.demo = SCRIPTS.DEMO;
430
697
  scripts.test = SCRIPTS.TEST;
698
+ const controllerShimPath = join(elementDir, 'controller.js');
699
+ const controllerShimContent = "export * from './dist/controller/index.js';\n";
700
+ const hasControllerShim = existsSync(controllerShimPath);
701
+ const currentControllerShim = hasControllerShim
702
+ ? await readFile(controllerShimPath, 'utf-8').catch(() => null)
703
+ : null;
704
+ const shouldWriteControllerShim = entryPoints.hasController && currentControllerShim !== controllerShimContent;
705
+ const shouldRemoveControllerShim = !entryPoints.hasController && hasControllerShim;
706
+ const configureShimPath = join(elementDir, 'configure.js');
707
+ const configureShimContent = legacyConfigureEntry
708
+ ? `export { default } from './dist/${legacyConfigureEntry}/index.js';\nexport * from './dist/${legacyConfigureEntry}/index.js';\n`
709
+ : null;
710
+ const hasConfigureShim = existsSync(configureShimPath);
711
+ const currentConfigureShim = hasConfigureShim
712
+ ? await readFile(configureShimPath, 'utf-8').catch(() => null)
713
+ : null;
714
+ const shouldWriteConfigureShim = configureShimContent !== null && currentConfigureShim !== configureShimContent;
715
+ const shouldRemoveConfigureShim = configureShimContent === null && hasConfigureShim;
716
+ // The IIFE bundlers alias `@pie-element/<element>` to a directory, so a `/print`
717
+ // request resolves as a literal path and never consults `exports`. The root shim is
718
+ // what makes that request land on the built print entry, the same way controller.js
719
+ // and configure.js do for their views.
720
+ const printShimPath = join(elementDir, 'print.js');
721
+ const printShimContent = entryPoints.hasPrint
722
+ ? "export { default } from './dist/print/index.js';\nexport * from './dist/print/index.js';\n"
723
+ : null;
724
+ const hasPrintShim = existsSync(printShimPath);
725
+ const currentPrintShim = hasPrintShim
726
+ ? await readFile(printShimPath, 'utf-8').catch(() => null)
727
+ : null;
728
+ const shouldWritePrintShim = printShimContent !== null && currentPrintShim !== printShimContent;
729
+ const shouldRemovePrintShim = printShimContent === null && hasPrintShim;
431
730
  // Check if content changed
432
731
  const nextContent = `${JSON.stringify(pkg, null, 2)}\n`;
433
732
  const currentContent = existsSync(pkgPath)
434
733
  ? await readFile(pkgPath, 'utf-8').catch(() => null)
435
734
  : null;
436
- if (currentContent === nextContent) {
735
+ if (currentContent === nextContent &&
736
+ !wroteRuntimeSupport &&
737
+ !shouldWriteControllerShim &&
738
+ !shouldRemoveControllerShim &&
739
+ !shouldWriteConfigureShim &&
740
+ !shouldRemoveConfigureShim &&
741
+ !shouldWritePrintShim &&
742
+ !shouldRemovePrintShim) {
437
743
  return false;
438
744
  }
439
745
  // Write updated package.json
440
- await writeFile(pkgPath, nextContent, 'utf-8');
746
+ if (currentContent !== nextContent) {
747
+ await writeFile(pkgPath, nextContent, 'utf-8');
748
+ }
749
+ if (shouldWriteControllerShim) {
750
+ await writeFile(controllerShimPath, controllerShimContent, 'utf-8');
751
+ }
752
+ else if (shouldRemoveControllerShim) {
753
+ await unlink(controllerShimPath).catch(() => { });
754
+ }
755
+ if (shouldWriteConfigureShim && configureShimContent !== null) {
756
+ await writeFile(configureShimPath, configureShimContent, 'utf-8');
757
+ }
758
+ else if (shouldRemoveConfigureShim) {
759
+ await unlink(configureShimPath).catch(() => { });
760
+ }
761
+ if (shouldWritePrintShim && printShimContent !== null) {
762
+ await writeFile(printShimPath, printShimContent, 'utf-8');
763
+ }
764
+ else if (shouldRemovePrintShim) {
765
+ await unlink(printShimPath).catch(() => { });
766
+ }
441
767
  return true;
442
768
  }
443
769
  /**
@@ -458,13 +784,9 @@ export async function ensurePieLibPackageJson(pkgName, pkgDir, config) {
458
784
  : null;
459
785
  // Extract upstream dependencies
460
786
  const upstreamDeps = upstreamPkg?.dependencies ?? {};
461
- const expectedDeps = {};
787
+ let expectedDeps = {};
462
788
  for (const [name, version] of Object.entries(upstreamDeps)) {
463
- // Transform @pie-framework/mathquill to @pie-element/shared-mathquill
464
- if (name === '@pie-framework/mathquill') {
465
- expectedDeps['@pie-element/shared-mathquill'] = WORKSPACE.VERSION;
466
- }
467
- else if (name.startsWith(WORKSPACE.PIE_LIB_PREFIX)) {
789
+ if (name.startsWith(WORKSPACE.PIE_LIB_PREFIX)) {
468
790
  expectedDeps[name] = WORKSPACE.VERSION;
469
791
  }
470
792
  else {
@@ -473,10 +795,6 @@ export async function ensurePieLibPackageJson(pkgName, pkgDir, config) {
473
795
  }
474
796
  const importedPackages = await extractImportsFromSources(pkgDir);
475
797
  for (const importedPkg of importedPackages) {
476
- if (importedPkg === '@pie-framework/mathquill') {
477
- expectedDeps['@pie-element/shared-mathquill'] = WORKSPACE.VERSION;
478
- continue;
479
- }
480
798
  if (importedPkg.startsWith(WORKSPACE.PIE_LIB_PREFIX)) {
481
799
  expectedDeps[importedPkg] = WORKSPACE.VERSION;
482
800
  continue;
@@ -500,16 +818,26 @@ export async function ensurePieLibPackageJson(pkgName, pkgDir, config) {
500
818
  }
501
819
  }
502
820
  }
503
- // graphing imports @dnd-kit/core directly in source but upstream metadata can omit it.
504
- if (pkgName === 'graphing' && !expectedDeps['@dnd-kit/core']) {
505
- expectedDeps['@dnd-kit/core'] = '^6.3.0';
821
+ await addTransitivePeerDependencies(expectedDeps, pkgDir);
822
+ addKnownPeerFallbacks(expectedDeps);
823
+ const dependencyAugmentations = getPieLibDependencyAugmentations(pkgName);
824
+ for (const [depName, version] of Object.entries(dependencyAugmentations)) {
825
+ if (!expectedDeps[depName]) {
826
+ expectedDeps[depName] = version;
827
+ }
506
828
  }
829
+ const declaresReactRuntime = typeof expectedDeps.react === 'string' || typeof expectedDeps['react-dom'] === 'string';
830
+ expectedDeps =
831
+ applyPackageJsonTransforms({ dependencies: expectedDeps }, {
832
+ removeReactInputAutosize: shouldGenerateAutosizeInputComponent(pkgName),
833
+ removeMathjs: shouldGenerateConfigUiFractionHelper(pkgName) && !importedPackages.has('mathjs'),
834
+ }).dependencies ?? {};
507
835
  // Create minimal package.json if missing
508
836
  if (!pkg) {
509
837
  pkg = {
510
838
  name: `${WORKSPACE.PIE_LIB_PREFIX}${pkgName}`,
511
839
  private: true,
512
- version: '0.1.0',
840
+ version: resolveSyncedVersion(upstreamPkg, null),
513
841
  description: upstreamPkg?.description ??
514
842
  `React implementation of @pie-lib/${pkgName} synced from pie-lib`,
515
843
  dependencies: expectedDeps,
@@ -519,36 +847,41 @@ export async function ensurePieLibPackageJson(pkgName, pkgDir, config) {
519
847
  if (Object.keys(expectedDeps).length > 0) {
520
848
  pkg.dependencies = expectedDeps;
521
849
  }
522
- // Special handling for math-rendering: reference MathJax adapter package
523
- if (pkgName === 'math-rendering') {
524
- pkg.dependencies = {
525
- [`${WORKSPACE.PIE_ELEMENT_PREFIX}shared-math-rendering-mathjax`]: WORKSPACE.VERSION,
850
+ const dependencyOverride = getPieLibDependencyOverride(pkgName);
851
+ if (dependencyOverride) {
852
+ pkg.dependencies = dependencyOverride;
853
+ }
854
+ if (declaresReactRuntime) {
855
+ pkg.peerDependencies = {
856
+ ...(pkg.peerDependencies ?? {}),
857
+ react: REACT.VERSION,
858
+ 'react-dom': REACT.VERSION,
526
859
  };
527
860
  }
528
- // Generate exports
529
- const exportsObj = {
530
- ...(typeof pkg.exports === 'object' && pkg.exports
531
- ? pkg.exports
532
- : {}),
533
- };
861
+ // Generate dist-only exports. Pie-lib packages expose only their compiled
862
+ // top-level entry; raw source paths are intentionally not public.
863
+ const exportsObj = {};
534
864
  exportsObj['.'] = {
535
865
  types: './dist/index.d.ts',
536
866
  default: './dist/index.js',
537
867
  };
538
868
  pkg.name = `${WORKSPACE.PIE_LIB_PREFIX}${pkgName}`;
869
+ pkg.version = resolveSyncedVersion(upstreamPkg, pkg);
539
870
  pkg.type = PACKAGE_DEFAULTS.TYPE;
540
871
  pkg.main = './dist/index.js';
541
872
  pkg.types = './dist/index.d.ts';
542
873
  pkg.exports = exportsObj;
543
- // Ensure files array
544
- const files = Array.isArray(pkg.files) ? pkg.files : [];
545
- const normalizedFiles = new Set(files.filter((v) => typeof v === 'string'));
546
- normalizedFiles.add('dist');
547
- normalizedFiles.add('src');
548
- pkg.files = Array.from(normalizedFiles).sort();
874
+ // Ensure publish surface is dist-only. Source remains available in the repo,
875
+ // but must not be published as a public package API.
876
+ pkg.files = ['dist'];
549
877
  if (typeof pkg.sideEffects === 'undefined') {
550
878
  pkg.sideEffects = PACKAGE_DEFAULTS.SIDE_EFFECTS;
551
879
  }
880
+ // Pie-lib packages use a vite.config.ts that imports @vitejs/plugin-react,
881
+ // so their devDependencies must include the same build toolchain that
882
+ // element packages do. Without this, a fresh `bun install` (no hoisting)
883
+ // fails to resolve the plugin when turbo runs `vite build` per package.
884
+ ensureBuildToolDependencies(pkg);
552
885
  // Ensure build scripts
553
886
  if (!pkg.scripts || typeof pkg.scripts !== 'object') {
554
887
  pkg.scripts = {};