@swoff/cli 0.3.14 → 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 (147) hide show
  1. package/dist/index.js +2 -2
  2. package/dist/index.js.map +1 -1
  3. package/dist/lib/cli/help.js +3 -3
  4. package/dist/lib/cli/help.js.map +1 -1
  5. package/dist/lib/commands/clean.js +8 -17
  6. package/dist/lib/commands/clean.js.map +1 -1
  7. package/dist/lib/commands/generate-guide.js +3 -5
  8. package/dist/lib/commands/generate-guide.js.map +1 -1
  9. package/dist/lib/commands/generate.js +9 -7
  10. package/dist/lib/commands/generate.js.map +1 -1
  11. package/dist/lib/commands/init.js +218 -184
  12. package/dist/lib/commands/init.js.map +1 -1
  13. package/dist/lib/commands/validate.js.map +1 -1
  14. package/dist/lib/config/minimal-config.js +64 -0
  15. package/dist/lib/config/minimal-config.js.map +1 -0
  16. package/dist/lib/config/validator.js +42 -19
  17. package/dist/lib/config/validator.js.map +1 -1
  18. package/dist/lib/generators/file-generators/client-injector-bundle.js +1 -1
  19. package/dist/lib/generators/file-generators/client-injector-bundle.js.map +1 -1
  20. package/dist/lib/generators/file-generators/context.js +3 -2
  21. package/dist/lib/generators/file-generators/context.js.map +1 -1
  22. package/dist/lib/generators/file-generators/generate-framework-adapters.js +1 -1
  23. package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -1
  24. package/dist/lib/generators/file-generators/sw-generator-build.js +34 -14
  25. package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
  26. package/dist/lib/generators/file-generators/sw-injector.js +1 -0
  27. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
  28. package/dist/lib/generators/sw-build-utils.js +17 -3
  29. package/dist/lib/generators/sw-build-utils.js.map +1 -1
  30. package/dist/lib/generators/sw-generator.js +5 -5
  31. package/dist/lib/generators/sw-generator.js.map +1 -1
  32. package/dist/lib/generators/sw-sections/activate-handler.js +4 -1
  33. package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
  34. package/dist/lib/generators/sw-sections/assemble-sw.js +7 -4
  35. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  36. package/dist/lib/generators/sw-sections/background-precache.js +118 -0
  37. package/dist/lib/generators/sw-sections/background-precache.js.map +1 -0
  38. package/dist/lib/generators/sw-sections/default-template.js +11 -3
  39. package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
  40. package/dist/lib/generators/sw-sections/fetch-handler.js +2 -2
  41. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
  42. package/dist/lib/generators/sw-sections/message-handler.js +9 -1
  43. package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
  44. package/dist/lib/generators/sw-sections/shared.js +2 -2
  45. package/dist/lib/generators/sw-sections/shared.js.map +1 -1
  46. package/dist/lib/generators/swoff-files-generator.js +2 -2
  47. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  48. package/dist/lib/shared/config-types.js +20 -18
  49. package/dist/lib/shared/config-types.js.map +1 -1
  50. package/dist/lib/utils/detect-framework.js +3 -27
  51. package/dist/lib/utils/detect-framework.js.map +1 -1
  52. package/dist/runtime/client-injector-bundle.js +16 -23
  53. package/dist/runtime/client-injector-bundle.js.map +1 -1
  54. package/dist/runtime/client-injector.js +15 -2
  55. package/dist/runtime/client-injector.js.map +1 -1
  56. package/dist/runtime/sw-injector.js +6 -19
  57. package/dist/runtime/sw-injector.js.map +1 -1
  58. package/dist/runtime/type-definitions.js +0 -5
  59. package/dist/runtime/type-definitions.js.map +1 -1
  60. package/package.json +9 -3
  61. package/templates/react/usePrecacheProgress.jsx +20 -0
  62. package/templates/react/usePrecacheProgress.tsx +20 -0
  63. package/dist/lib/commands/add.js +0 -62
  64. package/dist/lib/commands/add.js.map +0 -1
  65. package/dist/lib/commands/assets.js +0 -45
  66. package/dist/lib/commands/assets.js.map +0 -1
  67. package/dist/lib/commands/generate-assets.js +0 -44
  68. package/dist/lib/commands/generate-assets.js.map +0 -1
  69. package/dist/lib/commands/info.js +0 -183
  70. package/dist/lib/commands/info.js.map +0 -1
  71. package/dist/lib/generators/asset-generator/dependency-resolver.js +0 -85
  72. package/dist/lib/generators/asset-generator/dependency-resolver.js.map +0 -1
  73. package/dist/lib/generators/asset-generator/generate.js +0 -111
  74. package/dist/lib/generators/asset-generator/generate.js.map +0 -1
  75. package/dist/lib/generators/asset-generator/guide.js +0 -43
  76. package/dist/lib/generators/asset-generator/guide.js.map +0 -1
  77. package/dist/lib/generators/asset-generator/html-patcher.js +0 -65
  78. package/dist/lib/generators/asset-generator/html-patcher.js.map +0 -1
  79. package/dist/lib/generators/asset-generator/ico-encoder.js +0 -29
  80. package/dist/lib/generators/asset-generator/ico-encoder.js.map +0 -1
  81. package/dist/lib/generators/asset-generator/manifest-patcher.js +0 -23
  82. package/dist/lib/generators/asset-generator/manifest-patcher.js.map +0 -1
  83. package/dist/lib/generators/asset-generator/maskable.js +0 -15
  84. package/dist/lib/generators/asset-generator/maskable.js.map +0 -1
  85. package/dist/lib/generators/asset-generator/rasterize.js +0 -32
  86. package/dist/lib/generators/asset-generator/rasterize.js.map +0 -1
  87. package/dist/lib/generators/asset-generator/sizes.js +0 -25
  88. package/dist/lib/generators/asset-generator/sizes.js.map +0 -1
  89. package/dist/lib/generators/file-generators/auth-fetch.js +0 -151
  90. package/dist/lib/generators/file-generators/auth-fetch.js.map +0 -1
  91. package/dist/lib/generators/file-generators/auth-user.js +0 -13
  92. package/dist/lib/generators/file-generators/auth-user.js.map +0 -1
  93. package/dist/lib/generators/file-generators/connectivity-manager.js +0 -12
  94. package/dist/lib/generators/file-generators/connectivity-manager.js.map +0 -1
  95. package/dist/lib/generators/file-generators/fetch-state.js +0 -6
  96. package/dist/lib/generators/file-generators/fetch-state.js.map +0 -1
  97. package/dist/lib/generators/file-generators/generate-hooks.js +0 -44
  98. package/dist/lib/generators/file-generators/generate-hooks.js.map +0 -1
  99. package/dist/lib/generators/file-generators/indexeddb.js +0 -74
  100. package/dist/lib/generators/file-generators/indexeddb.js.map +0 -1
  101. package/dist/lib/generators/file-generators/manifest.js +0 -46
  102. package/dist/lib/generators/file-generators/manifest.js.map +0 -1
  103. package/dist/lib/generators/file-generators/mutation-reconcile.js +0 -57
  104. package/dist/lib/generators/file-generators/mutation-reconcile.js.map +0 -1
  105. package/dist/lib/generators/file-generators/notification-generator.js +0 -6
  106. package/dist/lib/generators/file-generators/notification-generator.js.map +0 -1
  107. package/dist/lib/generators/file-generators/quick-readme.js +0 -21
  108. package/dist/lib/generators/file-generators/quick-readme.js.map +0 -1
  109. package/dist/lib/generators/file-generators/reconcile.js +0 -50
  110. package/dist/lib/generators/file-generators/reconcile.js.map +0 -1
  111. package/dist/lib/generators/file-generators/storage-generator.js +0 -6
  112. package/dist/lib/generators/file-generators/storage-generator.js.map +0 -1
  113. package/dist/lib/generators/file-generators/storage-notify.js +0 -6
  114. package/dist/lib/generators/file-generators/storage-notify.js.map +0 -1
  115. package/dist/lib/generators/file-generators/store.js +0 -86
  116. package/dist/lib/generators/file-generators/store.js.map +0 -1
  117. package/dist/lib/generators/file-generators/sw-push.js +0 -67
  118. package/dist/lib/generators/file-generators/sw-push.js.map +0 -1
  119. package/dist/lib/generators/file-generators/sw-version-gen.js +0 -32
  120. package/dist/lib/generators/file-generators/sw-version-gen.js.map +0 -1
  121. package/dist/lib/generators/sw-sections/glob-matcher-code.js.map +0 -1
  122. package/dist/lib/generators/sw-sections/install-handler.js +0 -54
  123. package/dist/lib/generators/sw-sections/install-handler.js.map +0 -1
  124. package/dist/lib/utils/build-script.js +0 -35
  125. package/dist/lib/utils/build-script.js.map +0 -1
  126. package/dist/lib/utils/tty-status.js +0 -21
  127. package/dist/lib/utils/tty-status.js.map +0 -1
  128. package/dist/runtime/auth-user.js +0 -154
  129. package/dist/runtime/auth-user.js.map +0 -1
  130. package/dist/runtime/connectivity-manager.js +0 -83
  131. package/dist/runtime/connectivity-manager.js.map +0 -1
  132. package/dist/runtime/fetch-state.js +0 -42
  133. package/dist/runtime/fetch-state.js.map +0 -1
  134. package/dist/runtime/notification.js +0 -65
  135. package/dist/runtime/notification.js.map +0 -1
  136. package/dist/runtime/pwa-index.js +0 -11
  137. package/dist/runtime/pwa-index.js.map +0 -1
  138. package/dist/runtime/pwa-injector.js +0 -15
  139. package/dist/runtime/pwa-injector.js.map +0 -1
  140. package/dist/runtime/pwa-install.js +0 -83
  141. package/dist/runtime/pwa-install.js.map +0 -1
  142. package/dist/runtime/sw-version.js +0 -13
  143. package/dist/runtime/sw-version.js.map +0 -1
  144. package/dist/swoff-nkdhhmw8. +0 -18
  145. package/dist/swoff.js +0 -5
  146. package/templates/react/useSWUpdate.jsx +0 -31
  147. package/templates/react/useSWUpdate.tsx +0 -37
@@ -1 +1 @@
1
- {"version":3,"file":"client-injector-bundle.js","sourceRoot":"","sources":["../../src/runtime/client-injector-bundle.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAC9C,GAAmB,EACnB,YAAqB,EACrB,UAAkB,EAClB,UAAmB,EACnB,OAAgB,EAChB,WAAqB,EACrB,oBAA8B;IAE9B,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;+FAegE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnG,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;IAkBtC,CAAC,CAAC,CAAC,EAAE,CAAC;IAER,OAAO;;;;wBAIe,YAAY;;;;;;;;;;;;;;;;;;;;;;oEAsBgC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJ5E,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;EAuBrB,oBAAoB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;QAcjB,CAAC,CAAC,CAAC,EAAE;EACX,WAAW,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;QAuBR,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCZ,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"client-injector-bundle.js","sourceRoot":"","sources":["../../src/runtime/client-injector-bundle.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAC9C,GAAmB,EACnB,YAAqB,EACrB,UAAkB,EAClB,KAAyB,EACzB,UAAmB,EACnB,OAAgB,EAChB,WAAqB,EACrB,oBAA8B,EAC9B,mBAA6B,EAC7B,sBAAgC;IAEhC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;+FAegE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnG,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;IAkBtC,CAAC,CAAC,CAAC,EAAE,CAAC;IAER,OAAO;;;;wBAIe,YAAY;;;;;;;;;;;;;;;;;;;;;;mEAsB+B,KAAK,IAAI,GAAG,GAAG,UAAU,GAAG,KAAK;;;;;;;;;;;;;;;;EAgBlG,mBAAmB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoHpB,CAAC,CAAC,CAAC,EAAE;EACP,sBAAsB,CAAC,CAAC,CAAC;;;;;;;;IAQvB,CAAC,CAAC,CAAC,EAAE;EACP,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;EAuBrB,oBAAoB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;QAcjB,CAAC,CAAC,CAAC,EAAE;EACX,WAAW,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;QAuBR,CAAC,CAAC,CAAC,EAAE;EACX,sBAAsB,CAAC,CAAC,CAAC;;;;;QAKnB,CAAC,CAAC,CAAC,EAAE;;;;;;;EAOX,mBAAmB,CAAC,CAAC,CAAC;;;;;;;;;;MAUlB,CAAC,CAAC,CAAC,EAAE;;;EAGT,mBAAmB,CAAC,CAAC,CAAC;;;;IAIpB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;CASR,CAAC;AACF,CAAC"}
@@ -153,8 +153,6 @@ if (typeof history !== "undefined") {
153
153
  *
154
154
  * Window events (dispatched by this module):
155
155
  * sw-progress - Download progress (detail: { percent, downloaded, total })
156
- * sw-ready - SW active and controlling page
157
- * sw-error - SW registration failed
158
156
  * cache-invalidated - Cache entries cleared on SW confirmation (detail: { tags })
159
157
  * swoff:cache-updated - Background refresh completed (detail: { url })
160
158
  * swoff:offline-fallback - Offline fallback page served (detail: { route, fallbackLevel, timestamp })
@@ -270,6 +268,21 @@ if (typeof window !== "undefined" && "serviceWorker" in navigator) {
270
268
  }${invalidationHandler} });
271
269
  }
272
270
 
271
+ // --- Background Precache Resume ---
272
+ // Tells the SW to resume background precaching when the page becomes visible
273
+ // or the browser comes back online. The SW tracks progress via IndexedDB
274
+ // checkpoint so it safely picks up where it left off.
275
+ if (typeof document !== "undefined" && "serviceWorker" in navigator) {
276
+ var _resumeP = function() {
277
+ if (navigator.serviceWorker.controller)
278
+ navigator.serviceWorker.controller.postMessage({ type: "RESUME_PRECACHE" });
279
+ };
280
+ document.addEventListener("visibilitychange", function() {
281
+ if (document.visibilityState === "visible") _resumeP();
282
+ });
283
+ window.addEventListener("online", _resumeP);
284
+ }
285
+
273
286
  /** Initialize SW registration and all client-side features (PWA install, mutation queue, cross-tab sync). Call once at app startup. */
274
287
  export async function initServiceWorker()${ts ? ": Promise<void>" : " "}{
275
288
  await swInit();${storageInit}
@@ -1 +1 @@
1
- {"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../src/runtime/client-injector.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CACxC,GAAmB,EACnB,UAAmB,EACnB,oBAA6B,EAC7B,iBAA0B,EAC1B,OAAgB,EAChB,WAAqB,EACrB,mBAA6B,EAC7B,sBAAgC;IAEhC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,IAAI,sBAAsB,CAAC;IAE3D,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,iDAAiD,GAAG;CACzD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,OAAO,GAAG,UAAU;QACxB,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,iBAAiB;QAClC,CAAC,CAAC,yDAAyD,GAAG;CACjE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,iBAAiB;QAChC,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,oBAAoB;QACzC,CAAC,CAAC,sEAAsE,GAAG;CAC9E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC,kEAAkE,GAAG;CAC1E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,mBAAmB;QACvC,CAAC,CAAC,8DAA8D,GAAG;CACtE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,kBAAkB,GAAG,mBAAmB;QAC5C,CAAC,CAAC;;;;;yBAKmB,GAAG;CAC3B;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,mBAAmB;QACxC,CAAC,CAAC;;;;;;;;QAQE,oBAAoB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyB3D;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,sBAAsB;QAC1C,CAAC,CAAC;;;;;;;;;;;CAWL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,mBAAmB,GAAG,sBAAsB;QAChD,CAAC,CAAC;;;;;;;;CAQL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,8DAA8D,GAAG;CACnF,CAAC;IAEA,MAAM,kBAAkB,GAAG,MAAM;QAC/B,CAAC,CAAC,+CAA+C,GAAG;CACvD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,gBAAgB,GAAG,MAAM;QAC7B,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;CAoBL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,WAAW,GAAG,mBAAmB;QACrC,CAAC,CAAC;;;;;;;;;;;;;CAaL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;kEAMyD,GAAG;;;;;;;;;;;;;;;;;;;;;EAqBnE,SAAS,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,GAAG,UAAU,GAAG,kBAAkB;EACzH,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,aAAa,GAAG,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiGjE,mBAAmB;;;;2CAIiB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;mBACpD,WAAW;;CAE7B,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../src/runtime/client-injector.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CACxC,GAAmB,EACnB,UAAmB,EACnB,oBAA6B,EAC7B,iBAA0B,EAC1B,OAAgB,EAChB,WAAqB,EACrB,mBAA6B,EAC7B,sBAAgC;IAEhC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,IAAI,sBAAsB,CAAC;IAE3D,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,iDAAiD,GAAG;CACzD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,OAAO,GAAG,UAAU;QACxB,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,iBAAiB;QAClC,CAAC,CAAC,yDAAyD,GAAG;CACjE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,iBAAiB;QAChC,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,oBAAoB;QACzC,CAAC,CAAC,sEAAsE,GAAG;CAC9E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC,kEAAkE,GAAG;CAC1E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,mBAAmB;QACvC,CAAC,CAAC,8DAA8D,GAAG;CACtE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,kBAAkB,GAAG,mBAAmB;QAC5C,CAAC,CAAC;;;;;yBAKmB,GAAG;CAC3B;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,mBAAmB;QACxC,CAAC,CAAC;;;;;;;;QAQE,oBAAoB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyB3D;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,sBAAsB;QAC1C,CAAC,CAAC;;;;;;;;;;;CAWL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,mBAAmB,GAAG,sBAAsB;QAChD,CAAC,CAAC;;;;;;;;CAQL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,8DAA8D,GAAG;CACnF,CAAC;IAEA,MAAM,kBAAkB,GAAG,MAAM;QAC/B,CAAC,CAAC,+CAA+C,GAAG;CACvD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,gBAAgB,GAAG,MAAM;QAC7B,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;CAoBL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,WAAW,GAAG,mBAAmB;QACrC,CAAC,CAAC;;;;;;;;;;;;;CAaL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;kEAMyD,GAAG;;;;;;;;;;;;;;;;;;;EAmBnE,SAAS,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,GAAG,UAAU,GAAG,kBAAkB;EACzH,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,aAAa,GAAG,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiGjE,mBAAmB;;;;;;;;;;;;;;;;;;;2CAmBiB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;mBACpD,WAAW;;CAE7B,CAAC;AACF,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { R } from "./utils.js";
2
2
  export function generateSwInjectorCode(ctx) {
3
- const { ext, ts, autoActivate, swFilename } = ctx;
3
+ const { ext, ts, autoActivate, swFilename, swUrl } = ctx;
4
4
  return `/**
5
5
  * Swoff SW Injector
6
- * Registers the service worker and tracks installation progress.
6
+ * Registers the service worker.
7
7
  *
8
8
  * Usage:
9
9
  * import { initServiceWorker } from './swoff/sw/injector.${ext}';
@@ -11,8 +11,6 @@ export function generateSwInjectorCode(ctx) {
11
11
  *
12
12
  * Window events:
13
13
  * sw-progress - Download progress (detail: { percent, downloaded, total })
14
- * sw-ready - SW active and controlling page
15
- * sw-error - SW registration failed
16
14
  */
17
15
  const AUTO_ACTIVATE = ${autoActivate};
18
16
 
@@ -38,30 +36,19 @@ export async function initServiceWorker()${R(ts, "Promise<void>")}{
38
36
  }
39
37
 
40
38
  try {
41
- const registration = await navigator.serviceWorker.register("/${swFilename}.js");
39
+ const registration = await navigator.serviceWorker.register("${swUrl || '/' + swFilename + '.js'}");
42
40
 
43
- var swReadyDispatched = false;
44
41
  if (registration.installing) {
45
- const installingWorker = registration.installing;
46
- installingWorker.addEventListener("statechange", () => {
47
- if (installingWorker.state === "installed") {
48
- if (AUTO_ACTIVATE) {
49
- registration.waiting?.postMessage({ type: "SKIP_WAITING" });
50
- }
51
- swReadyDispatched = true;
52
- window.dispatchEvent(new CustomEvent("sw-ready"));
42
+ registration.installing.addEventListener("statechange", () => {
43
+ if (registration.installing?.state === "installed" && AUTO_ACTIVATE) {
44
+ registration.waiting?.postMessage({ type: "SKIP_WAITING" });
53
45
  }
54
46
  });
55
47
  }
56
48
 
57
49
  await waitForController();
58
- if (!swReadyDispatched) {
59
- window.dispatchEvent(new CustomEvent("sw-ready"));
60
- }
61
50
  } catch (error) {
62
51
  console.error("Service Worker registration failed:", error);
63
- window.swError = true;
64
- window.dispatchEvent(new CustomEvent("sw-error"));
65
52
  }
66
53
  }
67
54
 
@@ -1 +1 @@
1
- {"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../src/runtime/sw-injector.ts"],"names":[],"mappings":"AACA,OAAO,EAAK,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,sBAAsB,CACpC,GAAmE;IAEnE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAElD,OAAO;;;;;8DAKqD,GAAG;;;;;;;;wBAQzC,YAAY;;oCAEA,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;;2CAef,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;oEAOG,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA4BzC,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;CAM1D,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../src/runtime/sw-injector.ts"],"names":[],"mappings":"AACA,OAAO,EAAK,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,sBAAsB,CACpC,GAAmF;IAEnF,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAEzD,OAAO;;;;;8DAKqD,GAAG;;;;;;wBAMzC,YAAY;;oCAEA,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;;2CAef,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;mEAOE,KAAK,IAAI,GAAG,GAAG,UAAU,GAAG,KAAK;;;;;;;;;;;;;;;;;qCAiB/D,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;CAM1D,CAAC;AACF,CAAC"}
@@ -39,9 +39,6 @@ declare global {
39
39
  interface WindowEventMap {
40
40
  beforeinstallprompt: BeforeInstallPromptEvent;
41
41
  "sw-progress": CustomEvent<{ percent: number; downloaded: number; total: number }>;
42
- "sw-ready": CustomEvent;
43
- "sw-error": CustomEvent;
44
- "sw-version-detected": CustomEvent;
45
42
  "sw-auth-state-change": CustomEvent;
46
43
  "mutation-sync-complete": CustomEvent<{ succeeded: number; failed: number }>;
47
44
  "mutation-queue-changed": CustomEvent;
@@ -67,8 +64,6 @@ declare global {
67
64
  pwaInstallable?: boolean;
68
65
  latestSWVersion?: string;
69
66
  currentSWVersion?: string;
70
- swReady?: boolean;
71
- swError?: boolean;
72
67
  swAuthState?: "authenticated" | "unauthenticated" | "loading";
73
68
  SyncManager?: { new(): SyncManager };
74
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"type-definitions.js","sourceRoot":"","sources":["../../src/runtime/type-definitions.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,2BAA2B;IACzC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuIR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"type-definitions.js","sourceRoot":"","sources":["../../src/runtime/type-definitions.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,2BAA2B;IACzC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkIR,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@swoff/cli",
3
- "version": "0.3.14",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
- "description": "CLI for Swoff - Offline-first web apps made easy",
5
+ "description": "CLI for Swoff - Offline Infrastructure Platform",
6
6
  "bin": {
7
7
  "swoff": "bin/swoff"
8
8
  },
@@ -27,9 +27,15 @@
27
27
  "pwa",
28
28
  "caching"
29
29
  ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "sideEffects": false,
30
34
  "author": "Swoff",
31
35
  "license": "MIT",
32
- "dependencies": {},
36
+ "dependencies": {
37
+ "@clack/prompts": "^1.6.0"
38
+ },
33
39
  "devDependencies": {
34
40
  "@types/node": "^25.9.1",
35
41
  "typescript": "^5.0.0",
@@ -0,0 +1,20 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ export function usePrecacheProgress() {
4
+ const [state, setState] = useState(() => ({
5
+ status: "idle",
6
+ progress: 0,
7
+ }));
8
+
9
+ useEffect(() => {
10
+ const onProgress = (e) =>
11
+ setState({ status: "installing", progress: e.detail.percent });
12
+
13
+ window.addEventListener("sw-progress", onProgress);
14
+ return () => {
15
+ window.removeEventListener("sw-progress", onProgress);
16
+ };
17
+ }, []);
18
+
19
+ return state;
20
+ }
@@ -0,0 +1,20 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ export function usePrecacheProgress() {
4
+ const [state, setState] = useState(() => ({
5
+ status: "idle" as "idle" | "installing",
6
+ progress: 0,
7
+ }));
8
+
9
+ useEffect(() => {
10
+ const onProgress = (e: WindowEventMap["sw-progress"]) =>
11
+ setState({ status: "installing", progress: e.detail.percent });
12
+
13
+ window.addEventListener("sw-progress", onProgress);
14
+ return () => {
15
+ window.removeEventListener("sw-progress", onProgress);
16
+ };
17
+ }, []);
18
+
19
+ return state;
20
+ }
@@ -1,62 +0,0 @@
1
- /**
2
- * add command - enables one or more feature flags and regenerates.
3
- * Supports comma-separated features: swoff add auth,graphql,pwa
4
- */
5
- import { writeFileSync } from "fs";
6
- import { join } from "path";
7
- import { log } from "../cli/logger.js";
8
- import { loadConfigAsync } from "../config/loader.js";
9
- import { deepMerge } from "../shared/config-types.js";
10
- import { FEATURES, resolveDependencies, getAuthConflicts, buildConfigUpdate } from "../shared/feature-registry.js";
11
- import { generateCommand } from "./generate.js";
12
- const FEATURE_ALIASES = {
13
- mutationqueue: "mutation-queue",
14
- backgroundsync: "background-sync",
15
- pushnotification: "push-notification",
16
- };
17
- const FEATURE_NAMES = Object.keys(FEATURES);
18
- function normalizeFeature(name) {
19
- const lower = name.toLowerCase().trim();
20
- return FEATURE_ALIASES[lower] ?? lower;
21
- }
22
- export async function addCommand(projectRoot, featureArg) {
23
- const rawFeatures = featureArg.split(",").map(normalizeFeature).filter(Boolean);
24
- const coreFeatures = rawFeatures;
25
- const invalid = coreFeatures.filter((f) => !FEATURES[f]);
26
- if (invalid.length > 0) {
27
- log.error(`Unknown feature(s): ${invalid.join(", ")}`);
28
- log.info(`Available: ${FEATURE_NAMES.join(", ")}`);
29
- return;
30
- }
31
- const label = rawFeatures.length === 1 ? rawFeatures[0] : `${rawFeatures.length} features`;
32
- log.header(`Adding ${label}`);
33
- const loadResult = await loadConfigAsync(projectRoot);
34
- const configPath = loadResult.configPath;
35
- const existingConfig = loadResult.config;
36
- const deps = resolveDependencies(coreFeatures);
37
- const authConflicts = getAuthConflicts(deps, existingConfig);
38
- if (authConflicts.length > 0) {
39
- log.error(`Cannot add ${authConflicts.join(", ")} with auth type "${existingConfig.features.auth.type}" — these features require cookie auth`);
40
- log.info("Change auth type to \"cookie\" in swoff.config.json and try again, or run: swoff add auth");
41
- return;
42
- }
43
- const combinedUpdate = buildConfigUpdate(coreFeatures);
44
- let mergedConfig = deepMerge(existingConfig, { features: combinedUpdate });
45
- const isJsConfig = configPath ? configPath.endsWith(".js") : false;
46
- const resolvedConfigPath = (!configPath || isJsConfig)
47
- ? join(projectRoot, "swoff.config.json")
48
- : configPath;
49
- if (!configPath) {
50
- log.warn("No config found. Creating new config with features...");
51
- }
52
- else if (isJsConfig) {
53
- log.warn("JS config detected. Converting to swoff.config.json for simplicity.");
54
- }
55
- writeFileSync(resolvedConfigPath, JSON.stringify(mergedConfig, null, 2));
56
- log.success(`${!configPath ? "Created" : "Updated"} swoff.config.json with ${label}`);
57
- if (coreFeatures.length > 0) {
58
- await generateCommand(projectRoot);
59
- }
60
- log.success(`${label} added successfully!`);
61
- }
62
- //# sourceMappingURL=add.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/lib/commands/add.ts"],"names":[],"mappings":"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"}
@@ -1,45 +0,0 @@
1
- import { join } from "path";
2
- import { log } from "../cli/logger.js";
3
- import { loadConfigAsync } from "../config/loader.js";
4
- export async function generateAssetsCommand(projectRoot, opts = {}) {
5
- let assetsPkg;
6
- try {
7
- assetsPkg = await import("@swoff/assets");
8
- }
9
- catch {
10
- log.error("@swoff/assets is required to generate PWA assets.");
11
- log.help("Install it with: npm install -D @swoff/assets");
12
- process.exit(1);
13
- }
14
- log.header("Generating PWA Assets");
15
- const { config } = await loadConfigAsync(projectRoot);
16
- const assets = config.features.pwa.assets;
17
- const sourceArg = opts.source || (assets.source ? join(projectRoot, assets.source) : "");
18
- if (!sourceArg) {
19
- log.error("No source specified. Use --source <path> or configure pwa.assets.source in swoff.config.json");
20
- log.help("Usage: swoff assets --source ./logo.svg");
21
- process.exit(1);
22
- }
23
- const outputDir = opts.outputDir || assets.outputDir;
24
- const result = await assetsPkg.generateAssets({
25
- source: sourceArg,
26
- outputDir: join(projectRoot, outputDir),
27
- appName: config.framework || "App",
28
- themeColor: assets.themeColor,
29
- bgColor: assets.bgColor,
30
- appleSplash: !opts.noSplash,
31
- });
32
- log.success(`Generated ${result.files.length} PWA assets`);
33
- if (result.warnings.length > 0) {
34
- for (const w of result.warnings)
35
- log.warn(w);
36
- }
37
- assetsPkg.printAssetGuide({
38
- appName: config.framework || "App",
39
- themeColor: assets.themeColor,
40
- bgColor: assets.bgColor,
41
- outputDir,
42
- hasSplash: !opts.noSplash,
43
- });
44
- }
45
- //# sourceMappingURL=assets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../src/lib/commands/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAQtD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB,EAAE,OAAsB,EAAE;IACvF,IAAI,SAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC/D,GAAG,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAEpC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;IAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEzF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,8FAA8F,CAAC,CAAC;QAC1G,GAAG,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;IAErD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC;QAC5C,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ;KAC5B,CAAC,CAAC;IAEH,GAAG,CAAC,OAAO,CAAC,aAAa,MAAM,CAAC,KAAK,CAAC,MAAM,aAAa,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,SAAS,CAAC,eAAe,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS;QACT,SAAS,EAAE,CAAC,IAAI,CAAC,QAAQ;KAC1B,CAAC,CAAC;AACL,CAAC"}
@@ -1,44 +0,0 @@
1
- import { join } from "path";
2
- import { log } from "../cli/logger.js";
3
- import { loadConfigAsync } from "../config/loader.js";
4
- import { generateAssets } from "../generators/asset-generator/generate.js";
5
- import { printAssetGuide } from "../generators/asset-generator/guide.js";
6
- export async function generateAssetsCommand(projectRoot, args) {
7
- log.header("Generating PWA Assets");
8
- const { config } = await loadConfigAsync(projectRoot);
9
- const assets = config.features.pwa.assets;
10
- const sourceArg = (() => {
11
- const idx = args.indexOf("--source");
12
- if (idx !== -1 && idx + 1 < args.length)
13
- return args[idx + 1];
14
- if (assets.source)
15
- return join(projectRoot, assets.source);
16
- return "";
17
- })();
18
- if (!sourceArg) {
19
- log.error("No source specified. Use --source <path> or configure pwa.assets.source in swoff.config.json");
20
- log.help("Usage: swoff generate-assets --source ./logo.svg");
21
- process.exit(1);
22
- }
23
- const result = await generateAssets({
24
- source: sourceArg,
25
- outputDir: join(projectRoot, assets.outputDir),
26
- appName: config.framework || "App",
27
- themeColor: assets.themeColor,
28
- bgColor: assets.bgColor,
29
- appleSplash: !args.includes("--no-splash"),
30
- });
31
- log.success(`Generated ${result.files.length} PWA assets`);
32
- if (result.warnings.length > 0) {
33
- for (const w of result.warnings)
34
- log.warn(w);
35
- }
36
- printAssetGuide({
37
- appName: config.framework || "App",
38
- themeColor: assets.themeColor,
39
- bgColor: assets.bgColor,
40
- outputDir: assets.outputDir,
41
- hasSplash: !args.includes("--no-splash"),
42
- });
43
- }
44
- //# sourceMappingURL=generate-assets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-assets.js","sourceRoot":"","sources":["../../../src/lib/commands/generate-assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB,EAAE,IAAc;IAC7E,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAEpC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;IAE1C,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3D,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,EAAE,CAAC;IAEL,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,8FAA8F,CAAC,CAAC;QAC1G,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC;QAC9C,OAAO,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;KAC3C,CAAC,CAAC;IAEH,GAAG,CAAC,OAAO,CAAC,aAAa,MAAM,CAAC,KAAK,CAAC,MAAM,aAAa,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,eAAe,CAAC;QACd,OAAO,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;KACzC,CAAC,CAAC;AACL,CAAC"}
@@ -1,183 +0,0 @@
1
- import { readFileSync, existsSync, readdirSync } from "fs";
2
- import { join, dirname } from "path";
3
- import { fileURLToPath } from "url";
4
- import { log } from "../cli/logger.js";
5
- import { loadConfigAsync } from "../config/loader.js";
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const FEATURES = {
8
- "mutation-queue": {
9
- label: "Mutation Queue",
10
- description: "Queues offline write operations in IndexedDB and replays them when the connection returns. Supports configurable batch size, rate limiting between mutations, and exponential backoff on retry. Uses the Background Sync API or the online event listener.",
11
- files: ["mutation-queue.ts", "mutation-state.ts"],
12
- functions: [
13
- "queueMutation(mutation) — store a write for later sync",
14
- "processMutationQueue() — replay all queued writes (respects batchSize, batchDelayMs, maxRetries, retryBackoffMs)",
15
- "flushMutations() — same as processMutationQueue, call after re-login",
16
- "getPendingCount() — number of mutations waiting to sync",
17
- "trackMutation(id, status) / getMutationState(id) / clearMutationState(id) — per-mutation state tracking",
18
- ],
19
- },
20
- "background-sync": {
21
- label: "Background Sync",
22
- description: "Registers Background Sync API events so mutations are processed even after the tab is closed. Falls back to online event listener in unsupported browsers (Firefox, Safari).",
23
- files: ["background-sync.ts"],
24
- functions: [
25
- "syncWhenPossible(mutation) — queue and register background sync",
26
- "retrySync() — re-register sync if mutations are still pending",
27
- ],
28
- },
29
- auth: {
30
- label: "Auth",
31
- description: "Token-based authentication with memory-only tokens, IndexedDB user caching, and auth-aware fetch with automatic 401 handling.",
32
- files: ["auth/store.ts", "auth/user.ts", "auth/state.ts"],
33
- functions: [
34
- "setAuth(authData) / getAuth() / clearAuth() — manage auth state",
35
- "isAuthValid(auth) — check expiry",
36
- "createAuthFromResponse(response) — extract AuthData from login response (edit this)",
37
- "fetchWithCache(input, { auth: true }) — auth-aware fetch (handles bearer, cookie, custom)",
38
- "ensureValidAuth() — check expiry and refresh token",
39
- "fetchCurrentUser() / getCachedUser() / cacheUser(user) / clearCachedUser() — user caching",
40
- "getAuthState() — detect 4-state matrix (online/offline × authenticated/not)",
41
- ],
42
- },
43
- "tag-invalidation": {
44
- label: "Tag Invalidation",
45
- description: "Generates cache tags from URLs and invalidates stale cache entries after mutations. Keeps cached data fresh.",
46
- files: ["invalidation-tags.ts", "cache.ts"],
47
- functions: [
48
- "generateTags(url) — extract tags from URL (e.g. /api/todos/42 → ['todos', 'todo:42'])",
49
- "generateTagsFromMethod(method, url) — method-prefixed tags",
50
- "invalidateUrl(url) — invalidate all cache entries matching a URL's tags",
51
- "invalidateByTag(tag) / invalidateByTags(tags) — low-level invalidation",
52
- ],
53
- },
54
- "cross-tab": {
55
- label: "Cross-tab Sync",
56
- description: "Broadcasts cache invalidation and auth state changes across all open tabs via the service worker.",
57
- files: ["client-injector.ts (internal handling)"],
58
- functions: ["No separate imports needed — handled automatically by client-injector.ts"],
59
- },
60
- graphql: {
61
- label: "GraphQL",
62
- description: "A fetchWithGql wrapper that brings Swoff's caching, offline queue, and tag-based invalidation to GraphQL APIs. Hashes query + variables for deterministic cache keys, auto-detects queries vs mutations, and generates tags from operation names.",
63
- files: ["gql-wrapper.ts"],
64
- functions: [
65
- "fetchWithGql<T>(query, options?) — unified GQL fetch with caching, auth, offline queue, auto-invalidation",
66
- "queryGql<T>(query, variables?, options?) — shorthand for GQL queries (type: 'read')",
67
- "mutateGql<T>(mutation, variables?, options?) — shorthand for GQL mutations (type: 'mutation')",
68
- ],
69
- },
70
- "push-notification": {
71
- label: "Push Notifications",
72
- description: "Push notification subscription management with IndexedDB persistence, VAPID key support, and service worker push/notificationclick event handlers.",
73
- files: ["push.ts"],
74
- functions: [
75
- "subscribeToPush() — request permission and subscribe (uses VAPID key from config)",
76
- "unsubscribeFromPush() — unsubscribe and clear stored subscription",
77
- "isSubscribed() — check subscription status",
78
- "getPushSubscription() — get current PushSubscription object",
79
- "requestNotificationPermission() — request permission only",
80
- ],
81
- },
82
- "server-push": {
83
- label: "Server Push Events",
84
- description: "Real-time cache invalidation via SSE or WebSocket. The service worker connects to a push endpoint and invalidates cache tags when the server signals data changes — no polling needed.",
85
- files: ["server-push.ts"],
86
- functions: [
87
- "startPushEvents() — connect to push endpoint and listen for invalidate events",
88
- "stopPushEvents() — disconnect from push endpoint",
89
- "isPushConnected() — check connection status",
90
- ],
91
- },
92
- pwa: {
93
- label: "PWA",
94
- description: "Install prompt handling, manifest generation, and React hooks for update management.",
95
- files: ["pwa/install.ts", "manifest.json"],
96
- functions: [
97
- "setupPwaInstall() — listen for beforeinstallprompt/appinstalled events",
98
- "isInstallable() — check if install prompt is available",
99
- "promptInstall() — show native install prompt",
100
- ],
101
- },
102
- };
103
- function countFilesRecursive(dir) {
104
- let count = 0;
105
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
106
- const full = join(dir, entry.name);
107
- if (entry.isDirectory()) {
108
- count += countFilesRecursive(full);
109
- }
110
- else {
111
- count++;
112
- }
113
- }
114
- return count;
115
- }
116
- function showFeatureDetail(feature) {
117
- const key = feature.toLowerCase().replace(/[_-]/g, "-").replace(/^-+|-+$/g, "");
118
- const info = FEATURES[key];
119
- if (!info) {
120
- log.error(`Unknown feature: ${feature}`);
121
- log.info("Available: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification, server-push, pwa");
122
- return;
123
- }
124
- log.header(info.label);
125
- log.normal(info.description);
126
- log.normal("\nGenerated files:");
127
- info.files.forEach((f) => log.help(` swoff/${f}`));
128
- log.normal("\nFunctions:");
129
- info.functions.forEach((f) => log.help(` ${f}`));
130
- log.help("\n Read swoff/GUIDE.md for documentation links.");
131
- }
132
- export async function infoCommand(projectRoot, feature) {
133
- if (feature) {
134
- return showFeatureDetail(feature);
135
- }
136
- const { config, configPath } = await loadConfigAsync(projectRoot);
137
- if (!configPath) {
138
- log.warn('No swoff.config.json found. Run "swoff init" first.');
139
- return;
140
- }
141
- log.header("Swoff");
142
- try {
143
- const pkgDir = join(__dirname, "..", "..", "..");
144
- const pkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf8"));
145
- log.normal(`Version: ${pkg.version}`);
146
- }
147
- catch {
148
- // version not available
149
- }
150
- const enabled = [];
151
- if (config.features.mutationQueue.enabled)
152
- enabled.push("mutation-queue");
153
- if (config.features.backgroundSync)
154
- enabled.push("background-sync");
155
- if (config.features.auth.enabled)
156
- enabled.push("auth");
157
- if (config.features.crossTabSync)
158
- enabled.push("cross-tab");
159
- if (config.features.graphql.enabled)
160
- enabled.push("graphql");
161
- if (config.features.pushNotifications?.enabled)
162
- enabled.push("push-notification");
163
- if (config.features.serverPush.enabled)
164
- enabled.push("server-push");
165
- if (config.features.pwa.enabled)
166
- enabled.push("pwa");
167
- enabled.push("tag-invalidation");
168
- if (enabled.length > 0) {
169
- log.normal(`\nEnabled features: ${enabled.join(", ")}`);
170
- }
171
- else {
172
- log.normal("\nEnabled features: (none)");
173
- }
174
- const swoffDir = join(projectRoot, "swoff");
175
- if (existsSync(swoffDir)) {
176
- const count = countFilesRecursive(swoffDir);
177
- log.normal(`Generated files: ${count} in swoff/`);
178
- }
179
- log.help("\n swoff info <feature> — detailed info for a feature");
180
- log.help(" Features: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification, server-push, pwa");
181
- log.help(" Read swoff/GUIDE.md for documentation links");
182
- }
183
- //# sourceMappingURL=info.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/lib/commands/info.ts"],"names":[],"mappings":"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"}