@antelopejs/dms 0.5.4 → 0.5.6

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.5.6
4
+
5
+ [compare changes](https://github.com/AntelopeJS/dms/compare/v0.5.5...v0.5.6)
6
+
7
+ ### 🩹 Fixes
8
+
9
+ - **tab:** Space the blocks of a tab like the page spaces its own ([#98](https://github.com/AntelopeJS/dms/pull/98))
10
+ - **dev-reload:** End the reload streams when the module stops ([#125](https://github.com/AntelopeJS/dms/pull/125))
11
+
12
+ ### ❤️ Contributors
13
+
14
+ - Antony Rizzitelli <rizzitelli.antony@pm.me>
15
+ - Glastis ([@Glastis](http://github.com/Glastis))
16
+
17
+ ## v0.5.5
18
+
19
+ [compare changes](https://github.com/AntelopeJS/dms/compare/v0.5.4...v0.5.5)
20
+
21
+ ### 🩹 Fixes
22
+
23
+ - **layout:** Hold the in-flight modules listing fetch on the DMS app ([#121](https://github.com/AntelopeJS/dms/pull/121))
24
+
25
+ ### ❤️ Contributors
26
+
27
+ - Alessandro Aloisio
28
+
3
29
  ## v0.5.4
4
30
 
5
31
  [compare changes](https://github.com/AntelopeJS/dms/compare/v0.5.3...v0.5.4)
@@ -3,6 +3,7 @@ type SlugProvider = () => string[];
3
3
  export declare function setSlugProvider(provider: SlugProvider): void;
4
4
  export declare function scheduleBroadcast(): void;
5
5
  export declare function cancelScheduledBroadcast(): void;
6
+ export declare function closeDevReloadStreams(): void;
6
7
  declare const DevReloadController_base: import("@antelopejs/interface-api").ControllerClass<object>;
7
8
  export declare class DevReloadController extends DevReloadController_base {
8
9
  reload(out: PassThrough): void;
@@ -16,6 +16,7 @@ exports.DevReloadController = void 0;
16
16
  exports.setSlugProvider = setSlugProvider;
17
17
  exports.scheduleBroadcast = scheduleBroadcast;
18
18
  exports.cancelScheduledBroadcast = cancelScheduledBroadcast;
19
+ exports.closeDevReloadStreams = closeDevReloadStreams;
19
20
  const interface_api_1 = require("@antelopejs/interface-api");
20
21
  const BROADCAST_DEBOUNCE_MS = 250;
21
22
  const SSE_CONTENT_TYPE = "text/event-stream";
@@ -62,6 +63,14 @@ function cancelScheduledBroadcast() {
62
63
  clearTimeout(broadcastTimer);
63
64
  broadcastTimer = null;
64
65
  }
66
+ function closeDevReloadStreams() {
67
+ cancelScheduledBroadcast();
68
+ const streams = [...clients];
69
+ clients.clear();
70
+ for (const stream of streams) {
71
+ stream.end();
72
+ }
73
+ }
65
74
  function registerClient(stream) {
66
75
  clients.add(stream);
67
76
  writeToClient(stream, SSE_HELLO_PAYLOAD);
@@ -1 +1 @@
1
- {"version":3,"file":"dev-reload.js","sourceRoot":"","sources":["../../../src/implementations/dms/dev-reload.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAiBA,0CAEC;AAyCD,8CAIC;AAGD,4DAIC;AAtED,6DAAyE;AAEzE,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAC7C,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,iBAAiB,GAAG,UAAU,qBAAqB,mBAAmB,CAAC;AAC7E,MAAM,cAAc,GAAG,YAAY,CAAC;AAIpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;AACvC,IAAI,cAAc,GAA0B,IAAI,CAAC;AACjD,IAAI,YAAY,GAAiB,GAAG,EAAE,CAAC,EAAE,CAAC;AAE1C,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,cAAc,CAAC;AAEnE,SAAgB,eAAe,CAAC,QAAsB;IACpD,YAAY,GAAG,QAAQ,CAAC;AAC1B,CAAC;AAYD,SAAS,gBAAgB,CAAC,IAAwB;IAChD,OAAO,iCAAiC,IAAI,QAAQ,CAAC;AACvD,CAAC;AAED,SAAS,aAAa,CAAC,MAAmB,EAAE,OAAe;IACzD,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,YAAY;IACnB,cAAc,GAAG,IAAI,CAAC;IACtB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO;IAO/B,MAAM,OAAO,GAAG,gBAAgB,CAC9B,YAAY,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CACjD,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB;IAC/B,IAAI,YAAY,EAAE;QAAE,OAAO;IAC3B,IAAI,cAAc;QAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IACjD,cAAc,GAAG,UAAU,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;AACnE,CAAC;AAGD,SAAgB,wBAAwB;IACtC,IAAI,CAAC,cAAc;QAAE,OAAO;IAC5B,YAAY,CAAC,cAAc,CAAC,CAAC;IAC7B,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC;AAED,SAAS,cAAc,CAAC,MAAmB;IACzC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,aAAa,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,YAAY,CAAC,MAAmB;IACvC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,MAAa,mBAAoB,SAAQ,IAAA,0BAAU,EAAC,UAAU,CAAC;IAE7D,MAAM,CAAgC,GAAgB;QACpD,IAAI,YAAY,EAAE,EAAE,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC;CACF;AAXD,kDAWC;AATC;IADC,IAAA,mBAAG,GAAE;IACE,WAAA,IAAA,2BAAW,EAAC,gBAAgB,CAAC,CAAA;;;;iDAQpC"}
1
+ {"version":3,"file":"dev-reload.js","sourceRoot":"","sources":["../../../src/implementations/dms/dev-reload.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -167,6 +167,7 @@ function cancelDeferredNotifications() {
167
167
  }
168
168
  function destroy() {
169
169
  cancelDeferredNotifications();
170
+ (0, dev_reload_1.closeDevReloadStreams)();
170
171
  }
171
172
  async function start() {
172
173
  await (0, realtime_1.configureRealtime)(globalRealtimeConfig);
@@ -196,6 +197,7 @@ async function stop() {
196
197
  cronTasks = [];
197
198
  await (0, realtime_1.stopRealtime)();
198
199
  cancelDeferredNotifications();
200
+ (0, dev_reload_1.closeDevReloadStreams)();
199
201
  }
200
202
  }
201
203
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,8BAgBC;AA4JD,0BAEC;AAED,sBAUC;AAED,oBAmBC;AApRD,0DAA6B;AAC7B,+DAAgE;AAChE,gEAA6D;AAC7D,gEAAoE;AACpE,6FAA2E;AAC3E,mEAG6C;AAC7C,gBAAc;AAId,sBAAoB;AACpB,mBAAiB;AACjB,oBAAkB;AAClB,2DAKyC;AACzC,yDAAmE;AAEnE,6CAGsB;AACtB,qCAOkB;AAClB,mCAA2C;AAC3C,qEAAmE;AACnE,mFAG2C;AAC3C,iEAA2E;AAC3E,2DAAsE;AACtE,iEAA4E;AAC5E,uEAAoF;AACpF,iFAAuF;AACvF,qDAA4E;AAC5E,yCAIoB;AACpB,qEAI0C;AAC1C,uDAAuE;AACvE,qDAAmE;AACnE,mCAAoD;AACpD,+DAA+E;AAE/E,2CAAyB;AAEzB,IAAI,SAAS,GAAoB,EAAE,CAAC;AAEpC,IAAI,oBAAgD,CAAC;AAE9C,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,IAAA,oBAAW,EAAC,MAAM,CAAC,CAAC;IACpB,oBAAoB,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEvC,MAAM,sBAAsB,EAAE,CAAC;IAE/B,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,IAAA,iCAAyB,GAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,IAAA,6CAA4B,GAAE,CAAC;IAC/B,IAAA,kDAA8B,GAAE,CAAC;IAEjC,MAAM,mBAAmB,EAAE,CAAC;IAC5B,MAAM,mBAAmB,EAAE,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,sBAAsB;IACnC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,IAAA,wBAAc,GAAE,CAAC;IACvC,IAAA,gDAA2B,EAAC,GAAG,CAAC,CAAC;IAEjC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAA,6CAA6B,GAAE,CAAC;QACtC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAA,0BAAiB,GAAE,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QACjD,iBAAO,CAAC,IAAI,CACV,uGAAuG;YACrG,gGAAgG;YAChG,iGAAiG;YACjG,sDAAsD,CACzD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gCAAgC,GAAC,EAC9C,wDAAa,4BAA4B,GAAC,CAC3C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,0CAA0C,GAAC,EACxD,wDAAa,sCAAsC,GAAC,CACrD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,6CAA6C,GAAC,EAC3D,wDAAa,yCAAyC,GAAC,CACxD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gDAAgD,GAAC,EAC9D,wDAAa,4CAA4C,GAAC,CAC3D,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,iCAAiC,GAAC,CAChD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,oCAAoC,GAAC,EAClD,wDAAa,gCAAgC,GAAC,CAC/C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,mCAAmC,GAAC,EACjD,wDAAa,+BAA+B,GAAC,CAC9C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,kCAAkC,GAAC,EAChD,wDAAa,8BAA8B,GAAC,CAC7C,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,uCAAuC,GAAC,CACtD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,4CAA4C,GAAC,EAC1D,wDAAa,wCAAwC,GAAC,CACvD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,sDAAsD,GAAC,EACpE,wDAAa,kDAAkD,GAAC,CACjE,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,uCAAuC,GAAC,CACtD,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gCAAgC,GAAC,EAC9C,wDAAa,4BAA4B,GAAC,CAC3C,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAA,sBAAa,GAAE,CAAC;IACnC,MAAM,aAAa,GAAG;QACpB,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE;YAChC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;YACzC,iBAAiB,EAAE,KAAK;YACxB,KAAK,EAAE;gBACL,eAAe,EACb,UAAU,CAAC,mBAAmB,GAAG,8BAAuB;aAC3D;YACD,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,GAAG;YAChC,cAAc,EAAE,IAAA,kCAAyB,GAAE,CAAC,GAAG,CAC7C,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBACxB,EAAE;gBACF,KAAK;gBACL,IAAI;aACL,CAAC,CACH;SACF;QACD,cAAc,EAAE;YACd,UAAU,EAAE;gBACV,aAAa,EAAE,IAAA,4BAAmB,GAAE,CAAC,aAAa,IAAI,IAAI;aAC3D;YACD,KAAK,EAAE;gBACL,WAAW,EAAE,IAAA,8BAAsB,GAAE;gBACrC,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,IAAI,KAAK;aAClD;SACF;KACF,CAAC;IAEF,MAAM,IAAA,wBAAiB,EAAC;QACtB,GAAG,aAAa;QAChB,IAAI,EAAE,8BAA8B;QACpC,UAAU,EAAE,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACnD,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE;KACxC,CAAC,CAAC;AACL,CAAC;AAMD,SAAS,2BAA2B;IAClC,IAAA,qCAA8B,GAAE,CAAC;IACjC,IAAA,qCAAwB,GAAE,CAAC;IAC3B,IAAA,6CAA4B,GAAE,CAAC;AACjC,CAAC;AAED,SAAgB,OAAO;IACrB,2BAA2B,EAAE,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,KAAK;IACzB,MAAM,IAAA,4BAAiB,EAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAA,8CAAc,EAAC,4BAAgB,CAAC,CAAC;IACvC,MAAM,IAAA,8CAAc,EAAC,8BAAkB,CAAC,CAAC;IACzC,MAAM,IAAA,kBAAU,EAAC,YAAI,CAAC,oBAAoB,CAAC,CAAC;IAC5C,MAAM,IAAA,0CAAoB,GAAE,CAAC;IAC7B,SAAS,GAAG,IAAA,wBAAgB,GAAE,CAAC;IAC/B,MAAM,IAAA,oCAAuB,GAAE,CAAC;IAChC,MAAM,IAAA,sDAAwB,GAAE,CAAC;IACjC,IAAA,4CAA2B,GAAE,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,IAAI;IACxB,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,CAAC,CAAC;IACxC,IAAA,2CAA0B,GAAE,CAAC;IAC7B,MAAM,IAAA,qDAAuB,GAAE,CAAC;IAChC,MAAM,IAAA,sCAAyB,GAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,CACxC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAC9C,CAAC;QACF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACnC,iBAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,SAAS,GAAG,EAAE,CAAC;QACf,MAAM,IAAA,uBAAY,GAAE,CAAC;QACrB,2BAA2B,EAAE,CAAC;IAChC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwEA,8BAgBC;AA4JD,0BAGC;AAED,sBAUC;AAED,oBAoBC;AAzRD,0DAA6B;AAC7B,+DAAgE;AAChE,gEAA6D;AAC7D,gEAAoE;AACpE,6FAA2E;AAC3E,mEAG6C;AAC7C,gBAAc;AAId,sBAAoB;AACpB,mBAAiB;AACjB,oBAAkB;AAClB,2DAKyC;AACzC,yDAAmE;AAEnE,6CAGsB;AACtB,qCAOkB;AAClB,mCAA2C;AAC3C,qEAAmE;AACnE,mFAG2C;AAC3C,iEAA2E;AAC3E,2DAAsE;AACtE,iEAG0C;AAC1C,uEAAoF;AACpF,iFAAuF;AACvF,qDAA4E;AAC5E,yCAIoB;AACpB,qEAI0C;AAC1C,uDAAuE;AACvE,qDAAmE;AACnE,mCAAoD;AACpD,+DAA+E;AAE/E,2CAAyB;AAEzB,IAAI,SAAS,GAAoB,EAAE,CAAC;AAEpC,IAAI,oBAAgD,CAAC;AAE9C,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,IAAA,oBAAW,EAAC,MAAM,CAAC,CAAC;IACpB,oBAAoB,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEvC,MAAM,sBAAsB,EAAE,CAAC;IAE/B,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,IAAA,iCAAyB,GAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,IAAA,6CAA4B,GAAE,CAAC;IAC/B,IAAA,kDAA8B,GAAE,CAAC;IAEjC,MAAM,mBAAmB,EAAE,CAAC;IAC5B,MAAM,mBAAmB,EAAE,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,sBAAsB;IACnC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,IAAA,wBAAc,GAAE,CAAC;IACvC,IAAA,gDAA2B,EAAC,GAAG,CAAC,CAAC;IAEjC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAA,6CAA6B,GAAE,CAAC;QACtC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAA,0BAAiB,GAAE,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QACjD,iBAAO,CAAC,IAAI,CACV,uGAAuG;YACrG,gGAAgG;YAChG,iGAAiG;YACjG,sDAAsD,CACzD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gCAAgC,GAAC,EAC9C,wDAAa,4BAA4B,GAAC,CAC3C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,0CAA0C,GAAC,EACxD,wDAAa,sCAAsC,GAAC,CACrD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,6CAA6C,GAAC,EAC3D,wDAAa,yCAAyC,GAAC,CACxD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gDAAgD,GAAC,EAC9D,wDAAa,4CAA4C,GAAC,CAC3D,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,iCAAiC,GAAC,CAChD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,uCAAuC,GAAC,EACrD,wDAAa,mCAAmC,GAAC,CAClD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,oCAAoC,GAAC,EAClD,wDAAa,gCAAgC,GAAC,CAC/C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,mCAAmC,GAAC,EACjD,wDAAa,+BAA+B,GAAC,CAC9C,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,kCAAkC,GAAC,EAChD,wDAAa,8BAA8B,GAAC,CAC7C,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,uCAAuC,GAAC,CACtD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,4CAA4C,GAAC,EAC1D,wDAAa,wCAAwC,GAAC,CACvD,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,sDAAsD,GAAC,EACpE,wDAAa,kDAAkD,GAAC,CACjE,CAAC;IACF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,2CAA2C,GAAC,EACzD,wDAAa,uCAAuC,GAAC,CACtD,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,gCAAgC,GAAC,EAC9C,wDAAa,4BAA4B,GAAC,CAC3C,CAAC;IAEF,KAAK,IAAA,mCAAkB,EACrB,wDAAa,yCAAyC,GAAC,EACvD,wDAAa,qCAAqC,GAAC,CACpD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAA,sBAAa,GAAE,CAAC;IACnC,MAAM,aAAa,GAAG;QACpB,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE;YAChC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;YACzC,iBAAiB,EAAE,KAAK;YACxB,KAAK,EAAE;gBACL,eAAe,EACb,UAAU,CAAC,mBAAmB,GAAG,8BAAuB;aAC3D;YACD,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,GAAG;YAChC,cAAc,EAAE,IAAA,kCAAyB,GAAE,CAAC,GAAG,CAC7C,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBACxB,EAAE;gBACF,KAAK;gBACL,IAAI;aACL,CAAC,CACH;SACF;QACD,cAAc,EAAE;YACd,UAAU,EAAE;gBACV,aAAa,EAAE,IAAA,4BAAmB,GAAE,CAAC,aAAa,IAAI,IAAI;aAC3D;YACD,KAAK,EAAE;gBACL,WAAW,EAAE,IAAA,8BAAsB,GAAE;gBACrC,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,IAAI,KAAK;aAClD;SACF;KACF,CAAC;IAEF,MAAM,IAAA,wBAAiB,EAAC;QACtB,GAAG,aAAa;QAChB,IAAI,EAAE,8BAA8B;QACpC,UAAU,EAAE,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACnD,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE;KACxC,CAAC,CAAC;AACL,CAAC;AAMD,SAAS,2BAA2B;IAClC,IAAA,qCAA8B,GAAE,CAAC;IACjC,IAAA,qCAAwB,GAAE,CAAC;IAC3B,IAAA,6CAA4B,GAAE,CAAC;AACjC,CAAC;AAED,SAAgB,OAAO;IACrB,2BAA2B,EAAE,CAAC;IAC9B,IAAA,kCAAqB,GAAE,CAAC;AAC1B,CAAC;AAEM,KAAK,UAAU,KAAK;IACzB,MAAM,IAAA,4BAAiB,EAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAA,8CAAc,EAAC,4BAAgB,CAAC,CAAC;IACvC,MAAM,IAAA,8CAAc,EAAC,8BAAkB,CAAC,CAAC;IACzC,MAAM,IAAA,kBAAU,EAAC,YAAI,CAAC,oBAAoB,CAAC,CAAC;IAC5C,MAAM,IAAA,0CAAoB,GAAE,CAAC;IAC7B,SAAS,GAAG,IAAA,wBAAgB,GAAE,CAAC;IAC/B,MAAM,IAAA,oCAAuB,GAAE,CAAC;IAChC,MAAM,IAAA,sDAAwB,GAAE,CAAC;IACjC,IAAA,4CAA2B,GAAE,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,IAAI;IACxB,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,CAAC,CAAC;IACxC,IAAA,2CAA0B,GAAE,CAAC;IAC7B,MAAM,IAAA,qDAAuB,GAAE,CAAC;IAChC,MAAM,IAAA,sCAAyB,GAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,CACxC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAC9C,CAAC;QACF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACnC,iBAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,SAAS,GAAG,EAAE,CAAC;QACf,MAAM,IAAA,uBAAY,GAAE,CAAC;QACrB,2BAA2B,EAAE,CAAC;QAC9B,IAAA,kCAAqB,GAAE,CAAC;IAC1B,CAAC;AACH,CAAC"}
@@ -12,6 +12,12 @@ function connect() {
12
12
  function read(stream) {
13
13
  return String(stream.read() ?? "");
14
14
  }
15
+ function ended(stream) {
16
+ return new Promise((resolve) => {
17
+ stream.once("end", resolve);
18
+ stream.resume();
19
+ });
20
+ }
15
21
  function settle() {
16
22
  return new Promise((resolve) => setTimeout(resolve, SETTLE_MS));
17
23
  }
@@ -55,5 +61,40 @@ describe("[unit] implementations/dms/dev-reload", () => {
55
61
  await settle();
56
62
  (0, chai_1.expect)(read(stream)).to.equal("");
57
63
  });
64
+ describe("closeDevReloadStreams", () => {
65
+ it("ends every open stream", async () => {
66
+ const other = connect();
67
+ (0, dev_reload_1.closeDevReloadStreams)();
68
+ await Promise.all([ended(stream), ended(other)]);
69
+ (0, chai_1.expect)(stream.writableEnded).to.equal(true);
70
+ (0, chai_1.expect)(other.writableEnded).to.equal(true);
71
+ });
72
+ it("drops the broadcast scheduled before the streams closed", async () => {
73
+ (0, dev_reload_1.setSlugProvider)(() => ["/form/form-simple"]);
74
+ (0, dev_reload_1.scheduleBroadcast)();
75
+ (0, dev_reload_1.closeDevReloadStreams)();
76
+ await settle();
77
+ (0, chai_1.expect)(read(stream)).to.equal("");
78
+ });
79
+ it("keeps no ended stream to write to", async () => {
80
+ (0, dev_reload_1.closeDevReloadStreams)();
81
+ const errors = [];
82
+ stream.on("error", (error) => errors.push(error));
83
+ (0, dev_reload_1.setSlugProvider)(() => ["/form/form-simple"]);
84
+ (0, dev_reload_1.scheduleBroadcast)();
85
+ await settle();
86
+ (0, chai_1.expect)(errors).to.deep.equal([]);
87
+ });
88
+ it("serves the streams that connect once the module is back", async () => {
89
+ (0, dev_reload_1.closeDevReloadStreams)();
90
+ const reconnected = connect();
91
+ read(reconnected);
92
+ (0, dev_reload_1.setSlugProvider)(() => ["/form/form-simple"]);
93
+ (0, dev_reload_1.scheduleBroadcast)();
94
+ await settle();
95
+ (0, chai_1.expect)(read(reconnected)).to.equal('event: reload\ndata: {"type":"resync"}\n\n');
96
+ reconnected.end();
97
+ });
98
+ });
58
99
  });
59
100
  //# sourceMappingURL=dev-reload.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev-reload.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/implementations/dms/dev-reload.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev-reload.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/implementations/dms/dev-reload.test.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ type ModulesListingEntry = ModuleInfo & {
6
6
  const STATE_KEY_MODULES = "dms-modulesListing";
7
7
  const STATE_KEY_LOADING = "dms-modulesListingLoading";
8
8
  const STATE_KEY_ERROR = "dms-modulesListingError";
9
+ const IN_FLIGHT_MODULES_LISTING_KEY = "__dmsInFlightModulesListing";
9
10
  const ENDPOINT_MODULES_LISTING = "/dms/modules-listing";
10
11
  const ERROR_FORBIDDEN_MESSAGE = "Forbidden: only owners can list modules";
11
12
  const ERROR_UNKNOWN_MESSAGE = "Unknown error loading modules listing";
@@ -26,8 +27,6 @@ function extractErrorMessage(error: unknown): string {
26
27
  return ERROR_UNKNOWN_MESSAGE;
27
28
  }
28
29
 
29
- let inFlightLoadingPromise: Promise<void> | null = null;
30
-
31
30
  export const useModulesListing = () => {
32
31
  const modules = useDmsState<ModulesListingEntry[] | undefined>(
33
32
  STATE_KEY_MODULES,
@@ -36,6 +35,21 @@ export const useModulesListing = () => {
36
35
  const isLoading = useDmsState<boolean>(STATE_KEY_LOADING, () => false);
37
36
  const loadingError = useDmsState<string | null>(STATE_KEY_ERROR, () => null);
38
37
 
38
+ // Held on the DMS app, like the in-flight fetches of useSiteLayout: every
39
+ // caller writes the same listing state, so they share one fetch. Not module
40
+ // scope, which the server shares across the requests it renders at once: a
41
+ // second render would wait on the first one's fetch, whose answer lands in
42
+ // the first request's state, and render an empty listing.
43
+ const dmsApp = useDmsApp() as unknown as Record<PropertyKey, unknown>;
44
+ const inFlightLoadingPromise = {
45
+ get value(): Promise<void> | null {
46
+ return (dmsApp[IN_FLIGHT_MODULES_LISTING_KEY] as Promise<void>) ?? null;
47
+ },
48
+ set value(promise: Promise<void> | null) {
49
+ dmsApp[IN_FLIGHT_MODULES_LISTING_KEY] = promise;
50
+ },
51
+ };
52
+
39
53
  function fetchModulesListing(): Promise<void> {
40
54
  const { $authFetch } = useAuthFetch();
41
55
  isLoading.value = true;
@@ -51,16 +65,16 @@ export const useModulesListing = () => {
51
65
  })
52
66
  .finally(() => {
53
67
  isLoading.value = false;
54
- inFlightLoadingPromise = null;
68
+ inFlightLoadingPromise.value = null;
55
69
  });
56
70
 
57
- inFlightLoadingPromise = promise;
71
+ inFlightLoadingPromise.value = promise;
58
72
  return promise;
59
73
  }
60
74
 
61
75
  async function loadModulesListing(): Promise<void> {
62
- if (inFlightLoadingPromise) {
63
- await inFlightLoadingPromise;
76
+ if (inFlightLoadingPromise.value) {
77
+ await inFlightLoadingPromise.value;
64
78
  return;
65
79
  }
66
80
  if (modules.value !== undefined) {
@@ -70,8 +84,8 @@ export const useModulesListing = () => {
70
84
  }
71
85
 
72
86
  async function refresh(): Promise<void> {
73
- if (inFlightLoadingPromise) {
74
- await inFlightLoadingPromise;
87
+ if (inFlightLoadingPromise.value) {
88
+ await inFlightLoadingPromise.value;
75
89
  }
76
90
  modules.value = undefined;
77
91
  loadingError.value = null;
@@ -1,4 +1,3 @@
1
- const RELOAD_EVENT_NAME = "reload";
2
1
  const RELOAD_ENDPOINT_PATH = "/dms/dev/reload";
3
2
 
4
3
  function resolveBackendBase(): string | null {
@@ -23,23 +22,18 @@ export default defineDmsPlugin(() => {
23
22
 
24
23
  const endpoint = `${backendBase}${RELOAD_ENDPOINT_PATH}`;
25
24
  const { coordinator } = useDevReloadHolder();
26
- const source = new EventSource(endpoint);
27
-
28
- source.addEventListener("error", () => {
29
- console.warn(
30
- "[dms-dev-reload] SSE connection lost, waiting for backend...",
31
- );
32
- });
33
-
34
- source.addEventListener(RELOAD_EVENT_NAME, () => {
35
- void coordinator.requestRefresh().catch((err: unknown) => {
36
- console.error("[dms-dev-reload] Reload handler failed:", err);
37
- });
25
+ const stream = openDevReloadStream({
26
+ endpoint,
27
+ onReload: () => {
28
+ void coordinator.requestRefresh().catch((err: unknown) => {
29
+ console.error("[dms-dev-reload] Reload handler failed:", err);
30
+ });
31
+ },
38
32
  });
39
33
 
40
34
  if (import.meta.hot) {
41
35
  import.meta.hot.dispose(() => {
42
- source.close();
36
+ stream.close();
43
37
  });
44
38
  }
45
39
  });
@@ -0,0 +1,80 @@
1
+ const RELOAD_EVENT_NAME = "reload";
2
+ const REOPEN_DELAY_MS = 2000;
3
+
4
+ export interface DevReloadStreamOptions {
5
+ endpoint: string;
6
+ onReload: () => void;
7
+ }
8
+
9
+ export interface DevReloadStream {
10
+ close: () => void;
11
+ }
12
+
13
+ interface StreamState {
14
+ options: DevReloadStreamOptions;
15
+ source: EventSource | null;
16
+ reopenTimer: ReturnType<typeof setTimeout> | null;
17
+ isConnectionLost: boolean;
18
+ isClosed: boolean;
19
+ }
20
+
21
+ // The browser fires `error` on every failed retry while the backend is down,
22
+ // so only the first one after a working connection is worth a warning.
23
+ function handleError(state: StreamState): void {
24
+ if (!state.isConnectionLost) {
25
+ state.isConnectionLost = true;
26
+ console.warn(
27
+ "[dms-dev-reload] SSE connection lost, waiting for backend...",
28
+ );
29
+ }
30
+ // EventSource retries a dropped connection by itself, but gives up for good
31
+ // on an answer that is not an event stream (a 404 while the module reloads,
32
+ // a proxy error page): only then does it need a new source.
33
+ if (state.source?.readyState !== EventSource.CLOSED) return;
34
+ scheduleReopen(state);
35
+ }
36
+
37
+ function scheduleReopen(state: StreamState): void {
38
+ if (state.reopenTimer || state.isClosed) return;
39
+ state.reopenTimer = setTimeout(() => {
40
+ state.reopenTimer = null;
41
+ open(state);
42
+ }, REOPEN_DELAY_MS);
43
+ }
44
+
45
+ function open(state: StreamState): void {
46
+ if (state.isClosed) return;
47
+ state.source?.close();
48
+ const source = new EventSource(state.options.endpoint);
49
+ state.source = source;
50
+ source.addEventListener("open", () => {
51
+ state.isConnectionLost = false;
52
+ });
53
+ source.addEventListener("error", () => handleError(state));
54
+ source.addEventListener(RELOAD_EVENT_NAME, () => state.options.onReload());
55
+ }
56
+
57
+ /**
58
+ * Keeps one `reload` stream open to the backend for as long as the page lives,
59
+ * across backend restarts, and warns once per lost connection.
60
+ */
61
+ export function openDevReloadStream(
62
+ options: DevReloadStreamOptions,
63
+ ): DevReloadStream {
64
+ const state: StreamState = {
65
+ options,
66
+ source: null,
67
+ reopenTimer: null,
68
+ isConnectionLost: false,
69
+ isClosed: false,
70
+ };
71
+ open(state);
72
+ return {
73
+ close: () => {
74
+ state.isClosed = true;
75
+ if (state.reopenTimer) clearTimeout(state.reopenTimer);
76
+ state.reopenTimer = null;
77
+ state.source?.close();
78
+ },
79
+ };
80
+ }
@@ -73,7 +73,7 @@ defineExpose({
73
73
  :unmount-on-hide="props.unmountOnHide"
74
74
  >
75
75
  <template v-for="item in props.items" :key="item.slot" #[item.slot]>
76
- <div class="p-4">
76
+ <div class="space-y-6 p-4">
77
77
  <slot :name="item.slot" />
78
78
  </div>
79
79
  </template>
@@ -0,0 +1,139 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { openDevReloadStream } from "../layers/dms-layout/app/utils/dev-reload-stream";
3
+
4
+ const ENDPOINT = "http://backend.test/dms/dev/reload";
5
+ // Comfortably past the delay before a source the browser gave up on is reopened.
6
+ const REOPEN_WAIT_MS = 5000;
7
+
8
+ type Listener = () => void;
9
+
10
+ /**
11
+ * Stands in for the browser's EventSource: the tests play the browser's part by
12
+ * firing its events, including the state it reaches before each one.
13
+ */
14
+ class FakeEventSource {
15
+ static readonly CONNECTING = 0;
16
+ static readonly OPEN = 1;
17
+ static readonly CLOSED = 2;
18
+ static instances: FakeEventSource[] = [];
19
+
20
+ readyState = FakeEventSource.CONNECTING;
21
+ private readonly listeners = new Map<string, Listener[]>();
22
+
23
+ constructor(readonly url: string) {
24
+ FakeEventSource.instances.push(this);
25
+ }
26
+
27
+ addEventListener(type: string, listener: Listener): void {
28
+ this.listeners.set(type, [...(this.listeners.get(type) ?? []), listener]);
29
+ }
30
+
31
+ close(): void {
32
+ this.readyState = FakeEventSource.CLOSED;
33
+ }
34
+
35
+ emit(type: string, readyState = this.readyState): void {
36
+ this.readyState = readyState;
37
+ for (const listener of this.listeners.get(type) ?? []) listener();
38
+ }
39
+
40
+ /** The backend went away; the browser keeps retrying on its own. */
41
+ drop(): void {
42
+ this.emit("error", FakeEventSource.CONNECTING);
43
+ }
44
+
45
+ /** The backend answered with something other than an event stream. */
46
+ refuse(): void {
47
+ this.emit("error", FakeEventSource.CLOSED);
48
+ }
49
+ }
50
+
51
+ function latestSource(): FakeEventSource {
52
+ const source = FakeEventSource.instances.at(-1);
53
+ if (!source) throw new Error("No EventSource was opened");
54
+ return source;
55
+ }
56
+
57
+ describe("dev reload stream", () => {
58
+ let warn: ReturnType<typeof vi.spyOn>;
59
+
60
+ beforeEach(() => {
61
+ vi.useFakeTimers();
62
+ vi.stubGlobal("EventSource", FakeEventSource);
63
+ FakeEventSource.instances = [];
64
+ warn = vi.spyOn(console, "warn").mockImplementation(() => {});
65
+ });
66
+
67
+ afterEach(() => {
68
+ vi.useRealTimers();
69
+ vi.unstubAllGlobals();
70
+ vi.restoreAllMocks();
71
+ });
72
+
73
+ it("forwards reload events", () => {
74
+ const onReload = vi.fn();
75
+ openDevReloadStream({ endpoint: ENDPOINT, onReload });
76
+
77
+ latestSource().emit("open", FakeEventSource.OPEN);
78
+ latestSource().emit("reload");
79
+
80
+ expect(latestSource().url).toBe(ENDPOINT);
81
+ expect(onReload).toHaveBeenCalledOnce();
82
+ });
83
+
84
+ it("warns once while the browser retries a lost backend", () => {
85
+ openDevReloadStream({ endpoint: ENDPOINT, onReload: vi.fn() });
86
+ const source = latestSource();
87
+ source.emit("open", FakeEventSource.OPEN);
88
+
89
+ source.drop();
90
+ source.drop();
91
+ source.drop();
92
+
93
+ expect(warn).toHaveBeenCalledOnce();
94
+ // The browser owns these retries: no second source competes with it.
95
+ vi.advanceTimersByTime(REOPEN_WAIT_MS);
96
+ expect(FakeEventSource.instances).toHaveLength(1);
97
+ });
98
+
99
+ it("warns again for the next loss once the stream is back", () => {
100
+ openDevReloadStream({ endpoint: ENDPOINT, onReload: vi.fn() });
101
+ const source = latestSource();
102
+ source.emit("open", FakeEventSource.OPEN);
103
+
104
+ source.drop();
105
+ source.emit("open", FakeEventSource.OPEN);
106
+ source.drop();
107
+
108
+ expect(warn).toHaveBeenCalledTimes(2);
109
+ });
110
+
111
+ it("reopens a source the browser gave up on", () => {
112
+ const onReload = vi.fn();
113
+ openDevReloadStream({ endpoint: ENDPOINT, onReload });
114
+ latestSource().refuse();
115
+
116
+ vi.advanceTimersByTime(REOPEN_WAIT_MS);
117
+ const reopened = latestSource();
118
+ reopened.emit("open", FakeEventSource.OPEN);
119
+ reopened.emit("reload");
120
+
121
+ expect(FakeEventSource.instances).toHaveLength(2);
122
+ expect(onReload).toHaveBeenCalledOnce();
123
+ expect(warn).toHaveBeenCalledOnce();
124
+ });
125
+
126
+ it("stays closed once closed", () => {
127
+ const stream = openDevReloadStream({
128
+ endpoint: ENDPOINT,
129
+ onReload: vi.fn(),
130
+ });
131
+ latestSource().refuse();
132
+
133
+ stream.close();
134
+ vi.advanceTimersByTime(REOPEN_WAIT_MS);
135
+
136
+ expect(FakeEventSource.instances).toHaveLength(1);
137
+ expect(latestSource().readyState).toBe(FakeEventSource.CLOSED);
138
+ });
139
+ });
@@ -0,0 +1,104 @@
1
+ /**
2
+ * The modules listing as a server runs it: every request it renders has its
3
+ * own DMS app and its own state, and two renders of the modules page can be in
4
+ * flight at once. Each one must fetch and render its own listing.
5
+ */
6
+ import { ref, type Ref } from "vue";
7
+ import { afterEach, beforeEach, expect, it, vi } from "vitest";
8
+ import { useModulesListing } from "../layers/dms-layout/app/composables/page/useModulesListing";
9
+
10
+ interface Render {
11
+ app: Record<PropertyKey, unknown>;
12
+ state: Map<string, Ref>;
13
+ authFetch: ReturnType<typeof vi.fn>;
14
+ }
15
+
16
+ const ordersModule = {
17
+ id: "orders",
18
+ title: "Orders",
19
+ description: "",
20
+ icon: "i-lucide-package",
21
+ hasAccess: true,
22
+ landingSlug: "/modules/orders/list",
23
+ };
24
+ const billingModule = {
25
+ id: "billing",
26
+ title: "Billing",
27
+ description: "",
28
+ icon: "i-lucide-receipt",
29
+ hasAccess: true,
30
+ landingSlug: "/modules/billing/invoices",
31
+ };
32
+
33
+ let current: Render;
34
+
35
+ function createRender(): Render {
36
+ return { app: {}, state: new Map(), authFetch: vi.fn() };
37
+ }
38
+
39
+ // What the renderer resolves from the component being set up: the app and
40
+ // the state of the request that component belongs to.
41
+ function inRender<T>(render: Render, callback: () => T): T {
42
+ current = render;
43
+ return callback();
44
+ }
45
+
46
+ function deferred<T>() {
47
+ let resolve!: (value: T) => void;
48
+ const promise = new Promise<T>((settle) => {
49
+ resolve = settle;
50
+ });
51
+ return { promise, resolve };
52
+ }
53
+
54
+ beforeEach(() => {
55
+ vi.stubGlobal("useDmsApp", () => current.app);
56
+ vi.stubGlobal("useDmsState", (key: string, initial: () => unknown) => {
57
+ if (!current.state.has(key)) current.state.set(key, ref(initial()));
58
+ return current.state.get(key);
59
+ });
60
+ vi.stubGlobal("useAuthFetch", () => ({ $authFetch: current.authFetch }));
61
+ });
62
+
63
+ afterEach(() => {
64
+ vi.unstubAllGlobals();
65
+ });
66
+
67
+ it("fetches the listing of a render that starts while another render's fetch is in flight", async () => {
68
+ const first = createRender();
69
+ const second = createRender();
70
+ const firstResponse = deferred<unknown[]>();
71
+ first.authFetch.mockReturnValueOnce(firstResponse.promise);
72
+ second.authFetch.mockResolvedValueOnce([billingModule]);
73
+
74
+ const firstListing = inRender(first, () => useModulesListing());
75
+ const firstLoad = inRender(first, () => firstListing.loadModulesListing());
76
+ const secondListing = inRender(second, () => useModulesListing());
77
+ const secondLoad = inRender(second, () => secondListing.loadModulesListing());
78
+ firstResponse.resolve([ordersModule]);
79
+ await Promise.all([firstLoad, secondLoad]);
80
+
81
+ expect(secondListing.modules.value).toEqual([billingModule]);
82
+ expect(second.authFetch).toHaveBeenCalledOnce();
83
+ expect(firstListing.modules.value).toEqual([ordersModule]);
84
+ });
85
+
86
+ it("still shares one fetch between the callers of one render", async () => {
87
+ const render = createRender();
88
+ const response = deferred<unknown[]>();
89
+ render.authFetch.mockReturnValueOnce(response.promise);
90
+
91
+ const [page, widget] = inRender(render, () => [
92
+ useModulesListing(),
93
+ useModulesListing(),
94
+ ]);
95
+ const loads = inRender(render, () => [
96
+ page.loadModulesListing(),
97
+ widget.loadModulesListing(),
98
+ ]);
99
+ response.resolve([ordersModule]);
100
+ await Promise.all(loads);
101
+
102
+ expect(render.authFetch).toHaveBeenCalledOnce();
103
+ expect(widget.modules.value).toEqual([ordersModule]);
104
+ });
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { expect, it } from "vitest";
3
+
4
+ /** The room the page leaves between its blocks. */
5
+ const BLOCK_SPACING = "space-y-6";
6
+
7
+ const sourceOf = (file: string) =>
8
+ readFileSync(new URL(`../layers/${file}`, import.meta.url), "utf8");
9
+
10
+ // A tab holding two blocks stacked them edge to edge, while the page spaces
11
+ // the same two blocks placed outside a tab.
12
+ it("spaces the blocks of a tab the way the page spaces its own", () => {
13
+ expect(sourceOf("dms-layout/app/pages/[...slug].vue")).toContain(
14
+ `dms-page-stack ${BLOCK_SPACING}`,
15
+ );
16
+ expect(sourceOf("dms-ui/app/components/tab/Tab.vue")).toMatch(
17
+ new RegExp(
18
+ `<div class="[^"]*\\b${BLOCK_SPACING}\\b[^"]*">\\s*<slot :name="item.slot" />`,
19
+ ),
20
+ );
21
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/AntelopeJS/dms.git"