@scenar/cli 0.3.0 → 0.4.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 (94) hide show
  1. package/package.json +4 -9
  2. package/src/__tests__/embed-snippet.test.ts +1 -1
  3. package/src/__tests__/install-command.test.ts +97 -0
  4. package/src/__tests__/local-url.test.ts +17 -0
  5. package/src/__tests__/run-install.test.ts +222 -0
  6. package/src/api.d.ts +3 -1
  7. package/src/api.d.ts.map +1 -1
  8. package/src/api.js +3 -1
  9. package/src/api.js.map +1 -1
  10. package/src/api.ts +10 -1
  11. package/src/commands/install.d.ts +3 -0
  12. package/src/commands/install.d.ts.map +1 -0
  13. package/src/commands/install.js +67 -0
  14. package/src/commands/install.js.map +1 -0
  15. package/src/commands/install.ts +89 -0
  16. package/src/commands/pack.js +2 -2
  17. package/src/commands/pack.js.map +1 -1
  18. package/src/commands/pack.ts +2 -2
  19. package/src/commands/serve.d.ts.map +1 -1
  20. package/src/commands/serve.js +1 -2
  21. package/src/commands/serve.js.map +1 -1
  22. package/src/commands/serve.ts +1 -2
  23. package/src/commands/try.js +1 -1
  24. package/src/commands/try.ts +1 -1
  25. package/src/embed/embed-snippet.d.ts.map +1 -0
  26. package/src/embed/embed-snippet.js.map +1 -0
  27. package/src/index.d.ts.map +1 -1
  28. package/src/index.js +3 -5
  29. package/src/index.js.map +1 -1
  30. package/src/index.ts +3 -5
  31. package/src/install/run-install.d.ts +72 -0
  32. package/src/install/run-install.d.ts.map +1 -0
  33. package/src/install/run-install.js +378 -0
  34. package/src/install/run-install.js.map +1 -0
  35. package/src/install/run-install.ts +461 -0
  36. package/src/install/scaffold.d.ts +29 -0
  37. package/src/install/scaffold.d.ts.map +1 -0
  38. package/src/install/scaffold.js +233 -0
  39. package/src/install/scaffold.js.map +1 -0
  40. package/src/install/scaffold.ts +255 -0
  41. package/src/pack/pack-manifest.d.ts +1 -1
  42. package/src/pack/pack-manifest.d.ts.map +1 -1
  43. package/src/pack/pack-manifest.ts +1 -1
  44. package/src/publish/publish-flow.d.ts +3 -3
  45. package/src/publish/publish-flow.js +3 -3
  46. package/src/publish/publish-flow.ts +3 -3
  47. package/src/publish/run-publish.js +1 -1
  48. package/src/publish/run-publish.js.map +1 -1
  49. package/src/publish/run-publish.ts +1 -1
  50. package/src/render/detect-render-export.d.ts +2 -2
  51. package/src/render/detect-render-export.js +2 -2
  52. package/src/render/detect-render-export.ts +2 -2
  53. package/src/serve/local-url.d.ts +8 -0
  54. package/src/serve/local-url.d.ts.map +1 -0
  55. package/src/serve/local-url.js +21 -0
  56. package/src/serve/local-url.js.map +1 -0
  57. package/src/serve/local-url.ts +20 -0
  58. package/src/serve/run-serve.js +2 -2
  59. package/src/serve/run-serve.js.map +1 -1
  60. package/src/serve/run-serve.ts +2 -2
  61. package/tsconfig.tsbuildinfo +1 -1
  62. package/src/__tests__/deploy-command.test.ts +0 -45
  63. package/src/__tests__/deploy-flow.test.ts +0 -125
  64. package/src/__tests__/deploy-upload.test.ts +0 -39
  65. package/src/commands/deploy.d.ts +0 -3
  66. package/src/commands/deploy.d.ts.map +0 -1
  67. package/src/commands/deploy.js +0 -150
  68. package/src/commands/deploy.js.map +0 -1
  69. package/src/commands/deploy.ts +0 -186
  70. package/src/commands/preview.d.ts +0 -3
  71. package/src/commands/preview.d.ts.map +0 -1
  72. package/src/commands/preview.js +0 -93
  73. package/src/commands/preview.js.map +0 -1
  74. package/src/commands/preview.ts +0 -138
  75. package/src/deploy/client.d.ts +0 -20
  76. package/src/deploy/client.d.ts.map +0 -1
  77. package/src/deploy/client.js +0 -22
  78. package/src/deploy/client.js.map +0 -1
  79. package/src/deploy/client.ts +0 -28
  80. package/src/deploy/deploy-flow.d.ts +0 -78
  81. package/src/deploy/deploy-flow.d.ts.map +0 -1
  82. package/src/deploy/deploy-flow.js +0 -53
  83. package/src/deploy/deploy-flow.js.map +0 -1
  84. package/src/deploy/deploy-flow.ts +0 -115
  85. package/src/deploy/embed-snippet.d.ts.map +0 -1
  86. package/src/deploy/embed-snippet.js.map +0 -1
  87. package/src/deploy/upload.d.ts +0 -10
  88. package/src/deploy/upload.d.ts.map +0 -1
  89. package/src/deploy/upload.js +0 -23
  90. package/src/deploy/upload.js.map +0 -1
  91. package/src/deploy/upload.ts +0 -29
  92. /package/src/{deploy → embed}/embed-snippet.d.ts +0 -0
  93. /package/src/{deploy → embed}/embed-snippet.js +0 -0
  94. /package/src/{deploy → embed}/embed-snippet.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-install.js","sourceRoot":"","sources":["../../../src/install/run-install.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAuB,MAAM,eAAe,CAAC;AA6CrE;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAE/C,sEAAsE;IACtE,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,QAAQ,GAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QAChC,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,MAAM,aAAa,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,cAAc,GAClB,OAAO,CAAC,cAAc,IAAI,oBAAoB,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,aAAa,IAAI,GAAG,CAAC;IAExC,4DAA4D;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,WAAW,GAAG,aAAa;YAC/B,CAAC,CAAC,oBAAoB,CAAC,aAAa,CAAC;YACrC,CAAC,CAAC,IAAI,GAAG,EAAU,CAAC;QACtB,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,sBAAsB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,sCAAsC,cAAc,EAAE;YACpD,CAAC,aAAa,CAAC,CAAC,CAAC,qBAAqB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACvF,CAAC;QACF,wBAAwB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACrD,UAAU,GAAG,IAAI,CAAC;QAClB,qEAAqE;QACrE,mEAAmE;QACnE,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,OAAO;QACL,UAAU;QACV,eAAe,EAAE,QAAQ,CAAC,OAAO;QACjC,KAAK;QACL,cAAc;QACd,aAAa;QACb,UAAU;KACX,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,6EAA6E;AAC7E,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAC3C,MAAM,WAAW,GAAG,kDAAkD,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAExB,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,uCAAuC,IAAI,wBAAwB;gBACjE,kDAAkD,CACrD,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,uBAAuB,IAAI,mCAAmC;YAC5D,mCAAmC,IAAI,gCAAgC,CAC1E,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAChD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;AAChE,CAAC;AAWD;;;;;GAKG;AACH,SAAS,iBAAiB,CACxB,OAAe,EACf,KAA4B,EAC5B,GAAiB;IAEjB,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAA2B,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;IAErE,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC;QACpC,IAAI,KAAK,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,oBAAoB;QAE9D,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACrB,CAAC;aAAM,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC;gBACR,GAAG,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QACnB,CAAC;IACH,CAAC;IAED,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,OAAe,EAAE,KAA4B;IACtE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAA2B,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;IAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC;IACrE,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG;YAAE,SAAS;QACjC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YAC3B,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;QACxB,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,wCAAwC;AACxC,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,8EAA8E;IAC9E,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEhC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;YAChE,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,SAAS,kBAAkB,CAAC,GAAW;IACrC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAEvD,CAAC;YACT,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;YAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBAAE,OAAO,EAAc,CAAC;YAC7C,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,CAAE,EAA8B,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClE,OAAQ,EAA6B,CAAC,QAAQ,CAAC;YACjD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,SAAS,cAAc,CAAC,SAAiB,EAAE,KAAwB;IACjE,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC3B,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,EAAE,CAAC;gBACJ,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;oBAAE,CAAC,EAAE,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,EAAE,IAAI,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,uEAAuE;AACvE,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,SAAS,IAAI,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;YACxC,IAAI,IAAI;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAElB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBACxC,IAAI,KAAK,CAAC,WAAW,EAAE;wBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC;QACvE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC;QAClE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACrC,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,sEAAsE;AACtE,SAAS,wBAAwB,CAAC,EAAkB,EAAE,GAAW;IAC/D,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE;QACxC,GAAG,EAAE,GAAG;QACR,KAAK,EAAE,SAAS;QAChB,gDAAgD;QAChD,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,GAAI,MAAM,CAAC,KAA+B,CAAC,IAAI,CAAC;QAC1D,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,mDAAmD;gBACtD,oCAAoC,CACvC,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,GAAG,EAAE,8BAA8B,MAAM,CAAC,MAAM,qBAAqB;YACnE,wEAAwE,CAC3E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAwB,CAAC;AAC3E,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAc;IAC7C,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;QACpC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC1C,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,GAA2B;IAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAE,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,461 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { spawnSync } from "node:child_process";
4
+ import { parse as parseYaml } from "yaml";
5
+ import { scaffoldProject, type ScaffoldResult } from "./scaffold.js";
6
+
7
+ /** Supported package managers, detected by lockfile / workspace manifest. */
8
+ export type PackageManager = "npm" | "yarn" | "pnpm";
9
+
10
+ /** A dependency parsed from a positional install argument. */
11
+ export interface ParsedSpec {
12
+ /** The package name (registry key written into `dependencies`). */
13
+ readonly name: string;
14
+ /**
15
+ * The version range / locator to record. Empty string means "bare" — the
16
+ * concrete value is decided at merge time (`workspace:*` for a workspace
17
+ * member, otherwise `*`, later pinned to the installed version).
18
+ */
19
+ readonly range: string;
20
+ }
21
+
22
+ export interface RunInstallOptions {
23
+ /** Project directory to operate in (absolute or relative to cwd). */
24
+ readonly cwd: string;
25
+ /** Positional dependency specs to add (names, ranges, file:/git/workspace). */
26
+ readonly packages: readonly string[];
27
+ /** Line-oriented log sink (the CLI wires this to stderr). */
28
+ readonly onLog: (line: string) => void;
29
+ /** Scaffold and record deps but skip the package-manager subprocess. */
30
+ readonly skipInstall?: boolean;
31
+ /** Force a package manager instead of detecting one. */
32
+ readonly packageManager?: PackageManager;
33
+ }
34
+
35
+ export interface RunInstallResult {
36
+ /** Whether a fresh project was scaffolded (no prior `package.json`). */
37
+ readonly scaffolded: boolean;
38
+ /** Files created by scaffolding, relative to the project directory. */
39
+ readonly scaffoldCreated: readonly string[];
40
+ /** Dependencies added (or already present) from the positional specs. */
41
+ readonly added: readonly ParsedSpec[];
42
+ /** The package manager used. */
43
+ readonly packageManager: PackageManager;
44
+ /** Workspace root if the project is a workspace member, else null. */
45
+ readonly workspaceRoot: string | null;
46
+ /** Whether the package-manager install actually ran. */
47
+ readonly installRan: boolean;
48
+ }
49
+
50
+ /**
51
+ * Bootstrap a Scenar demos project: scaffold (if empty), record the requested
52
+ * component packages as ordinary dependencies, and run the package manager.
53
+ *
54
+ * The command is intentionally resolver-agnostic — it only writes dependency
55
+ * entries and delegates resolution to the package manager — so a positional
56
+ * argument can be a registry version, a `workspace:*` spec, a `file:`/`link:`
57
+ * path, or a git URL. Dependency resolution is the package manager's job, not
58
+ * ours.
59
+ */
60
+ export function runInstall(options: RunInstallOptions): RunInstallResult {
61
+ const cwd = path.resolve(options.cwd);
62
+ const pkgPath = path.join(cwd, "package.json");
63
+
64
+ // --- 1. Scaffold a fresh project if there's no package.json yet. ---
65
+ let scaffolded = false;
66
+ let scaffold: ScaffoldResult = { created: [] };
67
+ if (!fs.existsSync(pkgPath)) {
68
+ scaffold = scaffoldProject(cwd);
69
+ scaffolded = true;
70
+ options.onLog(`\x1b[36m●\x1b[0m Scaffolded a new Scenar demos project`);
71
+ for (const file of scaffold.created) {
72
+ options.onLog(` \x1b[32m✓\x1b[0m ${file}`);
73
+ }
74
+ }
75
+
76
+ // --- 2. Detect workspace + package manager. ---
77
+ const workspaceRoot = findWorkspaceRoot(cwd);
78
+ const packageManager =
79
+ options.packageManager ?? detectPackageManager(workspaceRoot ?? cwd);
80
+ const installDir = workspaceRoot ?? cwd;
81
+
82
+ // --- 3. Record the requested packages as dependencies. ---
83
+ const added = options.packages.map((raw) => parseSpec(raw, cwd));
84
+ if (added.length > 0) {
85
+ const memberNames = workspaceRoot
86
+ ? workspaceMemberNames(workspaceRoot)
87
+ : new Set<string>();
88
+ mergeDependencies(pkgPath, added, { packageManager, memberNames });
89
+ options.onLog(`\x1b[36m●\x1b[0m Added dependencies`);
90
+ for (const spec of added) {
91
+ options.onLog(` \x1b[32m✓\x1b[0m ${spec.name}`);
92
+ }
93
+ }
94
+
95
+ // --- 4. Install. ---
96
+ let installRan = false;
97
+ if (!options.skipInstall) {
98
+ options.onLog(
99
+ `\n\x1b[36m●\x1b[0m Installing with ${packageManager}` +
100
+ (workspaceRoot ? ` (workspace root: ${path.relative(cwd, installDir) || "."})` : ""),
101
+ );
102
+ runPackageManagerInstall(packageManager, installDir);
103
+ installRan = true;
104
+ // Bare registry specs were written as "*"; pin them to what actually
105
+ // resolved so the project gets a clean, reproducible package.json.
106
+ pinResolvedRanges(pkgPath, added);
107
+ }
108
+
109
+ return {
110
+ scaffolded,
111
+ scaffoldCreated: scaffold.created,
112
+ added,
113
+ packageManager,
114
+ workspaceRoot,
115
+ installRan,
116
+ };
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Dependency-spec parsing
121
+ // ---------------------------------------------------------------------------
122
+
123
+ /** Locator-prefixed specs whose name lives in the target, not the string. */
124
+ const PATH_SPEC_RE = /^(file:|link:)(.+)$/;
125
+ const URL_SPEC_RE = /^(git\+|git:|https?:|github:|bitbucket:|gitlab:)/;
126
+
127
+ /**
128
+ * Parse one positional install argument into a `{ name, range }` pair.
129
+ *
130
+ * Handles the common forms (`name`, `name@range`, `@scope/name`,
131
+ * `@scope/name@range`), resolves `file:`/`link:` names from the target's
132
+ * `package.json`, and rejects git/URL specs that carry no package name (the
133
+ * user should add those to `package.json` directly, then re-run).
134
+ */
135
+ export function parseSpec(raw: string, cwd: string): ParsedSpec {
136
+ const spec = raw.trim();
137
+
138
+ const pathMatch = PATH_SPEC_RE.exec(spec);
139
+ if (pathMatch) {
140
+ const target = path.resolve(cwd, pathMatch[2]!);
141
+ const name = readPackageName(target);
142
+ if (!name) {
143
+ throw new Error(
144
+ `could not read a package name from "${spec}". Make sure the path ` +
145
+ `points at a directory containing a package.json.`,
146
+ );
147
+ }
148
+ return { name, range: spec };
149
+ }
150
+
151
+ if (URL_SPEC_RE.test(spec)) {
152
+ throw new Error(
153
+ `git/URL dependency "${spec}" has no package name. Add it to ` +
154
+ `package.json (e.g. "your-pkg": "${spec}") and run \`scenar install\`.`,
155
+ );
156
+ }
157
+
158
+ // name | name@range | @scope/name | @scope/name@range
159
+ const scoped = spec.startsWith("@");
160
+ const at = spec.indexOf("@", scoped ? 1 : 0);
161
+ if (at === -1) return { name: spec, range: "" };
162
+ return { name: spec.slice(0, at), range: spec.slice(at + 1) };
163
+ }
164
+
165
+ // ---------------------------------------------------------------------------
166
+ // package.json mutation
167
+ // ---------------------------------------------------------------------------
168
+
169
+ interface MergeContext {
170
+ readonly packageManager: PackageManager;
171
+ readonly memberNames: ReadonlySet<string>;
172
+ }
173
+
174
+ /**
175
+ * Merge parsed specs into `dependencies`, idempotently. Existing pins are kept
176
+ * when the user passed a bare name; an explicit range always wins. Bare names
177
+ * that match a workspace member become `workspace:*` (pnpm/yarn) or `*` (npm),
178
+ * and other bare names default to `*` (pinned post-install).
179
+ */
180
+ function mergeDependencies(
181
+ pkgPath: string,
182
+ specs: readonly ParsedSpec[],
183
+ ctx: MergeContext,
184
+ ): void {
185
+ const pkg = readJson(pkgPath);
186
+ const deps: Record<string, string> = { ...(pkg.dependencies ?? {}) };
187
+
188
+ for (const { name, range } of specs) {
189
+ if (range === "" && deps[name]) continue; // keep existing pin
190
+
191
+ if (range !== "") {
192
+ deps[name] = range;
193
+ } else if (ctx.memberNames.has(name)) {
194
+ deps[name] =
195
+ ctx.packageManager === "npm" ? "*" : "workspace:*";
196
+ } else {
197
+ deps[name] = "*";
198
+ }
199
+ }
200
+
201
+ pkg.dependencies = sortKeys(deps);
202
+ writeJson(pkgPath, pkg);
203
+ }
204
+
205
+ /**
206
+ * Replace any `"*"` dependency ranges with `^<installed version>` after a
207
+ * successful install, so a bare `scenar install @foo/bar` yields a clean,
208
+ * reproducible pin. Best-effort: workspace specs and unresolved packages are
209
+ * left untouched.
210
+ */
211
+ function pinResolvedRanges(pkgPath: string, specs: readonly ParsedSpec[]): void {
212
+ const pkg = readJson(pkgPath);
213
+ const deps: Record<string, string> = pkg.dependencies ?? {};
214
+ const nodeModules = path.join(path.dirname(pkgPath), "node_modules");
215
+ let changed = false;
216
+
217
+ for (const name of new Set(specs.map((s) => s.name))) {
218
+ if (deps[name] !== "*") continue;
219
+ const version = readPackageVersion(path.join(nodeModules, name));
220
+ if (version) {
221
+ deps[name] = `^${version}`;
222
+ changed = true;
223
+ }
224
+ }
225
+
226
+ if (changed) {
227
+ pkg.dependencies = deps;
228
+ writeJson(pkgPath, pkg);
229
+ }
230
+ }
231
+
232
+ // ---------------------------------------------------------------------------
233
+ // Workspace + package-manager detection
234
+ // ---------------------------------------------------------------------------
235
+
236
+ /**
237
+ * Walk up from `startDir` to find the nearest workspace root that actually
238
+ * contains `startDir` as a member — a directory with a `pnpm-workspace.yaml`
239
+ * or a `package.json` `workspaces` field whose globs match `startDir`. Returns
240
+ * null when the project is standalone.
241
+ */
242
+ export function findWorkspaceRoot(startDir: string): string | null {
243
+ let dir = path.resolve(startDir);
244
+ // The project's own package.json is never its workspace root, so start above.
245
+ let current = path.dirname(dir);
246
+
247
+ while (true) {
248
+ const globs = readWorkspaceGlobs(current);
249
+ if (globs && matchesAnyGlob(path.relative(current, dir), globs)) {
250
+ return current;
251
+ }
252
+ const parent = path.dirname(current);
253
+ if (parent === current) return null;
254
+ current = parent;
255
+ }
256
+ }
257
+
258
+ /** Read workspace package globs from pnpm-workspace.yaml or package.json. */
259
+ function readWorkspaceGlobs(dir: string): string[] | null {
260
+ const pnpmManifest = path.join(dir, "pnpm-workspace.yaml");
261
+ if (fs.existsSync(pnpmManifest)) {
262
+ try {
263
+ const parsed = parseYaml(fs.readFileSync(pnpmManifest, "utf-8")) as
264
+ | { packages?: string[] }
265
+ | null;
266
+ if (Array.isArray(parsed?.packages)) return parsed.packages;
267
+ } catch {
268
+ // Malformed manifest — fall through to package.json.
269
+ }
270
+ }
271
+
272
+ const pkgPath = path.join(dir, "package.json");
273
+ if (fs.existsSync(pkgPath)) {
274
+ try {
275
+ const pkg = readJson(pkgPath);
276
+ const ws = pkg.workspaces;
277
+ if (Array.isArray(ws)) return ws as string[];
278
+ if (ws && Array.isArray((ws as { packages?: string[] }).packages)) {
279
+ return (ws as { packages: string[] }).packages;
280
+ }
281
+ } catch {
282
+ // Ignore unreadable package.json.
283
+ }
284
+ }
285
+
286
+ return null;
287
+ }
288
+
289
+ /** Test a member path (relative to the workspace root) against workspace globs. */
290
+ function matchesAnyGlob(relMember: string, globs: readonly string[]): boolean {
291
+ const normalized = relMember.split(path.sep).join("/");
292
+ return globs.some((glob) => globToRegExp(glob).test(normalized));
293
+ }
294
+
295
+ /**
296
+ * Convert a workspace glob (e.g. `packages/*`, `apps/**`) to a RegExp. Supports
297
+ * the `*` (one segment) and `**` (any depth) wildcards that workspace manifests
298
+ * use; everything else is matched literally.
299
+ */
300
+ function globToRegExp(glob: string): RegExp {
301
+ const trimmed = glob.replace(/\/+$/, "");
302
+ let re = "";
303
+ for (let i = 0; i < trimmed.length; i++) {
304
+ const c = trimmed[i]!;
305
+ if (c === "*") {
306
+ if (trimmed[i + 1] === "*") {
307
+ re += ".*";
308
+ i++;
309
+ if (trimmed[i + 1] === "/") i++;
310
+ } else {
311
+ re += "[^/]*";
312
+ }
313
+ } else if (/[.+?^${}()|[\]\\]/.test(c)) {
314
+ re += "\\" + c;
315
+ } else {
316
+ re += c;
317
+ }
318
+ }
319
+ return new RegExp(`^${re}$`);
320
+ }
321
+
322
+ /** Collect the package names of all workspace members under `root`. */
323
+ function workspaceMemberNames(root: string): Set<string> {
324
+ const names = new Set<string>();
325
+ const globs = readWorkspaceGlobs(root);
326
+ if (!globs) return names;
327
+
328
+ for (const glob of globs) {
329
+ for (const memberDir of expandGlobDirs(root, glob)) {
330
+ const name = readPackageName(memberDir);
331
+ if (name) names.add(name);
332
+ }
333
+ }
334
+ return names;
335
+ }
336
+
337
+ /**
338
+ * Expand a single workspace glob into existing member directories. Only the
339
+ * `pkgs/*` and `pkgs/**` shapes that workspace manifests use are supported;
340
+ * each candidate is kept only if it contains a `package.json`.
341
+ */
342
+ function expandGlobDirs(root: string, glob: string): string[] {
343
+ const trimmed = glob.replace(/\/+$/, "");
344
+ const parts = trimmed.split("/");
345
+ let dirs = [root];
346
+
347
+ for (const part of parts) {
348
+ const next: string[] = [];
349
+ for (const dir of dirs) {
350
+ if (part === "*" || part === "**") {
351
+ for (const entry of safeReaddir(dir)) {
352
+ const full = path.join(dir, entry.name);
353
+ if (entry.isDirectory()) next.push(full);
354
+ }
355
+ } else {
356
+ const full = path.join(dir, part);
357
+ if (fs.existsSync(full)) next.push(full);
358
+ }
359
+ }
360
+ dirs = next;
361
+ }
362
+
363
+ return dirs.filter((dir) => fs.existsSync(path.join(dir, "package.json")));
364
+ }
365
+
366
+ /**
367
+ * Detect the package manager by the nearest lockfile, walking up from `dir`.
368
+ * Defaults to npm when nothing is found.
369
+ */
370
+ export function detectPackageManager(dir: string): PackageManager {
371
+ let current = path.resolve(dir);
372
+ while (true) {
373
+ if (fs.existsSync(path.join(current, "pnpm-lock.yaml"))) return "pnpm";
374
+ if (fs.existsSync(path.join(current, "yarn.lock"))) return "yarn";
375
+ if (fs.existsSync(path.join(current, "package-lock.json"))) return "npm";
376
+ const parent = path.dirname(current);
377
+ if (parent === current) return "npm";
378
+ current = parent;
379
+ }
380
+ }
381
+
382
+ // ---------------------------------------------------------------------------
383
+ // Subprocess
384
+ // ---------------------------------------------------------------------------
385
+
386
+ /** Run `<pm> install` in `dir`, throwing a clear error on failure. */
387
+ function runPackageManagerInstall(pm: PackageManager, dir: string): void {
388
+ const result = spawnSync(pm, ["install"], {
389
+ cwd: dir,
390
+ stdio: "inherit",
391
+ // Windows resolves npm/yarn/pnpm via the shell.
392
+ shell: process.platform === "win32",
393
+ });
394
+
395
+ if (result.error) {
396
+ const code = (result.error as NodeJS.ErrnoException).code;
397
+ if (code === "ENOENT") {
398
+ throw new Error(
399
+ `${pm} was not found on your PATH. Install it, or pass ` +
400
+ `--package-manager <npm|yarn|pnpm>.`,
401
+ );
402
+ }
403
+ throw result.error;
404
+ }
405
+
406
+ if (typeof result.status === "number" && result.status !== 0) {
407
+ throw new Error(
408
+ `${pm} install failed (exit code ${result.status}). If a package is ` +
409
+ `private or unpublished, check your registry access and authentication.`,
410
+ );
411
+ }
412
+ }
413
+
414
+ // ---------------------------------------------------------------------------
415
+ // JSON / fs helpers
416
+ // ---------------------------------------------------------------------------
417
+
418
+ function readJson(file: string): Record<string, any> {
419
+ return JSON.parse(fs.readFileSync(file, "utf-8")) as Record<string, any>;
420
+ }
421
+
422
+ function writeJson(file: string, value: unknown): void {
423
+ fs.writeFileSync(file, JSON.stringify(value, null, 2) + "\n", "utf-8");
424
+ }
425
+
426
+ function readPackageName(dir: string): string | null {
427
+ const pkgPath = path.join(dir, "package.json");
428
+ if (!fs.existsSync(pkgPath)) return null;
429
+ try {
430
+ const name = readJson(pkgPath).name;
431
+ return typeof name === "string" && name.length > 0 ? name : null;
432
+ } catch {
433
+ return null;
434
+ }
435
+ }
436
+
437
+ function readPackageVersion(dir: string): string | null {
438
+ const pkgPath = path.join(dir, "package.json");
439
+ if (!fs.existsSync(pkgPath)) return null;
440
+ try {
441
+ const version = readJson(pkgPath).version;
442
+ return typeof version === "string" && version.length > 0 ? version : null;
443
+ } catch {
444
+ return null;
445
+ }
446
+ }
447
+
448
+ function safeReaddir(dir: string): fs.Dirent[] {
449
+ try {
450
+ return fs.readdirSync(dir, { withFileTypes: true });
451
+ } catch {
452
+ return [];
453
+ }
454
+ }
455
+
456
+ /** Sort object keys so generated package.json deps stay stable across runs. */
457
+ function sortKeys(obj: Record<string, string>): Record<string, string> {
458
+ const sorted: Record<string, string> = {};
459
+ for (const key of Object.keys(obj).sort()) sorted[key] = obj[key]!;
460
+ return sorted;
461
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Base dependencies every Scenar demos project needs to author tours. The
3
+ * starter tour is built from `@scenar/react` shells, so `@scenar/react` is
4
+ * recorded as `"*"` (resolves to the latest published — pin it once you know
5
+ * the version you want). React is constrained to the major the `@scenar/*`
6
+ * packages target so the embed and the user's real components (added later)
7
+ * share a single React.
8
+ */
9
+ export declare const BASE_DEPENDENCIES: Readonly<Record<string, string>>;
10
+ /** Result of scaffolding a fresh demos project. */
11
+ export interface ScaffoldResult {
12
+ /** Files created, relative to the project directory. */
13
+ readonly created: readonly string[];
14
+ }
15
+ /**
16
+ * Scaffold a fresh Scenar demos project in `dir`.
17
+ *
18
+ * Creates a minimal `package.json`, a `tsconfig.json` tuned for JSX, a
19
+ * `.gitignore` that ignores build output, and a runnable **starter tour** under
20
+ * `tours/example-tour/` (a `steps.ts` timeline, an `index.tsx` that exports
21
+ * `renderStep`, and a `.scenar/providers.tsx`). The starter is built from
22
+ * `@scenar/react` shells so `scenar pack` works immediately; the author then
23
+ * swaps in their real components and wires data in `providers.tsx`.
24
+ *
25
+ * Existing files are never overwritten — this only fills in what is missing, so
26
+ * it is safe to re-run.
27
+ */
28
+ export declare function scaffoldProject(dir: string): ScaffoldResult;
29
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/install/scaffold.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI9D,CAAC;AAEF,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAW3D"}