@adobedjangir/commerce-admin-management 0.0.12 → 0.0.14

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 (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/setup.js +120 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobedjangir/commerce-admin-management",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Schema-driven system configuration for Adobe Commerce App Builder sync apps. Magento-style scoped config in Adobe App Builder Database (ABDB) with encryption, Commerce REST helpers, and React Admin UI.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Adobe Inc.",
package/scripts/setup.js CHANGED
@@ -230,13 +230,29 @@ configureWeb({
230
230
 
231
231
  window.React = React
232
232
 
233
+ // Mount strategy:
234
+ // - If we're inside the Experience Cloud Shell iframe, init(...) installs a
235
+ // ready-listener that the shell pings within ~100ms. bootstrapInExcShell
236
+ // renders with the IMS context.
237
+ // - If we're on the raw CDN URL (no shell), init(...) still completes but
238
+ // the ready event never arrives. We race a 2-second timer and fall back
239
+ // to bootstrapRaw so React still mounts.
240
+ let booted = false
241
+ function boot (fn) {
242
+ if (booted) return
243
+ booted = true
244
+ fn()
245
+ }
246
+
233
247
  try {
234
248
  require('./exc-runtime')
235
249
  init(bootstrapInExcShell)
236
250
  } catch (e) {
237
251
  console.log('application not running in Adobe Experience Cloud Shell')
238
- bootstrapRaw()
252
+ boot(bootstrapRaw)
239
253
  }
254
+ // Safety net: shell never sent 'ready' → mount raw so the page isn't blank.
255
+ setTimeout(() => boot(bootstrapRaw), 2000)
240
256
 
241
257
  function renderApp (runtime, ims) {
242
258
  createRoot(document.getElementById('root')).render(
@@ -254,11 +270,11 @@ function bootstrapInExcShell () {
254
270
 
255
271
  runtime.on('ready', ({ imsOrg, imsToken, imsProfile }) => {
256
272
  runtime.done()
257
- renderApp(runtime, {
273
+ boot(() => renderApp(runtime, {
258
274
  profile: imsProfile,
259
275
  org: imsOrg,
260
276
  token: imsToken
261
- })
277
+ }))
262
278
  })
263
279
 
264
280
  runtime.solution = {
@@ -480,6 +496,93 @@ function stripExcshellSourceDir (projectRoot) {
480
496
  return { changed, reason: changed ? 'removed' : 'absent' }
481
497
  }
482
498
 
499
+ /**
500
+ * Bump the host's package.json so the React 18 / Spectrum 4 stack we
501
+ * depend on is satisfied without the consumer running a long
502
+ * `npm install --save react@^18 …` chant. We declare these as peers (to
503
+ * avoid shipping duplicate React copies) but a fresh `aio app init` host
504
+ * still pins React 16 — so we patch the host's declared versions here.
505
+ *
506
+ * Strategy:
507
+ * - Only touch entries that are MISSING or pin a version below our floor.
508
+ * - Leave entries already satisfying the floor alone (don't downgrade).
509
+ * - We mutate package.json only; the next `npm install` actually applies
510
+ * the upgrade. We don't re-shell-out to npm from a postinstall — that
511
+ * causes recursive installs and is fragile in workspaces / monorepos.
512
+ */
513
+ const REQUIRED_HOST_DEPS = {
514
+ // React + DOM — package code uses createRoot/react-dom/client (React 18+).
515
+ 'react': '^18.3.1',
516
+ 'react-dom': '^18.3.1',
517
+ // React-error-boundary v4 dropped the default export the older versions
518
+ // shipped; we use named imports so v4 is the floor.
519
+ 'react-error-boundary': '^4.0.0',
520
+ 'react-router-dom': '^6.26.2',
521
+ // Adobe Spectrum trio — must be React-18 compatible.
522
+ '@adobe/react-spectrum': '^3.47.0',
523
+ '@spectrum-icons/workflow': '^4.2.4',
524
+ '@spectrum-icons/ui': '^3.7.1',
525
+ // Adobe app runtime + helpers used by the bootstrap and actions.
526
+ '@adobe/exc-app': '^1.6.0',
527
+ '@adobe/uix-guest': '^0.8.3',
528
+ '@adobe/aio-sdk': '^6.0.0'
529
+ }
530
+
531
+ // Parse a semver-ish version specifier ("^18.3.1", ">=3.0.0", "16.14.0",
532
+ // "16.14.0 || >=18") and return the lowest concrete major.minor.patch it
533
+ // could resolve to. Returns null for non-numeric specs we can't reason
534
+ // about (workspace:*, file:..., git URLs) — those we leave alone.
535
+ function lowestVersion (spec) {
536
+ if (!spec || typeof spec !== 'string') return null
537
+ const s = spec.split('||')[0].trim() // take the first range in an OR list
538
+ const m = s.match(/(\d+)\.(\d+)\.(\d+)/)
539
+ if (!m) return null
540
+ return { major: +m[1], minor: +m[2], patch: +m[3] }
541
+ }
542
+
543
+ function compareVersions (a, b) {
544
+ if (a.major !== b.major) return a.major - b.major
545
+ if (a.minor !== b.minor) return a.minor - b.minor
546
+ return a.patch - b.patch
547
+ }
548
+
549
+ function satisfiesFloor (currentSpec, floorSpec) {
550
+ const cur = lowestVersion(currentSpec)
551
+ const min = lowestVersion(floorSpec)
552
+ if (!cur || !min) return false
553
+ return compareVersions(cur, min) >= 0
554
+ }
555
+
556
+ function ensureHostDeps (projectRoot) {
557
+ const pkgPath = path.join(projectRoot, 'package.json')
558
+ if (!fs.existsSync(pkgPath)) {
559
+ return { changed: false, reason: 'no-package-json' }
560
+ }
561
+ let pkg
562
+ try { pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) } catch (_) {
563
+ return { changed: false, reason: 'unreadable-package-json' }
564
+ }
565
+ pkg.dependencies = pkg.dependencies || {}
566
+
567
+ const bumped = []
568
+ for (const [name, floor] of Object.entries(REQUIRED_HOST_DEPS)) {
569
+ const declared = pkg.dependencies[name] || (pkg.devDependencies && pkg.devDependencies[name])
570
+ if (declared && satisfiesFloor(declared, floor)) continue
571
+ // Move it to dependencies (out of devDependencies if it was there) and
572
+ // set to the floor.
573
+ pkg.dependencies[name] = floor
574
+ if (pkg.devDependencies && pkg.devDependencies[name]) {
575
+ delete pkg.devDependencies[name]
576
+ }
577
+ bumped.push({ name, was: declared || '(missing)', now: floor })
578
+ }
579
+
580
+ if (bumped.length === 0) return { changed: false, reason: 'already-satisfies' }
581
+
582
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8')
583
+ return { changed: true, bumped }
584
+ }
585
+
483
586
  function setupAppConfig (projectRoot) {
484
587
  const appConfigPath = path.join(projectRoot, 'app.config.yaml')
485
588
  if (!fs.existsSync(appConfigPath)) {
@@ -523,6 +626,20 @@ function main () {
523
626
  console.log('[@adobedjangir/commerce-admin-management] removed src/dx-excshell-1/ (replaced by commerce/backend-ui/1)')
524
627
  }
525
628
 
629
+ // Bump host package.json so React-18 + Spectrum-4 peers are satisfied
630
+ // without the consumer running a long `npm install --save react@^18 ...`
631
+ // chant. They still need to run `npm install` once more for npm to
632
+ // resolve the new versions — we can't safely re-shell-out to npm from
633
+ // inside a postinstall.
634
+ const deps = ensureHostDeps(projectRoot)
635
+ if (deps.changed) {
636
+ console.log('[@adobedjangir/commerce-admin-management] bumped host package.json:')
637
+ for (const b of deps.bumped) {
638
+ console.log(` • ${b.name}: ${b.was} → ${b.now}`)
639
+ }
640
+ console.log('[@adobedjangir/commerce-admin-management] run `npm install` once more to apply the upgrades.')
641
+ }
642
+
526
643
  const app = setupAppConfig(projectRoot)
527
644
  if (app.changed) {
528
645
  console.log(