@strapi/core 5.57.0 → 5.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/Strapi.d.ts +28 -0
  2. package/dist/Strapi.d.ts.map +1 -1
  3. package/dist/Strapi.js +5 -0
  4. package/dist/Strapi.js.map +1 -1
  5. package/dist/Strapi.mjs +5 -0
  6. package/dist/Strapi.mjs.map +1 -1
  7. package/dist/ee/entitlements.d.ts +44 -0
  8. package/dist/ee/entitlements.d.ts.map +1 -0
  9. package/dist/ee/entitlements.js +54 -0
  10. package/dist/ee/entitlements.js.map +1 -0
  11. package/dist/ee/entitlements.mjs +51 -0
  12. package/dist/ee/entitlements.mjs.map +1 -0
  13. package/dist/ee/index.d.ts +33 -0
  14. package/dist/ee/index.d.ts.map +1 -1
  15. package/dist/ee/index.js +70 -3
  16. package/dist/ee/index.js.map +1 -1
  17. package/dist/ee/index.mjs +71 -4
  18. package/dist/ee/index.mjs.map +1 -1
  19. package/dist/ee/license.d.ts +10 -0
  20. package/dist/ee/license.d.ts.map +1 -1
  21. package/dist/ee/license.js +25 -1
  22. package/dist/ee/license.js.map +1 -1
  23. package/dist/ee/license.mjs +25 -2
  24. package/dist/ee/license.mjs.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +1 -1
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/loaders/apis.d.ts.map +1 -1
  31. package/dist/loaders/apis.js.map +1 -1
  32. package/dist/loaders/apis.mjs.map +1 -1
  33. package/dist/loaders/plugins/get-enabled-plugins.js +2 -2
  34. package/dist/loaders/plugins/get-enabled-plugins.js.map +1 -1
  35. package/dist/loaders/plugins/get-enabled-plugins.mjs +2 -2
  36. package/dist/loaders/plugins/get-enabled-plugins.mjs.map +1 -1
  37. package/dist/middlewares/cors.d.ts.map +1 -1
  38. package/dist/middlewares/cors.js.map +1 -1
  39. package/dist/middlewares/cors.mjs.map +1 -1
  40. package/dist/migrations/database/5.0.0-discard-drafts.js +1 -1
  41. package/dist/migrations/database/5.0.0-discard-drafts.js.map +1 -1
  42. package/dist/migrations/database/5.0.0-discard-drafts.mjs +1 -1
  43. package/dist/migrations/database/5.0.0-discard-drafts.mjs.map +1 -1
  44. package/dist/migrations/first-published-at.js +1 -1
  45. package/dist/migrations/first-published-at.js.map +1 -1
  46. package/dist/migrations/first-published-at.mjs +1 -1
  47. package/dist/migrations/first-published-at.mjs.map +1 -1
  48. package/dist/package.json.js +18 -17
  49. package/dist/package.json.js.map +1 -1
  50. package/dist/package.json.mjs +18 -17
  51. package/dist/package.json.mjs.map +1 -1
  52. package/dist/registries/controllers.d.ts.map +1 -1
  53. package/dist/registries/controllers.js.map +1 -1
  54. package/dist/registries/controllers.mjs.map +1 -1
  55. package/dist/services/content-source-maps.js +6 -6
  56. package/dist/services/content-source-maps.js.map +1 -1
  57. package/dist/services/content-source-maps.mjs +6 -6
  58. package/dist/services/content-source-maps.mjs.map +1 -1
  59. package/dist/services/document-service/components.d.ts +13 -11
  60. package/dist/services/document-service/components.d.ts.map +1 -1
  61. package/dist/services/document-service/components.js +115 -66
  62. package/dist/services/document-service/components.js.map +1 -1
  63. package/dist/services/document-service/components.mjs +116 -67
  64. package/dist/services/document-service/components.mjs.map +1 -1
  65. package/dist/services/document-service/events.d.ts.map +1 -1
  66. package/dist/services/document-service/events.js +5 -1
  67. package/dist/services/document-service/events.js.map +1 -1
  68. package/dist/services/document-service/events.mjs +5 -1
  69. package/dist/services/document-service/events.mjs.map +1 -1
  70. package/dist/services/document-service/repository.d.ts.map +1 -1
  71. package/dist/services/document-service/repository.js +26 -7
  72. package/dist/services/document-service/repository.js.map +1 -1
  73. package/dist/services/document-service/repository.mjs +27 -8
  74. package/dist/services/document-service/repository.mjs.map +1 -1
  75. package/dist/services/document-service/transform/data.d.ts.map +1 -1
  76. package/dist/services/document-service/transform/data.js.map +1 -1
  77. package/dist/services/document-service/transform/data.mjs.map +1 -1
  78. package/dist/services/document-service/transform/fields.d.ts.map +1 -1
  79. package/dist/services/document-service/transform/fields.js +7 -1
  80. package/dist/services/document-service/transform/fields.js.map +1 -1
  81. package/dist/services/document-service/transform/fields.mjs +7 -1
  82. package/dist/services/document-service/transform/fields.mjs.map +1 -1
  83. package/dist/services/document-service/transform/populate.d.ts.map +1 -1
  84. package/dist/services/document-service/transform/populate.js +8 -1
  85. package/dist/services/document-service/transform/populate.js.map +1 -1
  86. package/dist/services/document-service/transform/populate.mjs +8 -1
  87. package/dist/services/document-service/transform/populate.mjs.map +1 -1
  88. package/dist/services/document-service/transform/relations/transform/default-locale.d.ts +4 -1
  89. package/dist/services/document-service/transform/relations/transform/default-locale.d.ts.map +1 -1
  90. package/dist/services/document-service/transform/relations/transform/default-locale.js +12 -9
  91. package/dist/services/document-service/transform/relations/transform/default-locale.js.map +1 -1
  92. package/dist/services/document-service/transform/relations/transform/default-locale.mjs +12 -10
  93. package/dist/services/document-service/transform/relations/transform/default-locale.mjs.map +1 -1
  94. package/dist/services/document-service/transform/relations/utils/map-relation.d.ts.map +1 -1
  95. package/dist/services/document-service/transform/relations/utils/map-relation.js +10 -4
  96. package/dist/services/document-service/transform/relations/utils/map-relation.js.map +1 -1
  97. package/dist/services/document-service/transform/relations/utils/map-relation.mjs +10 -4
  98. package/dist/services/document-service/transform/relations/utils/map-relation.mjs.map +1 -1
  99. package/dist/services/document-service/utils/clone-relations.d.ts +21 -4
  100. package/dist/services/document-service/utils/clone-relations.d.ts.map +1 -1
  101. package/dist/services/document-service/utils/clone-relations.js +619 -34
  102. package/dist/services/document-service/utils/clone-relations.js.map +1 -1
  103. package/dist/services/document-service/utils/clone-relations.mjs +619 -36
  104. package/dist/services/document-service/utils/clone-relations.mjs.map +1 -1
  105. package/dist/services/document-service/utils/unidirectional-relations.d.ts +4 -2
  106. package/dist/services/document-service/utils/unidirectional-relations.d.ts.map +1 -1
  107. package/dist/services/document-service/utils/unidirectional-relations.js +1 -10
  108. package/dist/services/document-service/utils/unidirectional-relations.js.map +1 -1
  109. package/dist/services/document-service/utils/unidirectional-relations.mjs +1 -10
  110. package/dist/services/document-service/utils/unidirectional-relations.mjs.map +1 -1
  111. package/dist/services/event-hub.d.ts.map +1 -1
  112. package/dist/services/event-hub.js +23 -5
  113. package/dist/services/event-hub.js.map +1 -1
  114. package/dist/services/event-hub.mjs +23 -5
  115. package/dist/services/event-hub.mjs.map +1 -1
  116. package/dist/services/webhook-store.js +2 -2
  117. package/dist/services/webhook-store.js.map +1 -1
  118. package/dist/services/webhook-store.mjs +2 -2
  119. package/dist/services/webhook-store.mjs.map +1 -1
  120. package/dist/utils/detect-customizations.d.ts +31 -0
  121. package/dist/utils/detect-customizations.d.ts.map +1 -0
  122. package/dist/utils/detect-customizations.js +173 -0
  123. package/dist/utils/detect-customizations.js.map +1 -0
  124. package/dist/utils/detect-customizations.mjs +165 -0
  125. package/dist/utils/detect-customizations.mjs.map +1 -0
  126. package/dist/utils/fetch.d.ts.map +1 -1
  127. package/dist/utils/fetch.js +44 -8
  128. package/dist/utils/fetch.js.map +1 -1
  129. package/dist/utils/fetch.mjs +37 -8
  130. package/dist/utils/fetch.mjs.map +1 -1
  131. package/dist/utils/transform-content-types-to-models.js +5 -5
  132. package/dist/utils/transform-content-types-to-models.js.map +1 -1
  133. package/dist/utils/transform-content-types-to-models.mjs +5 -5
  134. package/dist/utils/transform-content-types-to-models.mjs.map +1 -1
  135. package/package.json +18 -17
@@ -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';\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":["ValidationError","errors","webhookModel","uid","singularName","tableName","attributes","id","type","name","url","headers","events","enabled","toDBObject","data","isEnabled","fromDBObject","row","toString","webhookEventValidator","allowedEvents","allowedValues","Array","from","values","forEach","event","includes","createWebhookStore","db","Map","addAllowedEvent","key","value","set","removeAllowedEvent","delete","listAllowedEvents","keys","getAllowedEvent","get","findWebhooks","results","query","findMany","map","findWebhook","result","findOne","where","createWebhook","create","then","updateWebhook","webhook","update","deleteWebhook"],"mappings":";;;;AAQA,MAAM,EAAEA,eAAe,EAAE,GAAGC,kBAAAA;AAE5B,MAAMC,YAAAA,GAAsB;IAC1BC,GAAAA,EAAK,iBAAA;IACLC,YAAAA,EAAc,iBAAA;IACdC,SAAAA,EAAW,iBAAA;IACXC,UAAAA,EAAY;QACVC,EAAAA,EAAI;YACFC,IAAAA,EAAM;AACR,SAAA;QACAC,IAAAA,EAAM;YACJD,IAAAA,EAAM;AACR,SAAA;QACAE,GAAAA,EAAK;YACHF,IAAAA,EAAM;AACR,SAAA;QACAG,OAAAA,EAAS;YACPH,IAAAA,EAAM;AACR,SAAA;QACAI,MAAAA,EAAQ;YACNJ,IAAAA,EAAM;AACR,SAAA;QACAK,OAAAA,EAAS;YACPL,IAAAA,EAAM;AACR;AACF;AACF;AAMA,MAAMM,aAAa,CAACC,IAAAA,GAAAA;IAClB,OAAO;AACLN,QAAAA,IAAAA,EAAMM,KAAKN,IAAI;AACfC,QAAAA,GAAAA,EAAKK,KAAKL,GAAG;AACbC,QAAAA,OAAAA,EAASI,KAAKJ,OAAO;AACrBC,QAAAA,MAAAA,EAAQG,KAAKH,MAAM;AACnBC,QAAAA,OAAAA,EAASE,KAAKC;AAChB,KAAA;AACF,CAAA;AAEA,MAAMC,eAAe,CAACC,GAAAA,GAAAA;IACpB,OAAO;QACLX,EAAAA,EAAI,OAAOW,GAAAA,CAAIX,EAAE,KAAK,QAAA,GAAWW,GAAAA,CAAIX,EAAE,CAACY,QAAQ,EAAA,GAAKD,GAAAA,CAAIX,EAAE;AAC3DE,QAAAA,IAAAA,EAAMS,IAAIT,IAAI;AACdC,QAAAA,GAAAA,EAAKQ,IAAIR,GAAG;AACZC,QAAAA,OAAAA,EAASO,IAAIP,OAAO;AACpBC,QAAAA,MAAAA,EAAQM,IAAIN,MAAM;AAClBI,QAAAA,SAAAA,EAAWE,IAAIL;AACjB,KAAA;AACF,CAAA;AAEA,MAAMO,qBAAAA,GAAwB,OAAOC,aAAAA,EAAoCT,MAAAA,GAAAA;AACvE,IAAA,MAAMU,aAAAA,GAAgBC,KAAAA,CAAMC,IAAI,CAACH,cAAcI,MAAM,EAAA,CAAA;IAErDb,MAAAA,CAAOc,OAAO,CAAC,CAACC,KAAAA,GAAAA;QACd,IAAIL,aAAAA,CAAcM,QAAQ,CAACD,KAAAA,CAAAA,EAAQ;AACjC,YAAA;AACF,QAAA;AAEA,QAAA,MAAM,IAAI3B,eAAAA,CAAgB,CAAC,cAAc,EAAE2B,KAAAA,CAAM,iBAAiB,CAAC,CAAA;AACrE,IAAA,CAAA,CAAA;AACF,CAAA;AAeA,MAAME,kBAAAA,GAAqB,CAAC,EAAEC,EAAE,EAAoB,GAAA;IAClD,OAAO;AACLT,QAAAA,aAAAA,EAAe,IAAIU,GAAAA,CAAI;AACrB,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,eAAA;AAAiB,gBAAA;AAAgB,aAAA;AAClC,YAAA;AAAC,gBAAA,iBAAA;AAAmB,gBAAA;AAAkB,aAAA;AACtC,YAAA;AAAC,gBAAA,qBAAA;AAAuB,gBAAA;AAAsB;AAC/C,SAAA,CAAA;QACDC,eAAAA,CAAAA,CAAgBC,GAAG,EAAEC,KAAK,EAAA;AACxB,YAAA,IAAI,CAACb,aAAa,CAACc,GAAG,CAACF,GAAAA,EAAKC,KAAAA,CAAAA;AAC9B,QAAA,CAAA;AACAE,QAAAA,kBAAAA,CAAAA,CAAmBH,GAAG,EAAA;AACpB,YAAA,IAAI,CAACZ,aAAa,CAACgB,MAAM,CAACJ,GAAAA,CAAAA;AAC5B,QAAA,CAAA;AACAK,QAAAA,iBAAAA,CAAAA,GAAAA;AACE,YAAA,OAAOf,MAAMC,IAAI,CAAC,IAAI,CAACH,aAAa,CAACkB,IAAI,EAAA,CAAA;AAC3C,QAAA,CAAA;AACAC,QAAAA,eAAAA,CAAAA,CAAgBP,GAAG,EAAA;AACjB,YAAA,OAAO,IAAI,CAACZ,aAAa,CAACoB,GAAG,CAACR,GAAAA,CAAAA;AAChC,QAAA,CAAA;QACA,MAAMS,YAAAA,CAAAA,GAAAA;AACJ,YAAA,MAAMC,UAAU,MAAMb,EAAAA,CAAGc,KAAK,CAAC,mBAAmBC,QAAQ,EAAA;YAE1D,OAAOF,OAAAA,CAAQG,GAAG,CAAC7B,YAAAA,CAAAA;AACrB,QAAA,CAAA;AACA,QAAA,MAAM8B,aAAYxC,EAAE,EAAA;AAClB,YAAA,MAAMyC,SAAS,MAAMlB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBK,OAAO,CAAC;gBAAEC,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAOyC,MAAAA,GAAS/B,aAAa+B,MAAAA,CAAAA,GAAU,IAAA;AACzC,QAAA,CAAA;AACA,QAAA,MAAMG,eAAcpC,IAAI,EAAA;AACtB,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,OAAOkB,EAAAA,CACJc,KAAK,CAAC,iBAAA,CAAA,CACNQ,MAAM,CAAC;AACNrC,gBAAAA,IAAAA,EAAMD,UAAAA,CAAW;AAAE,oBAAA,GAAGC,IAAI;oBAAEC,SAAAA,EAAW;AAAK,iBAAA;AAC9C,aAAA,CAAA,CACCqC,IAAI,CAACpC,YAAAA,CAAAA;AACV,QAAA,CAAA;QACA,MAAMqC,aAAAA,CAAAA,CAAc/C,EAAE,EAAEQ,IAAI,EAAA;AAC1B,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,MAAM2C,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBY,MAAM,CAAC;gBACvDN,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG,iBAAA;AACZQ,gBAAAA,IAAAA,EAAMD,UAAAA,CAAWC,IAAAA;AACnB,aAAA,CAAA;YAEA,OAAOwC,OAAAA,GAAUtC,aAAasC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA,CAAA;AACA,QAAA,MAAME,eAAclD,EAAE,EAAA;AACpB,YAAA,MAAMgD,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBP,MAAM,CAAC;gBAAEa,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAOgD,OAAAA,GAAUtC,aAAasC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA;AACF,KAAA;AACF;;;;;"}
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 = new Set(Array.from(allowedEvents.values()));\n\n events.forEach((event) => {\n if (allowedValues.has(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":["ValidationError","errors","webhookModel","uid","singularName","tableName","attributes","id","type","name","url","headers","events","enabled","toDBObject","data","isEnabled","fromDBObject","row","toString","webhookEventValidator","allowedEvents","allowedValues","Set","Array","from","values","forEach","event","has","createWebhookStore","db","Map","addAllowedEvent","key","value","set","removeAllowedEvent","delete","listAllowedEvents","keys","getAllowedEvent","get","findWebhooks","results","query","findMany","map","findWebhook","result","findOne","where","createWebhook","create","then","updateWebhook","webhook","update","deleteWebhook"],"mappings":";;;;AAQA,MAAM,EAAEA,eAAe,EAAE,GAAGC,kBAAAA;AAE5B,MAAMC,YAAAA,GAAsB;IAC1BC,GAAAA,EAAK,iBAAA;IACLC,YAAAA,EAAc,iBAAA;IACdC,SAAAA,EAAW,iBAAA;IACXC,UAAAA,EAAY;QACVC,EAAAA,EAAI;YACFC,IAAAA,EAAM;AACR,SAAA;QACAC,IAAAA,EAAM;YACJD,IAAAA,EAAM;AACR,SAAA;QACAE,GAAAA,EAAK;YACHF,IAAAA,EAAM;AACR,SAAA;QACAG,OAAAA,EAAS;YACPH,IAAAA,EAAM;AACR,SAAA;QACAI,MAAAA,EAAQ;YACNJ,IAAAA,EAAM;AACR,SAAA;QACAK,OAAAA,EAAS;YACPL,IAAAA,EAAM;AACR;AACF;AACF;AAMA,MAAMM,aAAa,CAACC,IAAAA,GAAAA;IAClB,OAAO;AACLN,QAAAA,IAAAA,EAAMM,KAAKN,IAAI;AACfC,QAAAA,GAAAA,EAAKK,KAAKL,GAAG;AACbC,QAAAA,OAAAA,EAASI,KAAKJ,OAAO;AACrBC,QAAAA,MAAAA,EAAQG,KAAKH,MAAM;AACnBC,QAAAA,OAAAA,EAASE,KAAKC;AAChB,KAAA;AACF,CAAA;AAEA,MAAMC,eAAe,CAACC,GAAAA,GAAAA;IACpB,OAAO;QACLX,EAAAA,EAAI,OAAOW,GAAAA,CAAIX,EAAE,KAAK,QAAA,GAAWW,GAAAA,CAAIX,EAAE,CAACY,QAAQ,EAAA,GAAKD,GAAAA,CAAIX,EAAE;AAC3DE,QAAAA,IAAAA,EAAMS,IAAIT,IAAI;AACdC,QAAAA,GAAAA,EAAKQ,IAAIR,GAAG;AACZC,QAAAA,OAAAA,EAASO,IAAIP,OAAO;AACpBC,QAAAA,MAAAA,EAAQM,IAAIN,MAAM;AAClBI,QAAAA,SAAAA,EAAWE,IAAIL;AACjB,KAAA;AACF,CAAA;AAEA,MAAMO,qBAAAA,GAAwB,OAAOC,aAAAA,EAAoCT,MAAAA,GAAAA;AACvE,IAAA,MAAMU,gBAAgB,IAAIC,GAAAA,CAAIC,MAAMC,IAAI,CAACJ,cAAcK,MAAM,EAAA,CAAA,CAAA;IAE7Dd,MAAAA,CAAOe,OAAO,CAAC,CAACC,KAAAA,GAAAA;QACd,IAAIN,aAAAA,CAAcO,GAAG,CAACD,KAAAA,CAAAA,EAAQ;AAC5B,YAAA;AACF,QAAA;AAEA,QAAA,MAAM,IAAI5B,eAAAA,CAAgB,CAAC,cAAc,EAAE4B,KAAAA,CAAM,iBAAiB,CAAC,CAAA;AACrE,IAAA,CAAA,CAAA;AACF,CAAA;AAeA,MAAME,kBAAAA,GAAqB,CAAC,EAAEC,EAAE,EAAoB,GAAA;IAClD,OAAO;AACLV,QAAAA,aAAAA,EAAe,IAAIW,GAAAA,CAAI;AACrB,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,eAAA;AAAiB,gBAAA;AAAgB,aAAA;AAClC,YAAA;AAAC,gBAAA,iBAAA;AAAmB,gBAAA;AAAkB,aAAA;AACtC,YAAA;AAAC,gBAAA,qBAAA;AAAuB,gBAAA;AAAsB;AAC/C,SAAA,CAAA;QACDC,eAAAA,CAAAA,CAAgBC,GAAG,EAAEC,KAAK,EAAA;AACxB,YAAA,IAAI,CAACd,aAAa,CAACe,GAAG,CAACF,GAAAA,EAAKC,KAAAA,CAAAA;AAC9B,QAAA,CAAA;AACAE,QAAAA,kBAAAA,CAAAA,CAAmBH,GAAG,EAAA;AACpB,YAAA,IAAI,CAACb,aAAa,CAACiB,MAAM,CAACJ,GAAAA,CAAAA;AAC5B,QAAA,CAAA;AACAK,QAAAA,iBAAAA,CAAAA,GAAAA;AACE,YAAA,OAAOf,MAAMC,IAAI,CAAC,IAAI,CAACJ,aAAa,CAACmB,IAAI,EAAA,CAAA;AAC3C,QAAA,CAAA;AACAC,QAAAA,eAAAA,CAAAA,CAAgBP,GAAG,EAAA;AACjB,YAAA,OAAO,IAAI,CAACb,aAAa,CAACqB,GAAG,CAACR,GAAAA,CAAAA;AAChC,QAAA,CAAA;QACA,MAAMS,YAAAA,CAAAA,GAAAA;AACJ,YAAA,MAAMC,UAAU,MAAMb,EAAAA,CAAGc,KAAK,CAAC,mBAAmBC,QAAQ,EAAA;YAE1D,OAAOF,OAAAA,CAAQG,GAAG,CAAC9B,YAAAA,CAAAA;AACrB,QAAA,CAAA;AACA,QAAA,MAAM+B,aAAYzC,EAAE,EAAA;AAClB,YAAA,MAAM0C,SAAS,MAAMlB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBK,OAAO,CAAC;gBAAEC,KAAAA,EAAO;AAAE5C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAO0C,MAAAA,GAAShC,aAAagC,MAAAA,CAAAA,GAAU,IAAA;AACzC,QAAA,CAAA;AACA,QAAA,MAAMG,eAAcrC,IAAI,EAAA;AACtB,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,OAAOmB,EAAAA,CACJc,KAAK,CAAC,iBAAA,CAAA,CACNQ,MAAM,CAAC;AACNtC,gBAAAA,IAAAA,EAAMD,UAAAA,CAAW;AAAE,oBAAA,GAAGC,IAAI;oBAAEC,SAAAA,EAAW;AAAK,iBAAA;AAC9C,aAAA,CAAA,CACCsC,IAAI,CAACrC,YAAAA,CAAAA;AACV,QAAA,CAAA;QACA,MAAMsC,aAAAA,CAAAA,CAAchD,EAAE,EAAEQ,IAAI,EAAA;AAC1B,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,MAAM4C,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBY,MAAM,CAAC;gBACvDN,KAAAA,EAAO;AAAE5C,oBAAAA;AAAG,iBAAA;AACZQ,gBAAAA,IAAAA,EAAMD,UAAAA,CAAWC,IAAAA;AACnB,aAAA,CAAA;YAEA,OAAOyC,OAAAA,GAAUvC,aAAauC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA,CAAA;AACA,QAAA,MAAME,eAAcnD,EAAE,EAAA;AACpB,YAAA,MAAMiD,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBP,MAAM,CAAC;gBAAEa,KAAAA,EAAO;AAAE5C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAOiD,OAAAA,GAAUvC,aAAauC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA;AACF,KAAA;AACF;;;;;"}
@@ -46,9 +46,9 @@ const fromDBObject = (row)=>{
46
46
  };
47
47
  };
48
48
  const webhookEventValidator = async (allowedEvents, events)=>{
49
- const allowedValues = Array.from(allowedEvents.values());
49
+ const allowedValues = new Set(Array.from(allowedEvents.values()));
50
50
  events.forEach((event)=>{
51
- if (allowedValues.includes(event)) {
51
+ if (allowedValues.has(event)) {
52
52
  return;
53
53
  }
54
54
  throw new ValidationError(`Webhook event ${event} is not supported`);
@@ -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';\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":["ValidationError","errors","webhookModel","uid","singularName","tableName","attributes","id","type","name","url","headers","events","enabled","toDBObject","data","isEnabled","fromDBObject","row","toString","webhookEventValidator","allowedEvents","allowedValues","Array","from","values","forEach","event","includes","createWebhookStore","db","Map","addAllowedEvent","key","value","set","removeAllowedEvent","delete","listAllowedEvents","keys","getAllowedEvent","get","findWebhooks","results","query","findMany","map","findWebhook","result","findOne","where","createWebhook","create","then","updateWebhook","webhook","update","deleteWebhook"],"mappings":";;AAQA,MAAM,EAAEA,eAAe,EAAE,GAAGC,MAAAA;AAE5B,MAAMC,YAAAA,GAAsB;IAC1BC,GAAAA,EAAK,iBAAA;IACLC,YAAAA,EAAc,iBAAA;IACdC,SAAAA,EAAW,iBAAA;IACXC,UAAAA,EAAY;QACVC,EAAAA,EAAI;YACFC,IAAAA,EAAM;AACR,SAAA;QACAC,IAAAA,EAAM;YACJD,IAAAA,EAAM;AACR,SAAA;QACAE,GAAAA,EAAK;YACHF,IAAAA,EAAM;AACR,SAAA;QACAG,OAAAA,EAAS;YACPH,IAAAA,EAAM;AACR,SAAA;QACAI,MAAAA,EAAQ;YACNJ,IAAAA,EAAM;AACR,SAAA;QACAK,OAAAA,EAAS;YACPL,IAAAA,EAAM;AACR;AACF;AACF;AAMA,MAAMM,aAAa,CAACC,IAAAA,GAAAA;IAClB,OAAO;AACLN,QAAAA,IAAAA,EAAMM,KAAKN,IAAI;AACfC,QAAAA,GAAAA,EAAKK,KAAKL,GAAG;AACbC,QAAAA,OAAAA,EAASI,KAAKJ,OAAO;AACrBC,QAAAA,MAAAA,EAAQG,KAAKH,MAAM;AACnBC,QAAAA,OAAAA,EAASE,KAAKC;AAChB,KAAA;AACF,CAAA;AAEA,MAAMC,eAAe,CAACC,GAAAA,GAAAA;IACpB,OAAO;QACLX,EAAAA,EAAI,OAAOW,GAAAA,CAAIX,EAAE,KAAK,QAAA,GAAWW,GAAAA,CAAIX,EAAE,CAACY,QAAQ,EAAA,GAAKD,GAAAA,CAAIX,EAAE;AAC3DE,QAAAA,IAAAA,EAAMS,IAAIT,IAAI;AACdC,QAAAA,GAAAA,EAAKQ,IAAIR,GAAG;AACZC,QAAAA,OAAAA,EAASO,IAAIP,OAAO;AACpBC,QAAAA,MAAAA,EAAQM,IAAIN,MAAM;AAClBI,QAAAA,SAAAA,EAAWE,IAAIL;AACjB,KAAA;AACF,CAAA;AAEA,MAAMO,qBAAAA,GAAwB,OAAOC,aAAAA,EAAoCT,MAAAA,GAAAA;AACvE,IAAA,MAAMU,aAAAA,GAAgBC,KAAAA,CAAMC,IAAI,CAACH,cAAcI,MAAM,EAAA,CAAA;IAErDb,MAAAA,CAAOc,OAAO,CAAC,CAACC,KAAAA,GAAAA;QACd,IAAIL,aAAAA,CAAcM,QAAQ,CAACD,KAAAA,CAAAA,EAAQ;AACjC,YAAA;AACF,QAAA;AAEA,QAAA,MAAM,IAAI3B,eAAAA,CAAgB,CAAC,cAAc,EAAE2B,KAAAA,CAAM,iBAAiB,CAAC,CAAA;AACrE,IAAA,CAAA,CAAA;AACF,CAAA;AAeA,MAAME,kBAAAA,GAAqB,CAAC,EAAEC,EAAE,EAAoB,GAAA;IAClD,OAAO;AACLT,QAAAA,aAAAA,EAAe,IAAIU,GAAAA,CAAI;AACrB,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,cAAA;AAAgB,gBAAA;AAAe,aAAA;AAChC,YAAA;AAAC,gBAAA,eAAA;AAAiB,gBAAA;AAAgB,aAAA;AAClC,YAAA;AAAC,gBAAA,iBAAA;AAAmB,gBAAA;AAAkB,aAAA;AACtC,YAAA;AAAC,gBAAA,qBAAA;AAAuB,gBAAA;AAAsB;AAC/C,SAAA,CAAA;QACDC,eAAAA,CAAAA,CAAgBC,GAAG,EAAEC,KAAK,EAAA;AACxB,YAAA,IAAI,CAACb,aAAa,CAACc,GAAG,CAACF,GAAAA,EAAKC,KAAAA,CAAAA;AAC9B,QAAA,CAAA;AACAE,QAAAA,kBAAAA,CAAAA,CAAmBH,GAAG,EAAA;AACpB,YAAA,IAAI,CAACZ,aAAa,CAACgB,MAAM,CAACJ,GAAAA,CAAAA;AAC5B,QAAA,CAAA;AACAK,QAAAA,iBAAAA,CAAAA,GAAAA;AACE,YAAA,OAAOf,MAAMC,IAAI,CAAC,IAAI,CAACH,aAAa,CAACkB,IAAI,EAAA,CAAA;AAC3C,QAAA,CAAA;AACAC,QAAAA,eAAAA,CAAAA,CAAgBP,GAAG,EAAA;AACjB,YAAA,OAAO,IAAI,CAACZ,aAAa,CAACoB,GAAG,CAACR,GAAAA,CAAAA;AAChC,QAAA,CAAA;QACA,MAAMS,YAAAA,CAAAA,GAAAA;AACJ,YAAA,MAAMC,UAAU,MAAMb,EAAAA,CAAGc,KAAK,CAAC,mBAAmBC,QAAQ,EAAA;YAE1D,OAAOF,OAAAA,CAAQG,GAAG,CAAC7B,YAAAA,CAAAA;AACrB,QAAA,CAAA;AACA,QAAA,MAAM8B,aAAYxC,EAAE,EAAA;AAClB,YAAA,MAAMyC,SAAS,MAAMlB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBK,OAAO,CAAC;gBAAEC,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAOyC,MAAAA,GAAS/B,aAAa+B,MAAAA,CAAAA,GAAU,IAAA;AACzC,QAAA,CAAA;AACA,QAAA,MAAMG,eAAcpC,IAAI,EAAA;AACtB,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,OAAOkB,EAAAA,CACJc,KAAK,CAAC,iBAAA,CAAA,CACNQ,MAAM,CAAC;AACNrC,gBAAAA,IAAAA,EAAMD,UAAAA,CAAW;AAAE,oBAAA,GAAGC,IAAI;oBAAEC,SAAAA,EAAW;AAAK,iBAAA;AAC9C,aAAA,CAAA,CACCqC,IAAI,CAACpC,YAAAA,CAAAA;AACV,QAAA,CAAA;QACA,MAAMqC,aAAAA,CAAAA,CAAc/C,EAAE,EAAEQ,IAAI,EAAA;AAC1B,YAAA,MAAMK,sBAAsB,IAAI,CAACC,aAAa,EAAEN,KAAKH,MAAM,CAAA;AAE3D,YAAA,MAAM2C,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBY,MAAM,CAAC;gBACvDN,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG,iBAAA;AACZQ,gBAAAA,IAAAA,EAAMD,UAAAA,CAAWC,IAAAA;AACnB,aAAA,CAAA;YAEA,OAAOwC,OAAAA,GAAUtC,aAAasC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA,CAAA;AACA,QAAA,MAAME,eAAclD,EAAE,EAAA;AACpB,YAAA,MAAMgD,UAAU,MAAMzB,EAAAA,CAAGc,KAAK,CAAC,iBAAA,CAAA,CAAmBP,MAAM,CAAC;gBAAEa,KAAAA,EAAO;AAAE3C,oBAAAA;AAAG;AAAE,aAAA,CAAA;YACzE,OAAOgD,OAAAA,GAAUtC,aAAasC,OAAAA,CAAAA,GAAW,IAAA;AAC3C,QAAA;AACF,KAAA;AACF;;;;"}
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 = new Set(Array.from(allowedEvents.values()));\n\n events.forEach((event) => {\n if (allowedValues.has(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":["ValidationError","errors","webhookModel","uid","singularName","tableName","attributes","id","type","name","url","headers","events","enabled","toDBObject","data","isEnabled","fromDBObject","row","toString","webhookEventValidator","allowedEvents","allowedValues","Set","Array","from","values","forEach","event","has","createWebhookStore","db","Map","addAllowedEvent","key","value","set","removeAllowedEvent","delete","listAllowedEvents","keys","getAllowedEvent","get","findWebhooks","results","query","findMany","map","findWebhook","result","findOne","where","createWebhook","create","then","updateWebhook","webhook","update","deleteWebhook"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Core } from '@strapi/types';
2
+ export declare const isLifecycleNonEmpty: (fn: unknown) => boolean;
3
+ export declare const detectCustomizations: (strapi: Core.Strapi) => {
4
+ apis: {
5
+ uid: string;
6
+ customController: boolean;
7
+ customService: boolean;
8
+ customRoutes: boolean;
9
+ }[];
10
+ controllers: {
11
+ uid: string;
12
+ custom: boolean;
13
+ }[];
14
+ extendedPlugins: string[];
15
+ counts: {
16
+ customControllers: number;
17
+ customServices: number;
18
+ customRoutes: number;
19
+ };
20
+ srcIndex: {
21
+ present: boolean;
22
+ registerDefined: boolean;
23
+ registerNonEmpty: boolean;
24
+ bootstrapDefined: boolean;
25
+ bootstrapNonEmpty: boolean;
26
+ destroyDefined: boolean;
27
+ destroyNonEmpty: boolean;
28
+ beyondTemplate: boolean;
29
+ };
30
+ };
31
+ //# sourceMappingURL=detect-customizations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-customizations.d.ts","sourceRoot":"","sources":["../../src/utils/detect-customizations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgB1C,eAAO,MAAM,mBAAmB,GAAI,IAAI,OAAO,KAAG,OAsBjD,CAAC;AAgHF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,IAAI,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DvD,CAAC"}
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+ var factories = require('../factories.js');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var fs__default = /*#__PURE__*/_interopDefault(fs);
10
+ var path__default = /*#__PURE__*/_interopDefault(path);
11
+
12
+ const APP_UID_PREFIX = 'api::';
13
+ /**
14
+ * True when a lifecycle function has a non-empty body. The compiled function
15
+ * source is inspected here only to derive a boolean; it is never returned.
16
+ */ const stripComments = (body)=>body.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/[^\n]*/g, '').trim();
17
+ const isLifecycleNonEmpty = (fn)=>{
18
+ if (typeof fn !== 'function') {
19
+ return false;
20
+ }
21
+ const source = Function.prototype.toString.call(fn);
22
+ // The body starts at the first `{` AFTER the parameter list closes, not the
23
+ // first `{` overall: a real lifecycle signature like `register({ strapi })`
24
+ // or the template's `register(/*{ strapi }*/)` puts a `{` in the params/comment.
25
+ const parenEnd = source.indexOf(')');
26
+ const bodyStart = source.indexOf('{', parenEnd === -1 ? 0 : parenEnd);
27
+ // No brace anywhere after the parameters means a concise arrow body
28
+ // (`register: ({ strapi }) => strapi.log.info('x')`), where everything after the
29
+ // arrow IS the body. Treating that as empty under-reported a real customization,
30
+ // telling Support an app was stock when it was not. The template only ever ships
31
+ // braced method shorthand, so this branch cannot misread a fresh app.
32
+ if (bodyStart === -1) {
33
+ const arrow = source.indexOf('=>');
34
+ return arrow === -1 ? false : stripComments(source.slice(arrow + 2)).length > 0;
35
+ }
36
+ return stripComments(source.slice(bodyStart + 1, source.lastIndexOf('}'))).length > 0;
37
+ };
38
+ /**
39
+ * A default `createCoreService` result has its CRUD methods on its class
40
+ * prototype and only `contentType` as an own key; that own key is copied onto
41
+ * the direct prototype (the base service instance) too, so a default service
42
+ * never has an own key that its direct prototype doesn't also have. A custom
43
+ * service (built via a `cfg` object/callback) has extra own method keys that
44
+ * are absent from the prototype it was assigned. Comparing own keys against
45
+ * the DIRECT prototype's own keys (rather than guessing base method names)
46
+ * avoids flagging every real service as custom.
47
+ */ const isCustomService = (service)=>{
48
+ if (service === null || typeof service !== 'object') {
49
+ return false;
50
+ }
51
+ const proto = Object.getPrototypeOf(service);
52
+ const protoOwnKeys = proto ? Object.keys(proto) : [];
53
+ return Object.keys(service).some((key)=>!protoOwnKeys.includes(key));
54
+ };
55
+ /**
56
+ * Custom routes in Strapi are added as separate files in an api's `routes/`
57
+ * directory (each exporting a plain `{ routes: [...] }` object), never by
58
+ * editing the factory-generated route file, because Koa needs explicit route
59
+ * ordering. The factory router exposes `routes` as a getter, so any route
60
+ * file exposing `routes` as a plain data property is a hand-written custom
61
+ * route file.
62
+ */ const hasCustomRoutes = (strapi, apiName)=>{
63
+ const api = strapi.api(apiName);
64
+ const routeFiles = api?.routes ?? {};
65
+ return Object.values(routeFiles).some((router)=>{
66
+ if (router === null || typeof router !== 'object') {
67
+ return false;
68
+ }
69
+ const descriptor = Object.getOwnPropertyDescriptor(router, 'routes');
70
+ // A factory router exposes `routes` as an accessor (getter); a hand-written
71
+ // custom routes file exports it as a plain data property.
72
+ return descriptor ? typeof descriptor.get !== 'function' : false;
73
+ });
74
+ };
75
+ /**
76
+ * `createCoreController` sets the controller's prototype to the factory's base controller, and
77
+ * marks it when the app passed its own config. Anything else was not minted by the factory: a
78
+ * plain action map (`module.exports = { async find() {} }`) is entirely hand-written, and a
79
+ * factory that returned a non-object is not stock either. Neither may throw out of the dump.
80
+ */ const isCustomApiController = (controller)=>{
81
+ if (controller === null || typeof controller !== 'object') {
82
+ return true;
83
+ }
84
+ const prototype = Object.getPrototypeOf(controller);
85
+ if (prototype === Object.prototype || prototype === null) {
86
+ return true;
87
+ }
88
+ return factories.isCustomController(controller);
89
+ };
90
+ /**
91
+ * Plugin and admin controllers are plain objects even when stock, so only the factory's
92
+ * custom-config mark can single one out here (the same test startup telemetry uses).
93
+ */ const isCustomFactoryController = (controller)=>controller !== null && typeof controller === 'object' && factories.isCustomController(controller);
94
+ /**
95
+ * Plugins the app overrides through `src/extensions/<plugin>/`: a `strapi-server.js`, which can
96
+ * replace any controller, service or route, or content-type schema overrides. A plugin
97
+ * controller looks the same stock or overridden, so this folder is what tells Support a
98
+ * plugin was changed.
99
+ */ // The loader applies content-type overrides from `content-types/<name>/schema.json` only
100
+ const hasSchemaOverride = (pluginDir)=>{
101
+ const contentTypesDir = path__default.default.join(pluginDir, 'content-types');
102
+ if (!fs__default.default.existsSync(contentTypesDir)) {
103
+ return false;
104
+ }
105
+ return fs__default.default.readdirSync(contentTypesDir, {
106
+ withFileTypes: true
107
+ }).some((entry)=>entry.isDirectory() && fs__default.default.existsSync(path__default.default.join(contentTypesDir, entry.name, 'schema.json')));
108
+ };
109
+ const listExtendedPlugins = (strapi)=>{
110
+ const extensionsDir = strapi.dirs?.dist?.extensions;
111
+ if (!extensionsDir || !fs__default.default.existsSync(extensionsDir)) {
112
+ return [];
113
+ }
114
+ return fs__default.default.readdirSync(extensionsDir, {
115
+ withFileTypes: true
116
+ }).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name).filter((name)=>fs__default.default.existsSync(path__default.default.join(extensionsDir, name, 'strapi-server.js')) || hasSchemaOverride(path__default.default.join(extensionsDir, name))).sort();
117
+ };
118
+ // Return shape is mirrored in @strapi/types Core.Strapi['getCustomizations'];
119
+ // keep the two in sync.
120
+ const detectCustomizations = (strapi)=>{
121
+ const controllers = strapi.controllers ?? {};
122
+ const services = strapi.services ?? {};
123
+ const appControllerUids = Object.keys(controllers).filter((uid)=>uid.startsWith(APP_UID_PREFIX));
124
+ const apis = appControllerUids.map((uid)=>{
125
+ const controller = controllers[uid];
126
+ const service = services[uid];
127
+ // uid is `api::<name>.<name>`; map to the bare api name for route lookup.
128
+ const apiName = uid.slice(APP_UID_PREFIX.length).split('.')[0];
129
+ return {
130
+ uid,
131
+ customController: isCustomApiController(controller),
132
+ customService: isCustomService(service),
133
+ customRoutes: hasCustomRoutes(strapi, apiName)
134
+ };
135
+ });
136
+ // Every controller, not only the app's own: the dump is used to rebuild an app for debugging.
137
+ const allControllers = Object.keys(controllers).map((uid)=>({
138
+ uid,
139
+ custom: uid.startsWith(APP_UID_PREFIX) ? isCustomApiController(controllers[uid]) : isCustomFactoryController(controllers[uid])
140
+ }));
141
+ const app = strapi.app;
142
+ const registerDefined = typeof app?.register === 'function';
143
+ const bootstrapDefined = typeof app?.bootstrap === 'function';
144
+ const destroyDefined = typeof app?.destroy === 'function';
145
+ const registerNonEmpty = isLifecycleNonEmpty(app?.register);
146
+ const bootstrapNonEmpty = isLifecycleNonEmpty(app?.bootstrap);
147
+ const destroyNonEmpty = isLifecycleNonEmpty(app?.destroy);
148
+ return {
149
+ apis,
150
+ controllers: allControllers,
151
+ extendedPlugins: listExtendedPlugins(strapi),
152
+ counts: {
153
+ customControllers: allControllers.filter((c)=>c.custom).length,
154
+ customServices: apis.filter((a)=>a.customService).length,
155
+ customRoutes: apis.filter((a)=>a.customRoutes).length
156
+ },
157
+ srcIndex: {
158
+ present: app != null,
159
+ registerDefined,
160
+ registerNonEmpty,
161
+ bootstrapDefined,
162
+ bootstrapNonEmpty,
163
+ destroyDefined,
164
+ destroyNonEmpty,
165
+ // Template ships only empty register + bootstrap and no destroy.
166
+ beyondTemplate: destroyDefined || registerNonEmpty || bootstrapNonEmpty
167
+ }
168
+ };
169
+ };
170
+
171
+ exports.detectCustomizations = detectCustomizations;
172
+ exports.isLifecycleNonEmpty = isLifecycleNonEmpty;
173
+ //# sourceMappingURL=detect-customizations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-customizations.js","sources":["../../src/utils/detect-customizations.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { Core } from '@strapi/types';\n\nimport * as factories from '../factories';\n\nconst APP_UID_PREFIX = 'api::';\n\n/**\n * True when a lifecycle function has a non-empty body. The compiled function\n * source is inspected here only to derive a boolean; it is never returned.\n */\nconst stripComments = (body: string): string =>\n body\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/[^\\n]*/g, '')\n .trim();\n\nexport const isLifecycleNonEmpty = (fn: unknown): boolean => {\n if (typeof fn !== 'function') {\n return false;\n }\n const source = Function.prototype.toString.call(fn);\n // The body starts at the first `{` AFTER the parameter list closes, not the\n // first `{` overall: a real lifecycle signature like `register({ strapi })`\n // or the template's `register(/*{ strapi }*/)` puts a `{` in the params/comment.\n const parenEnd = source.indexOf(')');\n const bodyStart = source.indexOf('{', parenEnd === -1 ? 0 : parenEnd);\n\n // No brace anywhere after the parameters means a concise arrow body\n // (`register: ({ strapi }) => strapi.log.info('x')`), where everything after the\n // arrow IS the body. Treating that as empty under-reported a real customization,\n // telling Support an app was stock when it was not. The template only ever ships\n // braced method shorthand, so this branch cannot misread a fresh app.\n if (bodyStart === -1) {\n const arrow = source.indexOf('=>');\n return arrow === -1 ? false : stripComments(source.slice(arrow + 2)).length > 0;\n }\n\n return stripComments(source.slice(bodyStart + 1, source.lastIndexOf('}'))).length > 0;\n};\n\n/**\n * A default `createCoreService` result has its CRUD methods on its class\n * prototype and only `contentType` as an own key; that own key is copied onto\n * the direct prototype (the base service instance) too, so a default service\n * never has an own key that its direct prototype doesn't also have. A custom\n * service (built via a `cfg` object/callback) has extra own method keys that\n * are absent from the prototype it was assigned. Comparing own keys against\n * the DIRECT prototype's own keys (rather than guessing base method names)\n * avoids flagging every real service as custom.\n */\nconst isCustomService = (service: unknown): boolean => {\n if (service === null || typeof service !== 'object') {\n return false;\n }\n const proto = Object.getPrototypeOf(service);\n const protoOwnKeys = proto ? Object.keys(proto) : [];\n return Object.keys(service).some((key) => !protoOwnKeys.includes(key));\n};\n\n/**\n * Custom routes in Strapi are added as separate files in an api's `routes/`\n * directory (each exporting a plain `{ routes: [...] }` object), never by\n * editing the factory-generated route file, because Koa needs explicit route\n * ordering. The factory router exposes `routes` as a getter, so any route\n * file exposing `routes` as a plain data property is a hand-written custom\n * route file.\n */\nconst hasCustomRoutes = (strapi: Core.Strapi, apiName: string): boolean => {\n const api = strapi.api(apiName);\n const routeFiles = api?.routes ?? {};\n return Object.values(routeFiles).some((router) => {\n if (router === null || typeof router !== 'object') {\n return false;\n }\n const descriptor = Object.getOwnPropertyDescriptor(router, 'routes');\n // A factory router exposes `routes` as an accessor (getter); a hand-written\n // custom routes file exports it as a plain data property.\n return descriptor ? typeof descriptor.get !== 'function' : false;\n });\n};\n\n/**\n * `createCoreController` sets the controller's prototype to the factory's base controller, and\n * marks it when the app passed its own config. Anything else was not minted by the factory: a\n * plain action map (`module.exports = { async find() {} }`) is entirely hand-written, and a\n * factory that returned a non-object is not stock either. Neither may throw out of the dump.\n */\nconst isCustomApiController = (controller: unknown): boolean => {\n if (controller === null || typeof controller !== 'object') {\n return true;\n }\n\n const prototype = Object.getPrototypeOf(controller);\n if (prototype === Object.prototype || prototype === null) {\n return true;\n }\n\n return factories.isCustomController(controller as Core.Controller);\n};\n\n/**\n * Plugin and admin controllers are plain objects even when stock, so only the factory's\n * custom-config mark can single one out here (the same test startup telemetry uses).\n */\nconst isCustomFactoryController = (controller: unknown): boolean =>\n controller !== null &&\n typeof controller === 'object' &&\n factories.isCustomController(controller as Core.Controller);\n\n/**\n * Plugins the app overrides through `src/extensions/<plugin>/`: a `strapi-server.js`, which can\n * replace any controller, service or route, or content-type schema overrides. A plugin\n * controller looks the same stock or overridden, so this folder is what tells Support a\n * plugin was changed.\n */\n// The loader applies content-type overrides from `content-types/<name>/schema.json` only\nconst hasSchemaOverride = (pluginDir: string): boolean => {\n const contentTypesDir = path.join(pluginDir, 'content-types');\n if (!fs.existsSync(contentTypesDir)) {\n return false;\n }\n\n return fs\n .readdirSync(contentTypesDir, { withFileTypes: true })\n .some(\n (entry) =>\n entry.isDirectory() && fs.existsSync(path.join(contentTypesDir, entry.name, 'schema.json'))\n );\n};\n\nconst listExtendedPlugins = (strapi: Core.Strapi): string[] => {\n const extensionsDir = strapi.dirs?.dist?.extensions;\n if (!extensionsDir || !fs.existsSync(extensionsDir)) {\n return [];\n }\n\n return fs\n .readdirSync(extensionsDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .filter(\n (name) =>\n fs.existsSync(path.join(extensionsDir, name, 'strapi-server.js')) ||\n hasSchemaOverride(path.join(extensionsDir, name))\n )\n .sort();\n};\n\n// Return shape is mirrored in @strapi/types Core.Strapi['getCustomizations'];\n// keep the two in sync.\nexport const detectCustomizations = (strapi: Core.Strapi) => {\n const controllers = strapi.controllers ?? {};\n const services = strapi.services ?? {};\n\n const appControllerUids = Object.keys(controllers).filter((uid) =>\n uid.startsWith(APP_UID_PREFIX)\n );\n\n const apis = appControllerUids.map((uid) => {\n const controller = controllers[uid];\n const service = services[uid];\n // uid is `api::<name>.<name>`; map to the bare api name for route lookup.\n const apiName = uid.slice(APP_UID_PREFIX.length).split('.')[0];\n\n return {\n uid,\n customController: isCustomApiController(controller),\n customService: isCustomService(service),\n customRoutes: hasCustomRoutes(strapi, apiName),\n };\n });\n\n // Every controller, not only the app's own: the dump is used to rebuild an app for debugging.\n const allControllers = Object.keys(controllers).map((uid) => ({\n uid,\n custom: uid.startsWith(APP_UID_PREFIX)\n ? isCustomApiController(controllers[uid])\n : isCustomFactoryController(controllers[uid]),\n }));\n\n const app = strapi.app;\n const registerDefined = typeof app?.register === 'function';\n const bootstrapDefined = typeof app?.bootstrap === 'function';\n const destroyDefined = typeof app?.destroy === 'function';\n const registerNonEmpty = isLifecycleNonEmpty(app?.register);\n const bootstrapNonEmpty = isLifecycleNonEmpty(app?.bootstrap);\n const destroyNonEmpty = isLifecycleNonEmpty(app?.destroy);\n\n return {\n apis,\n controllers: allControllers,\n extendedPlugins: listExtendedPlugins(strapi),\n counts: {\n customControllers: allControllers.filter((c) => c.custom).length,\n customServices: apis.filter((a) => a.customService).length,\n customRoutes: apis.filter((a) => a.customRoutes).length,\n },\n srcIndex: {\n present: app != null,\n registerDefined,\n registerNonEmpty,\n bootstrapDefined,\n bootstrapNonEmpty,\n destroyDefined,\n destroyNonEmpty,\n // Template ships only empty register + bootstrap and no destroy.\n beyondTemplate: destroyDefined || registerNonEmpty || bootstrapNonEmpty,\n },\n };\n};\n"],"names":["APP_UID_PREFIX","stripComments","body","replace","trim","isLifecycleNonEmpty","fn","source","Function","prototype","toString","call","parenEnd","indexOf","bodyStart","arrow","slice","length","lastIndexOf","isCustomService","service","proto","Object","getPrototypeOf","protoOwnKeys","keys","some","key","includes","hasCustomRoutes","strapi","apiName","api","routeFiles","routes","values","router","descriptor","getOwnPropertyDescriptor","get","isCustomApiController","controller","factories","isCustomFactoryController","hasSchemaOverride","pluginDir","contentTypesDir","path","join","fs","existsSync","readdirSync","withFileTypes","entry","isDirectory","name","listExtendedPlugins","extensionsDir","dirs","dist","extensions","filter","map","sort","detectCustomizations","controllers","services","appControllerUids","uid","startsWith","apis","split","customController","customService","customRoutes","allControllers","custom","app","registerDefined","register","bootstrapDefined","bootstrap","destroyDefined","destroy","registerNonEmpty","bootstrapNonEmpty","destroyNonEmpty","extendedPlugins","counts","customControllers","c","customServices","a","srcIndex","present","beyondTemplate"],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { isCustomController } from '../factories.mjs';
4
+
5
+ const APP_UID_PREFIX = 'api::';
6
+ /**
7
+ * True when a lifecycle function has a non-empty body. The compiled function
8
+ * source is inspected here only to derive a boolean; it is never returned.
9
+ */ const stripComments = (body)=>body.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/[^\n]*/g, '').trim();
10
+ const isLifecycleNonEmpty = (fn)=>{
11
+ if (typeof fn !== 'function') {
12
+ return false;
13
+ }
14
+ const source = Function.prototype.toString.call(fn);
15
+ // The body starts at the first `{` AFTER the parameter list closes, not the
16
+ // first `{` overall: a real lifecycle signature like `register({ strapi })`
17
+ // or the template's `register(/*{ strapi }*/)` puts a `{` in the params/comment.
18
+ const parenEnd = source.indexOf(')');
19
+ const bodyStart = source.indexOf('{', parenEnd === -1 ? 0 : parenEnd);
20
+ // No brace anywhere after the parameters means a concise arrow body
21
+ // (`register: ({ strapi }) => strapi.log.info('x')`), where everything after the
22
+ // arrow IS the body. Treating that as empty under-reported a real customization,
23
+ // telling Support an app was stock when it was not. The template only ever ships
24
+ // braced method shorthand, so this branch cannot misread a fresh app.
25
+ if (bodyStart === -1) {
26
+ const arrow = source.indexOf('=>');
27
+ return arrow === -1 ? false : stripComments(source.slice(arrow + 2)).length > 0;
28
+ }
29
+ return stripComments(source.slice(bodyStart + 1, source.lastIndexOf('}'))).length > 0;
30
+ };
31
+ /**
32
+ * A default `createCoreService` result has its CRUD methods on its class
33
+ * prototype and only `contentType` as an own key; that own key is copied onto
34
+ * the direct prototype (the base service instance) too, so a default service
35
+ * never has an own key that its direct prototype doesn't also have. A custom
36
+ * service (built via a `cfg` object/callback) has extra own method keys that
37
+ * are absent from the prototype it was assigned. Comparing own keys against
38
+ * the DIRECT prototype's own keys (rather than guessing base method names)
39
+ * avoids flagging every real service as custom.
40
+ */ const isCustomService = (service)=>{
41
+ if (service === null || typeof service !== 'object') {
42
+ return false;
43
+ }
44
+ const proto = Object.getPrototypeOf(service);
45
+ const protoOwnKeys = proto ? Object.keys(proto) : [];
46
+ return Object.keys(service).some((key)=>!protoOwnKeys.includes(key));
47
+ };
48
+ /**
49
+ * Custom routes in Strapi are added as separate files in an api's `routes/`
50
+ * directory (each exporting a plain `{ routes: [...] }` object), never by
51
+ * editing the factory-generated route file, because Koa needs explicit route
52
+ * ordering. The factory router exposes `routes` as a getter, so any route
53
+ * file exposing `routes` as a plain data property is a hand-written custom
54
+ * route file.
55
+ */ const hasCustomRoutes = (strapi, apiName)=>{
56
+ const api = strapi.api(apiName);
57
+ const routeFiles = api?.routes ?? {};
58
+ return Object.values(routeFiles).some((router)=>{
59
+ if (router === null || typeof router !== 'object') {
60
+ return false;
61
+ }
62
+ const descriptor = Object.getOwnPropertyDescriptor(router, 'routes');
63
+ // A factory router exposes `routes` as an accessor (getter); a hand-written
64
+ // custom routes file exports it as a plain data property.
65
+ return descriptor ? typeof descriptor.get !== 'function' : false;
66
+ });
67
+ };
68
+ /**
69
+ * `createCoreController` sets the controller's prototype to the factory's base controller, and
70
+ * marks it when the app passed its own config. Anything else was not minted by the factory: a
71
+ * plain action map (`module.exports = { async find() {} }`) is entirely hand-written, and a
72
+ * factory that returned a non-object is not stock either. Neither may throw out of the dump.
73
+ */ const isCustomApiController = (controller)=>{
74
+ if (controller === null || typeof controller !== 'object') {
75
+ return true;
76
+ }
77
+ const prototype = Object.getPrototypeOf(controller);
78
+ if (prototype === Object.prototype || prototype === null) {
79
+ return true;
80
+ }
81
+ return isCustomController(controller);
82
+ };
83
+ /**
84
+ * Plugin and admin controllers are plain objects even when stock, so only the factory's
85
+ * custom-config mark can single one out here (the same test startup telemetry uses).
86
+ */ const isCustomFactoryController = (controller)=>controller !== null && typeof controller === 'object' && isCustomController(controller);
87
+ /**
88
+ * Plugins the app overrides through `src/extensions/<plugin>/`: a `strapi-server.js`, which can
89
+ * replace any controller, service or route, or content-type schema overrides. A plugin
90
+ * controller looks the same stock or overridden, so this folder is what tells Support a
91
+ * plugin was changed.
92
+ */ // The loader applies content-type overrides from `content-types/<name>/schema.json` only
93
+ const hasSchemaOverride = (pluginDir)=>{
94
+ const contentTypesDir = path.join(pluginDir, 'content-types');
95
+ if (!fs.existsSync(contentTypesDir)) {
96
+ return false;
97
+ }
98
+ return fs.readdirSync(contentTypesDir, {
99
+ withFileTypes: true
100
+ }).some((entry)=>entry.isDirectory() && fs.existsSync(path.join(contentTypesDir, entry.name, 'schema.json')));
101
+ };
102
+ const listExtendedPlugins = (strapi)=>{
103
+ const extensionsDir = strapi.dirs?.dist?.extensions;
104
+ if (!extensionsDir || !fs.existsSync(extensionsDir)) {
105
+ return [];
106
+ }
107
+ return fs.readdirSync(extensionsDir, {
108
+ withFileTypes: true
109
+ }).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name).filter((name)=>fs.existsSync(path.join(extensionsDir, name, 'strapi-server.js')) || hasSchemaOverride(path.join(extensionsDir, name))).sort();
110
+ };
111
+ // Return shape is mirrored in @strapi/types Core.Strapi['getCustomizations'];
112
+ // keep the two in sync.
113
+ const detectCustomizations = (strapi)=>{
114
+ const controllers = strapi.controllers ?? {};
115
+ const services = strapi.services ?? {};
116
+ const appControllerUids = Object.keys(controllers).filter((uid)=>uid.startsWith(APP_UID_PREFIX));
117
+ const apis = appControllerUids.map((uid)=>{
118
+ const controller = controllers[uid];
119
+ const service = services[uid];
120
+ // uid is `api::<name>.<name>`; map to the bare api name for route lookup.
121
+ const apiName = uid.slice(APP_UID_PREFIX.length).split('.')[0];
122
+ return {
123
+ uid,
124
+ customController: isCustomApiController(controller),
125
+ customService: isCustomService(service),
126
+ customRoutes: hasCustomRoutes(strapi, apiName)
127
+ };
128
+ });
129
+ // Every controller, not only the app's own: the dump is used to rebuild an app for debugging.
130
+ const allControllers = Object.keys(controllers).map((uid)=>({
131
+ uid,
132
+ custom: uid.startsWith(APP_UID_PREFIX) ? isCustomApiController(controllers[uid]) : isCustomFactoryController(controllers[uid])
133
+ }));
134
+ const app = strapi.app;
135
+ const registerDefined = typeof app?.register === 'function';
136
+ const bootstrapDefined = typeof app?.bootstrap === 'function';
137
+ const destroyDefined = typeof app?.destroy === 'function';
138
+ const registerNonEmpty = isLifecycleNonEmpty(app?.register);
139
+ const bootstrapNonEmpty = isLifecycleNonEmpty(app?.bootstrap);
140
+ const destroyNonEmpty = isLifecycleNonEmpty(app?.destroy);
141
+ return {
142
+ apis,
143
+ controllers: allControllers,
144
+ extendedPlugins: listExtendedPlugins(strapi),
145
+ counts: {
146
+ customControllers: allControllers.filter((c)=>c.custom).length,
147
+ customServices: apis.filter((a)=>a.customService).length,
148
+ customRoutes: apis.filter((a)=>a.customRoutes).length
149
+ },
150
+ srcIndex: {
151
+ present: app != null,
152
+ registerDefined,
153
+ registerNonEmpty,
154
+ bootstrapDefined,
155
+ bootstrapNonEmpty,
156
+ destroyDefined,
157
+ destroyNonEmpty,
158
+ // Template ships only empty register + bootstrap and no destroy.
159
+ beyondTemplate: destroyDefined || registerNonEmpty || bootstrapNonEmpty
160
+ }
161
+ };
162
+ };
163
+
164
+ export { detectCustomizations, isLifecycleNonEmpty };
165
+ //# sourceMappingURL=detect-customizations.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-customizations.mjs","sources":["../../src/utils/detect-customizations.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { Core } from '@strapi/types';\n\nimport * as factories from '../factories';\n\nconst APP_UID_PREFIX = 'api::';\n\n/**\n * True when a lifecycle function has a non-empty body. The compiled function\n * source is inspected here only to derive a boolean; it is never returned.\n */\nconst stripComments = (body: string): string =>\n body\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/[^\\n]*/g, '')\n .trim();\n\nexport const isLifecycleNonEmpty = (fn: unknown): boolean => {\n if (typeof fn !== 'function') {\n return false;\n }\n const source = Function.prototype.toString.call(fn);\n // The body starts at the first `{` AFTER the parameter list closes, not the\n // first `{` overall: a real lifecycle signature like `register({ strapi })`\n // or the template's `register(/*{ strapi }*/)` puts a `{` in the params/comment.\n const parenEnd = source.indexOf(')');\n const bodyStart = source.indexOf('{', parenEnd === -1 ? 0 : parenEnd);\n\n // No brace anywhere after the parameters means a concise arrow body\n // (`register: ({ strapi }) => strapi.log.info('x')`), where everything after the\n // arrow IS the body. Treating that as empty under-reported a real customization,\n // telling Support an app was stock when it was not. The template only ever ships\n // braced method shorthand, so this branch cannot misread a fresh app.\n if (bodyStart === -1) {\n const arrow = source.indexOf('=>');\n return arrow === -1 ? false : stripComments(source.slice(arrow + 2)).length > 0;\n }\n\n return stripComments(source.slice(bodyStart + 1, source.lastIndexOf('}'))).length > 0;\n};\n\n/**\n * A default `createCoreService` result has its CRUD methods on its class\n * prototype and only `contentType` as an own key; that own key is copied onto\n * the direct prototype (the base service instance) too, so a default service\n * never has an own key that its direct prototype doesn't also have. A custom\n * service (built via a `cfg` object/callback) has extra own method keys that\n * are absent from the prototype it was assigned. Comparing own keys against\n * the DIRECT prototype's own keys (rather than guessing base method names)\n * avoids flagging every real service as custom.\n */\nconst isCustomService = (service: unknown): boolean => {\n if (service === null || typeof service !== 'object') {\n return false;\n }\n const proto = Object.getPrototypeOf(service);\n const protoOwnKeys = proto ? Object.keys(proto) : [];\n return Object.keys(service).some((key) => !protoOwnKeys.includes(key));\n};\n\n/**\n * Custom routes in Strapi are added as separate files in an api's `routes/`\n * directory (each exporting a plain `{ routes: [...] }` object), never by\n * editing the factory-generated route file, because Koa needs explicit route\n * ordering. The factory router exposes `routes` as a getter, so any route\n * file exposing `routes` as a plain data property is a hand-written custom\n * route file.\n */\nconst hasCustomRoutes = (strapi: Core.Strapi, apiName: string): boolean => {\n const api = strapi.api(apiName);\n const routeFiles = api?.routes ?? {};\n return Object.values(routeFiles).some((router) => {\n if (router === null || typeof router !== 'object') {\n return false;\n }\n const descriptor = Object.getOwnPropertyDescriptor(router, 'routes');\n // A factory router exposes `routes` as an accessor (getter); a hand-written\n // custom routes file exports it as a plain data property.\n return descriptor ? typeof descriptor.get !== 'function' : false;\n });\n};\n\n/**\n * `createCoreController` sets the controller's prototype to the factory's base controller, and\n * marks it when the app passed its own config. Anything else was not minted by the factory: a\n * plain action map (`module.exports = { async find() {} }`) is entirely hand-written, and a\n * factory that returned a non-object is not stock either. Neither may throw out of the dump.\n */\nconst isCustomApiController = (controller: unknown): boolean => {\n if (controller === null || typeof controller !== 'object') {\n return true;\n }\n\n const prototype = Object.getPrototypeOf(controller);\n if (prototype === Object.prototype || prototype === null) {\n return true;\n }\n\n return factories.isCustomController(controller as Core.Controller);\n};\n\n/**\n * Plugin and admin controllers are plain objects even when stock, so only the factory's\n * custom-config mark can single one out here (the same test startup telemetry uses).\n */\nconst isCustomFactoryController = (controller: unknown): boolean =>\n controller !== null &&\n typeof controller === 'object' &&\n factories.isCustomController(controller as Core.Controller);\n\n/**\n * Plugins the app overrides through `src/extensions/<plugin>/`: a `strapi-server.js`, which can\n * replace any controller, service or route, or content-type schema overrides. A plugin\n * controller looks the same stock or overridden, so this folder is what tells Support a\n * plugin was changed.\n */\n// The loader applies content-type overrides from `content-types/<name>/schema.json` only\nconst hasSchemaOverride = (pluginDir: string): boolean => {\n const contentTypesDir = path.join(pluginDir, 'content-types');\n if (!fs.existsSync(contentTypesDir)) {\n return false;\n }\n\n return fs\n .readdirSync(contentTypesDir, { withFileTypes: true })\n .some(\n (entry) =>\n entry.isDirectory() && fs.existsSync(path.join(contentTypesDir, entry.name, 'schema.json'))\n );\n};\n\nconst listExtendedPlugins = (strapi: Core.Strapi): string[] => {\n const extensionsDir = strapi.dirs?.dist?.extensions;\n if (!extensionsDir || !fs.existsSync(extensionsDir)) {\n return [];\n }\n\n return fs\n .readdirSync(extensionsDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .filter(\n (name) =>\n fs.existsSync(path.join(extensionsDir, name, 'strapi-server.js')) ||\n hasSchemaOverride(path.join(extensionsDir, name))\n )\n .sort();\n};\n\n// Return shape is mirrored in @strapi/types Core.Strapi['getCustomizations'];\n// keep the two in sync.\nexport const detectCustomizations = (strapi: Core.Strapi) => {\n const controllers = strapi.controllers ?? {};\n const services = strapi.services ?? {};\n\n const appControllerUids = Object.keys(controllers).filter((uid) =>\n uid.startsWith(APP_UID_PREFIX)\n );\n\n const apis = appControllerUids.map((uid) => {\n const controller = controllers[uid];\n const service = services[uid];\n // uid is `api::<name>.<name>`; map to the bare api name for route lookup.\n const apiName = uid.slice(APP_UID_PREFIX.length).split('.')[0];\n\n return {\n uid,\n customController: isCustomApiController(controller),\n customService: isCustomService(service),\n customRoutes: hasCustomRoutes(strapi, apiName),\n };\n });\n\n // Every controller, not only the app's own: the dump is used to rebuild an app for debugging.\n const allControllers = Object.keys(controllers).map((uid) => ({\n uid,\n custom: uid.startsWith(APP_UID_PREFIX)\n ? isCustomApiController(controllers[uid])\n : isCustomFactoryController(controllers[uid]),\n }));\n\n const app = strapi.app;\n const registerDefined = typeof app?.register === 'function';\n const bootstrapDefined = typeof app?.bootstrap === 'function';\n const destroyDefined = typeof app?.destroy === 'function';\n const registerNonEmpty = isLifecycleNonEmpty(app?.register);\n const bootstrapNonEmpty = isLifecycleNonEmpty(app?.bootstrap);\n const destroyNonEmpty = isLifecycleNonEmpty(app?.destroy);\n\n return {\n apis,\n controllers: allControllers,\n extendedPlugins: listExtendedPlugins(strapi),\n counts: {\n customControllers: allControllers.filter((c) => c.custom).length,\n customServices: apis.filter((a) => a.customService).length,\n customRoutes: apis.filter((a) => a.customRoutes).length,\n },\n srcIndex: {\n present: app != null,\n registerDefined,\n registerNonEmpty,\n bootstrapDefined,\n bootstrapNonEmpty,\n destroyDefined,\n destroyNonEmpty,\n // Template ships only empty register + bootstrap and no destroy.\n beyondTemplate: destroyDefined || registerNonEmpty || bootstrapNonEmpty,\n },\n };\n};\n"],"names":["APP_UID_PREFIX","stripComments","body","replace","trim","isLifecycleNonEmpty","fn","source","Function","prototype","toString","call","parenEnd","indexOf","bodyStart","arrow","slice","length","lastIndexOf","isCustomService","service","proto","Object","getPrototypeOf","protoOwnKeys","keys","some","key","includes","hasCustomRoutes","strapi","apiName","api","routeFiles","routes","values","router","descriptor","getOwnPropertyDescriptor","get","isCustomApiController","controller","factories","isCustomFactoryController","hasSchemaOverride","pluginDir","contentTypesDir","path","join","fs","existsSync","readdirSync","withFileTypes","entry","isDirectory","name","listExtendedPlugins","extensionsDir","dirs","dist","extensions","filter","map","sort","detectCustomizations","controllers","services","appControllerUids","uid","startsWith","apis","split","customController","customService","customRoutes","allControllers","custom","app","registerDefined","register","bootstrapDefined","bootstrap","destroyDefined","destroy","registerNonEmpty","bootstrapNonEmpty","destroyNonEmpty","extendedPlugins","counts","customControllers","c","customServices","a","srcIndex","present","beyondTemplate"],"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;AAKnD,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAGD,eAAO,MAAM,iBAAiB,GAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,kBAAkB,KAAG,KA4BrF,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;AAiBnD,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAgCD,eAAO,MAAM,iBAAiB,GAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,kBAAkB,KAAG,KAiCrF,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC"}