@strapi/core 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.bd712ad3930045f4a5d2144c119e0b7856e97fc4

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 (140) hide show
  1. package/dist/Strapi.d.ts +3 -1
  2. package/dist/Strapi.d.ts.map +1 -1
  3. package/dist/Strapi.js +57 -13
  4. package/dist/Strapi.js.map +1 -1
  5. package/dist/Strapi.mjs +38 -13
  6. package/dist/Strapi.mjs.map +1 -1
  7. package/dist/core-api/controller/collection-type.d.ts.map +1 -1
  8. package/dist/core-api/controller/collection-type.js +2 -0
  9. package/dist/core-api/controller/collection-type.js.map +1 -1
  10. package/dist/core-api/controller/collection-type.mjs +2 -0
  11. package/dist/core-api/controller/collection-type.mjs.map +1 -1
  12. package/dist/core-api/controller/single-type.d.ts.map +1 -1
  13. package/dist/core-api/controller/single-type.js +1 -0
  14. package/dist/core-api/controller/single-type.js.map +1 -1
  15. package/dist/core-api/controller/single-type.mjs +1 -0
  16. package/dist/core-api/controller/single-type.mjs.map +1 -1
  17. package/dist/core-api/service/collection-type.d.ts +1 -7
  18. package/dist/core-api/service/collection-type.d.ts.map +1 -1
  19. package/dist/core-api/service/collection-type.js +3 -2
  20. package/dist/core-api/service/collection-type.js.map +1 -1
  21. package/dist/core-api/service/collection-type.mjs +4 -3
  22. package/dist/core-api/service/collection-type.mjs.map +1 -1
  23. package/dist/core-api/service/pagination.d.ts +4 -11
  24. package/dist/core-api/service/pagination.d.ts.map +1 -1
  25. package/dist/core-api/service/pagination.js +14 -40
  26. package/dist/core-api/service/pagination.js.map +1 -1
  27. package/dist/core-api/service/pagination.mjs +16 -42
  28. package/dist/core-api/service/pagination.mjs.map +1 -1
  29. package/dist/loaders/plugins/get-enabled-plugins.d.ts.map +1 -1
  30. package/dist/loaders/plugins/get-enabled-plugins.js.map +1 -1
  31. package/dist/loaders/plugins/get-enabled-plugins.mjs.map +1 -1
  32. package/dist/middlewares/cors.d.ts.map +1 -1
  33. package/dist/middlewares/cors.js +6 -8
  34. package/dist/middlewares/cors.js.map +1 -1
  35. package/dist/middlewares/cors.mjs +6 -8
  36. package/dist/middlewares/cors.mjs.map +1 -1
  37. package/dist/middlewares/security.d.ts.map +1 -1
  38. package/dist/middlewares/security.js +10 -3
  39. package/dist/middlewares/security.js.map +1 -1
  40. package/dist/middlewares/security.mjs +11 -4
  41. package/dist/middlewares/security.mjs.map +1 -1
  42. package/dist/migrations/database/5.0.0-discard-drafts.d.ts +19 -1
  43. package/dist/migrations/database/5.0.0-discard-drafts.d.ts.map +1 -1
  44. package/dist/migrations/database/5.0.0-discard-drafts.js +1 -0
  45. package/dist/migrations/database/5.0.0-discard-drafts.js.map +1 -1
  46. package/dist/migrations/database/5.0.0-discard-drafts.mjs +2 -1
  47. package/dist/migrations/database/5.0.0-discard-drafts.mjs.map +1 -1
  48. package/dist/migrations/draft-publish.d.ts.map +1 -1
  49. package/dist/migrations/draft-publish.js +14 -31
  50. package/dist/migrations/draft-publish.js.map +1 -1
  51. package/dist/migrations/draft-publish.mjs +15 -32
  52. package/dist/migrations/draft-publish.mjs.map +1 -1
  53. package/dist/services/document-service/entries.d.ts +1 -1
  54. package/dist/services/document-service/entries.d.ts.map +1 -1
  55. package/dist/services/document-service/entries.js +2 -1
  56. package/dist/services/document-service/entries.js.map +1 -1
  57. package/dist/services/document-service/entries.mjs +2 -1
  58. package/dist/services/document-service/entries.mjs.map +1 -1
  59. package/dist/services/document-service/events.d.ts +25 -0
  60. package/dist/services/document-service/events.d.ts.map +1 -0
  61. package/dist/services/document-service/events.js +47 -0
  62. package/dist/services/document-service/events.js.map +1 -0
  63. package/dist/services/document-service/events.mjs +47 -0
  64. package/dist/services/document-service/events.mjs.map +1 -0
  65. package/dist/services/document-service/index.d.ts.map +1 -1
  66. package/dist/services/document-service/index.js.map +1 -1
  67. package/dist/services/document-service/index.mjs.map +1 -1
  68. package/dist/services/document-service/internationalization.d.ts.map +1 -1
  69. package/dist/services/document-service/internationalization.js +14 -5
  70. package/dist/services/document-service/internationalization.js.map +1 -1
  71. package/dist/services/document-service/internationalization.mjs +14 -5
  72. package/dist/services/document-service/internationalization.mjs.map +1 -1
  73. package/dist/services/document-service/repository.d.ts.map +1 -1
  74. package/dist/services/document-service/repository.js +67 -39
  75. package/dist/services/document-service/repository.js.map +1 -1
  76. package/dist/services/document-service/repository.mjs +69 -41
  77. package/dist/services/document-service/repository.mjs.map +1 -1
  78. package/dist/services/document-service/transform/relations/extract/data-ids.d.ts.map +1 -1
  79. package/dist/services/document-service/transform/relations/extract/data-ids.js +3 -0
  80. package/dist/services/document-service/transform/relations/extract/data-ids.js.map +1 -1
  81. package/dist/services/document-service/transform/relations/extract/data-ids.mjs +3 -0
  82. package/dist/services/document-service/transform/relations/extract/data-ids.mjs.map +1 -1
  83. package/dist/services/document-service/transform/relations/transform/data-ids.d.ts.map +1 -1
  84. package/dist/services/document-service/transform/relations/transform/data-ids.js +3 -0
  85. package/dist/services/document-service/transform/relations/transform/data-ids.js.map +1 -1
  86. package/dist/services/document-service/transform/relations/transform/data-ids.mjs +3 -0
  87. package/dist/services/document-service/transform/relations/transform/data-ids.mjs.map +1 -1
  88. package/dist/services/document-service/transform/relations/utils/map-relation.d.ts.map +1 -1
  89. package/dist/services/document-service/transform/relations/utils/map-relation.js +7 -3
  90. package/dist/services/document-service/transform/relations/utils/map-relation.js.map +1 -1
  91. package/dist/services/document-service/transform/relations/utils/map-relation.mjs +7 -3
  92. package/dist/services/document-service/transform/relations/utils/map-relation.mjs.map +1 -1
  93. package/dist/services/document-service/utils/populate.d.ts.map +1 -1
  94. package/dist/services/document-service/utils/populate.js +4 -0
  95. package/dist/services/document-service/utils/populate.js.map +1 -1
  96. package/dist/services/document-service/utils/populate.mjs +4 -0
  97. package/dist/services/document-service/utils/populate.mjs.map +1 -1
  98. package/dist/services/entity-validator/index.d.ts +14 -1
  99. package/dist/services/entity-validator/index.d.ts.map +1 -1
  100. package/dist/services/entity-validator/index.js +87 -30
  101. package/dist/services/entity-validator/index.js.map +1 -1
  102. package/dist/services/entity-validator/index.mjs +87 -30
  103. package/dist/services/entity-validator/index.mjs.map +1 -1
  104. package/dist/services/entity-validator/validators.d.ts +10 -8
  105. package/dist/services/entity-validator/validators.d.ts.map +1 -1
  106. package/dist/services/entity-validator/validators.js +60 -19
  107. package/dist/services/entity-validator/validators.js.map +1 -1
  108. package/dist/services/entity-validator/validators.mjs +53 -11
  109. package/dist/services/entity-validator/validators.mjs.map +1 -1
  110. package/dist/services/event-hub.d.ts +1 -0
  111. package/dist/services/event-hub.d.ts.map +1 -1
  112. package/dist/services/event-hub.js +9 -4
  113. package/dist/services/event-hub.js.map +1 -1
  114. package/dist/services/event-hub.mjs +9 -4
  115. package/dist/services/event-hub.mjs.map +1 -1
  116. package/dist/services/server/index.js +1 -1
  117. package/dist/services/server/index.js.map +1 -1
  118. package/dist/services/server/index.mjs +1 -1
  119. package/dist/services/server/index.mjs.map +1 -1
  120. package/dist/services/webhook-runner.d.ts +2 -1
  121. package/dist/services/webhook-runner.d.ts.map +1 -1
  122. package/dist/services/webhook-runner.js.map +1 -1
  123. package/dist/services/webhook-runner.mjs.map +1 -1
  124. package/dist/services/webhook-store.d.ts +2 -8
  125. package/dist/services/webhook-store.d.ts.map +1 -1
  126. package/dist/services/webhook-store.js +9 -2
  127. package/dist/services/webhook-store.js.map +1 -1
  128. package/dist/services/webhook-store.mjs +9 -2
  129. package/dist/services/webhook-store.mjs.map +1 -1
  130. package/dist/utils/fetch.d.ts.map +1 -1
  131. package/dist/utils/fetch.js +4 -3
  132. package/dist/utils/fetch.js.map +1 -1
  133. package/dist/utils/fetch.mjs +4 -3
  134. package/dist/utils/fetch.mjs.map +1 -1
  135. package/dist/utils/transform-content-types-to-models.d.ts.map +1 -1
  136. package/dist/utils/transform-content-types-to-models.js +10 -0
  137. package/dist/utils/transform-content-types-to-models.js.map +1 -1
  138. package/dist/utils/transform-content-types-to-models.mjs +10 -0
  139. package/dist/utils/transform-content-types-to-models.mjs.map +1 -1
  140. package/package.json +16 -14
@@ -1 +1 @@
1
- {"version":3,"file":"event-hub.js","sources":["../../src/services/event-hub.ts"],"sourcesContent":["export type Subscriber = (eventName: string, ...args: any[]) => Promise<void>;\nexport type Listener = (...args: any[]) => Promise<void>;\n\nexport interface EventHub {\n emit(eventName: string, ...args: unknown[]): Promise<void>;\n subscribe(subscriber: Subscriber): () => void;\n unsubscribe(subscriber: Subscriber): void;\n on(eventName: string, listener: Listener): () => void;\n off(eventName: string, listener: Listener): void;\n once(eventName: string, listener: Listener): () => void;\n destroy(): EventHub;\n removeListener(eventName: string, listener: Listener): void;\n removeAllListeners(): EventHub;\n addListener(eventName: string, listener: Listener): () => void;\n}\n\n/**\n * The event hub is Strapi's event control center.\n */\nexport default function createEventHub(): EventHub {\n const listeners = new Map();\n\n // Default subscriber to easily add listeners with the on() method\n const defaultSubscriber = async (eventName: string, ...args: unknown[]) => {\n if (listeners.has(eventName)) {\n for (const listener of listeners.get(eventName)) {\n await listener(...args);\n }\n }\n };\n\n // Store of subscribers that will be called when an event is emitted\n const subscribers = [defaultSubscriber];\n\n const eventHub: EventHub = {\n async emit(eventName, ...args) {\n for (const subscriber of subscribers) {\n await subscriber(eventName, ...args);\n }\n },\n\n subscribe(subscriber) {\n subscribers.push(subscriber);\n\n // Return a function to remove the subscriber\n return () => {\n eventHub.unsubscribe(subscriber);\n };\n },\n\n unsubscribe(subscriber) {\n const subscriberIndex = subscribers.indexOf(subscriber);\n\n // Only remove the subscriber if it exists\n if (subscriberIndex >= 0) {\n subscribers.splice(subscriberIndex, 1);\n }\n },\n\n on(eventName, listener) {\n if (!listeners.has(eventName)) {\n listeners.set(eventName, [listener]);\n } else {\n listeners.get(eventName).push(listener);\n }\n\n // Return a function to remove the listener\n return () => {\n eventHub.off(eventName, listener);\n };\n },\n\n off(eventName, listener) {\n listeners.get(eventName).splice(listeners.get(eventName).indexOf(listener), 1);\n },\n\n once(eventName, listener) {\n return eventHub.on(eventName, async (...args) => {\n eventHub.off(eventName, listener);\n return listener(...args);\n });\n },\n\n destroy() {\n listeners.clear();\n subscribers.length = 0;\n return this;\n },\n\n removeListener(eventName, listener) {\n return eventHub.off(eventName, listener);\n },\n\n removeAllListeners() {\n return eventHub.destroy();\n },\n\n addListener(eventName, listener) {\n return eventHub.on(eventName, listener);\n },\n };\n\n return eventHub;\n}\n"],"names":[],"mappings":";AAmBA,SAAwB,iBAA2B;AAC3C,QAAA,gCAAgB;AAGhB,QAAA,oBAAoB,OAAO,cAAsB,SAAoB;AACrE,QAAA,UAAU,IAAI,SAAS,GAAG;AAC5B,iBAAW,YAAY,UAAU,IAAI,SAAS,GAAG;AACzC,cAAA,SAAS,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EAAA;AAII,QAAA,cAAc,CAAC,iBAAiB;AAEtC,QAAM,WAAqB;AAAA,IACzB,MAAM,KAAK,cAAc,MAAM;AAC7B,iBAAW,cAAc,aAAa;AAC9B,cAAA,WAAW,WAAW,GAAG,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,IAEA,UAAU,YAAY;AACpB,kBAAY,KAAK,UAAU;AAG3B,aAAO,MAAM;AACX,iBAAS,YAAY,UAAU;AAAA,MAAA;AAAA,IAEnC;AAAA,IAEA,YAAY,YAAY;AAChB,YAAA,kBAAkB,YAAY,QAAQ,UAAU;AAGtD,UAAI,mBAAmB,GAAG;AACZ,oBAAA,OAAO,iBAAiB,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,GAAG,WAAW,UAAU;AACtB,UAAI,CAAC,UAAU,IAAI,SAAS,GAAG;AAC7B,kBAAU,IAAI,WAAW,CAAC,QAAQ,CAAC;AAAA,MAAA,OAC9B;AACL,kBAAU,IAAI,SAAS,EAAE,KAAK,QAAQ;AAAA,MACxC;AAGA,aAAO,MAAM;AACF,iBAAA,IAAI,WAAW,QAAQ;AAAA,MAAA;AAAA,IAEpC;AAAA,IAEA,IAAI,WAAW,UAAU;AACb,gBAAA,IAAI,SAAS,EAAE,OAAO,UAAU,IAAI,SAAS,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAC/E;AAAA,IAEA,KAAK,WAAW,UAAU;AACxB,aAAO,SAAS,GAAG,WAAW,UAAU,SAAS;AACtC,iBAAA,IAAI,WAAW,QAAQ;AACzB,eAAA,SAAS,GAAG,IAAI;AAAA,MAAA,CACxB;AAAA,IACH;AAAA,IAEA,UAAU;AACR,gBAAU,MAAM;AAChB,kBAAY,SAAS;AACd,aAAA;AAAA,IACT;AAAA,IAEA,eAAe,WAAW,UAAU;AAC3B,aAAA,SAAS,IAAI,WAAW,QAAQ;AAAA,IACzC;AAAA,IAEA,qBAAqB;AACnB,aAAO,SAAS;IAClB;AAAA,IAEA,YAAY,WAAW,UAAU;AACxB,aAAA,SAAS,GAAG,WAAW,QAAQ;AAAA,IACxC;AAAA,EAAA;AAGK,SAAA;AACT;;"}
1
+ {"version":3,"file":"event-hub.js","sources":["../../src/services/event-hub.ts"],"sourcesContent":["export type Subscriber = (eventName: string, ...args: any[]) => Promise<void>;\nexport type Listener = (...args: any[]) => Promise<void>;\n\nexport interface EventHub {\n emit(eventName: string, ...args: unknown[]): Promise<void>;\n subscribe(subscriber: Subscriber): () => void;\n unsubscribe(subscriber: Subscriber): void;\n on(eventName: string, listener: Listener): () => void;\n off(eventName: string, listener: Listener): void;\n once(eventName: string, listener: Listener): () => void;\n destroy(): EventHub;\n removeListener(eventName: string, listener: Listener): void;\n removeAllListeners(): EventHub;\n removeAllSubscribers(): EventHub;\n addListener(eventName: string, listener: Listener): () => void;\n}\n\n/**\n * The event hub is Strapi's event control center.\n */\nexport default function createEventHub(): EventHub {\n const listeners = new Map();\n\n // Default subscriber to easily add listeners with the on() method\n const defaultSubscriber = async (eventName: string, ...args: unknown[]) => {\n if (listeners.has(eventName)) {\n for (const listener of listeners.get(eventName)) {\n await listener(...args);\n }\n }\n };\n\n // Store of subscribers that will be called when an event is emitted\n const subscribers = [defaultSubscriber];\n\n const eventHub: EventHub = {\n async emit(eventName, ...args) {\n for (const subscriber of subscribers) {\n await subscriber(eventName, ...args);\n }\n },\n\n subscribe(subscriber) {\n subscribers.push(subscriber);\n\n // Return a function to remove the subscriber\n return () => {\n eventHub.unsubscribe(subscriber);\n };\n },\n\n unsubscribe(subscriber) {\n const subscriberIndex = subscribers.indexOf(subscriber);\n\n // Only remove the subscriber if it exists\n if (subscriberIndex >= 0) {\n subscribers.splice(subscriberIndex, 1);\n }\n },\n\n on(eventName, listener) {\n if (!listeners.has(eventName)) {\n listeners.set(eventName, [listener]);\n } else {\n listeners.get(eventName).push(listener);\n }\n\n // Return a function to remove the listener\n return () => {\n eventHub.off(eventName, listener);\n };\n },\n\n off(eventName, listener) {\n listeners.get(eventName)?.splice(listeners.get(eventName).indexOf(listener), 1);\n },\n\n once(eventName, listener) {\n return eventHub.on(eventName, async (...args) => {\n eventHub.off(eventName, listener);\n return listener(...args);\n });\n },\n\n destroy() {\n this.removeAllListeners();\n this.removeAllSubscribers();\n return this;\n },\n\n removeListener(eventName, listener) {\n return eventHub.off(eventName, listener);\n },\n\n removeAllListeners() {\n listeners.clear();\n return this;\n },\n\n removeAllSubscribers() {\n subscribers.length = 0;\n return this;\n },\n\n addListener(eventName, listener) {\n return eventHub.on(eventName, listener);\n },\n };\n\n return eventHub;\n}\n"],"names":[],"mappings":";AAoBA,SAAwB,iBAA2B;AAC3C,QAAA,gCAAgB;AAGhB,QAAA,oBAAoB,OAAO,cAAsB,SAAoB;AACrE,QAAA,UAAU,IAAI,SAAS,GAAG;AAC5B,iBAAW,YAAY,UAAU,IAAI,SAAS,GAAG;AACzC,cAAA,SAAS,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EAAA;AAII,QAAA,cAAc,CAAC,iBAAiB;AAEtC,QAAM,WAAqB;AAAA,IACzB,MAAM,KAAK,cAAc,MAAM;AAC7B,iBAAW,cAAc,aAAa;AAC9B,cAAA,WAAW,WAAW,GAAG,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,IAEA,UAAU,YAAY;AACpB,kBAAY,KAAK,UAAU;AAG3B,aAAO,MAAM;AACX,iBAAS,YAAY,UAAU;AAAA,MAAA;AAAA,IAEnC;AAAA,IAEA,YAAY,YAAY;AAChB,YAAA,kBAAkB,YAAY,QAAQ,UAAU;AAGtD,UAAI,mBAAmB,GAAG;AACZ,oBAAA,OAAO,iBAAiB,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,GAAG,WAAW,UAAU;AACtB,UAAI,CAAC,UAAU,IAAI,SAAS,GAAG;AAC7B,kBAAU,IAAI,WAAW,CAAC,QAAQ,CAAC;AAAA,MAAA,OAC9B;AACL,kBAAU,IAAI,SAAS,EAAE,KAAK,QAAQ;AAAA,MACxC;AAGA,aAAO,MAAM;AACF,iBAAA,IAAI,WAAW,QAAQ;AAAA,MAAA;AAAA,IAEpC;AAAA,IAEA,IAAI,WAAW,UAAU;AACb,gBAAA,IAAI,SAAS,GAAG,OAAO,UAAU,IAAI,SAAS,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAChF;AAAA,IAEA,KAAK,WAAW,UAAU;AACxB,aAAO,SAAS,GAAG,WAAW,UAAU,SAAS;AACtC,iBAAA,IAAI,WAAW,QAAQ;AACzB,eAAA,SAAS,GAAG,IAAI;AAAA,MAAA,CACxB;AAAA,IACH;AAAA,IAEA,UAAU;AACR,WAAK,mBAAmB;AACxB,WAAK,qBAAqB;AACnB,aAAA;AAAA,IACT;AAAA,IAEA,eAAe,WAAW,UAAU;AAC3B,aAAA,SAAS,IAAI,WAAW,QAAQ;AAAA,IACzC;AAAA,IAEA,qBAAqB;AACnB,gBAAU,MAAM;AACT,aAAA;AAAA,IACT;AAAA,IAEA,uBAAuB;AACrB,kBAAY,SAAS;AACd,aAAA;AAAA,IACT;AAAA,IAEA,YAAY,WAAW,UAAU;AACxB,aAAA,SAAS,GAAG,WAAW,QAAQ;AAAA,IACxC;AAAA,EAAA;AAGK,SAAA;AACT;;"}
@@ -37,7 +37,7 @@ function createEventHub() {
37
37
  };
38
38
  },
39
39
  off(eventName, listener) {
40
- listeners.get(eventName).splice(listeners.get(eventName).indexOf(listener), 1);
40
+ listeners.get(eventName)?.splice(listeners.get(eventName).indexOf(listener), 1);
41
41
  },
42
42
  once(eventName, listener) {
43
43
  return eventHub.on(eventName, async (...args) => {
@@ -46,15 +46,20 @@ function createEventHub() {
46
46
  });
47
47
  },
48
48
  destroy() {
49
- listeners.clear();
50
- subscribers.length = 0;
49
+ this.removeAllListeners();
50
+ this.removeAllSubscribers();
51
51
  return this;
52
52
  },
53
53
  removeListener(eventName, listener) {
54
54
  return eventHub.off(eventName, listener);
55
55
  },
56
56
  removeAllListeners() {
57
- return eventHub.destroy();
57
+ listeners.clear();
58
+ return this;
59
+ },
60
+ removeAllSubscribers() {
61
+ subscribers.length = 0;
62
+ return this;
58
63
  },
59
64
  addListener(eventName, listener) {
60
65
  return eventHub.on(eventName, listener);
@@ -1 +1 @@
1
- {"version":3,"file":"event-hub.mjs","sources":["../../src/services/event-hub.ts"],"sourcesContent":["export type Subscriber = (eventName: string, ...args: any[]) => Promise<void>;\nexport type Listener = (...args: any[]) => Promise<void>;\n\nexport interface EventHub {\n emit(eventName: string, ...args: unknown[]): Promise<void>;\n subscribe(subscriber: Subscriber): () => void;\n unsubscribe(subscriber: Subscriber): void;\n on(eventName: string, listener: Listener): () => void;\n off(eventName: string, listener: Listener): void;\n once(eventName: string, listener: Listener): () => void;\n destroy(): EventHub;\n removeListener(eventName: string, listener: Listener): void;\n removeAllListeners(): EventHub;\n addListener(eventName: string, listener: Listener): () => void;\n}\n\n/**\n * The event hub is Strapi's event control center.\n */\nexport default function createEventHub(): EventHub {\n const listeners = new Map();\n\n // Default subscriber to easily add listeners with the on() method\n const defaultSubscriber = async (eventName: string, ...args: unknown[]) => {\n if (listeners.has(eventName)) {\n for (const listener of listeners.get(eventName)) {\n await listener(...args);\n }\n }\n };\n\n // Store of subscribers that will be called when an event is emitted\n const subscribers = [defaultSubscriber];\n\n const eventHub: EventHub = {\n async emit(eventName, ...args) {\n for (const subscriber of subscribers) {\n await subscriber(eventName, ...args);\n }\n },\n\n subscribe(subscriber) {\n subscribers.push(subscriber);\n\n // Return a function to remove the subscriber\n return () => {\n eventHub.unsubscribe(subscriber);\n };\n },\n\n unsubscribe(subscriber) {\n const subscriberIndex = subscribers.indexOf(subscriber);\n\n // Only remove the subscriber if it exists\n if (subscriberIndex >= 0) {\n subscribers.splice(subscriberIndex, 1);\n }\n },\n\n on(eventName, listener) {\n if (!listeners.has(eventName)) {\n listeners.set(eventName, [listener]);\n } else {\n listeners.get(eventName).push(listener);\n }\n\n // Return a function to remove the listener\n return () => {\n eventHub.off(eventName, listener);\n };\n },\n\n off(eventName, listener) {\n listeners.get(eventName).splice(listeners.get(eventName).indexOf(listener), 1);\n },\n\n once(eventName, listener) {\n return eventHub.on(eventName, async (...args) => {\n eventHub.off(eventName, listener);\n return listener(...args);\n });\n },\n\n destroy() {\n listeners.clear();\n subscribers.length = 0;\n return this;\n },\n\n removeListener(eventName, listener) {\n return eventHub.off(eventName, listener);\n },\n\n removeAllListeners() {\n return eventHub.destroy();\n },\n\n addListener(eventName, listener) {\n return eventHub.on(eventName, listener);\n },\n };\n\n return eventHub;\n}\n"],"names":[],"mappings":"AAmBA,SAAwB,iBAA2B;AAC3C,QAAA,gCAAgB;AAGhB,QAAA,oBAAoB,OAAO,cAAsB,SAAoB;AACrE,QAAA,UAAU,IAAI,SAAS,GAAG;AAC5B,iBAAW,YAAY,UAAU,IAAI,SAAS,GAAG;AACzC,cAAA,SAAS,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EAAA;AAII,QAAA,cAAc,CAAC,iBAAiB;AAEtC,QAAM,WAAqB;AAAA,IACzB,MAAM,KAAK,cAAc,MAAM;AAC7B,iBAAW,cAAc,aAAa;AAC9B,cAAA,WAAW,WAAW,GAAG,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,IAEA,UAAU,YAAY;AACpB,kBAAY,KAAK,UAAU;AAG3B,aAAO,MAAM;AACX,iBAAS,YAAY,UAAU;AAAA,MAAA;AAAA,IAEnC;AAAA,IAEA,YAAY,YAAY;AAChB,YAAA,kBAAkB,YAAY,QAAQ,UAAU;AAGtD,UAAI,mBAAmB,GAAG;AACZ,oBAAA,OAAO,iBAAiB,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,GAAG,WAAW,UAAU;AACtB,UAAI,CAAC,UAAU,IAAI,SAAS,GAAG;AAC7B,kBAAU,IAAI,WAAW,CAAC,QAAQ,CAAC;AAAA,MAAA,OAC9B;AACL,kBAAU,IAAI,SAAS,EAAE,KAAK,QAAQ;AAAA,MACxC;AAGA,aAAO,MAAM;AACF,iBAAA,IAAI,WAAW,QAAQ;AAAA,MAAA;AAAA,IAEpC;AAAA,IAEA,IAAI,WAAW,UAAU;AACb,gBAAA,IAAI,SAAS,EAAE,OAAO,UAAU,IAAI,SAAS,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAC/E;AAAA,IAEA,KAAK,WAAW,UAAU;AACxB,aAAO,SAAS,GAAG,WAAW,UAAU,SAAS;AACtC,iBAAA,IAAI,WAAW,QAAQ;AACzB,eAAA,SAAS,GAAG,IAAI;AAAA,MAAA,CACxB;AAAA,IACH;AAAA,IAEA,UAAU;AACR,gBAAU,MAAM;AAChB,kBAAY,SAAS;AACd,aAAA;AAAA,IACT;AAAA,IAEA,eAAe,WAAW,UAAU;AAC3B,aAAA,SAAS,IAAI,WAAW,QAAQ;AAAA,IACzC;AAAA,IAEA,qBAAqB;AACnB,aAAO,SAAS;IAClB;AAAA,IAEA,YAAY,WAAW,UAAU;AACxB,aAAA,SAAS,GAAG,WAAW,QAAQ;AAAA,IACxC;AAAA,EAAA;AAGK,SAAA;AACT;"}
1
+ {"version":3,"file":"event-hub.mjs","sources":["../../src/services/event-hub.ts"],"sourcesContent":["export type Subscriber = (eventName: string, ...args: any[]) => Promise<void>;\nexport type Listener = (...args: any[]) => Promise<void>;\n\nexport interface EventHub {\n emit(eventName: string, ...args: unknown[]): Promise<void>;\n subscribe(subscriber: Subscriber): () => void;\n unsubscribe(subscriber: Subscriber): void;\n on(eventName: string, listener: Listener): () => void;\n off(eventName: string, listener: Listener): void;\n once(eventName: string, listener: Listener): () => void;\n destroy(): EventHub;\n removeListener(eventName: string, listener: Listener): void;\n removeAllListeners(): EventHub;\n removeAllSubscribers(): EventHub;\n addListener(eventName: string, listener: Listener): () => void;\n}\n\n/**\n * The event hub is Strapi's event control center.\n */\nexport default function createEventHub(): EventHub {\n const listeners = new Map();\n\n // Default subscriber to easily add listeners with the on() method\n const defaultSubscriber = async (eventName: string, ...args: unknown[]) => {\n if (listeners.has(eventName)) {\n for (const listener of listeners.get(eventName)) {\n await listener(...args);\n }\n }\n };\n\n // Store of subscribers that will be called when an event is emitted\n const subscribers = [defaultSubscriber];\n\n const eventHub: EventHub = {\n async emit(eventName, ...args) {\n for (const subscriber of subscribers) {\n await subscriber(eventName, ...args);\n }\n },\n\n subscribe(subscriber) {\n subscribers.push(subscriber);\n\n // Return a function to remove the subscriber\n return () => {\n eventHub.unsubscribe(subscriber);\n };\n },\n\n unsubscribe(subscriber) {\n const subscriberIndex = subscribers.indexOf(subscriber);\n\n // Only remove the subscriber if it exists\n if (subscriberIndex >= 0) {\n subscribers.splice(subscriberIndex, 1);\n }\n },\n\n on(eventName, listener) {\n if (!listeners.has(eventName)) {\n listeners.set(eventName, [listener]);\n } else {\n listeners.get(eventName).push(listener);\n }\n\n // Return a function to remove the listener\n return () => {\n eventHub.off(eventName, listener);\n };\n },\n\n off(eventName, listener) {\n listeners.get(eventName)?.splice(listeners.get(eventName).indexOf(listener), 1);\n },\n\n once(eventName, listener) {\n return eventHub.on(eventName, async (...args) => {\n eventHub.off(eventName, listener);\n return listener(...args);\n });\n },\n\n destroy() {\n this.removeAllListeners();\n this.removeAllSubscribers();\n return this;\n },\n\n removeListener(eventName, listener) {\n return eventHub.off(eventName, listener);\n },\n\n removeAllListeners() {\n listeners.clear();\n return this;\n },\n\n removeAllSubscribers() {\n subscribers.length = 0;\n return this;\n },\n\n addListener(eventName, listener) {\n return eventHub.on(eventName, listener);\n },\n };\n\n return eventHub;\n}\n"],"names":[],"mappings":"AAoBA,SAAwB,iBAA2B;AAC3C,QAAA,gCAAgB;AAGhB,QAAA,oBAAoB,OAAO,cAAsB,SAAoB;AACrE,QAAA,UAAU,IAAI,SAAS,GAAG;AAC5B,iBAAW,YAAY,UAAU,IAAI,SAAS,GAAG;AACzC,cAAA,SAAS,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EAAA;AAII,QAAA,cAAc,CAAC,iBAAiB;AAEtC,QAAM,WAAqB;AAAA,IACzB,MAAM,KAAK,cAAc,MAAM;AAC7B,iBAAW,cAAc,aAAa;AAC9B,cAAA,WAAW,WAAW,GAAG,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,IAEA,UAAU,YAAY;AACpB,kBAAY,KAAK,UAAU;AAG3B,aAAO,MAAM;AACX,iBAAS,YAAY,UAAU;AAAA,MAAA;AAAA,IAEnC;AAAA,IAEA,YAAY,YAAY;AAChB,YAAA,kBAAkB,YAAY,QAAQ,UAAU;AAGtD,UAAI,mBAAmB,GAAG;AACZ,oBAAA,OAAO,iBAAiB,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,GAAG,WAAW,UAAU;AACtB,UAAI,CAAC,UAAU,IAAI,SAAS,GAAG;AAC7B,kBAAU,IAAI,WAAW,CAAC,QAAQ,CAAC;AAAA,MAAA,OAC9B;AACL,kBAAU,IAAI,SAAS,EAAE,KAAK,QAAQ;AAAA,MACxC;AAGA,aAAO,MAAM;AACF,iBAAA,IAAI,WAAW,QAAQ;AAAA,MAAA;AAAA,IAEpC;AAAA,IAEA,IAAI,WAAW,UAAU;AACb,gBAAA,IAAI,SAAS,GAAG,OAAO,UAAU,IAAI,SAAS,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAChF;AAAA,IAEA,KAAK,WAAW,UAAU;AACxB,aAAO,SAAS,GAAG,WAAW,UAAU,SAAS;AACtC,iBAAA,IAAI,WAAW,QAAQ;AACzB,eAAA,SAAS,GAAG,IAAI;AAAA,MAAA,CACxB;AAAA,IACH;AAAA,IAEA,UAAU;AACR,WAAK,mBAAmB;AACxB,WAAK,qBAAqB;AACnB,aAAA;AAAA,IACT;AAAA,IAEA,eAAe,WAAW,UAAU;AAC3B,aAAA,SAAS,IAAI,WAAW,QAAQ;AAAA,IACzC;AAAA,IAEA,qBAAqB;AACnB,gBAAU,MAAM;AACT,aAAA;AAAA,IACT;AAAA,IAEA,uBAAuB;AACrB,kBAAY,SAAS;AACd,aAAA;AAAA,IACT;AAAA,IAEA,YAAY,WAAW,UAAU;AACxB,aAAA,SAAS,GAAG,WAAW,QAAQ;AAAA,IACxC;AAAA,EAAA;AAGK,SAAA;AACT;"}
@@ -17,7 +17,7 @@ const healthCheck = async (ctx) => {
17
17
  };
18
18
  const createServer = (strapi) => {
19
19
  const app = koa({
20
- proxy: strapi.config.get("server.proxy"),
20
+ proxy: strapi.config.get("server.proxy.koa"),
21
21
  keys: strapi.config.get("server.app.keys")
22
22
  });
23
23
  app.use((ctx, next) => requestContext.run(ctx, () => next()));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":["createKoaApp","requestCtx","Router","createRouteManager","httpServer","createHTTPServer","createContentAPI","createAdminAPI","registerAllRoutes","registerApplicationMiddlewares"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAMA,IAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,cAAc;AAAA,IACvC,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAASC,eAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAIC,gBAAAA;AAEb,QAAA,eAAeC,2BAAmB,MAAM;AAExC,QAAAC,eAAaC,WAAAA,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAeC,4BAAiB,MAAM;AAAA,IACtC,OAAOC,wBAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IAAA,YACAH;AAAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZI,qBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAMC,oBAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAAL,aAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAMA,aAAW;IACnB;AAAA,EAAA;AAEJ;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy.koa'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":["createKoaApp","requestCtx","Router","createRouteManager","httpServer","createHTTPServer","createContentAPI","createAdminAPI","registerAllRoutes","registerApplicationMiddlewares"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAMA,IAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,kBAAkB;AAAA,IAC3C,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAASC,eAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAIC,gBAAAA;AAEb,QAAA,eAAeC,2BAAmB,MAAM;AAExC,QAAAC,eAAaC,WAAAA,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAeC,4BAAiB,MAAM;AAAA,IACtC,OAAOC,wBAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IAAA,YACAH;AAAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZI,qBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAMC,oBAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAAL,aAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAMA,aAAW;IACnB;AAAA,EAAA;AAEJ;;"}
@@ -13,7 +13,7 @@ const healthCheck = async (ctx) => {
13
13
  };
14
14
  const createServer = (strapi) => {
15
15
  const app = createKoaApp({
16
- proxy: strapi.config.get("server.proxy"),
16
+ proxy: strapi.config.get("server.proxy.koa"),
17
17
  keys: strapi.config.get("server.app.keys")
18
18
  });
19
19
  app.use((ctx, next) => requestCtx.run(ctx, () => next()));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":[],"mappings":";;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAM,aAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,cAAc;AAAA,IACvC,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAAS,WAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAI;AAEb,QAAA,eAAe,mBAAmB,MAAM;AAExC,QAAA,aAAa,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAe,iBAAiB,MAAM;AAAA,IACtC,OAAO,eAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZ,wBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAM,+BAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAA,WAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAM,WAAW;IACnB;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy.koa'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":[],"mappings":";;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAM,aAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,kBAAkB;AAAA,IAC3C,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAAS,WAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAI;AAEb,QAAA,eAAe,mBAAmB,MAAM;AAExC,QAAA,aAAa,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAe,iBAAiB,MAAM;AAAA,IACtC,OAAO,eAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZ,wBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAM,+BAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAA,WAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAM,WAAW;IACnB;AAAA,EAAA;AAEJ;"}
@@ -2,9 +2,10 @@
2
2
  * The event hub is Strapi's event control center.
3
3
  */
4
4
  import type { Logger } from '@strapi/logger';
5
- import type { Webhook } from './webhook-store';
5
+ import type { Modules } from '@strapi/types';
6
6
  import type { EventHub } from './event-hub';
7
7
  import type { Fetch } from '../utils/fetch';
8
+ type Webhook = Modules.WebhookStore.Webhook;
8
9
  interface ConstructorParameters {
9
10
  eventHub: EventHub;
10
11
  logger: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-runner.d.ts","sourceRoot":"","sources":["../../src/services/webhook-runner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAM5C,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,KAAK,EAAE,KAAK,CAAC;CACd;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAUD,cAAM,aAAa;IACjB,OAAO,CAAC,QAAQ,CAAW;IAE3B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,WAAW,CAAqC;IAExD,OAAO,CAAC,SAAS,CAAoC;IAErD,OAAO,CAAC,KAAK,CAA2B;IAExC,OAAO,CAAC,KAAK,CAAQ;gBAET,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAkB,EAAE,KAAK,EAAE,EAAE,qBAAqB;IAmBlF,cAAc,CAAC,KAAK,EAAE,MAAM;IAW5B,cAAc,CAAC,KAAK,EAAE,MAAM;IAgBtB,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK;IAa5C,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK;;;;;;;;;;IAsC9C,GAAG,CAAC,OAAO,EAAE,OAAO;IAcpB,MAAM,CAAC,OAAO,EAAE,OAAO;IAMvB,MAAM,CAAC,OAAO,EAAE,OAAO;CAexB;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,aAAa,CAEtF;AAED,YAAY,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"webhook-runner.d.ts","sourceRoot":"","sources":["../../src/services/webhook-runner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,KAAK,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;AAM5C,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,KAAK,EAAE,KAAK,CAAC;CACd;AAED,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAUD,cAAM,aAAa;IACjB,OAAO,CAAC,QAAQ,CAAW;IAE3B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,WAAW,CAAqC;IAExD,OAAO,CAAC,SAAS,CAAoC;IAErD,OAAO,CAAC,KAAK,CAA2B;IAExC,OAAO,CAAC,KAAK,CAAQ;gBAET,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAkB,EAAE,KAAK,EAAE,EAAE,qBAAqB;IAmBlF,cAAc,CAAC,KAAK,EAAE,MAAM;IAW5B,cAAc,CAAC,KAAK,EAAE,MAAM;IAgBtB,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK;IAa5C,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK;;;;;;;;;;IAsC9C,GAAG,CAAC,OAAO,EAAE,OAAO;IAcpB,MAAM,CAAC,OAAO,EAAE,OAAO;IAMvB,MAAM,CAAC,OAAO,EAAE,OAAO;CAexB;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,aAAa,CAEtF;AAED,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-runner.js","sources":["../../src/services/webhook-runner.ts"],"sourcesContent":["/**\n * The event hub is Strapi's event control center.\n */\n\nimport createdDebugger from 'debug';\nimport _ from 'lodash';\nimport type { Logger } from '@strapi/logger';\n\nimport WorkerQueue from './worker-queue';\nimport type { Webhook } from './webhook-store';\nimport type { EventHub } from './event-hub';\nimport type { Fetch } from '../utils/fetch';\n\ninterface Config {\n defaultHeaders: Record<string, string>;\n}\n\ninterface ConstructorParameters {\n eventHub: EventHub;\n logger: Logger;\n configuration?: Record<string, unknown>;\n fetch: Fetch;\n}\n\ninterface Event {\n event: string;\n info: Record<string, unknown>;\n}\n\ntype Listener = (info: Record<string, unknown>) => Promise<void>;\n\nconst debug = createdDebugger('strapi:webhook');\n\nconst defaultConfiguration: Config = {\n defaultHeaders: {},\n};\n\nclass WebhookRunner {\n private eventHub: EventHub;\n\n private logger: Logger;\n\n private config: Config;\n\n private webhooksMap: Map<string, Webhook[]> = new Map();\n\n private listeners: Map<string, Listener> = new Map();\n\n private queue: WorkerQueue<Event, void>;\n\n private fetch: Fetch;\n\n constructor({ eventHub, logger, configuration = {}, fetch }: ConstructorParameters) {\n debug('Initialized webhook runner');\n this.eventHub = eventHub;\n this.logger = logger;\n this.fetch = fetch;\n\n if (typeof configuration !== 'object') {\n throw new Error(\n 'Invalid configuration provided to the webhookRunner.\\nCheck your server.json -> webhooks configuration'\n );\n }\n\n this.config = _.merge(defaultConfiguration, configuration);\n\n this.queue = new WorkerQueue({ logger, concurrency: 5 });\n\n this.queue.subscribe(this.executeListener.bind(this));\n }\n\n deleteListener(event: string) {\n debug(`Deleting listener for event '${event}'`);\n\n const fn = this.listeners.get(event);\n\n if (fn !== undefined) {\n this.eventHub.off(event, fn);\n this.listeners.delete(event);\n }\n }\n\n createListener(event: string) {\n debug(`Creating listener for event '${event}'`);\n if (this.listeners.has(event)) {\n this.logger.error(\n `The webhook runner is already listening for the event '${event}'. Did you mean to call .register() ?`\n );\n }\n\n const listen = async (info: Event['info']) => {\n this.queue.enqueue({ event, info });\n };\n\n this.listeners.set(event, listen);\n this.eventHub.on(event, listen);\n }\n\n async executeListener({ event, info }: Event) {\n debug(`Executing webhook for event '${event}'`);\n const webhooks = this.webhooksMap.get(event) || [];\n const activeWebhooks = webhooks.filter((webhook) => webhook.isEnabled === true);\n\n for (const webhook of activeWebhooks) {\n await this.run(webhook, event, info).catch((error: unknown) => {\n this.logger.error('Error running webhook');\n this.logger.error(error);\n });\n }\n }\n\n run(webhook: Webhook, event: string, info = {}) {\n const { url, headers } = webhook;\n\n return this.fetch(url, {\n method: 'post',\n body: JSON.stringify({\n event,\n createdAt: new Date(),\n ...info,\n }),\n headers: {\n ...this.config.defaultHeaders,\n ...headers,\n 'X-Strapi-Event': event,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(10000),\n })\n .then(async (res) => {\n if (res.ok) {\n return {\n statusCode: res.status,\n };\n }\n\n return {\n statusCode: res.status,\n message: await res.text(),\n };\n })\n .catch((err) => {\n return {\n statusCode: 500,\n message: err.message,\n };\n });\n }\n\n add(webhook: Webhook) {\n debug(`Registering webhook '${webhook.id}'`);\n const { events } = webhook;\n\n events.forEach((event) => {\n if (this.webhooksMap.has(event)) {\n this.webhooksMap.get(event)?.push(webhook);\n } else {\n this.webhooksMap.set(event, [webhook]);\n this.createListener(event);\n }\n });\n }\n\n update(webhook: Webhook) {\n debug(`Refreshing webhook '${webhook.id}'`);\n this.remove(webhook);\n this.add(webhook);\n }\n\n remove(webhook: Webhook) {\n debug(`Unregistering webhook '${webhook.id}'`);\n\n this.webhooksMap.forEach((webhooks, event) => {\n const filteredWebhooks = webhooks.filter((value) => value.id !== webhook.id);\n\n // Cleanup hanging listeners\n if (filteredWebhooks.length === 0) {\n this.webhooksMap.delete(event);\n this.deleteListener(event);\n } else {\n this.webhooksMap.set(event, filteredWebhooks);\n }\n });\n }\n}\n\n/**\n * Expose a factory function instead of the class\n */\nexport default function createWebhookRunner(opts: ConstructorParameters): WebhookRunner {\n return new WebhookRunner(opts);\n}\n\nexport type { WebhookRunner };\n"],"names":["createdDebugger","_","WorkerQueue"],"mappings":"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"}
1
+ {"version":3,"file":"webhook-runner.js","sources":["../../src/services/webhook-runner.ts"],"sourcesContent":["/**\n * The event hub is Strapi's event control center.\n */\n\nimport createdDebugger from 'debug';\nimport _ from 'lodash';\nimport type { Logger } from '@strapi/logger';\n\nimport type { Modules } from '@strapi/types';\nimport WorkerQueue from './worker-queue';\nimport type { EventHub } from './event-hub';\nimport type { Fetch } from '../utils/fetch';\n\ntype Webhook = Modules.WebhookStore.Webhook;\n\ninterface Config {\n defaultHeaders: Record<string, string>;\n}\n\ninterface ConstructorParameters {\n eventHub: EventHub;\n logger: Logger;\n configuration?: Record<string, unknown>;\n fetch: Fetch;\n}\n\ninterface Event {\n event: string;\n info: Record<string, unknown>;\n}\n\ntype Listener = (info: Record<string, unknown>) => Promise<void>;\n\nconst debug = createdDebugger('strapi:webhook');\n\nconst defaultConfiguration: Config = {\n defaultHeaders: {},\n};\n\nclass WebhookRunner {\n private eventHub: EventHub;\n\n private logger: Logger;\n\n private config: Config;\n\n private webhooksMap: Map<string, Webhook[]> = new Map();\n\n private listeners: Map<string, Listener> = new Map();\n\n private queue: WorkerQueue<Event, void>;\n\n private fetch: Fetch;\n\n constructor({ eventHub, logger, configuration = {}, fetch }: ConstructorParameters) {\n debug('Initialized webhook runner');\n this.eventHub = eventHub;\n this.logger = logger;\n this.fetch = fetch;\n\n if (typeof configuration !== 'object') {\n throw new Error(\n 'Invalid configuration provided to the webhookRunner.\\nCheck your server.json -> webhooks configuration'\n );\n }\n\n this.config = _.merge(defaultConfiguration, configuration);\n\n this.queue = new WorkerQueue({ logger, concurrency: 5 });\n\n this.queue.subscribe(this.executeListener.bind(this));\n }\n\n deleteListener(event: string) {\n debug(`Deleting listener for event '${event}'`);\n\n const fn = this.listeners.get(event);\n\n if (fn !== undefined) {\n this.eventHub.off(event, fn);\n this.listeners.delete(event);\n }\n }\n\n createListener(event: string) {\n debug(`Creating listener for event '${event}'`);\n if (this.listeners.has(event)) {\n this.logger.error(\n `The webhook runner is already listening for the event '${event}'. Did you mean to call .register() ?`\n );\n }\n\n const listen = async (info: Event['info']) => {\n this.queue.enqueue({ event, info });\n };\n\n this.listeners.set(event, listen);\n this.eventHub.on(event, listen);\n }\n\n async executeListener({ event, info }: Event) {\n debug(`Executing webhook for event '${event}'`);\n const webhooks = this.webhooksMap.get(event) || [];\n const activeWebhooks = webhooks.filter((webhook) => webhook.isEnabled === true);\n\n for (const webhook of activeWebhooks) {\n await this.run(webhook, event, info).catch((error: unknown) => {\n this.logger.error('Error running webhook');\n this.logger.error(error);\n });\n }\n }\n\n run(webhook: Webhook, event: string, info = {}) {\n const { url, headers } = webhook;\n\n return this.fetch(url, {\n method: 'post',\n body: JSON.stringify({\n event,\n createdAt: new Date(),\n ...info,\n }),\n headers: {\n ...this.config.defaultHeaders,\n ...headers,\n 'X-Strapi-Event': event,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(10000),\n })\n .then(async (res) => {\n if (res.ok) {\n return {\n statusCode: res.status,\n };\n }\n\n return {\n statusCode: res.status,\n message: await res.text(),\n };\n })\n .catch((err) => {\n return {\n statusCode: 500,\n message: err.message,\n };\n });\n }\n\n add(webhook: Webhook) {\n debug(`Registering webhook '${webhook.id}'`);\n const { events } = webhook;\n\n events.forEach((event) => {\n if (this.webhooksMap.has(event)) {\n this.webhooksMap.get(event)?.push(webhook);\n } else {\n this.webhooksMap.set(event, [webhook]);\n this.createListener(event);\n }\n });\n }\n\n update(webhook: Webhook) {\n debug(`Refreshing webhook '${webhook.id}'`);\n this.remove(webhook);\n this.add(webhook);\n }\n\n remove(webhook: Webhook) {\n debug(`Unregistering webhook '${webhook.id}'`);\n\n this.webhooksMap.forEach((webhooks, event) => {\n const filteredWebhooks = webhooks.filter((value) => value.id !== webhook.id);\n\n // Cleanup hanging listeners\n if (filteredWebhooks.length === 0) {\n this.webhooksMap.delete(event);\n this.deleteListener(event);\n } else {\n this.webhooksMap.set(event, filteredWebhooks);\n }\n });\n }\n}\n\n/**\n * Expose a factory function instead of the class\n */\nexport default function createWebhookRunner(opts: ConstructorParameters): WebhookRunner {\n return new WebhookRunner(opts);\n}\n\nexport type { WebhookRunner };\n"],"names":["createdDebugger","_","WorkerQueue"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-runner.mjs","sources":["../../src/services/webhook-runner.ts"],"sourcesContent":["/**\n * The event hub is Strapi's event control center.\n */\n\nimport createdDebugger from 'debug';\nimport _ from 'lodash';\nimport type { Logger } from '@strapi/logger';\n\nimport WorkerQueue from './worker-queue';\nimport type { Webhook } from './webhook-store';\nimport type { EventHub } from './event-hub';\nimport type { Fetch } from '../utils/fetch';\n\ninterface Config {\n defaultHeaders: Record<string, string>;\n}\n\ninterface ConstructorParameters {\n eventHub: EventHub;\n logger: Logger;\n configuration?: Record<string, unknown>;\n fetch: Fetch;\n}\n\ninterface Event {\n event: string;\n info: Record<string, unknown>;\n}\n\ntype Listener = (info: Record<string, unknown>) => Promise<void>;\n\nconst debug = createdDebugger('strapi:webhook');\n\nconst defaultConfiguration: Config = {\n defaultHeaders: {},\n};\n\nclass WebhookRunner {\n private eventHub: EventHub;\n\n private logger: Logger;\n\n private config: Config;\n\n private webhooksMap: Map<string, Webhook[]> = new Map();\n\n private listeners: Map<string, Listener> = new Map();\n\n private queue: WorkerQueue<Event, void>;\n\n private fetch: Fetch;\n\n constructor({ eventHub, logger, configuration = {}, fetch }: ConstructorParameters) {\n debug('Initialized webhook runner');\n this.eventHub = eventHub;\n this.logger = logger;\n this.fetch = fetch;\n\n if (typeof configuration !== 'object') {\n throw new Error(\n 'Invalid configuration provided to the webhookRunner.\\nCheck your server.json -> webhooks configuration'\n );\n }\n\n this.config = _.merge(defaultConfiguration, configuration);\n\n this.queue = new WorkerQueue({ logger, concurrency: 5 });\n\n this.queue.subscribe(this.executeListener.bind(this));\n }\n\n deleteListener(event: string) {\n debug(`Deleting listener for event '${event}'`);\n\n const fn = this.listeners.get(event);\n\n if (fn !== undefined) {\n this.eventHub.off(event, fn);\n this.listeners.delete(event);\n }\n }\n\n createListener(event: string) {\n debug(`Creating listener for event '${event}'`);\n if (this.listeners.has(event)) {\n this.logger.error(\n `The webhook runner is already listening for the event '${event}'. Did you mean to call .register() ?`\n );\n }\n\n const listen = async (info: Event['info']) => {\n this.queue.enqueue({ event, info });\n };\n\n this.listeners.set(event, listen);\n this.eventHub.on(event, listen);\n }\n\n async executeListener({ event, info }: Event) {\n debug(`Executing webhook for event '${event}'`);\n const webhooks = this.webhooksMap.get(event) || [];\n const activeWebhooks = webhooks.filter((webhook) => webhook.isEnabled === true);\n\n for (const webhook of activeWebhooks) {\n await this.run(webhook, event, info).catch((error: unknown) => {\n this.logger.error('Error running webhook');\n this.logger.error(error);\n });\n }\n }\n\n run(webhook: Webhook, event: string, info = {}) {\n const { url, headers } = webhook;\n\n return this.fetch(url, {\n method: 'post',\n body: JSON.stringify({\n event,\n createdAt: new Date(),\n ...info,\n }),\n headers: {\n ...this.config.defaultHeaders,\n ...headers,\n 'X-Strapi-Event': event,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(10000),\n })\n .then(async (res) => {\n if (res.ok) {\n return {\n statusCode: res.status,\n };\n }\n\n return {\n statusCode: res.status,\n message: await res.text(),\n };\n })\n .catch((err) => {\n return {\n statusCode: 500,\n message: err.message,\n };\n });\n }\n\n add(webhook: Webhook) {\n debug(`Registering webhook '${webhook.id}'`);\n const { events } = webhook;\n\n events.forEach((event) => {\n if (this.webhooksMap.has(event)) {\n this.webhooksMap.get(event)?.push(webhook);\n } else {\n this.webhooksMap.set(event, [webhook]);\n this.createListener(event);\n }\n });\n }\n\n update(webhook: Webhook) {\n debug(`Refreshing webhook '${webhook.id}'`);\n this.remove(webhook);\n this.add(webhook);\n }\n\n remove(webhook: Webhook) {\n debug(`Unregistering webhook '${webhook.id}'`);\n\n this.webhooksMap.forEach((webhooks, event) => {\n const filteredWebhooks = webhooks.filter((value) => value.id !== webhook.id);\n\n // Cleanup hanging listeners\n if (filteredWebhooks.length === 0) {\n this.webhooksMap.delete(event);\n this.deleteListener(event);\n } else {\n this.webhooksMap.set(event, filteredWebhooks);\n }\n });\n }\n}\n\n/**\n * Expose a factory function instead of the class\n */\nexport default function createWebhookRunner(opts: ConstructorParameters): WebhookRunner {\n return new WebhookRunner(opts);\n}\n\nexport type { WebhookRunner };\n"],"names":["createdDebugger"],"mappings":"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"}
1
+ {"version":3,"file":"webhook-runner.mjs","sources":["../../src/services/webhook-runner.ts"],"sourcesContent":["/**\n * The event hub is Strapi's event control center.\n */\n\nimport createdDebugger from 'debug';\nimport _ from 'lodash';\nimport type { Logger } from '@strapi/logger';\n\nimport type { Modules } from '@strapi/types';\nimport WorkerQueue from './worker-queue';\nimport type { EventHub } from './event-hub';\nimport type { Fetch } from '../utils/fetch';\n\ntype Webhook = Modules.WebhookStore.Webhook;\n\ninterface Config {\n defaultHeaders: Record<string, string>;\n}\n\ninterface ConstructorParameters {\n eventHub: EventHub;\n logger: Logger;\n configuration?: Record<string, unknown>;\n fetch: Fetch;\n}\n\ninterface Event {\n event: string;\n info: Record<string, unknown>;\n}\n\ntype Listener = (info: Record<string, unknown>) => Promise<void>;\n\nconst debug = createdDebugger('strapi:webhook');\n\nconst defaultConfiguration: Config = {\n defaultHeaders: {},\n};\n\nclass WebhookRunner {\n private eventHub: EventHub;\n\n private logger: Logger;\n\n private config: Config;\n\n private webhooksMap: Map<string, Webhook[]> = new Map();\n\n private listeners: Map<string, Listener> = new Map();\n\n private queue: WorkerQueue<Event, void>;\n\n private fetch: Fetch;\n\n constructor({ eventHub, logger, configuration = {}, fetch }: ConstructorParameters) {\n debug('Initialized webhook runner');\n this.eventHub = eventHub;\n this.logger = logger;\n this.fetch = fetch;\n\n if (typeof configuration !== 'object') {\n throw new Error(\n 'Invalid configuration provided to the webhookRunner.\\nCheck your server.json -> webhooks configuration'\n );\n }\n\n this.config = _.merge(defaultConfiguration, configuration);\n\n this.queue = new WorkerQueue({ logger, concurrency: 5 });\n\n this.queue.subscribe(this.executeListener.bind(this));\n }\n\n deleteListener(event: string) {\n debug(`Deleting listener for event '${event}'`);\n\n const fn = this.listeners.get(event);\n\n if (fn !== undefined) {\n this.eventHub.off(event, fn);\n this.listeners.delete(event);\n }\n }\n\n createListener(event: string) {\n debug(`Creating listener for event '${event}'`);\n if (this.listeners.has(event)) {\n this.logger.error(\n `The webhook runner is already listening for the event '${event}'. Did you mean to call .register() ?`\n );\n }\n\n const listen = async (info: Event['info']) => {\n this.queue.enqueue({ event, info });\n };\n\n this.listeners.set(event, listen);\n this.eventHub.on(event, listen);\n }\n\n async executeListener({ event, info }: Event) {\n debug(`Executing webhook for event '${event}'`);\n const webhooks = this.webhooksMap.get(event) || [];\n const activeWebhooks = webhooks.filter((webhook) => webhook.isEnabled === true);\n\n for (const webhook of activeWebhooks) {\n await this.run(webhook, event, info).catch((error: unknown) => {\n this.logger.error('Error running webhook');\n this.logger.error(error);\n });\n }\n }\n\n run(webhook: Webhook, event: string, info = {}) {\n const { url, headers } = webhook;\n\n return this.fetch(url, {\n method: 'post',\n body: JSON.stringify({\n event,\n createdAt: new Date(),\n ...info,\n }),\n headers: {\n ...this.config.defaultHeaders,\n ...headers,\n 'X-Strapi-Event': event,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(10000),\n })\n .then(async (res) => {\n if (res.ok) {\n return {\n statusCode: res.status,\n };\n }\n\n return {\n statusCode: res.status,\n message: await res.text(),\n };\n })\n .catch((err) => {\n return {\n statusCode: 500,\n message: err.message,\n };\n });\n }\n\n add(webhook: Webhook) {\n debug(`Registering webhook '${webhook.id}'`);\n const { events } = webhook;\n\n events.forEach((event) => {\n if (this.webhooksMap.has(event)) {\n this.webhooksMap.get(event)?.push(webhook);\n } else {\n this.webhooksMap.set(event, [webhook]);\n this.createListener(event);\n }\n });\n }\n\n update(webhook: Webhook) {\n debug(`Refreshing webhook '${webhook.id}'`);\n this.remove(webhook);\n this.add(webhook);\n }\n\n remove(webhook: Webhook) {\n debug(`Unregistering webhook '${webhook.id}'`);\n\n this.webhooksMap.forEach((webhooks, event) => {\n const filteredWebhooks = webhooks.filter((value) => value.id !== webhook.id);\n\n // Cleanup hanging listeners\n if (filteredWebhooks.length === 0) {\n this.webhooksMap.delete(event);\n this.deleteListener(event);\n } else {\n this.webhooksMap.set(event, filteredWebhooks);\n }\n });\n }\n}\n\n/**\n * Expose a factory function instead of the class\n */\nexport default function createWebhookRunner(opts: ConstructorParameters): WebhookRunner {\n return new WebhookRunner(opts);\n}\n\nexport type { WebhookRunner };\n"],"names":["createdDebugger"],"mappings":"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"}
@@ -2,15 +2,9 @@
2
2
  * Webhook store is the implementation of webhook storage over the core_store
3
3
  */
4
4
  import type { Model, Database } from '@strapi/database';
5
+ import type { Modules } from '@strapi/types';
5
6
  declare const webhookModel: Model;
6
- export interface Webhook {
7
- id: string;
8
- name: string;
9
- url: string;
10
- headers: Record<string, string>;
11
- events: string[];
12
- isEnabled: boolean;
13
- }
7
+ type Webhook = Modules.WebhookStore.Webhook;
14
8
  export interface WebhookStore {
15
9
  allowedEvents: Map<string, string>;
16
10
  addAllowedEvent(key: string, value: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-store.d.ts","sourceRoot":"","sources":["../../src/services/webhook-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIxD,QAAA,MAAM,YAAY,EAAE,KAwBnB,CAAC;AAmBF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAmCD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,IAAI,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACjD,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAClE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACpD;AAED,QAAA,MAAM,kBAAkB,WAAY;IAAE,EAAE,EAAE,QAAQ,CAAA;CAAE,KAAG,YAiDtD,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"webhook-store.d.ts","sourceRoot":"","sources":["../../src/services/webhook-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C,QAAA,MAAM,YAAY,EAAE,KAwBnB,CAAC;AAEF,KAAK,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;AAqC5C,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,IAAI,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACjD,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAClE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACpD;AAED,QAAA,MAAM,kBAAkB,WAAY;IAAE,EAAE,EAAE,QAAQ,CAAA;CAAE,KAAG,YAwDtD,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
@@ -38,7 +38,7 @@ const toDBObject = (data) => {
38
38
  };
39
39
  const fromDBObject = (row) => {
40
40
  return {
41
- id: row.id,
41
+ id: typeof row.id === "number" ? row.id.toString() : row.id,
42
42
  name: row.name,
43
43
  url: row.url,
44
44
  headers: row.headers,
@@ -57,7 +57,14 @@ const webhookEventValidator = async (allowedEvents, events) => {
57
57
  };
58
58
  const createWebhookStore = ({ db }) => {
59
59
  return {
60
- allowedEvents: /* @__PURE__ */ new Map([]),
60
+ allowedEvents: /* @__PURE__ */ new Map([
61
+ ["ENTRY_CREATE", "entry.create"],
62
+ ["ENTRY_UPDATE", "entry.update"],
63
+ ["ENTRY_DELETE", "entry.delete"],
64
+ ["ENTRY_PUBLISH", "entry.publish"],
65
+ ["ENTRY_UNPUBLISH", "entry.unpublish"],
66
+ ["ENTRY_DRAFT_DISCARD", "entry.draft-discard"]
67
+ ]),
61
68
  addAllowedEvent(key, value) {
62
69
  this.allowedEvents.set(key, value);
63
70
  },
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-store.js","sources":["../../src/services/webhook-store.ts"],"sourcesContent":["/**\n * Webhook store is the implementation of webhook storage over the core_store\n */\n\nimport { errors } from '@strapi/utils';\nimport type { Model, Database } from '@strapi/database';\n\nconst { ValidationError } = errors;\n\nconst webhookModel: Model = {\n uid: 'strapi::webhook',\n singularName: 'strapi_webhooks',\n tableName: 'strapi_webhooks',\n attributes: {\n id: {\n type: 'increments',\n },\n name: {\n type: 'string',\n },\n url: {\n type: 'text',\n },\n headers: {\n type: 'json',\n },\n events: {\n type: 'json',\n },\n enabled: {\n type: 'boolean',\n },\n },\n};\n\ninterface DBInput {\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n enabled: boolean;\n}\n\ninterface DBOutput {\n id: string;\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n enabled: boolean;\n}\n\nexport interface Webhook {\n id: string;\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n isEnabled: boolean;\n}\n\nconst toDBObject = (data: Webhook): DBInput => {\n return {\n name: data.name,\n url: data.url,\n headers: data.headers,\n events: data.events,\n enabled: data.isEnabled,\n };\n};\n\nconst fromDBObject = (row: DBOutput): Webhook => {\n return {\n id: row.id,\n name: row.name,\n url: row.url,\n headers: row.headers,\n events: row.events,\n isEnabled: row.enabled,\n };\n};\n\nconst webhookEventValidator = async (allowedEvents: Map<string, string>, events: string[]) => {\n const allowedValues = Array.from(allowedEvents.values());\n\n events.forEach((event) => {\n if (allowedValues.includes(event)) {\n return;\n }\n\n throw new ValidationError(`Webhook event ${event} is not supported`);\n });\n};\n\nexport interface WebhookStore {\n allowedEvents: Map<string, string>;\n addAllowedEvent(key: string, value: string): void;\n removeAllowedEvent(key: string): void;\n listAllowedEvents(): string[];\n getAllowedEvent(key: string): string | undefined;\n findWebhooks(): Promise<Webhook[]>;\n findWebhook(id: string): Promise<Webhook | null>;\n createWebhook(data: Webhook): Promise<Webhook>;\n updateWebhook(id: string, data: Webhook): Promise<Webhook | null>;\n deleteWebhook(id: string): Promise<Webhook | null>;\n}\n\nconst createWebhookStore = ({ db }: { db: Database }): WebhookStore => {\n return {\n allowedEvents: new Map([]),\n addAllowedEvent(key, value) {\n this.allowedEvents.set(key, value);\n },\n removeAllowedEvent(key) {\n this.allowedEvents.delete(key);\n },\n listAllowedEvents() {\n return Array.from(this.allowedEvents.keys());\n },\n getAllowedEvent(key) {\n return this.allowedEvents.get(key);\n },\n async findWebhooks() {\n const results = await db.query('strapi::webhook').findMany();\n\n return results.map(fromDBObject);\n },\n async findWebhook(id) {\n const result = await db.query('strapi::webhook').findOne({ where: { id } });\n return result ? fromDBObject(result) : null;\n },\n async createWebhook(data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n return db\n .query('strapi::webhook')\n .create({\n data: toDBObject({ ...data, isEnabled: true }),\n })\n .then(fromDBObject);\n },\n async updateWebhook(id, data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n const webhook = await db.query('strapi::webhook').update({\n where: { id },\n data: toDBObject(data),\n });\n\n return webhook ? fromDBObject(webhook) : null;\n },\n async deleteWebhook(id) {\n const webhook = await db.query('strapi::webhook').delete({ where: { id } });\n return webhook ? fromDBObject(webhook) : null;\n },\n };\n};\n\nexport { webhookModel, createWebhookStore };\n"],"names":["errors"],"mappings":"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"}
1
+ {"version":3,"file":"webhook-store.js","sources":["../../src/services/webhook-store.ts"],"sourcesContent":["/**\n * Webhook store is the implementation of webhook storage over the core_store\n */\n\nimport { errors } from '@strapi/utils';\nimport type { Model, Database } from '@strapi/database';\nimport type { Modules } from '@strapi/types';\n\nconst { ValidationError } = errors;\n\nconst webhookModel: Model = {\n uid: 'strapi::webhook',\n singularName: 'strapi_webhooks',\n tableName: 'strapi_webhooks',\n attributes: {\n id: {\n type: 'increments',\n },\n name: {\n type: 'string',\n },\n url: {\n type: 'text',\n },\n headers: {\n type: 'json',\n },\n events: {\n type: 'json',\n },\n enabled: {\n type: 'boolean',\n },\n },\n};\n\ntype Webhook = Modules.WebhookStore.Webhook;\ntype DBOutput = Omit<Webhook, 'id' | 'isEnabled'> & { id: string | number; enabled: boolean };\ntype DBInput = Omit<DBOutput, 'id'>;\n\nconst toDBObject = (data: Webhook): DBInput => {\n return {\n name: data.name,\n url: data.url,\n headers: data.headers,\n events: data.events,\n enabled: data.isEnabled,\n };\n};\n\nconst fromDBObject = (row: DBOutput): Webhook => {\n return {\n id: typeof row.id === 'number' ? row.id.toString() : row.id,\n name: row.name,\n url: row.url,\n headers: row.headers,\n events: row.events,\n isEnabled: row.enabled,\n };\n};\n\nconst webhookEventValidator = async (allowedEvents: Map<string, string>, events: string[]) => {\n const allowedValues = Array.from(allowedEvents.values());\n\n events.forEach((event) => {\n if (allowedValues.includes(event)) {\n return;\n }\n\n throw new ValidationError(`Webhook event ${event} is not supported`);\n });\n};\n\nexport interface WebhookStore {\n allowedEvents: Map<string, string>;\n addAllowedEvent(key: string, value: string): void;\n removeAllowedEvent(key: string): void;\n listAllowedEvents(): string[];\n getAllowedEvent(key: string): string | undefined;\n findWebhooks(): Promise<Webhook[]>;\n findWebhook(id: string): Promise<Webhook | null>;\n createWebhook(data: Webhook): Promise<Webhook>;\n updateWebhook(id: string, data: Webhook): Promise<Webhook | null>;\n deleteWebhook(id: string): Promise<Webhook | null>;\n}\n\nconst createWebhookStore = ({ db }: { db: Database }): WebhookStore => {\n return {\n allowedEvents: new Map([\n ['ENTRY_CREATE', 'entry.create'],\n ['ENTRY_UPDATE', 'entry.update'],\n ['ENTRY_DELETE', 'entry.delete'],\n ['ENTRY_PUBLISH', 'entry.publish'],\n ['ENTRY_UNPUBLISH', 'entry.unpublish'],\n ['ENTRY_DRAFT_DISCARD', 'entry.draft-discard'],\n ]),\n addAllowedEvent(key, value) {\n this.allowedEvents.set(key, value);\n },\n removeAllowedEvent(key) {\n this.allowedEvents.delete(key);\n },\n listAllowedEvents() {\n return Array.from(this.allowedEvents.keys());\n },\n getAllowedEvent(key) {\n return this.allowedEvents.get(key);\n },\n async findWebhooks() {\n const results = await db.query('strapi::webhook').findMany();\n\n return results.map(fromDBObject);\n },\n async findWebhook(id) {\n const result = await db.query('strapi::webhook').findOne({ where: { id } });\n return result ? fromDBObject(result) : null;\n },\n async createWebhook(data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n return db\n .query('strapi::webhook')\n .create({\n data: toDBObject({ ...data, isEnabled: true }),\n })\n .then(fromDBObject);\n },\n async updateWebhook(id, data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n const webhook = await db.query('strapi::webhook').update({\n where: { id },\n data: toDBObject(data),\n });\n\n return webhook ? fromDBObject(webhook) : null;\n },\n async deleteWebhook(id) {\n const webhook = await db.query('strapi::webhook').delete({ where: { id } });\n return webhook ? fromDBObject(webhook) : null;\n },\n };\n};\n\nexport { webhookModel, createWebhookStore };\n"],"names":["errors"],"mappings":"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"}
@@ -36,7 +36,7 @@ const toDBObject = (data) => {
36
36
  };
37
37
  const fromDBObject = (row) => {
38
38
  return {
39
- id: row.id,
39
+ id: typeof row.id === "number" ? row.id.toString() : row.id,
40
40
  name: row.name,
41
41
  url: row.url,
42
42
  headers: row.headers,
@@ -55,7 +55,14 @@ const webhookEventValidator = async (allowedEvents, events) => {
55
55
  };
56
56
  const createWebhookStore = ({ db }) => {
57
57
  return {
58
- allowedEvents: /* @__PURE__ */ new Map([]),
58
+ allowedEvents: /* @__PURE__ */ new Map([
59
+ ["ENTRY_CREATE", "entry.create"],
60
+ ["ENTRY_UPDATE", "entry.update"],
61
+ ["ENTRY_DELETE", "entry.delete"],
62
+ ["ENTRY_PUBLISH", "entry.publish"],
63
+ ["ENTRY_UNPUBLISH", "entry.unpublish"],
64
+ ["ENTRY_DRAFT_DISCARD", "entry.draft-discard"]
65
+ ]),
59
66
  addAllowedEvent(key, value) {
60
67
  this.allowedEvents.set(key, value);
61
68
  },
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-store.mjs","sources":["../../src/services/webhook-store.ts"],"sourcesContent":["/**\n * Webhook store is the implementation of webhook storage over the core_store\n */\n\nimport { errors } from '@strapi/utils';\nimport type { Model, Database } from '@strapi/database';\n\nconst { ValidationError } = errors;\n\nconst webhookModel: Model = {\n uid: 'strapi::webhook',\n singularName: 'strapi_webhooks',\n tableName: 'strapi_webhooks',\n attributes: {\n id: {\n type: 'increments',\n },\n name: {\n type: 'string',\n },\n url: {\n type: 'text',\n },\n headers: {\n type: 'json',\n },\n events: {\n type: 'json',\n },\n enabled: {\n type: 'boolean',\n },\n },\n};\n\ninterface DBInput {\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n enabled: boolean;\n}\n\ninterface DBOutput {\n id: string;\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n enabled: boolean;\n}\n\nexport interface Webhook {\n id: string;\n name: string;\n url: string;\n headers: Record<string, string>;\n events: string[];\n isEnabled: boolean;\n}\n\nconst toDBObject = (data: Webhook): DBInput => {\n return {\n name: data.name,\n url: data.url,\n headers: data.headers,\n events: data.events,\n enabled: data.isEnabled,\n };\n};\n\nconst fromDBObject = (row: DBOutput): Webhook => {\n return {\n id: row.id,\n name: row.name,\n url: row.url,\n headers: row.headers,\n events: row.events,\n isEnabled: row.enabled,\n };\n};\n\nconst webhookEventValidator = async (allowedEvents: Map<string, string>, events: string[]) => {\n const allowedValues = Array.from(allowedEvents.values());\n\n events.forEach((event) => {\n if (allowedValues.includes(event)) {\n return;\n }\n\n throw new ValidationError(`Webhook event ${event} is not supported`);\n });\n};\n\nexport interface WebhookStore {\n allowedEvents: Map<string, string>;\n addAllowedEvent(key: string, value: string): void;\n removeAllowedEvent(key: string): void;\n listAllowedEvents(): string[];\n getAllowedEvent(key: string): string | undefined;\n findWebhooks(): Promise<Webhook[]>;\n findWebhook(id: string): Promise<Webhook | null>;\n createWebhook(data: Webhook): Promise<Webhook>;\n updateWebhook(id: string, data: Webhook): Promise<Webhook | null>;\n deleteWebhook(id: string): Promise<Webhook | null>;\n}\n\nconst createWebhookStore = ({ db }: { db: Database }): WebhookStore => {\n return {\n allowedEvents: new Map([]),\n addAllowedEvent(key, value) {\n this.allowedEvents.set(key, value);\n },\n removeAllowedEvent(key) {\n this.allowedEvents.delete(key);\n },\n listAllowedEvents() {\n return Array.from(this.allowedEvents.keys());\n },\n getAllowedEvent(key) {\n return this.allowedEvents.get(key);\n },\n async findWebhooks() {\n const results = await db.query('strapi::webhook').findMany();\n\n return results.map(fromDBObject);\n },\n async findWebhook(id) {\n const result = await db.query('strapi::webhook').findOne({ where: { id } });\n return result ? fromDBObject(result) : null;\n },\n async createWebhook(data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n return db\n .query('strapi::webhook')\n .create({\n data: toDBObject({ ...data, isEnabled: true }),\n })\n .then(fromDBObject);\n },\n async updateWebhook(id, data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n const webhook = await db.query('strapi::webhook').update({\n where: { id },\n data: toDBObject(data),\n });\n\n return webhook ? fromDBObject(webhook) : null;\n },\n async deleteWebhook(id) {\n const webhook = await db.query('strapi::webhook').delete({ where: { id } });\n return webhook ? fromDBObject(webhook) : null;\n },\n };\n};\n\nexport { webhookModel, createWebhookStore };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhook-store.mjs","sources":["../../src/services/webhook-store.ts"],"sourcesContent":["/**\n * Webhook store is the implementation of webhook storage over the core_store\n */\n\nimport { errors } from '@strapi/utils';\nimport type { Model, Database } from '@strapi/database';\nimport type { Modules } from '@strapi/types';\n\nconst { ValidationError } = errors;\n\nconst webhookModel: Model = {\n uid: 'strapi::webhook',\n singularName: 'strapi_webhooks',\n tableName: 'strapi_webhooks',\n attributes: {\n id: {\n type: 'increments',\n },\n name: {\n type: 'string',\n },\n url: {\n type: 'text',\n },\n headers: {\n type: 'json',\n },\n events: {\n type: 'json',\n },\n enabled: {\n type: 'boolean',\n },\n },\n};\n\ntype Webhook = Modules.WebhookStore.Webhook;\ntype DBOutput = Omit<Webhook, 'id' | 'isEnabled'> & { id: string | number; enabled: boolean };\ntype DBInput = Omit<DBOutput, 'id'>;\n\nconst toDBObject = (data: Webhook): DBInput => {\n return {\n name: data.name,\n url: data.url,\n headers: data.headers,\n events: data.events,\n enabled: data.isEnabled,\n };\n};\n\nconst fromDBObject = (row: DBOutput): Webhook => {\n return {\n id: typeof row.id === 'number' ? row.id.toString() : row.id,\n name: row.name,\n url: row.url,\n headers: row.headers,\n events: row.events,\n isEnabled: row.enabled,\n };\n};\n\nconst webhookEventValidator = async (allowedEvents: Map<string, string>, events: string[]) => {\n const allowedValues = Array.from(allowedEvents.values());\n\n events.forEach((event) => {\n if (allowedValues.includes(event)) {\n return;\n }\n\n throw new ValidationError(`Webhook event ${event} is not supported`);\n });\n};\n\nexport interface WebhookStore {\n allowedEvents: Map<string, string>;\n addAllowedEvent(key: string, value: string): void;\n removeAllowedEvent(key: string): void;\n listAllowedEvents(): string[];\n getAllowedEvent(key: string): string | undefined;\n findWebhooks(): Promise<Webhook[]>;\n findWebhook(id: string): Promise<Webhook | null>;\n createWebhook(data: Webhook): Promise<Webhook>;\n updateWebhook(id: string, data: Webhook): Promise<Webhook | null>;\n deleteWebhook(id: string): Promise<Webhook | null>;\n}\n\nconst createWebhookStore = ({ db }: { db: Database }): WebhookStore => {\n return {\n allowedEvents: new Map([\n ['ENTRY_CREATE', 'entry.create'],\n ['ENTRY_UPDATE', 'entry.update'],\n ['ENTRY_DELETE', 'entry.delete'],\n ['ENTRY_PUBLISH', 'entry.publish'],\n ['ENTRY_UNPUBLISH', 'entry.unpublish'],\n ['ENTRY_DRAFT_DISCARD', 'entry.draft-discard'],\n ]),\n addAllowedEvent(key, value) {\n this.allowedEvents.set(key, value);\n },\n removeAllowedEvent(key) {\n this.allowedEvents.delete(key);\n },\n listAllowedEvents() {\n return Array.from(this.allowedEvents.keys());\n },\n getAllowedEvent(key) {\n return this.allowedEvents.get(key);\n },\n async findWebhooks() {\n const results = await db.query('strapi::webhook').findMany();\n\n return results.map(fromDBObject);\n },\n async findWebhook(id) {\n const result = await db.query('strapi::webhook').findOne({ where: { id } });\n return result ? fromDBObject(result) : null;\n },\n async createWebhook(data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n return db\n .query('strapi::webhook')\n .create({\n data: toDBObject({ ...data, isEnabled: true }),\n })\n .then(fromDBObject);\n },\n async updateWebhook(id, data) {\n await webhookEventValidator(this.allowedEvents, data.events);\n\n const webhook = await db.query('strapi::webhook').update({\n where: { id },\n data: toDBObject(data),\n });\n\n return webhook ? fromDBObject(webhook) : null;\n },\n async deleteWebhook(id) {\n const webhook = await db.query('strapi::webhook').delete({ where: { id } });\n return webhook ? fromDBObject(webhook) : null;\n },\n };\n};\n\nexport { webhookModel, createWebhookStore };\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAMnD,eAAO,MAAM,iBAAiB,WAAY,KAAK,MAAM,KAAG,aAAa,MAkBpE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAMnD,eAAO,MAAM,iBAAiB,WAAY,KAAK,MAAM,KAAG,aAAa,MAoBpE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC"}
@@ -10,9 +10,10 @@ const createStrapiFetch = (strapi) => {
10
10
  strapi.log.debug(`Making request for ${url}`);
11
11
  return fetch(url, fetchOptions);
12
12
  }
13
- const globalProxy = strapi.config.get("server.globalProxy");
14
- if (globalProxy) {
15
- strapiFetch.dispatcher = new undici.ProxyAgent(globalProxy);
13
+ const proxy = strapi.config.get("server.proxy.fetch") || strapi.config.get("server.proxy.global");
14
+ if (proxy) {
15
+ strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);
16
+ strapiFetch.dispatcher = new undici.ProxyAgent(proxy);
16
17
  }
17
18
  return strapiFetch;
18
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const globalProxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.globalProxy');\n\n if (globalProxy) {\n strapiFetch.dispatcher = new ProxyAgent(globalProxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":["ProxyAgent"],"mappings":";;;AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEA,QAAM,cACJ,OAAO,OAAO,IAAiD,oBAAoB;AAErF,MAAI,aAAa;AACH,gBAAA,aAAa,IAAIA,OAAA,WAAW,WAAW;AAAA,EACrD;AAEO,SAAA;AACT;;"}
1
+ {"version":3,"file":"fetch.js","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const proxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.proxy.fetch') ||\n strapi.config.get<string>('server.proxy.global');\n\n if (proxy) {\n strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);\n strapiFetch.dispatcher = new ProxyAgent(proxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":["ProxyAgent"],"mappings":";;;AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEM,QAAA,QACJ,OAAO,OAAO,IAAiD,oBAAoB,KACnF,OAAO,OAAO,IAAY,qBAAqB;AAEjD,MAAI,OAAO;AACT,WAAO,IAAI,KAAK,mCAAmC,KAAK,EAAE;AAC9C,gBAAA,aAAa,IAAIA,OAAA,WAAW,KAAK;AAAA,EAC/C;AAEO,SAAA;AACT;;"}
@@ -8,9 +8,10 @@ const createStrapiFetch = (strapi) => {
8
8
  strapi.log.debug(`Making request for ${url}`);
9
9
  return fetch(url, fetchOptions);
10
10
  }
11
- const globalProxy = strapi.config.get("server.globalProxy");
12
- if (globalProxy) {
13
- strapiFetch.dispatcher = new ProxyAgent(globalProxy);
11
+ const proxy = strapi.config.get("server.proxy.fetch") || strapi.config.get("server.proxy.global");
12
+ if (proxy) {
13
+ strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);
14
+ strapiFetch.dispatcher = new ProxyAgent(proxy);
14
15
  }
15
16
  return strapiFetch;
16
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.mjs","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const globalProxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.globalProxy');\n\n if (globalProxy) {\n strapiFetch.dispatcher = new ProxyAgent(globalProxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":[],"mappings":";AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEA,QAAM,cACJ,OAAO,OAAO,IAAiD,oBAAoB;AAErF,MAAI,aAAa;AACH,gBAAA,aAAa,IAAI,WAAW,WAAW;AAAA,EACrD;AAEO,SAAA;AACT;"}
1
+ {"version":3,"file":"fetch.mjs","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const proxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.proxy.fetch') ||\n strapi.config.get<string>('server.proxy.global');\n\n if (proxy) {\n strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);\n strapiFetch.dispatcher = new ProxyAgent(proxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":[],"mappings":";AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEM,QAAA,QACJ,OAAO,OAAO,IAAiD,oBAAoB,KACnF,OAAO,OAAO,IAAY,qBAAqB;AAEjD,MAAI,OAAO;AACT,WAAO,IAAI,KAAK,mCAAmC,KAAK,EAAE;AAC9C,gBAAA,aAAa,IAAI,WAAW,KAAK;AAAA,EAC/C;AAEO,SAAA;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"transform-content-types-to-models.d.ts","sourceRoot":"","sources":["../../src/utils/transform-content-types-to-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIhD;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,yBAAyB,mBAAoB,MAAM,eAAe,WAAW,WAKzF,CAAC;AAEF,eAAO,MAAM,kBAAkB,mBAAoB,MAAM,eAAe,WAAW,WAKlF,CAAC;AAEF,eAAO,MAAM,gCAAgC,gBAAiB,WAAW,WAKxE,CAAC;AAEF,eAAO,MAAM,iCAAiC,gBAAiB,WAAW,WAKzE,CAAC;AAEF,eAAO,MAAM,sBAAsB,gBAAiB,WAAW,WAE9D,CAAC;AAEF,eAAO,MAAM,uBAAuB,gBAAiB,MAAM,eAAe,WAAW,WAMpF,CAAC;AAIF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,iBAAiB,GAC3D,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;AAGnF,eAAO,MAAM,kBAAkB,SACvB,MAAM,aACD,OAAO,SAAS,CAAC,YAAY,eAC3B,sBAAsB,eACtB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,gBACjB,sBAAsB,eACtB,WAAW,OAazB,CAAC;AAEF,eAAO,MAAM,iBAAiB,gBACf,sBAAsB;UACc,aAAa,GAAG,WAAW;CAI7E,CAAC;AAEF,eAAO,MAAM,gBAAgB,iBAAW,CAAC;AAgFzC,eAAO,MAAM,6BAA6B,iBAC1B,sBAAsB,EAAE,eACzB,WAAW,KACvB,KAAK,EAiDP,CAAC"}
1
+ {"version":3,"file":"transform-content-types-to-models.d.ts","sourceRoot":"","sources":["../../src/utils/transform-content-types-to-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIhD;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,yBAAyB,mBAAoB,MAAM,eAAe,WAAW,WAKzF,CAAC;AAEF,eAAO,MAAM,kBAAkB,mBAAoB,MAAM,eAAe,WAAW,WAKlF,CAAC;AAEF,eAAO,MAAM,gCAAgC,gBAAiB,WAAW,WAKxE,CAAC;AAEF,eAAO,MAAM,iCAAiC,gBAAiB,WAAW,WAKzE,CAAC;AAEF,eAAO,MAAM,sBAAsB,gBAAiB,WAAW,WAE9D,CAAC;AAEF,eAAO,MAAM,uBAAuB,gBAAiB,MAAM,eAAe,WAAW,WAMpF,CAAC;AAIF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,iBAAiB,GAC3D,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;AAGnF,eAAO,MAAM,kBAAkB,SACvB,MAAM,aACD,OAAO,SAAS,CAAC,YAAY,eAC3B,sBAAsB,eACtB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,gBACjB,sBAAsB,eACtB,WAAW,OAazB,CAAC;AAEF,eAAO,MAAM,iBAAiB,gBACf,sBAAsB;UACc,aAAa,GAAG,WAAW;CAI7E,CAAC;AAEF,eAAO,MAAM,gBAAgB,iBAAW,CAAC;AAgFzC,eAAO,MAAM,6BAA6B,iBAC1B,sBAAsB,EAAE,eACzB,WAAW,KACvB,KAAK,EA+DP,CAAC"}
@@ -257,6 +257,16 @@ const transformContentTypesToModels = (contentTypes, identifiers) => {
257
257
  ...transformAttributes(contentType, identifiers)
258
258
  }
259
259
  };
260
+ if (contentType.modelType === "contentType") {
261
+ model.indexes = [
262
+ ...model.indexes || [],
263
+ {
264
+ name: identifiers.getIndexName([contentType.collectionName, "documents"]),
265
+ // Filter attributes that are not in the schema
266
+ columns: ["documentId", "locale", "publishedAt"].filter((n) => model.attributes[n]).map((name) => identifiers.getColumnName(___default.default.snakeCase(name)))
267
+ }
268
+ ];
269
+ }
260
270
  models.push(model);
261
271
  });
262
272
  return models;
@@ -1 +1 @@
1
- {"version":3,"file":"transform-content-types-to-models.js","sources":["../../src/utils/transform-content-types-to-models.ts"],"sourcesContent":["import { type Model, type Identifiers } from '@strapi/database';\nimport type { Struct, Schema } from '@strapi/types';\nimport { createId } from '@paralleldrive/cuid2';\nimport assert from 'node:assert';\nimport _ from 'lodash/fp';\n\n/**\n * Because strapi/database models don't know about things like components or dynamic zones, we use this file to convert them\n * to a relations format that it recognizes\n *\n * Therefore we have to keep an additional set of helpers/extensions to the database naming methods\n *\n * IMPORTANT!\n * If we use short versions of anything, we MUST call getNameFromTokens directly; attempting to shorten them ourselves\n * prevents the unshortened name map from being filled properly, so for example it will think that the short name\n * 'collection4f3a_cmps' maps to the unshortened 'collectionname_cmps' rather than 'collectionname_components'\n * Therefore, we only use the identifiers helpers in cases where we do not do any of our own shortening\n */\n\nexport const getComponentJoinTableName = (collectionName: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: collectionName, compressible: true },\n { name: 'components', shortName: 'cmps', compressible: false },\n ]);\n};\n\nexport const getDzJoinTableName = (collectionName: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: collectionName, compressible: true },\n { name: 'components', shortName: 'cmps', compressible: false },\n ]);\n};\n\nexport const getComponentJoinColumnEntityName = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: 'entity', compressible: false },\n { name: 'id', compressible: false },\n ]);\n};\n\nexport const getComponentJoinColumnInverseName = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: 'component', shortName: 'cmp', compressible: false },\n { name: 'id', compressible: false },\n ]);\n};\n\nexport const getComponentTypeColumn = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([{ name: 'component_type', compressible: false }]);\n};\n\nexport const getComponentFkIndexName = (contentType: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: contentType, compressible: true },\n { name: 'entity', compressible: false },\n { name: 'fk', compressible: false },\n ]);\n};\n\n// const { ID_COLUMN: id, FIELD_COLUMN: field, ORDER_COLUMN: order } = identifiers;\n\nexport type LoadedContentTypeModel = Struct.ContentTypeSchema &\n Required<Pick<Struct.ContentTypeSchema, 'collectionName' | 'uid' | 'modelName'>>;\n\n// Transforms an attribute (particularly for relation types) into the format that strapi/database accepts\nexport const transformAttribute = (\n name: string,\n attribute: Schema.Attribute.AnyAttribute,\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n) => {\n switch (attribute.type) {\n case 'media': {\n return {\n type: 'relation',\n relation: attribute.multiple === true ? 'morphMany' : 'morphOne',\n target: 'plugin::upload.file',\n morphBy: 'related',\n };\n }\n case 'component': {\n const joinTableName = getComponentJoinTableName(contentType.collectionName, identifiers);\n const joinColumnEntityName = getComponentJoinColumnEntityName(identifiers);\n const joinColumnInverseName = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n return {\n type: 'relation',\n relation: attribute.repeatable === true ? 'oneToMany' : 'oneToOne',\n target: attribute.component,\n\n // We need the join table name to be deterministic,\n // We need to allow passing the join table name as an option\n joinTable: {\n name: joinTableName,\n joinColumn: {\n name: joinColumnEntityName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n inverseJoinColumn: {\n name: joinColumnInverseName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n on: {\n field: name,\n },\n orderColumnName: identifiers.ORDER_COLUMN,\n orderBy: {\n order: 'asc',\n },\n pivotColumns: [\n joinColumnEntityName,\n joinColumnInverseName,\n identifiers.FIELD_COLUMN,\n compTypeColumn,\n ],\n },\n };\n }\n case 'dynamiczone': {\n const joinTableName = getDzJoinTableName(contentType.collectionName, identifiers);\n const joinColumnEntityName = getComponentJoinColumnEntityName(identifiers);\n const joinColumnInverseName = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n\n return {\n type: 'relation',\n relation: 'morphToMany',\n // TODO: handle restrictions at some point\n // target: attribute.components,\n joinTable: {\n name: joinTableName,\n joinColumn: {\n name: joinColumnEntityName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n morphColumn: {\n idColumn: {\n name: joinColumnInverseName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n typeColumn: {\n name: compTypeColumn,\n },\n typeField: '__component',\n },\n on: {\n field: name,\n },\n orderBy: {\n order: 'asc',\n },\n pivotColumns: [\n joinColumnEntityName,\n joinColumnInverseName,\n identifiers.FIELD_COLUMN,\n compTypeColumn,\n ],\n },\n };\n }\n default: {\n return attribute;\n }\n }\n};\n\nexport const transformAttributes = (\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n) => {\n return Object.keys(contentType.attributes! || {}).reduce((attrs, attrName) => {\n return {\n ...attrs,\n [attrName]: transformAttribute(\n attrName,\n contentType.attributes[attrName]!,\n contentType,\n identifiers\n ),\n };\n }, {});\n};\n\nexport const hasComponentsOrDz = (\n contentType: LoadedContentTypeModel\n): contentType is LoadedContentTypeModel & { type: 'dynamiczone' | 'component' } => {\n return Object.values(contentType.attributes || {}).some(\n (({ type }: { type: string }) => type === 'dynamiczone' || type === 'component') as any\n );\n};\n\nexport const createDocumentId = createId;\n\nconst createCompoLinkModel = (\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n): Model => {\n const name = getComponentJoinTableName(contentType.collectionName, identifiers);\n\n const entityId = getComponentJoinColumnEntityName(identifiers);\n const componentId = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n const fkIndex = getComponentFkIndexName(contentType.collectionName, identifiers);\n\n return {\n // TODO: make sure there can't be any conflicts with a prefix\n singularName: name,\n uid: name,\n tableName: name,\n attributes: {\n [identifiers.ID_COLUMN]: {\n type: 'increments',\n },\n [entityId]: {\n type: 'integer',\n column: {\n unsigned: true,\n },\n },\n [componentId]: {\n type: 'integer',\n column: {\n unsigned: true,\n },\n },\n [compTypeColumn]: {\n type: 'string',\n },\n [identifiers.FIELD_COLUMN]: {\n type: 'string',\n },\n [identifiers.ORDER_COLUMN]: {\n type: 'float',\n column: {\n unsigned: true,\n defaultTo: null,\n },\n },\n },\n indexes: [\n {\n name: identifiers.getIndexName([contentType.collectionName, identifiers.FIELD_COLUMN]),\n columns: [identifiers.FIELD_COLUMN],\n },\n {\n name: identifiers.getIndexName([contentType.collectionName, compTypeColumn]),\n columns: [compTypeColumn],\n },\n {\n name: fkIndex,\n columns: [entityId],\n },\n {\n // NOTE: since we don't include attribute names, we need to be careful not to create another unique index\n name: identifiers.getUniqueIndexName([contentType.collectionName]),\n columns: [entityId, componentId, identifiers.FIELD_COLUMN, compTypeColumn],\n type: 'unique',\n },\n ],\n foreignKeys: [\n {\n name: fkIndex,\n columns: [entityId],\n referencedColumns: [identifiers.ID_COLUMN],\n referencedTable: identifiers.getTableName(contentType.collectionName),\n onDelete: 'CASCADE',\n },\n ],\n };\n};\n\nexport const transformContentTypesToModels = (\n contentTypes: LoadedContentTypeModel[],\n identifiers: Identifiers\n): Model[] => {\n const models: Model[] = [];\n\n contentTypes.forEach((contentType) => {\n assert(contentType.collectionName, 'Content type \"collectionName\" is required');\n assert(contentType.modelName, 'Content type \"modelName\" is required');\n assert(contentType.uid, 'Content type \"uid\" is required');\n\n // Add document id to content types\n // as it is not documented\n const documentIdAttribute: Record<string, Schema.Attribute.AnyAttribute> =\n contentType.modelType === 'contentType'\n ? { documentId: { type: 'string', default: createDocumentId } }\n : {};\n\n // TODO: this needs to be combined with getReservedNames, we should not be maintaining two lists\n // Prevent user from creating a documentId attribute\n const reservedAttributeNames = ['document_id', identifiers.ID_COLUMN];\n Object.keys(contentType.attributes || {}).forEach((attributeName) => {\n const snakeCasedAttributeName = _.snakeCase(attributeName);\n if (reservedAttributeNames.includes(snakeCasedAttributeName)) {\n throw new Error(\n `The attribute \"${attributeName}\" is reserved and cannot be used in a model. Please rename \"${contentType.modelName}\" attribute \"${attributeName}\" to something else.`\n );\n }\n });\n\n if (hasComponentsOrDz(contentType)) {\n const compoLinkModel = createCompoLinkModel(contentType, identifiers);\n models.push(compoLinkModel);\n }\n\n const model: Model = {\n uid: contentType.uid,\n singularName: contentType.modelName,\n tableName: contentType.collectionName, // This gets shortened in metadata.loadModels(), so we don't shorten here or it will happen twice\n attributes: {\n [identifiers.ID_COLUMN]: {\n type: 'increments',\n },\n ...documentIdAttribute,\n ...transformAttributes(contentType, identifiers),\n },\n };\n\n models.push(model);\n });\n\n return models;\n};\n"],"names":["createId","assert","_"],"mappings":";;;;;;;;AAmBa,MAAA,4BAA4B,CAAC,gBAAwB,gBAA6B;AAC7F,SAAO,YAAY,kBAAkB;AAAA,IACnC,EAAE,MAAM,gBAAgB,cAAc,KAAK;AAAA,IAC3C,EAAE,MAAM,cAAc,WAAW,QAAQ,cAAc,MAAM;AAAA,EAAA,CAC9D;AACH;AAEa,MAAA,qBAAqB,CAAC,gBAAwB,gBAA6B;AACtF,SAAO,YAAY,kBAAkB;AAAA,IACnC,EAAE,MAAM,gBAAgB,cAAc,KAAK;AAAA,IAC3C,EAAE,MAAM,cAAc,WAAW,QAAQ,cAAc,MAAM;AAAA,EAAA,CAC9D;AACH;AAEa,MAAA,mCAAmC,CAAC,gBAA6B;AAC5E,SAAO,YAAY,kBAAkB;AAAA,IACnC,EAAE,MAAM,UAAU,cAAc,MAAM;AAAA,IACtC,EAAE,MAAM,MAAM,cAAc,MAAM;AAAA,EAAA,CACnC;AACH;AAEa,MAAA,oCAAoC,CAAC,gBAA6B;AAC7E,SAAO,YAAY,kBAAkB;AAAA,IACnC,EAAE,MAAM,aAAa,WAAW,OAAO,cAAc,MAAM;AAAA,IAC3D,EAAE,MAAM,MAAM,cAAc,MAAM;AAAA,EAAA,CACnC;AACH;AAEa,MAAA,yBAAyB,CAAC,gBAA6B;AAC3D,SAAA,YAAY,kBAAkB,CAAC,EAAE,MAAM,kBAAkB,cAAc,MAAO,CAAA,CAAC;AACxF;AAEa,MAAA,0BAA0B,CAAC,aAAqB,gBAA6B;AACxF,SAAO,YAAY,kBAAkB;AAAA,IACnC,EAAE,MAAM,aAAa,cAAc,KAAK;AAAA,IACxC,EAAE,MAAM,UAAU,cAAc,MAAM;AAAA,IACtC,EAAE,MAAM,MAAM,cAAc,MAAM;AAAA,EAAA,CACnC;AACH;AAQO,MAAM,qBAAqB,CAChC,MACA,WACA,aACA,gBACG;AACH,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK,SAAS;AACL,aAAA;AAAA,QACL,MAAM;AAAA,QACN,UAAU,UAAU,aAAa,OAAO,cAAc;AAAA,QACtD,QAAQ;AAAA,QACR,SAAS;AAAA,MAAA;AAAA,IAEb;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,gBAAgB,0BAA0B,YAAY,gBAAgB,WAAW;AACjF,YAAA,uBAAuB,iCAAiC,WAAW;AACnE,YAAA,wBAAwB,kCAAkC,WAAW;AACrE,YAAA,iBAAiB,uBAAuB,WAAW;AAClD,aAAA;AAAA,QACL,MAAM;AAAA,QACN,UAAU,UAAU,eAAe,OAAO,cAAc;AAAA,QACxD,QAAQ,UAAU;AAAA;AAAA;AAAA,QAIlB,WAAW;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,YACV,MAAM;AAAA,YACN,kBAAkB,YAAY;AAAA,UAChC;AAAA,UACA,mBAAmB;AAAA,YACjB,MAAM;AAAA,YACN,kBAAkB,YAAY;AAAA,UAChC;AAAA,UACA,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,iBAAiB,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,cAAc;AAAA,YACZ;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,gBAAgB,mBAAmB,YAAY,gBAAgB,WAAW;AAC1E,YAAA,uBAAuB,iCAAiC,WAAW;AACnE,YAAA,wBAAwB,kCAAkC,WAAW;AACrE,YAAA,iBAAiB,uBAAuB,WAAW;AAElD,aAAA;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA;AAAA;AAAA,QAGV,WAAW;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,YACV,MAAM;AAAA,YACN,kBAAkB,YAAY;AAAA,UAChC;AAAA,UACA,aAAa;AAAA,YACX,UAAU;AAAA,cACR,MAAM;AAAA,cACN,kBAAkB,YAAY;AAAA,YAChC;AAAA,YACA,YAAY;AAAA,cACV,MAAM;AAAA,YACR;AAAA,YACA,WAAW;AAAA,UACb;AAAA,UACA,IAAI;AAAA,YACF,OAAO;AAAA,UACT;AAAA,UACA,SAAS;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA,cAAc;AAAA,YACZ;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,SAAS;AACA,aAAA;AAAA,IACT;AAAA,EACF;AACF;AAEa,MAAA,sBAAsB,CACjC,aACA,gBACG;AACI,SAAA,OAAO,KAAK,YAAY,cAAe,CAAE,CAAA,EAAE,OAAO,CAAC,OAAO,aAAa;AACrE,WAAA;AAAA,MACL,GAAG;AAAA,MACH,CAAC,QAAQ,GAAG;AAAA,QACV;AAAA,QACA,YAAY,WAAW,QAAQ;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAE,CAAA;AACP;AAEa,MAAA,oBAAoB,CAC/B,gBACkF;AAClF,SAAO,OAAO,OAAO,YAAY,cAAc,CAAA,CAAE,EAAE;AAAA,IAChD,CAAC,EAAE,KAA6B,MAAA,SAAS,iBAAiB,SAAS;AAAA,EAAA;AAExE;AAEO,MAAM,mBAAmBA,MAAA;AAEhC,MAAM,uBAAuB,CAC3B,aACA,gBACU;AACV,QAAM,OAAO,0BAA0B,YAAY,gBAAgB,WAAW;AAExE,QAAA,WAAW,iCAAiC,WAAW;AACvD,QAAA,cAAc,kCAAkC,WAAW;AAC3D,QAAA,iBAAiB,uBAAuB,WAAW;AACzD,QAAM,UAAU,wBAAwB,YAAY,gBAAgB,WAAW;AAExE,SAAA;AAAA;AAAA,IAEL,cAAc;AAAA,IACd,KAAK;AAAA,IACL,WAAW;AAAA,IACX,YAAY;AAAA,MACV,CAAC,YAAY,SAAS,GAAG;AAAA,QACvB,MAAM;AAAA,MACR;AAAA,MACA,CAAC,QAAQ,GAAG;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,CAAC,WAAW,GAAG;AAAA,QACb,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,CAAC,cAAc,GAAG;AAAA,QAChB,MAAM;AAAA,MACR;AAAA,MACA,CAAC,YAAY,YAAY,GAAG;AAAA,QAC1B,MAAM;AAAA,MACR;AAAA,MACA,CAAC,YAAY,YAAY,GAAG;AAAA,QAC1B,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,MAAM,YAAY,aAAa,CAAC,YAAY,gBAAgB,YAAY,YAAY,CAAC;AAAA,QACrF,SAAS,CAAC,YAAY,YAAY;AAAA,MACpC;AAAA,MACA;AAAA,QACE,MAAM,YAAY,aAAa,CAAC,YAAY,gBAAgB,cAAc,CAAC;AAAA,QAC3E,SAAS,CAAC,cAAc;AAAA,MAC1B;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS,CAAC,QAAQ;AAAA,MACpB;AAAA,MACA;AAAA;AAAA,QAEE,MAAM,YAAY,mBAAmB,CAAC,YAAY,cAAc,CAAC;AAAA,QACjE,SAAS,CAAC,UAAU,aAAa,YAAY,cAAc,cAAc;AAAA,QACzE,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,aAAa;AAAA,MACX;AAAA,QACE,MAAM;AAAA,QACN,SAAS,CAAC,QAAQ;AAAA,QAClB,mBAAmB,CAAC,YAAY,SAAS;AAAA,QACzC,iBAAiB,YAAY,aAAa,YAAY,cAAc;AAAA,QACpE,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EAAA;AAEJ;AAEa,MAAA,gCAAgC,CAC3C,cACA,gBACY;AACZ,QAAM,SAAkB,CAAA;AAEX,eAAA,QAAQ,CAAC,gBAAgB;AAC7BC,oBAAAA,QAAA,YAAY,gBAAgB,2CAA2C;AACvEA,oBAAAA,QAAA,YAAY,WAAW,sCAAsC;AAC7DA,oBAAAA,QAAA,YAAY,KAAK,gCAAgC;AAIxD,UAAM,sBACJ,YAAY,cAAc,gBACtB,EAAE,YAAY,EAAE,MAAM,UAAU,SAAS,iBAAiB,EAAA,IAC1D,CAAA;AAIN,UAAM,yBAAyB,CAAC,eAAe,YAAY,SAAS;AAC7D,WAAA,KAAK,YAAY,cAAc,CAAA,CAAE,EAAE,QAAQ,CAAC,kBAAkB;AAC7D,YAAA,0BAA0BC,WAAAA,QAAE,UAAU,aAAa;AACrD,UAAA,uBAAuB,SAAS,uBAAuB,GAAG;AAC5D,cAAM,IAAI;AAAA,UACR,kBAAkB,aAAa,+DAA+D,YAAY,SAAS,gBAAgB,aAAa;AAAA,QAAA;AAAA,MAEpJ;AAAA,IAAA,CACD;AAEG,QAAA,kBAAkB,WAAW,GAAG;AAC5B,YAAA,iBAAiB,qBAAqB,aAAa,WAAW;AACpE,aAAO,KAAK,cAAc;AAAA,IAC5B;AAEA,UAAM,QAAe;AAAA,MACnB,KAAK,YAAY;AAAA,MACjB,cAAc,YAAY;AAAA,MAC1B,WAAW,YAAY;AAAA;AAAA,MACvB,YAAY;AAAA,QACV,CAAC,YAAY,SAAS,GAAG;AAAA,UACvB,MAAM;AAAA,QACR;AAAA,QACA,GAAG;AAAA,QACH,GAAG,oBAAoB,aAAa,WAAW;AAAA,MACjD;AAAA,IAAA;AAGF,WAAO,KAAK,KAAK;AAAA,EAAA,CAClB;AAEM,SAAA;AACT;;;;;;;;;;;;"}
1
+ {"version":3,"file":"transform-content-types-to-models.js","sources":["../../src/utils/transform-content-types-to-models.ts"],"sourcesContent":["import { type Model, type Identifiers } from '@strapi/database';\nimport type { Struct, Schema } from '@strapi/types';\nimport { createId } from '@paralleldrive/cuid2';\nimport assert from 'node:assert';\nimport _ from 'lodash/fp';\n\n/**\n * Because strapi/database models don't know about things like components or dynamic zones, we use this file to convert them\n * to a relations format that it recognizes\n *\n * Therefore we have to keep an additional set of helpers/extensions to the database naming methods\n *\n * IMPORTANT!\n * If we use short versions of anything, we MUST call getNameFromTokens directly; attempting to shorten them ourselves\n * prevents the unshortened name map from being filled properly, so for example it will think that the short name\n * 'collection4f3a_cmps' maps to the unshortened 'collectionname_cmps' rather than 'collectionname_components'\n * Therefore, we only use the identifiers helpers in cases where we do not do any of our own shortening\n */\n\nexport const getComponentJoinTableName = (collectionName: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: collectionName, compressible: true },\n { name: 'components', shortName: 'cmps', compressible: false },\n ]);\n};\n\nexport const getDzJoinTableName = (collectionName: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: collectionName, compressible: true },\n { name: 'components', shortName: 'cmps', compressible: false },\n ]);\n};\n\nexport const getComponentJoinColumnEntityName = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: 'entity', compressible: false },\n { name: 'id', compressible: false },\n ]);\n};\n\nexport const getComponentJoinColumnInverseName = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: 'component', shortName: 'cmp', compressible: false },\n { name: 'id', compressible: false },\n ]);\n};\n\nexport const getComponentTypeColumn = (identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([{ name: 'component_type', compressible: false }]);\n};\n\nexport const getComponentFkIndexName = (contentType: string, identifiers: Identifiers) => {\n return identifiers.getNameFromTokens([\n { name: contentType, compressible: true },\n { name: 'entity', compressible: false },\n { name: 'fk', compressible: false },\n ]);\n};\n\n// const { ID_COLUMN: id, FIELD_COLUMN: field, ORDER_COLUMN: order } = identifiers;\n\nexport type LoadedContentTypeModel = Struct.ContentTypeSchema &\n Required<Pick<Struct.ContentTypeSchema, 'collectionName' | 'uid' | 'modelName'>>;\n\n// Transforms an attribute (particularly for relation types) into the format that strapi/database accepts\nexport const transformAttribute = (\n name: string,\n attribute: Schema.Attribute.AnyAttribute,\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n) => {\n switch (attribute.type) {\n case 'media': {\n return {\n type: 'relation',\n relation: attribute.multiple === true ? 'morphMany' : 'morphOne',\n target: 'plugin::upload.file',\n morphBy: 'related',\n };\n }\n case 'component': {\n const joinTableName = getComponentJoinTableName(contentType.collectionName, identifiers);\n const joinColumnEntityName = getComponentJoinColumnEntityName(identifiers);\n const joinColumnInverseName = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n return {\n type: 'relation',\n relation: attribute.repeatable === true ? 'oneToMany' : 'oneToOne',\n target: attribute.component,\n\n // We need the join table name to be deterministic,\n // We need to allow passing the join table name as an option\n joinTable: {\n name: joinTableName,\n joinColumn: {\n name: joinColumnEntityName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n inverseJoinColumn: {\n name: joinColumnInverseName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n on: {\n field: name,\n },\n orderColumnName: identifiers.ORDER_COLUMN,\n orderBy: {\n order: 'asc',\n },\n pivotColumns: [\n joinColumnEntityName,\n joinColumnInverseName,\n identifiers.FIELD_COLUMN,\n compTypeColumn,\n ],\n },\n };\n }\n case 'dynamiczone': {\n const joinTableName = getDzJoinTableName(contentType.collectionName, identifiers);\n const joinColumnEntityName = getComponentJoinColumnEntityName(identifiers);\n const joinColumnInverseName = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n\n return {\n type: 'relation',\n relation: 'morphToMany',\n // TODO: handle restrictions at some point\n // target: attribute.components,\n joinTable: {\n name: joinTableName,\n joinColumn: {\n name: joinColumnEntityName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n morphColumn: {\n idColumn: {\n name: joinColumnInverseName,\n referencedColumn: identifiers.ID_COLUMN,\n },\n typeColumn: {\n name: compTypeColumn,\n },\n typeField: '__component',\n },\n on: {\n field: name,\n },\n orderBy: {\n order: 'asc',\n },\n pivotColumns: [\n joinColumnEntityName,\n joinColumnInverseName,\n identifiers.FIELD_COLUMN,\n compTypeColumn,\n ],\n },\n };\n }\n default: {\n return attribute;\n }\n }\n};\n\nexport const transformAttributes = (\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n) => {\n return Object.keys(contentType.attributes! || {}).reduce((attrs, attrName) => {\n return {\n ...attrs,\n [attrName]: transformAttribute(\n attrName,\n contentType.attributes[attrName]!,\n contentType,\n identifiers\n ),\n };\n }, {});\n};\n\nexport const hasComponentsOrDz = (\n contentType: LoadedContentTypeModel\n): contentType is LoadedContentTypeModel & { type: 'dynamiczone' | 'component' } => {\n return Object.values(contentType.attributes || {}).some(\n (({ type }: { type: string }) => type === 'dynamiczone' || type === 'component') as any\n );\n};\n\nexport const createDocumentId = createId;\n\nconst createCompoLinkModel = (\n contentType: LoadedContentTypeModel,\n identifiers: Identifiers\n): Model => {\n const name = getComponentJoinTableName(contentType.collectionName, identifiers);\n\n const entityId = getComponentJoinColumnEntityName(identifiers);\n const componentId = getComponentJoinColumnInverseName(identifiers);\n const compTypeColumn = getComponentTypeColumn(identifiers);\n const fkIndex = getComponentFkIndexName(contentType.collectionName, identifiers);\n\n return {\n // TODO: make sure there can't be any conflicts with a prefix\n singularName: name,\n uid: name,\n tableName: name,\n attributes: {\n [identifiers.ID_COLUMN]: {\n type: 'increments',\n },\n [entityId]: {\n type: 'integer',\n column: {\n unsigned: true,\n },\n },\n [componentId]: {\n type: 'integer',\n column: {\n unsigned: true,\n },\n },\n [compTypeColumn]: {\n type: 'string',\n },\n [identifiers.FIELD_COLUMN]: {\n type: 'string',\n },\n [identifiers.ORDER_COLUMN]: {\n type: 'float',\n column: {\n unsigned: true,\n defaultTo: null,\n },\n },\n },\n indexes: [\n {\n name: identifiers.getIndexName([contentType.collectionName, identifiers.FIELD_COLUMN]),\n columns: [identifiers.FIELD_COLUMN],\n },\n {\n name: identifiers.getIndexName([contentType.collectionName, compTypeColumn]),\n columns: [compTypeColumn],\n },\n {\n name: fkIndex,\n columns: [entityId],\n },\n {\n // NOTE: since we don't include attribute names, we need to be careful not to create another unique index\n name: identifiers.getUniqueIndexName([contentType.collectionName]),\n columns: [entityId, componentId, identifiers.FIELD_COLUMN, compTypeColumn],\n type: 'unique',\n },\n ],\n foreignKeys: [\n {\n name: fkIndex,\n columns: [entityId],\n referencedColumns: [identifiers.ID_COLUMN],\n referencedTable: identifiers.getTableName(contentType.collectionName),\n onDelete: 'CASCADE',\n },\n ],\n };\n};\n\nexport const transformContentTypesToModels = (\n contentTypes: LoadedContentTypeModel[],\n identifiers: Identifiers\n): Model[] => {\n const models: Model[] = [];\n\n contentTypes.forEach((contentType) => {\n assert(contentType.collectionName, 'Content type \"collectionName\" is required');\n assert(contentType.modelName, 'Content type \"modelName\" is required');\n assert(contentType.uid, 'Content type \"uid\" is required');\n\n // Add document id to content types\n // as it is not documented\n const documentIdAttribute: Record<string, Schema.Attribute.AnyAttribute> =\n contentType.modelType === 'contentType'\n ? { documentId: { type: 'string', default: createDocumentId } }\n : {};\n\n // TODO: this needs to be combined with getReservedNames, we should not be maintaining two lists\n // Prevent user from creating a documentId attribute\n const reservedAttributeNames = ['document_id', identifiers.ID_COLUMN];\n Object.keys(contentType.attributes || {}).forEach((attributeName) => {\n const snakeCasedAttributeName = _.snakeCase(attributeName);\n if (reservedAttributeNames.includes(snakeCasedAttributeName)) {\n throw new Error(\n `The attribute \"${attributeName}\" is reserved and cannot be used in a model. Please rename \"${contentType.modelName}\" attribute \"${attributeName}\" to something else.`\n );\n }\n });\n\n if (hasComponentsOrDz(contentType)) {\n const compoLinkModel = createCompoLinkModel(contentType, identifiers);\n models.push(compoLinkModel);\n }\n\n const model: Model = {\n uid: contentType.uid,\n singularName: contentType.modelName,\n tableName: contentType.collectionName, // This gets shortened in metadata.loadModels(), so we don't shorten here or it will happen twice\n attributes: {\n [identifiers.ID_COLUMN]: {\n type: 'increments',\n },\n ...documentIdAttribute,\n ...transformAttributes(contentType, identifiers),\n },\n };\n\n // Add indexes to model\n if (contentType.modelType === 'contentType') {\n model.indexes = [\n ...(model.indexes || []),\n {\n name: identifiers.getIndexName([contentType.collectionName, 'documents']),\n // Filter attributes that are not in the schema\n columns: ['documentId', 'locale', 'publishedAt']\n .filter((n) => model.attributes[n])\n .map((name) => identifiers.getColumnName(_.snakeCase(name))),\n },\n ];\n }\n\n models.push(model);\n });\n\n return models;\n};\n"],"names":["createId","assert","_"],"mappings":"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"}