@communecter/cocolight-api-client 1.0.149 → 1.0.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/1035.cocolight-api-client.browser.js +1 -0
- package/dist/1035.cocolight-api-client.cjs +1 -0
- package/dist/1035.cocolight-api-client.mjs.js +1 -0
- package/dist/1483.cocolight-api-client.browser.js +1 -0
- package/dist/1483.cocolight-api-client.cjs +1 -0
- package/dist/1483.cocolight-api-client.mjs.js +1 -0
- package/dist/1491.cocolight-api-client.browser.js +1 -0
- package/dist/1491.cocolight-api-client.cjs +1 -0
- package/dist/1491.cocolight-api-client.mjs.js +1 -0
- package/dist/1494.cocolight-api-client.browser.js +1 -0
- package/dist/1494.cocolight-api-client.cjs +1 -0
- package/dist/1494.cocolight-api-client.mjs.js +1 -0
- package/dist/1641.cocolight-api-client.browser.js +1 -0
- package/dist/1641.cocolight-api-client.cjs +1 -0
- package/dist/1641.cocolight-api-client.mjs.js +1 -0
- package/dist/1678.cocolight-api-client.browser.js +1 -0
- package/dist/1678.cocolight-api-client.cjs +1 -0
- package/dist/1678.cocolight-api-client.mjs.js +1 -0
- package/dist/2041.cocolight-api-client.browser.js +1 -0
- package/dist/2041.cocolight-api-client.cjs +1 -0
- package/dist/2041.cocolight-api-client.mjs.js +1 -0
- package/dist/2302.cocolight-api-client.browser.js +1 -0
- package/dist/2302.cocolight-api-client.cjs +1 -0
- package/dist/2302.cocolight-api-client.mjs.js +1 -0
- package/dist/2313.cocolight-api-client.browser.js +1 -0
- package/dist/2313.cocolight-api-client.cjs +1 -0
- package/dist/2313.cocolight-api-client.mjs.js +1 -0
- package/dist/2379.cocolight-api-client.browser.js +1 -0
- package/dist/2379.cocolight-api-client.cjs +1 -0
- package/dist/2379.cocolight-api-client.mjs.js +1 -0
- package/dist/2439.cocolight-api-client.browser.js +1 -0
- package/dist/2439.cocolight-api-client.cjs +1 -0
- package/dist/2439.cocolight-api-client.mjs.js +1 -0
- package/dist/2594.cocolight-api-client.browser.js +1 -0
- package/dist/2594.cocolight-api-client.cjs +1 -0
- package/dist/2594.cocolight-api-client.mjs.js +1 -0
- package/dist/2766.cocolight-api-client.browser.js +1 -0
- package/dist/2766.cocolight-api-client.cjs +1 -0
- package/dist/2766.cocolight-api-client.mjs.js +1 -0
- package/dist/2812.cocolight-api-client.browser.js +1 -0
- package/dist/2812.cocolight-api-client.cjs +1 -0
- package/dist/2812.cocolight-api-client.mjs.js +1 -0
- package/dist/2918.cocolight-api-client.browser.js +1 -0
- package/dist/2918.cocolight-api-client.cjs +1 -0
- package/dist/2918.cocolight-api-client.mjs.js +1 -0
- package/dist/3028.cocolight-api-client.browser.js +1 -0
- package/dist/3028.cocolight-api-client.cjs +1 -0
- package/dist/3028.cocolight-api-client.mjs.js +1 -0
- package/dist/3330.cocolight-api-client.browser.js +1 -0
- package/dist/3330.cocolight-api-client.cjs +1 -0
- package/dist/3330.cocolight-api-client.mjs.js +1 -0
- package/dist/3371.cocolight-api-client.browser.js +1 -0
- package/dist/3371.cocolight-api-client.cjs +1 -0
- package/dist/3371.cocolight-api-client.mjs.js +1 -0
- package/dist/3401.cocolight-api-client.browser.js +1 -0
- package/dist/3401.cocolight-api-client.cjs +1 -0
- package/dist/3401.cocolight-api-client.mjs.js +1 -0
- package/dist/3516.cocolight-api-client.browser.js +1 -0
- package/dist/3516.cocolight-api-client.cjs +1 -0
- package/dist/3516.cocolight-api-client.mjs.js +1 -0
- package/dist/3593.cocolight-api-client.browser.js +1 -0
- package/dist/3593.cocolight-api-client.cjs +1 -0
- package/dist/3593.cocolight-api-client.mjs.js +1 -0
- package/dist/3764.cocolight-api-client.browser.js +1 -0
- package/dist/3764.cocolight-api-client.cjs +1 -0
- package/dist/3764.cocolight-api-client.mjs.js +1 -0
- package/dist/3873.cocolight-api-client.browser.js +1 -0
- package/dist/3873.cocolight-api-client.cjs +1 -0
- package/dist/3873.cocolight-api-client.mjs.js +1 -0
- package/dist/3911.cocolight-api-client.browser.js +1 -0
- package/dist/3911.cocolight-api-client.cjs +1 -0
- package/dist/3911.cocolight-api-client.mjs.js +1 -0
- package/dist/4031.cocolight-api-client.browser.js +1 -0
- package/dist/4031.cocolight-api-client.cjs +1 -0
- package/dist/4031.cocolight-api-client.mjs.js +1 -0
- package/dist/4152.cocolight-api-client.browser.js +1 -0
- package/dist/4152.cocolight-api-client.cjs +1 -0
- package/dist/4152.cocolight-api-client.mjs.js +1 -0
- package/dist/4203.cocolight-api-client.browser.js +1 -0
- package/dist/4203.cocolight-api-client.cjs +1 -0
- package/dist/4203.cocolight-api-client.mjs.js +1 -0
- package/dist/424.cocolight-api-client.browser.js +1 -0
- package/dist/424.cocolight-api-client.cjs +1 -0
- package/dist/424.cocolight-api-client.mjs.js +1 -0
- package/dist/435.cocolight-api-client.browser.js +1 -0
- package/dist/435.cocolight-api-client.cjs +1 -0
- package/dist/435.cocolight-api-client.mjs.js +1 -0
- package/dist/4402.cocolight-api-client.browser.js +1 -0
- package/dist/4402.cocolight-api-client.cjs +1 -0
- package/dist/4402.cocolight-api-client.mjs.js +1 -0
- package/dist/4425.cocolight-api-client.browser.js +1 -0
- package/dist/4425.cocolight-api-client.cjs +1 -0
- package/dist/4425.cocolight-api-client.mjs.js +1 -0
- package/dist/4472.cocolight-api-client.browser.js +1 -0
- package/dist/4472.cocolight-api-client.cjs +1 -0
- package/dist/4472.cocolight-api-client.mjs.js +1 -0
- package/dist/4914.cocolight-api-client.browser.js +1 -0
- package/dist/4914.cocolight-api-client.cjs +1 -0
- package/dist/4914.cocolight-api-client.mjs.js +1 -0
- package/dist/4959.cocolight-api-client.browser.js +1 -0
- package/dist/4959.cocolight-api-client.cjs +1 -0
- package/dist/4959.cocolight-api-client.mjs.js +1 -0
- package/dist/5100.cocolight-api-client.browser.js +1 -0
- package/dist/5100.cocolight-api-client.cjs +1 -0
- package/dist/5100.cocolight-api-client.mjs.js +1 -0
- package/dist/5111.cocolight-api-client.browser.js +1 -0
- package/dist/5111.cocolight-api-client.cjs +1 -0
- package/dist/5111.cocolight-api-client.mjs.js +1 -0
- package/dist/5286.cocolight-api-client.browser.js +1 -0
- package/dist/5286.cocolight-api-client.cjs +1 -0
- package/dist/5286.cocolight-api-client.mjs.js +1 -0
- package/dist/5380.cocolight-api-client.browser.js +1 -0
- package/dist/5380.cocolight-api-client.cjs +1 -0
- package/dist/5380.cocolight-api-client.mjs.js +1 -0
- package/dist/5383.cocolight-api-client.browser.js +1 -0
- package/dist/5383.cocolight-api-client.cjs +1 -0
- package/dist/5383.cocolight-api-client.mjs.js +1 -0
- package/dist/5480.cocolight-api-client.browser.js +1 -0
- package/dist/5480.cocolight-api-client.cjs +1 -0
- package/dist/5480.cocolight-api-client.mjs.js +1 -0
- package/dist/5541.cocolight-api-client.browser.js +1 -0
- package/dist/5541.cocolight-api-client.cjs +1 -0
- package/dist/5541.cocolight-api-client.mjs.js +1 -0
- package/dist/5839.cocolight-api-client.browser.js +1 -0
- package/dist/5839.cocolight-api-client.cjs +1 -0
- package/dist/5839.cocolight-api-client.mjs.js +1 -0
- package/dist/5862.cocolight-api-client.browser.js +1 -0
- package/dist/5862.cocolight-api-client.cjs +1 -0
- package/dist/5862.cocolight-api-client.mjs.js +1 -0
- package/dist/5869.cocolight-api-client.browser.js +1 -0
- package/dist/5869.cocolight-api-client.cjs +1 -0
- package/dist/5869.cocolight-api-client.mjs.js +1 -0
- package/dist/588.cocolight-api-client.cjs +1 -1
- package/dist/588.cocolight-api-client.mjs.js +1 -1
- package/dist/601.cocolight-api-client.browser.js +1 -0
- package/dist/601.cocolight-api-client.cjs +1 -0
- package/dist/601.cocolight-api-client.mjs.js +1 -0
- package/dist/6012.cocolight-api-client.browser.js +1 -0
- package/dist/6012.cocolight-api-client.cjs +1 -0
- package/dist/6012.cocolight-api-client.mjs.js +1 -0
- package/dist/6200.cocolight-api-client.browser.js +1 -0
- package/dist/6200.cocolight-api-client.cjs +1 -0
- package/dist/6200.cocolight-api-client.mjs.js +1 -0
- package/dist/6369.cocolight-api-client.browser.js +1 -0
- package/dist/6369.cocolight-api-client.cjs +1 -0
- package/dist/6369.cocolight-api-client.mjs.js +1 -0
- package/dist/7009.cocolight-api-client.browser.js +1 -0
- package/dist/7009.cocolight-api-client.cjs +1 -0
- package/dist/7009.cocolight-api-client.mjs.js +1 -0
- package/dist/725.cocolight-api-client.browser.js +1 -0
- package/dist/725.cocolight-api-client.cjs +1 -0
- package/dist/725.cocolight-api-client.mjs.js +1 -0
- package/dist/7320.cocolight-api-client.browser.js +1 -0
- package/dist/7339.cocolight-api-client.browser.js +1 -0
- package/dist/7339.cocolight-api-client.cjs +1 -0
- package/dist/7339.cocolight-api-client.mjs.js +1 -0
- package/dist/7398.cocolight-api-client.browser.js +1 -0
- package/dist/7398.cocolight-api-client.cjs +1 -0
- package/dist/7398.cocolight-api-client.mjs.js +1 -0
- package/dist/7888.cocolight-api-client.browser.js +1 -0
- package/dist/7888.cocolight-api-client.cjs +1 -0
- package/dist/7888.cocolight-api-client.mjs.js +1 -0
- package/dist/7975.cocolight-api-client.browser.js +1 -0
- package/dist/7975.cocolight-api-client.cjs +1 -0
- package/dist/7975.cocolight-api-client.mjs.js +1 -0
- package/dist/809.cocolight-api-client.browser.js +1 -0
- package/dist/809.cocolight-api-client.cjs +1 -0
- package/dist/809.cocolight-api-client.mjs.js +1 -0
- package/dist/8300.cocolight-api-client.browser.js +1 -0
- package/dist/8300.cocolight-api-client.cjs +1 -0
- package/dist/8300.cocolight-api-client.mjs.js +1 -0
- package/dist/8317.cocolight-api-client.browser.js +1 -0
- package/dist/8317.cocolight-api-client.cjs +1 -0
- package/dist/8317.cocolight-api-client.mjs.js +1 -0
- package/dist/8525.cocolight-api-client.browser.js +1 -0
- package/dist/8525.cocolight-api-client.cjs +1 -0
- package/dist/8525.cocolight-api-client.mjs.js +1 -0
- package/dist/8894.cocolight-api-client.browser.js +1 -0
- package/dist/8894.cocolight-api-client.cjs +1 -0
- package/dist/8894.cocolight-api-client.mjs.js +1 -0
- package/dist/9301.cocolight-api-client.browser.js +1 -0
- package/dist/9301.cocolight-api-client.cjs +1 -0
- package/dist/9301.cocolight-api-client.mjs.js +1 -0
- package/dist/9438.cocolight-api-client.browser.js +1 -0
- package/dist/9438.cocolight-api-client.cjs +1 -0
- package/dist/9438.cocolight-api-client.mjs.js +1 -0
- package/dist/9478.cocolight-api-client.browser.js +1 -0
- package/dist/9478.cocolight-api-client.cjs +1 -0
- package/dist/9478.cocolight-api-client.mjs.js +1 -0
- package/dist/9568.cocolight-api-client.browser.js +1 -0
- package/dist/9568.cocolight-api-client.cjs +1 -0
- package/dist/9568.cocolight-api-client.mjs.js +1 -0
- package/dist/cocolight-api-client.browser.js +3 -3
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js.map +1 -1
- package/package.json +1 -1
- package/src/ApiClient.ts +53 -13
- package/src/api/BaseEntity.ts +237 -6
- package/src/api/EndpointApi.ts +17 -1
- package/src/api/EndpointApi.types.ts +20 -230
- package/src/api/Event.ts +6 -0
- package/src/api/Organization.ts +21 -85
- package/src/api/Poi.ts +10 -101
- package/src/api/Project.ts +6 -0
- package/src/api/User.ts +19 -1
- package/src/costum/normalize.ts +7 -0
- package/src/costum/registry.ts +138 -0
- package/src/costum/runtime-map.ts +221 -0
- package/src/costum/runtime.ts +221 -0
- package/src/costum/schemas/CercleTravailleursSociauxLiberauxLaPlumeSociale.ts +19 -0
- package/src/costum/schemas/FabEn.ts +19 -0
- package/src/costum/schemas/LivingLabInnovationSocialeBraspanon.ts +19 -0
- package/src/costum/schemas/alfph.ts +27 -0
- package/src/costum/schemas/campagne.ts +19 -0
- package/src/costum/schemas/chtitube.ts +19 -0
- package/src/costum/schemas/circuitCourt.ts +19 -0
- package/src/costum/schemas/cmcasHauteBretagne.ts +19 -0
- package/src/costum/schemas/coFinancementTierslieux.ts +27 -0
- package/src/costum/schemas/coeurNumerique.ts +19 -0
- package/src/costum/schemas/communLundi.ts +19 -0
- package/src/costum/schemas/cressReunion.ts +35 -0
- package/src/costum/schemas/cressReunionNetwork.ts +35 -0
- package/src/costum/schemas/ctenat.ts +43 -0
- package/src/costum/schemas/cyberReunion.ts +19 -0
- package/src/costum/schemas/ekisphere.ts +35 -0
- package/src/costum/schemas/equipementsSportifs974.ts +19 -0
- package/src/costum/schemas/federationDesCae.ts +19 -0
- package/src/costum/schemas/formationGenerique.ts +35 -0
- package/src/costum/schemas/franceTierslieux.ts +19 -0
- package/src/costum/schemas/hinaura.ts +27 -0
- package/src/costum/schemas/hubmayotte.ts +19 -0
- package/src/costum/schemas/hubnouvellecaledonie.ts +19 -0
- package/src/costum/schemas/hubpolynesiefrancaise.ts +19 -0
- package/src/costum/schemas/hubreunion.ts +19 -0
- package/src/costum/schemas/hubterritoires.ts +19 -0
- package/src/costum/schemas/hubwallisetfutuna.ts +19 -0
- package/src/costum/schemas/hva.ts +27 -0
- package/src/costum/schemas/ibv2.ts +19 -0
- package/src/costum/schemas/institutBleu.ts +19 -0
- package/src/costum/schemas/journalInsoumisChambery.ts +27 -0
- package/src/costum/schemas/kpacite.ts +19 -0
- package/src/costum/schemas/laCompagnieDesTierslieux.ts +43 -0
- package/src/costum/schemas/laMaisonDesFaiseurs.ts +19 -0
- package/src/costum/schemas/laReunionPourUnNumeriqueInclusif.ts +19 -0
- package/src/costum/schemas/laSemaineDesTierslieux.ts +19 -0
- package/src/costum/schemas/labEnCommuns.ts +19 -0
- package/src/costum/schemas/lakou.ts +27 -0
- package/src/costum/schemas/lesCommunsDesTierslieux.ts +19 -0
- package/src/costum/schemas/mayottePourUnNumeriqueInclusif.ts +19 -0
- package/src/costum/schemas/meir.ts +27 -0
- package/src/costum/schemas/navigatorDesTierslieux.ts +19 -0
- package/src/costum/schemas/notragora.ts +27 -0
- package/src/costum/schemas/nouvellecaledoniePourUnNumeriqueInclusif.ts +19 -0
- package/src/costum/schemas/openAtlas.ts +19 -0
- package/src/costum/schemas/polynesieFrancaisePourUnNumeriqueInclusif.ts +19 -0
- package/src/costum/schemas/prdr.ts +19 -0
- package/src/costum/schemas/reseauTierslieux.ts +19 -0
- package/src/costum/schemas/rfflabs.ts +19 -0
- package/src/costum/schemas/ries.ts +19 -0
- package/src/costum/schemas/siteDuPactePourLaTransition.ts +27 -0
- package/src/costum/schemas/sportSanteBienetre.ts +43 -0
- package/src/costum/schemas/suppa.ts +19 -0
- package/src/costum/schemas/terramies.ts +19 -0
- package/src/costum/schemas/testeTplFormation.ts +35 -0
- package/src/costum/schemas/tierslieuxbelgique.ts +19 -0
- package/src/costum/schemas/tierslieuxorg1.ts +35 -0
- package/src/costum/schemas/transiter.ts +35 -0
- package/src/costum/schemas/vhelioPeiTour2025.ts +19 -0
- package/src/costum/schemas/wallisetfutunaPourUnNumeriqueInclusif.ts +19 -0
- package/src/costum/symbol.ts +26 -0
- package/src/costum/types.ts +895 -0
- package/src/endpoints.module.ts +13 -13
- package/src/forms/entityForm.ts +142 -0
- package/src/index.ts +14 -0
- package/types/ApiClient.d.ts +1 -0
- package/types/api/BaseEntity.d.ts +69 -2
- package/types/api/EndpointApi.d.ts +11 -1
- package/types/api/EndpointApi.types.d.ts +18 -230
- package/types/api/Event.d.ts +2 -0
- package/types/api/Organization.d.ts +15 -71
- package/types/api/Poi.d.ts +2 -36
- package/types/api/Project.d.ts +2 -0
- package/types/api/User.d.ts +14 -0
- package/types/costum/normalize.d.ts +2 -0
- package/types/costum/registry.d.ts +11 -0
- package/types/costum/runtime-map.d.ts +3 -0
- package/types/costum/runtime.d.ts +99 -0
- package/types/costum/schemas/CercleTravailleursSociauxLiberauxLaPlumeSociale.d.ts +3 -0
- package/types/costum/schemas/FabEn.d.ts +3 -0
- package/types/costum/schemas/LivingLabInnovationSocialeBraspanon.d.ts +3 -0
- package/types/costum/schemas/alfph.d.ts +3 -0
- package/types/costum/schemas/campagne.d.ts +3 -0
- package/types/costum/schemas/chtitube.d.ts +3 -0
- package/types/costum/schemas/circuitCourt.d.ts +3 -0
- package/types/costum/schemas/cmcasHauteBretagne.d.ts +3 -0
- package/types/costum/schemas/coFinancementTierslieux.d.ts +3 -0
- package/types/costum/schemas/coeurNumerique.d.ts +3 -0
- package/types/costum/schemas/communLundi.d.ts +3 -0
- package/types/costum/schemas/cressReunion.d.ts +3 -0
- package/types/costum/schemas/cressReunionNetwork.d.ts +3 -0
- package/types/costum/schemas/ctenat.d.ts +3 -0
- package/types/costum/schemas/cyberReunion.d.ts +3 -0
- package/types/costum/schemas/ekisphere.d.ts +3 -0
- package/types/costum/schemas/equipementsSportifs974.d.ts +3 -0
- package/types/costum/schemas/federationDesCae.d.ts +3 -0
- package/types/costum/schemas/formationGenerique.d.ts +3 -0
- package/types/costum/schemas/franceTierslieux.d.ts +3 -0
- package/types/costum/schemas/hinaura.d.ts +3 -0
- package/types/costum/schemas/hubmayotte.d.ts +3 -0
- package/types/costum/schemas/hubnouvellecaledonie.d.ts +3 -0
- package/types/costum/schemas/hubpolynesiefrancaise.d.ts +3 -0
- package/types/costum/schemas/hubreunion.d.ts +3 -0
- package/types/costum/schemas/hubterritoires.d.ts +3 -0
- package/types/costum/schemas/hubwallisetfutuna.d.ts +3 -0
- package/types/costum/schemas/hva.d.ts +3 -0
- package/types/costum/schemas/ibv2.d.ts +3 -0
- package/types/costum/schemas/institutBleu.d.ts +3 -0
- package/types/costum/schemas/journalInsoumisChambery.d.ts +3 -0
- package/types/costum/schemas/kpacite.d.ts +3 -0
- package/types/costum/schemas/laCompagnieDesTierslieux.d.ts +3 -0
- package/types/costum/schemas/laMaisonDesFaiseurs.d.ts +3 -0
- package/types/costum/schemas/laReunionPourUnNumeriqueInclusif.d.ts +3 -0
- package/types/costum/schemas/laSemaineDesTierslieux.d.ts +3 -0
- package/types/costum/schemas/labEnCommuns.d.ts +3 -0
- package/types/costum/schemas/lakou.d.ts +3 -0
- package/types/costum/schemas/lesCommunsDesTierslieux.d.ts +3 -0
- package/types/costum/schemas/mayottePourUnNumeriqueInclusif.d.ts +3 -0
- package/types/costum/schemas/meir.d.ts +3 -0
- package/types/costum/schemas/navigatorDesTierslieux.d.ts +3 -0
- package/types/costum/schemas/notragora.d.ts +3 -0
- package/types/costum/schemas/nouvellecaledoniePourUnNumeriqueInclusif.d.ts +3 -0
- package/types/costum/schemas/openAtlas.d.ts +3 -0
- package/types/costum/schemas/polynesieFrancaisePourUnNumeriqueInclusif.d.ts +3 -0
- package/types/costum/schemas/prdr.d.ts +3 -0
- package/types/costum/schemas/reseauTierslieux.d.ts +3 -0
- package/types/costum/schemas/rfflabs.d.ts +3 -0
- package/types/costum/schemas/ries.d.ts +3 -0
- package/types/costum/schemas/siteDuPactePourLaTransition.d.ts +3 -0
- package/types/costum/schemas/sportSanteBienetre.d.ts +3 -0
- package/types/costum/schemas/suppa.d.ts +3 -0
- package/types/costum/schemas/terramies.d.ts +3 -0
- package/types/costum/schemas/testeTplFormation.d.ts +3 -0
- package/types/costum/schemas/tierslieuxbelgique.d.ts +3 -0
- package/types/costum/schemas/tierslieuxorg1.d.ts +3 -0
- package/types/costum/schemas/transiter.d.ts +3 -0
- package/types/costum/schemas/vhelioPeiTour2025.d.ts +3 -0
- package/types/costum/schemas/wallisetfutunaPourUnNumeriqueInclusif.d.ts +3 -0
- package/types/costum/symbol.d.ts +25 -0
- package/types/costum/types.d.ts +822 -0
- package/types/endpoints.module.d.ts +516 -5409
- package/types/forms/entityForm.d.ts +28 -0
- package/types/index.d.ts +4 -0
package/package.json
CHANGED
package/src/ApiClient.ts
CHANGED
|
@@ -6,6 +6,8 @@ import axiosRetryImport from "axios-retry";
|
|
|
6
6
|
import { jwtDecode } from "jwt-decode";
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
import { COSTUM_NUMBER_FIELDS, COSTUM_DATE_FIELDS } from "./costum/normalize.js";
|
|
10
|
+
import { COSTUM_REQUEST_ENVELOPE, type CostumRequestEnvelope } from "./costum/symbol.js";
|
|
9
11
|
import MongoID from "./EJSONType.js";
|
|
10
12
|
import endpointsJson from "./endpoints.module.js";
|
|
11
13
|
import { ApiClientError, ApiResponseError, ApiValidationError, CircuitBreakerError } from "./error.js";
|
|
@@ -131,6 +133,7 @@ export default class ApiClient extends EventEmitter {
|
|
|
131
133
|
|
|
132
134
|
private _offlineClientManager: OfflineClientManager | null = null;
|
|
133
135
|
private _ajv: any;
|
|
136
|
+
private _ajvNoDefaults: any;
|
|
134
137
|
public _logger: any;
|
|
135
138
|
private _client: AxiosInstance;
|
|
136
139
|
|
|
@@ -196,16 +199,19 @@ export default class ApiClient extends EventEmitter {
|
|
|
196
199
|
|
|
197
200
|
// AJV
|
|
198
201
|
this._ajv = new Ajv({ strict: false, useDefaults: true, allErrors: true, verbose: true });
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
// Variante SANS injection de défauts : utilisée pour l'UPDATE costum via `element/save`
|
|
203
|
+
// (enveloppe.isUpdate) — on n'envoie que les champs modifiés, jamais les défauts de création.
|
|
204
|
+
this._ajvNoDefaults = new Ajv({ strict: false, useDefaults: false, allErrors: true, verbose: true });
|
|
205
|
+
for (const ajv of [this._ajv, this._ajvNoDefaults]) {
|
|
206
|
+
addFormats(ajv);
|
|
207
|
+
ajv.addFormat("textarea", true);
|
|
208
|
+
ajv.addKeyword({
|
|
209
|
+
keyword: "startBeforeEnd",
|
|
210
|
+
type: "object",
|
|
211
|
+
errors: true,
|
|
212
|
+
validate: this._startBeforeEndValidate
|
|
213
|
+
});
|
|
214
|
+
}
|
|
209
215
|
|
|
210
216
|
// Pino logger
|
|
211
217
|
this._logger = pino({
|
|
@@ -766,8 +772,38 @@ export default class ApiClient extends EventEmitter {
|
|
|
766
772
|
schemaToCompile = this._cleanSchemaLeftoverAlias(requestSchema);
|
|
767
773
|
}
|
|
768
774
|
|
|
775
|
+
// Enveloppe costum (canal Symbol, cf. CostumScope) — injection UNIFIÉE données + contexte :
|
|
776
|
+
// - `properties` : champs DATA costum (per-costum) fusionnés dans le schéma racine compilé
|
|
777
|
+
// (`additionalProperties:false` ne voit que les properties du même objet schema, pas les allOf) ;
|
|
778
|
+
// - `context` : costumSlug/costumId/costumType acceptés par l'AJV (props) PUIS injectés dans le payload
|
|
779
|
+
// plus bas → le contrat n'a plus à déclarer le contexte costum.
|
|
780
|
+
const costumEnv = (data as Record<symbol, unknown>)[COSTUM_REQUEST_ENVELOPE] as CostumRequestEnvelope | undefined;
|
|
781
|
+
if (costumEnv) {
|
|
782
|
+
const ctxProps = Object.fromEntries(Object.keys(costumEnv.context ?? {}).map((k) => [k, { type: "string" }]));
|
|
783
|
+
if (costumEnv.isUpdate) {
|
|
784
|
+
// UPDATE costum via `element/save` (pendant de l'ADD) : on n'envoie que les champs MODIFIÉS
|
|
785
|
+
// (standard + costum, schémas portés dans `properties`). On compile un schéma PERMISSIF — pas
|
|
786
|
+
// les `required`/`default` du schéma de création (sinon échec sur `name`/`type`/… non envoyés et
|
|
787
|
+
// réinjection de `parent` par défaut). $defs conservés pour les éventuels $ref des properties.
|
|
788
|
+
schemaToCompile = {
|
|
789
|
+
type: "object",
|
|
790
|
+
$defs: { ...((schemaToCompile as { $defs?: Record<string, unknown> }).$defs ?? {}), ...(costumEnv.defs ?? {}) },
|
|
791
|
+
properties: { ...(costumEnv.properties ?? {}), ...ctxProps, id: { type: "string" }, collection: { type: "string" } },
|
|
792
|
+
additionalProperties: false,
|
|
793
|
+
};
|
|
794
|
+
} else {
|
|
795
|
+
schemaToCompile = {
|
|
796
|
+
...schemaToCompile,
|
|
797
|
+
properties: { ...(schemaToCompile.properties ?? {}), ...(costumEnv.properties ?? {}), ...ctxProps },
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
769
802
|
let dataForValidation = { ...data };
|
|
770
803
|
delete dataForValidation.pathParams;
|
|
804
|
+
delete (dataForValidation as Record<symbol, unknown>)[COSTUM_REQUEST_ENVELOPE];
|
|
805
|
+
// contexte costum injecté dans le payload (auto) → lu par resolveActiveCostum côté backend.
|
|
806
|
+
if (costumEnv?.context) Object.assign(dataForValidation, costumEnv.context);
|
|
771
807
|
|
|
772
808
|
// Normalize Dates to ISO strings for x-www-form-urlencoded BEFORE validation
|
|
773
809
|
if (realContentType === "application/x-www-form-urlencoded") {
|
|
@@ -778,7 +814,9 @@ export default class ApiClient extends EventEmitter {
|
|
|
778
814
|
|
|
779
815
|
const cleanedData = ApiClient.stripNullsInPlace(dataForValidation);
|
|
780
816
|
|
|
781
|
-
|
|
817
|
+
// UPDATE costum (enveloppe.isUpdate) : AJV SANS useDefaults — ne réinjecte aucun défaut de création.
|
|
818
|
+
const requestAjv = costumEnv?.isUpdate ? this._ajvNoDefaults : this._ajv;
|
|
819
|
+
const validateRequest: ValidateFunction = requestAjv.compile(schemaToCompile);
|
|
782
820
|
const valid = validateRequest(cleanedData);
|
|
783
821
|
if (!valid) {
|
|
784
822
|
const errorMessages = validateRequest.errors ? this._ajvErrorHuman(validateRequest.errors) : [];
|
|
@@ -1722,14 +1760,16 @@ export default class ApiClient extends EventEmitter {
|
|
|
1722
1760
|
/**
|
|
1723
1761
|
* Liste des champs de date à normaliser.
|
|
1724
1762
|
*/
|
|
1725
|
-
|
|
1763
|
+
// champs d'ENTITÉ génériques + champs costum (auto-générés depuis l'artefact via normalize.ts, coercés par NOM
|
|
1764
|
+
// sans dépendre de source.key ; les champs au type divergent entre costums — phone/rate — en sont exclus).
|
|
1765
|
+
private _dateFields = ["modified", "created", "updated", "birthDate", "lastLoginDate", "startDate", "endDate", "date", "issuedOn", ...COSTUM_DATE_FIELDS];
|
|
1726
1766
|
|
|
1727
1767
|
/**
|
|
1728
1768
|
* Liste des champs numériques à normaliser (le backend les renvoie en string
|
|
1729
1769
|
* via x-www-form-urlencoded ; sans cette coercion, JSON.stringify diff
|
|
1730
1770
|
* produit des faux positifs dans `hasChanges()`).
|
|
1731
1771
|
*/
|
|
1732
|
-
private _numberFields = ["
|
|
1772
|
+
private _numberFields = ["credits", "min", "max", "timeSpent", ...COSTUM_NUMBER_FIELDS];
|
|
1733
1773
|
|
|
1734
1774
|
/**
|
|
1735
1775
|
* Normalise récursivement un objet, un tableau ou une valeur simple.
|
package/src/api/BaseEntity.ts
CHANGED
|
@@ -5,6 +5,8 @@ import * as pkg from "file-type";
|
|
|
5
5
|
|
|
6
6
|
import { ApiAuthenticationError, ApiError, ApiResponseError, ApiValidationError } from "../error.js";
|
|
7
7
|
import { fromEntityJSON } from "./EntityRegistry.js";
|
|
8
|
+
import { resolveCostumCtxFromSource } from "../costum/runtime.js";
|
|
9
|
+
import { COSTUM_REQUEST_ENVELOPE } from "../costum/symbol.js";
|
|
8
10
|
import { EJSON } from "../utils/compat.js";
|
|
9
11
|
import { isReactive, isSignal, reactive } from "../utils/reactive.js";
|
|
10
12
|
|
|
@@ -62,8 +64,11 @@ import type {
|
|
|
62
64
|
GetMediawikiContributionsData,
|
|
63
65
|
CoremuOperationData,
|
|
64
66
|
DeleteDocumentByIdData,
|
|
67
|
+
DocumentListData,
|
|
65
68
|
UpdatePathValueData
|
|
66
69
|
} from "./EndpointApi.types.js";
|
|
70
|
+
import type { CostumRuntimeContext } from "../costum/runtime.js";
|
|
71
|
+
import type { Collection } from "../costum/types.js";
|
|
67
72
|
import type { GetElementsKeyResponse } from "../types/api-responses.js";
|
|
68
73
|
import type { TransformsMap } from "../types/entities.js";
|
|
69
74
|
import type { CountryItem } from "./serverDataType/Country.js";
|
|
@@ -195,6 +200,8 @@ interface Deps {
|
|
|
195
200
|
|
|
196
201
|
interface BaseEntityConfig {
|
|
197
202
|
entityTag?: string;
|
|
203
|
+
/** Contexte costum (résolu par `CostumScope`) — ouvre les champs costum sur draft/extraction/AJV. */
|
|
204
|
+
costumCtx?: CostumRuntimeContext;
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
// EntityTypeMap - mappe les clés "collection" vers leurs classes d'entités
|
|
@@ -467,6 +474,34 @@ function isNodeReadable(obj: any) {
|
|
|
467
474
|
* @template object TServerData
|
|
468
475
|
* @abstract
|
|
469
476
|
*/
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Identifie un document image dans une liste `document/list`, par `contentKey` :
|
|
480
|
+
* 1. `d.contentKey === contentKey` (backend cocolight, qui projette contentKey) ;
|
|
481
|
+
* 2. sinon par **nom de fichier** matché sur `imageUrl` (backend legacy : `document/list` ne
|
|
482
|
+
* renvoie PAS de contentKey → on rapproche le `name` du doc du basename de l'URL image).
|
|
483
|
+
* Pure (testable sans backend). Renvoie `undefined` si aucun doc identifiable.
|
|
484
|
+
*/
|
|
485
|
+
export function findImageDocument<T extends { id: string; name?: string; contentKey?: string }>(
|
|
486
|
+
docs: T[],
|
|
487
|
+
contentKey: string,
|
|
488
|
+
imageUrl?: string,
|
|
489
|
+
): T | undefined {
|
|
490
|
+
const byKey = docs.find((d) => d.contentKey === contentKey);
|
|
491
|
+
if (byKey) return byKey;
|
|
492
|
+
const base = ((imageUrl ?? "").split("?")[0] ?? "").split("/").pop() ?? "";
|
|
493
|
+
if (!base) return undefined;
|
|
494
|
+
return docs.find((d) => !!d.name && (d.name === base || (imageUrl ?? "").includes(d.name)));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** Document image de PROFIL (`findImageDocument` avec contentKey="profil"). */
|
|
498
|
+
export function findProfilDocument<T extends { id: string; name?: string; contentKey?: string }>(
|
|
499
|
+
docs: T[],
|
|
500
|
+
profilImageUrl?: string,
|
|
501
|
+
): T | undefined {
|
|
502
|
+
return findImageDocument(docs, "profil", profilImageUrl);
|
|
503
|
+
}
|
|
504
|
+
|
|
470
505
|
export class BaseEntity<TServerData = any> {
|
|
471
506
|
// Propriétés TypeScript avec types corrects
|
|
472
507
|
__entityTag: string;
|
|
@@ -488,6 +523,8 @@ export class BaseEntity<TServerData = any> {
|
|
|
488
523
|
_calledFromSave: boolean = false;
|
|
489
524
|
_syncReactiveDraft: boolean = false;
|
|
490
525
|
_isDeleted: boolean = false;
|
|
526
|
+
/** Contexte costum porté par cette instance (null hors d'un `CostumScope`). Posé au constructeur. */
|
|
527
|
+
_costumCtx: CostumRuntimeContext | null = null;
|
|
491
528
|
_add?: ((payload: any) => Promise<void | unknown>) | undefined;
|
|
492
529
|
_update?: ((payload: any) => Promise<boolean>) | undefined;
|
|
493
530
|
|
|
@@ -504,6 +541,9 @@ export class BaseEntity<TServerData = any> {
|
|
|
504
541
|
static SCHEMA_CONSTANTS?: string | string[];
|
|
505
542
|
static VIRTUAL_SCHEMAS?: Record<string, any>;
|
|
506
543
|
static CUSTOM_FIELD_HANDLERS?: Map<string, { updateMethod: string; schemaConstant?: string }>;
|
|
544
|
+
/** Constante de schéma du bloc de CRÉATION (ADD_*) où injecter les champs costum à la validation
|
|
545
|
+
* d'extraction. Définie par les entités créables sous costum (Poi/Organization/Event/Project). */
|
|
546
|
+
static COSTUM_ADD_CONSTANT?: string;
|
|
507
547
|
|
|
508
548
|
/**
|
|
509
549
|
* Vérifie que l'objet n'a pas été supprimé.
|
|
@@ -558,6 +598,13 @@ export class BaseEntity<TServerData = any> {
|
|
|
558
598
|
|
|
559
599
|
this._serverData = reactive({});
|
|
560
600
|
|
|
601
|
+
// ⚠ EAGER : `_buildDraftAndProxy` est appelé ICI (constructeur). Le `_costumCtx` doit donc être
|
|
602
|
+
// posé AVANT, sinon le draft est figé sans les champs costum (cf. map CostumScope ZONE A).
|
|
603
|
+
// NB : le CONTEXTE costum (costumSlug/costumId/costumType) n'est PAS posé dans le draft — il est
|
|
604
|
+
// injecté automatiquement au bord requête par `callEndpoint` (enveloppe COSTUM_REQUEST_ENVELOPE) ;
|
|
605
|
+
// seuls les champs DATA costum sont ouverts sur le draft (via `_costumCtx.schema` dans _buildDraftAndProxy).
|
|
606
|
+
this._costumCtx = config.costumCtx ?? null;
|
|
607
|
+
|
|
561
608
|
const { draft, proxy, initial } = this._buildDraftAndProxy({
|
|
562
609
|
data: { ...data, ...this.defaultFields },
|
|
563
610
|
serverData: this._serverData,
|
|
@@ -698,6 +745,12 @@ export class BaseEntity<TServerData = any> {
|
|
|
698
745
|
}
|
|
699
746
|
return await this.refresh();
|
|
700
747
|
} else if (typeof this._update === "function") {
|
|
748
|
+
// UPDATE : pour une entité costum-scopée, `_update` (par entité, après son garde d'auth) redirige vers
|
|
749
|
+
// `_saveCostumViaElementSave` → UN SEUL `element/save` avec id + enveloppe. C'est le pendant EXACT de
|
|
750
|
+
// l'ADD : côté backend, `element/save` (branche update) déclenche prepData + elementBeforeSave +
|
|
751
|
+
// elementAfterUpdate + elementAfterSave + la validation costum — donc les dérivations costum
|
|
752
|
+
// (tag taille ⇐ buildingSurfaceArea, siren/famille ⇐ siret/typeEtablissement, …) s'appliquent pour
|
|
753
|
+
// TOUS les costum. Entité non-costum : blocs `element/updateblock` standards (inchangé).
|
|
701
754
|
const hasChanged = await this._update(payload);
|
|
702
755
|
this._resetInitialDraftData();
|
|
703
756
|
if (hasChanged) return await this.refresh();
|
|
@@ -709,6 +762,91 @@ export class BaseEntity<TServerData = any> {
|
|
|
709
762
|
}
|
|
710
763
|
}
|
|
711
764
|
|
|
765
|
+
/**
|
|
766
|
+
* UPDATE d'une entité costum-scopée — pendant EXACT de l'ADD. Au lieu de N `updatepathvalue` champ-par-champ
|
|
767
|
+
* (route « édition inline » legacy : AUCUN hook, AUCUNE validation), on envoie UN SEUL `element/save` portant
|
|
768
|
+
* tous les champs MODIFIÉS (standard + costum) + l'id + l'enveloppe costum (contexte + schémas des champs
|
|
769
|
+
* envoyés, `isUpdate:true`). Côté backend, `element/save` branche update déclenche prepData / elementBeforeSave /
|
|
770
|
+
* elementAfterUpdate / elementAfterSave / validation costum (cf. legacy `Element::save` : ce sont les SEULES
|
|
771
|
+
* routes qui exécutent ces hooks ; updatepathvalue/updateblock n'en exécutent aucun de dérivation). Atomique
|
|
772
|
+
* (un seul `updated`/recalcul slug). Effacement (`null`/`""`/`[]`) → `""` (survit à `stripNulls`, backend → `$unset`).
|
|
773
|
+
*
|
|
774
|
+
* L'univers des champs éditables = `_allowedFieldsCache` (union writable des SCHEMA_CONSTANTS + schéma costum,
|
|
775
|
+
* calculée au build du draft) ∪ champs DATA costum déclarés (robuste si le cache est antérieur au costum).
|
|
776
|
+
* @returns true si au moins un champ a été envoyé (donc refresh ensuite).
|
|
777
|
+
*/
|
|
778
|
+
protected async _saveCostumViaElementSave(payload: Record<string, any>): Promise<boolean> {
|
|
779
|
+
const ctx = this._costumCtx;
|
|
780
|
+
if (!ctx || !this.id) return false;
|
|
781
|
+
if ("id" in payload) delete payload.id;
|
|
782
|
+
|
|
783
|
+
const fullData: Record<string, any> = { ...payload, ...this.defaultFields };
|
|
784
|
+
const initial = this.initialDraftData ?? {};
|
|
785
|
+
const combined = this._allowedFieldsMetadata?.combinedSchema as { allOf?: JsonSchema[] } | undefined;
|
|
786
|
+
const costumProps = (ctx.schema as { properties?: Record<string, unknown> } | undefined)?.properties ?? {};
|
|
787
|
+
|
|
788
|
+
// union des clés candidates : writable standard+costum (cache) ∪ champs data costum déclarés
|
|
789
|
+
const candidates = new Set<string>([
|
|
790
|
+
...(this._allowedFieldsCache ?? []),
|
|
791
|
+
...Object.keys(costumProps),
|
|
792
|
+
...((ctx.fields ?? []).map((f) => f.name)),
|
|
793
|
+
]);
|
|
794
|
+
|
|
795
|
+
const changed: Record<string, any> = {};
|
|
796
|
+
const props: Record<string, unknown> = {};
|
|
797
|
+
for (const key of candidates) {
|
|
798
|
+
// `profil_avatar` = IMAGE (bloc PROFIL_IMAGE dédié, upload multipart) → JAMAIS dans l'`element/save`
|
|
799
|
+
// (JSON) : un File ne s'y sérialise pas. Traité séparément ci-dessous (pendant de l'ADD via ADD_BLOCKS).
|
|
800
|
+
if (key === "id" || key === "slug" || key === "profil_avatar" || this.removeFields.includes(key)) continue;
|
|
801
|
+
if (fullData[key] === undefined) continue;
|
|
802
|
+
if (!this._compareValues(fullData[key], initial[key])) continue; // inchangé → on n'envoie pas
|
|
803
|
+
const v = fullData[key];
|
|
804
|
+
const isClear = v === null || v === "" || (Array.isArray(v) && v.length === 0);
|
|
805
|
+
changed[key] = isClear ? "" : v; // clear → "" : survit à stripNulls, backend prepElementData → $unset
|
|
806
|
+
props[key] = this._lookupPropSchema(combined, key) ?? (costumProps[key] as unknown) ?? {};
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
let didSave = false;
|
|
810
|
+
|
|
811
|
+
// Champs DATA modifiés → UN `element/save` (branche update : prepData + hooks costum).
|
|
812
|
+
if (Object.keys(changed).length > 0) {
|
|
813
|
+
changed.id = this.id;
|
|
814
|
+
changed.collection = ctx.collection;
|
|
815
|
+
(changed as Record<symbol, unknown>)[COSTUM_REQUEST_ENVELOPE] = {
|
|
816
|
+
properties: props,
|
|
817
|
+
context: { costumSlug: ctx.slug, costumId: ctx.costumId, costumType: ctx.costumType },
|
|
818
|
+
isUpdate: true,
|
|
819
|
+
defs: (combined as { $defs?: Record<string, unknown> } | undefined)?.$defs ?? {},
|
|
820
|
+
};
|
|
821
|
+
const response = await this.apiClient.callEndpoint(this._getCtor().COSTUM_ADD_CONSTANT!, changed);
|
|
822
|
+
// Surface une éventuelle erreur serveur {result:false} (ex. addressValid → "Invalid object ID") au lieu
|
|
823
|
+
// de l'avaler : `callEndpoint` ne lève PAS sur {result:false} (HTTP 200). Même garde que `call()`/
|
|
824
|
+
// `_invokeBlockMethod` (sinon un save costum rejeté passerait pour un succès → faux "enregistré").
|
|
825
|
+
this.apiClient.checkAndThrowApiResponseError(response);
|
|
826
|
+
didSave = true;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// IMAGE (`profil_avatar`) : hors schéma DATA → bloc PROFIL_IMAGE dédié (endpoint upload), exécuté
|
|
830
|
+
// séparément comme à l'ADD (Poi.ADD_BLOCKS). Sans ça l'édition costum perdait l'image (le court-circuit
|
|
831
|
+
// `_saveCostumViaElementSave` saute la boucle UPDATE_BLOCKS qui, en update standard, porte ce bloc).
|
|
832
|
+
if (payload.profil_avatar != null) {
|
|
833
|
+
await this.updateImageProfil({ profil_avatar: payload.profil_avatar as UploadInput });
|
|
834
|
+
didSave = true;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
return didSave;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/** Recherche le schéma d'une propriété dans un schéma combiné `{ allOf: [...] }` (1er match). */
|
|
841
|
+
private _lookupPropSchema(combined: { allOf?: JsonSchema[] } | undefined, key: string): unknown {
|
|
842
|
+
if (!combined?.allOf) return undefined;
|
|
843
|
+
for (const sub of combined.allOf) {
|
|
844
|
+
const p = (sub as { properties?: Record<string, unknown> })?.properties?.[key];
|
|
845
|
+
if (p) return p;
|
|
846
|
+
}
|
|
847
|
+
return undefined;
|
|
848
|
+
}
|
|
849
|
+
|
|
712
850
|
/**
|
|
713
851
|
* Crée une nouvelle instance d'entité à partir des données du serveur.
|
|
714
852
|
*
|
|
@@ -783,6 +921,16 @@ export class BaseEntity<TServerData = any> {
|
|
|
783
921
|
...clientDraft
|
|
784
922
|
};
|
|
785
923
|
|
|
924
|
+
// inc2 : contexte costum d'une entité CHARGÉE. Un élément appartient à UN costum = son `source.key`,
|
|
925
|
+
// qui fait donc AUTORITÉ (override un éventuel scope : on ne peut pas éditer un élément du costum B
|
|
926
|
+
// avec le schéma du costum A). Fallback sur le `_costumCtx` existant (scope) si source absente/inconnue
|
|
927
|
+
// (ex. entité neuve avant 1er save, ou refresh dont la réponse ne renvoie pas `source`). Sync (COSTUM_RUNTIME).
|
|
928
|
+
{
|
|
929
|
+
const src = (this._serverData as { source?: { key?: string; keys?: string[] } } | undefined)?.source;
|
|
930
|
+
const srcKey = src?.key ?? src?.keys?.[0];
|
|
931
|
+
this._costumCtx = resolveCostumCtxFromSource(srcKey, this.getEntityType() as Collection) ?? this._costumCtx;
|
|
932
|
+
}
|
|
933
|
+
|
|
786
934
|
const { draft, proxy, initial } = this._buildDraftAndProxy({
|
|
787
935
|
data: mergedData,
|
|
788
936
|
serverData: this._serverData,
|
|
@@ -1344,6 +1492,62 @@ export class BaseEntity<TServerData = any> {
|
|
|
1344
1492
|
await this.callIsConnected(() => this.endpointApi.deleteDocumentById(payload));
|
|
1345
1493
|
}
|
|
1346
1494
|
|
|
1495
|
+
/**
|
|
1496
|
+
* Liste les documents (images/fichiers) attachés à CETTE entité (`id` + `type`) via `DOCUMENT_LIST`
|
|
1497
|
+
* (port legacy `document/list`). Renvoie un tableau plat `{ id, name, path, author, contentKey }`.
|
|
1498
|
+
* Utile pour récupérer le `docId` d'une image (ex. profil) — non exposé sur l'élément — afin de la
|
|
1499
|
+
* supprimer (`deleteFile`).
|
|
1500
|
+
*/
|
|
1501
|
+
async getDocuments(): Promise<Array<{ id: string; name?: string; path?: string; author?: string; contentKey?: string }>> {
|
|
1502
|
+
if (!this.id) {
|
|
1503
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`, 404);
|
|
1504
|
+
}
|
|
1505
|
+
const type = this.getEntityType() as NonNullable<DocumentListData["pathParams"]>["type"];
|
|
1506
|
+
const res = await this.callIsConnected(() => this.endpointApi.documentList({ pathParams: { id: this.id as string, type } }));
|
|
1507
|
+
const list = (res as { list?: Record<string, Record<string, unknown>> } | null)?.list ?? {};
|
|
1508
|
+
return Object.values(list)
|
|
1509
|
+
.map((d) => ({
|
|
1510
|
+
id: String((d as Record<string, unknown>).id ?? ""),
|
|
1511
|
+
name: (d as Record<string, unknown>).name as string | undefined,
|
|
1512
|
+
path: (d as Record<string, unknown>).path as string | undefined,
|
|
1513
|
+
author: (d as Record<string, unknown>).author as string | undefined,
|
|
1514
|
+
contentKey: (d as Record<string, unknown>).contentKey as string | undefined,
|
|
1515
|
+
}))
|
|
1516
|
+
.filter((d) => d.id.length === 24);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
/**
|
|
1520
|
+
* Supprime l'image de PROFIL de cette entité : récupère le `docId` du document `contentKey:"profil"`
|
|
1521
|
+
* (via `getDocuments`) puis `deleteFile`. No-op (`false`) s'il n'y a pas d'image. Pendant exact de
|
|
1522
|
+
* `updateImageProfil` côté suppression.
|
|
1523
|
+
*/
|
|
1524
|
+
async removeProfilImage(): Promise<boolean> {
|
|
1525
|
+
const docs = await this.getDocuments();
|
|
1526
|
+
// La search peut ne projeter que la variante medium/thumb : on prend la 1re URL profil dispo
|
|
1527
|
+
// (le basename de fichier est identique entre variantes → suffit au match par nom côté legacy).
|
|
1528
|
+
const sd = this._serverData as { profilImageUrl?: string; profilMediumImageUrl?: string; profilThumbImageUrl?: string } | undefined;
|
|
1529
|
+
const url = sd?.profilImageUrl || sd?.profilMediumImageUrl || sd?.profilThumbImageUrl;
|
|
1530
|
+
const profil = findImageDocument(docs, "profil", url);
|
|
1531
|
+
if (!profil) return false;
|
|
1532
|
+
await this.deleteFile(profil.id);
|
|
1533
|
+
return true;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/**
|
|
1537
|
+
* Supprime l'image de BANNIÈRE de cette entité : récupère le `docId` du document `contentKey:"banner"`
|
|
1538
|
+
* (via `getDocuments`) puis `deleteFile`. No-op (`false`) s'il n'y a pas de bannière. Pendant de
|
|
1539
|
+
* `updateImageBanner` côté suppression (le backend désassigne `profilBannerUrl`/`profilRealBannerUrl`).
|
|
1540
|
+
*/
|
|
1541
|
+
async removeBannerImage(): Promise<boolean> {
|
|
1542
|
+
const docs = await this.getDocuments();
|
|
1543
|
+
const sd = this._serverData as { profilBannerUrl?: string; profilRealBannerUrl?: string } | undefined;
|
|
1544
|
+
const url = sd?.profilRealBannerUrl || sd?.profilBannerUrl;
|
|
1545
|
+
const banner = findImageDocument(docs, "banner", url);
|
|
1546
|
+
if (!banner) return false;
|
|
1547
|
+
await this.deleteFile(banner.id);
|
|
1548
|
+
return true;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1347
1551
|
/**
|
|
1348
1552
|
* Vide les objets réactifs et marque l'entité comme supprimée (tombstone),
|
|
1349
1553
|
* sans casser la réactivité. Pattern partagé par tous les `delete()`.
|
|
@@ -2088,6 +2292,13 @@ export class BaseEntity<TServerData = any> {
|
|
|
2088
2292
|
combinedSchema.allOf.push(sch as JsonSchema);
|
|
2089
2293
|
}
|
|
2090
2294
|
|
|
2295
|
+
// Couche 1 (draft) : ouvre les champs costum à l'écriture sur le proxy. Le schéma costum est
|
|
2296
|
+
// permissif (additionalProperties:true) ; `_extractWritableFields` recurse `allOf` → ses
|
|
2297
|
+
// `properties` deviennent writable. Isolé par instance (jamais via VIRTUAL_SCHEMAS statique).
|
|
2298
|
+
if (this._costumCtx?.schema) {
|
|
2299
|
+
combinedSchema.allOf.push(this._costumCtx.schema as unknown as JsonSchema);
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2091
2302
|
let allowed = this._extractWritableFields(combinedSchema, data);
|
|
2092
2303
|
|
|
2093
2304
|
if (data.id && allowed.indexOf("id") === -1) {
|
|
@@ -2260,7 +2471,15 @@ export class BaseEntity<TServerData = any> {
|
|
|
2260
2471
|
}
|
|
2261
2472
|
|
|
2262
2473
|
_extractChangedFieldsFromSchema(apiClient: ApiClient, constant: string, data: Record<string, any> = {}, getInitialDraft: () => Record<string, any> | void, removeFields: string[] = []): Record<string, any> | null {
|
|
2263
|
-
|
|
2474
|
+
let schema = apiClient.getRequestSchema(constant);
|
|
2475
|
+
// Couche 2 (extraction bloc ADD) : pour le bloc de création de l'entité, les champs costum
|
|
2476
|
+
// doivent survivre à l'extraction (sinon droppés avant l'envoi). On ne fusionne QUE pour
|
|
2477
|
+
// `COSTUM_ADD_CONSTANT` — jamais pour les UPDATE_BLOCK_* (à l'édition, une entité costum passe
|
|
2478
|
+
// ENTIÈREMENT par `_saveCostumViaElementSave` → `element/save`, pas par les blocs `updateblock`).
|
|
2479
|
+
const costumAddBlock = !!this._costumCtx?.schema && constant === this._getCtor().COSTUM_ADD_CONSTANT;
|
|
2480
|
+
if (costumAddBlock) {
|
|
2481
|
+
schema = this._mergeSchemas(schema, this._costumCtx!.schema);
|
|
2482
|
+
}
|
|
2264
2483
|
let allowed = this._extractWritableFields(schema, data);
|
|
2265
2484
|
const changed: Record<string, any> = {};
|
|
2266
2485
|
const initialDraft = getInitialDraft?.() || {};
|
|
@@ -2285,7 +2504,19 @@ export class BaseEntity<TServerData = any> {
|
|
|
2285
2504
|
}
|
|
2286
2505
|
}
|
|
2287
2506
|
|
|
2288
|
-
|
|
2507
|
+
if (Object.keys(changed).length === 0) return null;
|
|
2508
|
+
// Couche 3 (AJV réseau) : on greffe l'ENVELOPPE costum sur le payload via une clé Symbol — `callEndpoint`
|
|
2509
|
+
// fusionne ses `properties` (champs data) dans le schéma compilé ET injecte le `context`
|
|
2510
|
+
// (costumSlug/costumId/costumType) dans le payload. Le contexte n'est donc plus dans le draft ni le contrat.
|
|
2511
|
+
// Invisible au wire (Symbol ignoré par JSON/AJV/Object.keys).
|
|
2512
|
+
if (costumAddBlock) {
|
|
2513
|
+
const ctx = this._costumCtx!;
|
|
2514
|
+
(changed as Record<symbol, unknown>)[COSTUM_REQUEST_ENVELOPE] = {
|
|
2515
|
+
properties: (ctx.schema as { properties?: Record<string, unknown> }).properties ?? {},
|
|
2516
|
+
context: { costumSlug: ctx.slug, costumId: ctx.costumId, costumType: ctx.costumType },
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
return changed;
|
|
2289
2520
|
}
|
|
2290
2521
|
|
|
2291
2522
|
/**
|
|
@@ -2643,7 +2874,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
2643
2874
|
* @return {EntityTypeMap[T]}
|
|
2644
2875
|
* @private
|
|
2645
2876
|
*/
|
|
2646
|
-
_entityInstanceData<T extends keyof EntityTypeMap>(entityType: T, entityData: object): EntityTypeMap[T] {
|
|
2877
|
+
_entityInstanceData<T extends keyof EntityTypeMap>(entityType: T, entityData: object, config: BaseEntityConfig = {}): EntityTypeMap[T] {
|
|
2647
2878
|
const meta = this._getEntityMeta(entityType);
|
|
2648
2879
|
if (!meta) {
|
|
2649
2880
|
throw new ApiError(`Type d'entité inconnu: ${entityType}`, 400);
|
|
@@ -2658,7 +2889,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
2658
2889
|
return new meta.entityClass(parent, entityData, {
|
|
2659
2890
|
[selfKey]: selfClass,
|
|
2660
2891
|
...meta.deps
|
|
2661
|
-
}) as EntityTypeMap[T];
|
|
2892
|
+
}, config) as EntityTypeMap[T];
|
|
2662
2893
|
}
|
|
2663
2894
|
|
|
2664
2895
|
/**
|
|
@@ -2668,9 +2899,9 @@ export class BaseEntity<TServerData = any> {
|
|
|
2668
2899
|
* @param [entityData={}]
|
|
2669
2900
|
* @return {Promise<EntityTypeMap[T]>}
|
|
2670
2901
|
*/
|
|
2671
|
-
async entity<T extends keyof EntityTypeMap>(entityType: T, entityData: object = {}): Promise<EntityTypeMap[T]> {
|
|
2902
|
+
async entity<T extends keyof EntityTypeMap>(entityType: T, entityData: object = {}, config: BaseEntityConfig = {}): Promise<EntityTypeMap[T]> {
|
|
2672
2903
|
try {
|
|
2673
|
-
const entity = this._entityInstanceData(entityType, entityData);
|
|
2904
|
+
const entity = this._entityInstanceData(entityType, entityData, config);
|
|
2674
2905
|
|
|
2675
2906
|
const fetchKeysByEntity = {
|
|
2676
2907
|
citoyens: ["id", "slug"],
|
package/src/api/EndpointApi.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { ApiAuthenticationError } from "../error.js";
|
|
3
3
|
|
|
4
4
|
import type ApiClient from "../ApiClient.js";
|
|
5
|
-
import type { PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, ShareEventsData, InviteEventData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, GenerateAnswerFromFormData, FundingEnvelopeData, CoremuOperationData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData } from "./EndpointApi.types.js";
|
|
5
|
+
import type { DocumentListData, PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, ShareEventsData, InviteEventData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, GenerateAnswerFromFormData, FundingEnvelopeData, CoremuOperationData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData } from "./EndpointApi.types.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Classe EndpointApi générée automatiquement depuis endpoints-copie.json
|
|
@@ -80,6 +80,22 @@ export class EndpointApi {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Lister les documents d'une entité : Liste les documents (images/fichiers) attachés à un élément (id+type). Port de citizenToolKit document/ListAction (tpl=json). Sert notamment à récupérer le docId de l'image de profil (contentKey=profil) pour la supprimer via DELETE_DOCUMENT_BY_ID.
|
|
85
|
+
* Constant : DOCUMENT_LIST
|
|
86
|
+
* @param data - Données envoyées à l'API
|
|
87
|
+
* @returns Les données de réponse.
|
|
88
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
89
|
+
* @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
|
|
90
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
91
|
+
*/
|
|
92
|
+
async documentList(data: DocumentListData): Promise<any> {
|
|
93
|
+
if (!data || typeof data !== "object") {
|
|
94
|
+
throw new TypeError("Le paramètre data doit être un objet.");
|
|
95
|
+
}
|
|
96
|
+
return this.callIsConnected("DOCUMENT_LIST", data);
|
|
97
|
+
}
|
|
98
|
+
|
|
83
99
|
/**
|
|
84
100
|
* Enregistrement d'un utilisateur : Permet d’enregistrer un nouvel utilisateur avec ses informations personnelles.
|
|
85
101
|
* Constant : PERSON_REGISTER
|