From 99dbc985eb834b5a688db0d07cfc7a2a07ae7ed4 Mon Sep 17 00:00:00 2001 From: Ali Amori Kadhim Date: Tue, 12 Nov 2024 17:36:55 +0100 Subject: [PATCH] feat: align overige-objecten-api response with kiss --- .../src/__mocks__/getStrapiVacData.ts | 6 + .../src/__mocks__/kennisartikelObject.ts | 81 ++-- .../src/__mocks__/objectsResponseData.ts | 242 ++++++---- .../src/__mocks__/vacObject.ts | 61 +-- .../src/controllers/objects/index.test.ts | 36 +- .../src/controllers/objects/index.ts | 60 ++- .../src/docs/openapi.yaml | 415 +++++++++++++----- .../overige-objecten-api/src/queries/index.ts | 4 + .../src/strapi-product-type.ts | 3 + .../src/utils/generateKennisartikelObject.ts | 48 +- 10 files changed, 635 insertions(+), 321 deletions(-) diff --git a/apps/overige-objecten-api/src/__mocks__/getStrapiVacData.ts b/apps/overige-objecten-api/src/__mocks__/getStrapiVacData.ts index bbf3cebc..e32cbf58 100644 --- a/apps/overige-objecten-api/src/__mocks__/getStrapiVacData.ts +++ b/apps/overige-objecten-api/src/__mocks__/getStrapiVacData.ts @@ -6,6 +6,8 @@ export const getStrapiVacData = () => { { id: '1', attributes: { + createdAt: '2024-11-05T16:03:50.975Z', + updatedAt: '2024-11-05T16:03:50.975Z', vac: { uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', vraag: 'Wat is het proces om een paspoort aan te vragen?', @@ -34,6 +36,8 @@ export const getStrapiVacData = () => { { id: '2', attributes: { + createdAt: '2024-11-05T16:03:50.975Z', + updatedAt: '2024-11-05T16:03:50.975Z', vac: { uuid: 'b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7', vraag: 'Hoe kan ik een rijbewijs aanvragen?', @@ -62,6 +66,8 @@ export const getStrapiVacData = () => { { id: '3', attributes: { + createdAt: '2024-11-05T16:03:50.975Z', + updatedAt: '2024-11-05T16:03:50.975Z', vac: { uuid: 'c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8', vraag: 'Wat moet ik doen bij verhuizing?', diff --git a/apps/overige-objecten-api/src/__mocks__/kennisartikelObject.ts b/apps/overige-objecten-api/src/__mocks__/kennisartikelObject.ts index d65d481a..7374549f 100644 --- a/apps/overige-objecten-api/src/__mocks__/kennisartikelObject.ts +++ b/apps/overige-objecten-api/src/__mocks__/kennisartikelObject.ts @@ -1,38 +1,51 @@ export const kennisartikelObject = () => ({ - url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel', + url: 'http://localhost:3000/api/v2/objects/b77a89a0-3ec2-467d-84b2-b484d5726ceb', uuid: 'b77a89a0-3ec2-467d-84b2-b484d5726ceb', - upnUri: 'http://standaarden.overheid.nl/owms/terms/UPL-naam_nog_niet_beschikbaar', - publicatieDatum: '2024-11-05', - productAanwezig: true, - productValtOnder: null, - verantwoordelijkeOrganisatie: { - url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel#verantwoordelijkeOrganisatie', - owmsIdentifier: 'http://standaarden.overheid.nl/owms/terms/Utrecht_(gemeente)', - owmsPrefLabel: 'Gemeente Utrecht', - owmsEndDate: '2024-11-05T23:00:00.000Z', - }, - locaties: null, - doelgroep: 'eu-burger', - afdelingen: [ - { - afdelingId: '463de311-fbe3-48d8-bd87-722de5c80b04', - afdelingnaam: 'Demo Afdeling', - }, - ], - beschikbareTalen: ['nl'], - vertalingen: [ - { - datumWijziging: '2024-11-06T12:05:42.541Z', - taal: 'nl', - titel: 'Demo Product', - trefwoorden: [{ trefwoord: 'Demo' }, { trefwoord: 'Page' }], - vereisten: '

Voorwaarden - 1

Body text

', - bewijs: '

Bewijs - 1

Body text

', - bezwaarEnBeroep: '

Bezwaar - 1

Body text

', - deskMemo: '', - kostenEnBetaalmethoden: '

Kosten - 1

', - procedureBeschrijving: '

Aanvraag  - 1

Body text

', - tekst: '

Inleiding - 1

Body text

Inleiding - 2

Body text

', + type: 'http://localhost:3000/api/v2/objecttypes/kennisartikel', + record: { + endAt: null, + geometry: null, + index: 1, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 3, + data: { + url: 'http://localhost:3000/api/v2/objects/b77a89a0-3ec2-467d-84b2-b484d5726ceb', + uuid: 'b77a89a0-3ec2-467d-84b2-b484d5726ceb', + upnUri: 'http://standaarden.overheid.nl/owms/terms/UPL-naam_nog_niet_beschikbaar', + publicatieDatum: '2024-11-05', + productAanwezig: true, + productValtOnder: null, + verantwoordelijkeOrganisatie: { + url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel#verantwoordelijkeOrganisatie', + owmsIdentifier: 'http://standaarden.overheid.nl/owms/terms/Utrecht_(gemeente)', + owmsPrefLabel: 'Gemeente Utrecht', + owmsEndDate: '2024-11-05T23:00:00.000Z', + }, + locaties: null, + doelgroep: 'eu-burger', + afdelingen: [ + { + afdelingId: '463de311-fbe3-48d8-bd87-722de5c80b04', + afdelingnaam: 'Demo Afdeling', + }, + ], + beschikbareTalen: ['nl'], + vertalingen: [ + { + datumWijziging: '2024-11-06T12:05:42.541Z', + taal: 'nl', + titel: 'Demo Product', + trefwoorden: [{ trefwoord: 'Demo' }, { trefwoord: 'Page' }], + vereisten: '

Voorwaarden - 1

Body text

', + bewijs: '

Bewijs - 1

Body text

', + bezwaarEnBeroep: '

Bezwaar - 1

Body text

', + deskMemo: '', + kostenEnBetaalmethoden: '

Kosten - 1

', + procedureBeschrijving: '

Aanvraag  - 1

Body text

', + tekst: '

Inleiding - 1

Body text

Inleiding - 2

Body text

', + }, + ], }, - ], + }, }); diff --git a/apps/overige-objecten-api/src/__mocks__/objectsResponseData.ts b/apps/overige-objecten-api/src/__mocks__/objectsResponseData.ts index 0041b723..b5e70713 100644 --- a/apps/overige-objecten-api/src/__mocks__/objectsResponseData.ts +++ b/apps/overige-objecten-api/src/__mocks__/objectsResponseData.ts @@ -2,121 +2,173 @@ export const objectsResponseData = ({ type }: { type?: 'kennisartikel' | 'vac' } const data = { results: [ { - url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel', + type: 'http://localhost:3000/api/v2/objecttypes/kennisartikel', + url: 'http://localhost:3000/api/v2/objects/b77a89a0-3ec2-467d-84b2-b484d5726ceb', uuid: 'b77a89a0-3ec2-467d-84b2-b484d5726ceb', - upnUri: 'http://standaarden.overheid.nl/owms/terms/UPL-naam_nog_niet_beschikbaar', - publicatieDatum: '2024-11-05', - productAanwezig: true, - productValtOnder: null, - verantwoordelijkeOrganisatie: { - url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel#verantwoordelijkeOrganisatie', - owmsIdentifier: 'http://standaarden.overheid.nl/owms/terms/Utrecht_(gemeente)', - owmsPrefLabel: 'Gemeente Utrecht', - owmsEndDate: '2024-11-05T23:00:00.000Z', - }, - locaties: null, - doelgroep: 'eu-burger', - afdelingen: [ - { - afdelingId: '463de311-fbe3-48d8-bd87-722de5c80b04', - afdelingnaam: 'Demo Afdeling', - }, - ], - beschikbareTalen: ['nl'], - vertalingen: [ - { - datumWijziging: '2024-11-06T12:05:42.541Z', - taal: 'nl', - titel: 'Demo Product', - trefwoorden: [{ trefwoord: 'Demo' }, { trefwoord: 'Page' }], - vereisten: '

Voorwaarden - 1

Body text

', - bewijs: '

Bewijs - 1

Body text

', - bezwaarEnBeroep: '

Bezwaar - 1

Body text

', - deskMemo: '', - kostenEnBetaalmethoden: '

Kosten - 1

', - procedureBeschrijving: '

Aanvraag  - 1

Body text

', - tekst: '

Inleiding - 1

Body text

Inleiding - 2

Body text

', + record: { + endAt: null, + geometry: null, + index: 1, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 3, + data: { + url: 'http://localhost:3000/api/v2/objects/b77a89a0-3ec2-467d-84b2-b484d5726ceb', + uuid: 'b77a89a0-3ec2-467d-84b2-b484d5726ceb', + upnUri: 'http://standaarden.overheid.nl/owms/terms/UPL-naam_nog_niet_beschikbaar', + publicatieDatum: '2024-11-05', + productAanwezig: true, + productValtOnder: null, + verantwoordelijkeOrganisatie: { + url: 'http://localhost:3000/api/v2/objecttypes/kennisartikel#verantwoordelijkeOrganisatie', + owmsIdentifier: 'http://standaarden.overheid.nl/owms/terms/Utrecht_(gemeente)', + owmsPrefLabel: 'Gemeente Utrecht', + owmsEndDate: '2024-11-05T23:00:00.000Z', + }, + locaties: null, + doelgroep: 'eu-burger', + afdelingen: [ + { + afdelingId: '463de311-fbe3-48d8-bd87-722de5c80b04', + afdelingnaam: 'Demo Afdeling', + }, + ], + beschikbareTalen: ['nl'], + vertalingen: [ + { + datumWijziging: '2024-11-06T12:05:42.541Z', + taal: 'nl', + titel: 'Demo Product', + trefwoorden: [{ trefwoord: 'Demo' }, { trefwoord: 'Page' }], + vereisten: '

Voorwaarden - 1

Body text

', + bewijs: '

Bewijs - 1

Body text

', + bezwaarEnBeroep: '

Bezwaar - 1

Body text

', + deskMemo: '', + kostenEnBetaalmethoden: '

Kosten - 1

', + procedureBeschrijving: '

Aanvraag  - 1

Body text

', + tekst: '

Inleiding - 1

Body text

Inleiding - 2

Body text

', + }, + ], }, - ], + }, }, { + type: 'http://localhost:3000/api/v2/objecttypes/vac', uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', - vraag: 'Wat is het proces om een paspoort aan te vragen?', - status: 'actief', - antwoord: - 'U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren.', - doelgroep: 'eu_burger', - afdelingen: [ - { - afdelingId: '4DFE293E-FCDE-4913-81E5-E82F92CC8DB6', - afdelingnaam: 'Demo Afdeling', + url: 'http://localhost:3000/api/v2/objects/22D89EB2-2238-4885-A352-07C02CF8FCDF', + record: { + endAt: null, + geometry: null, + index: 1, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 1, + data: { + uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', + vraag: 'Wat is het proces om een paspoort aan te vragen?', + status: 'actief', + antwoord: + 'U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren.', + doelgroep: 'eu_burger', + afdelingen: [ + { + afdelingId: '4DFE293E-FCDE-4913-81E5-E82F92CC8DB6', + afdelingnaam: 'Demo Afdeling', + }, + ], + toelichting: null, + trefwoorden: [ + { + trefwoord: 'paspoort', + }, + { + trefwoord: 'aanvraag', + }, + ], + url: 'http://localhost:3000/api/v2/objects/22D89EB2-2238-4885-A352-07C02CF8FCDF', }, - ], - toelichting: null, - trefwoorden: [ - { - trefwoord: 'paspoort', - }, - { - trefwoord: 'aanvraag', - }, - ], - url: 'http://localhost:3000/api/v2/objecttypes/vac', + }, }, { + type: 'http://localhost:3000/api/v2/objecttypes/vac', uuid: 'b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7', - vraag: 'Hoe kan ik een rijbewijs aanvragen?', - status: 'actief', - antwoord: - 'Voor het aanvragen van een rijbewijs moet u een aanvraagformulier invullen en uw identiteitsbewijs meenemen naar het gemeentehuis.', - doelgroep: 'eu_burger', - afdelingen: [ - { - afdelingId: 'B97257C5-589E-4FC0-8C7E-F744649A13B7', - afdelingnaam: 'Demo Afdeling', + url: 'http://localhost:3000/api/v2/objects/b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7', + record: { + endAt: null, + geometry: null, + index: 2, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 1, + data: { + uuid: 'b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7', + vraag: 'Hoe kan ik een rijbewijs aanvragen?', + status: 'actief', + antwoord: + 'Voor het aanvragen van een rijbewijs moet u een aanvraagformulier invullen en uw identiteitsbewijs meenemen naar het gemeentehuis.', + doelgroep: 'eu_burger', + afdelingen: [ + { + afdelingId: 'B97257C5-589E-4FC0-8C7E-F744649A13B7', + afdelingnaam: 'Demo Afdeling', + }, + ], + toelichting: null, + trefwoorden: [ + { + trefwoord: 'rijbewijs', + }, + { + trefwoord: 'aanvraag', + }, + ], + url: 'http://localhost:3000/api/v2/objects/b2c3d4e5-f6g7-8h9i-0j1k-l2m3n4o5p6q7', }, - ], - toelichting: null, - trefwoorden: [ - { - trefwoord: 'rijbewijs', - }, - { - trefwoord: 'aanvraag', - }, - ], - url: 'http://localhost:3000/api/v2/objecttypes/vac', + }, }, { + type: 'http://localhost:3000/api/v2/objecttypes/vac', uuid: 'c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8', - vraag: 'Wat moet ik doen bij verhuizing?', - status: 'actief', - antwoord: 'Bij verhuizing moet u zich binnen 5 dagen inschrijven op uw nieuwe adres bij de gemeente.', - doelgroep: 'eu_burger', - afdelingen: [ - { - afdelingId: '8B2EC293-AB4D-46BA-A4FE-7B5E84772D93', - afdelingnaam: 'Demo Afdeling', + url: 'http://localhost:3000/api/v2/objects/c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8', + record: { + endAt: null, + geometry: null, + index: 3, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 1, + data: { + uuid: 'c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8', + vraag: 'Wat moet ik doen bij verhuizing?', + status: 'actief', + antwoord: 'Bij verhuizing moet u zich binnen 5 dagen inschrijven op uw nieuwe adres bij de gemeente.', + doelgroep: 'eu_burger', + afdelingen: [ + { + afdelingId: '8B2EC293-AB4D-46BA-A4FE-7B5E84772D93', + afdelingnaam: 'Demo Afdeling', + }, + ], + toelichting: null, + trefwoorden: [ + { + trefwoord: 'verhuizing', + }, + { + trefwoord: 'inschrijven', + }, + ], + url: 'http://localhost:3000/api/v2/objects/c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r8', }, - ], - toelichting: null, - trefwoorden: [ - { - trefwoord: 'verhuizing', - }, - { - trefwoord: 'inschrijven', - }, - ], - url: 'http://localhost:3000/api/v2/objecttypes/vac', + }, }, ], }; switch (type) { case 'kennisartikel': - return data.results.filter(({ url }) => url.endsWith('kennisartikel')); + return { results: data.results.filter(({ type }) => type.endsWith('kennisartikel')) }; case 'vac': - return data.results.filter(({ url }) => url.endsWith('vac')); + return { results: data.results.filter(({ type }) => type.endsWith('vac')) }; default: return data; } diff --git a/apps/overige-objecten-api/src/__mocks__/vacObject.ts b/apps/overige-objecten-api/src/__mocks__/vacObject.ts index 5896459a..76df0e30 100644 --- a/apps/overige-objecten-api/src/__mocks__/vacObject.ts +++ b/apps/overige-objecten-api/src/__mocks__/vacObject.ts @@ -1,26 +1,37 @@ -export const vacObject = () => [ - { - uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', - vraag: 'Wat is het proces om een paspoort aan te vragen?', - antwoord: - 'U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren.', - status: 'actief', - doelgroep: 'eu_burger', - afdelingen: [ - { - afdelingId: '4DFE293E-FCDE-4913-81E5-E82F92CC8DB6', - afdelingnaam: 'Demo Afdeling', - }, - ], - toelichting: null, - trefwoorden: [ - { - trefwoord: 'paspoort', - }, - { - trefwoord: 'aanvraag', - }, - ], - url: 'http://localhost:3000/api/v2/objecttypes/vac', +export const vacObject = () => ({ + type: 'http://localhost:3000/api/v2/objecttypes/vac', + uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', + url: 'http://localhost:3000/api/v2/objects/22D89EB2-2238-4885-A352-07C02CF8FCDF', + record: { + endAt: null, + geometry: null, + index: 1, + registrationAt: '2024-11-05T16:03:50.975Z', + startAt: '2024-11-05T16:03:50.975Z', + typeVersion: 1, + data: { + uuid: '22D89EB2-2238-4885-A352-07C02CF8FCDF', + vraag: 'Wat is het proces om een paspoort aan te vragen?', + antwoord: + 'U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren.', + status: 'actief', + doelgroep: 'eu_burger', + afdelingen: [ + { + afdelingId: '4DFE293E-FCDE-4913-81E5-E82F92CC8DB6', + afdelingnaam: 'Demo Afdeling', + }, + ], + toelichting: null, + trefwoorden: [ + { + trefwoord: 'paspoort', + }, + { + trefwoord: 'aanvraag', + }, + ], + url: 'http://localhost:3000/api/v2/objects/22D89EB2-2238-4885-A352-07C02CF8FCDF', + }, }, -]; +}); diff --git a/apps/overige-objecten-api/src/controllers/objects/index.test.ts b/apps/overige-objecten-api/src/controllers/objects/index.test.ts index 59e9ef39..8399b3f2 100644 --- a/apps/overige-objecten-api/src/controllers/objects/index.test.ts +++ b/apps/overige-objecten-api/src/controllers/objects/index.test.ts @@ -210,29 +210,25 @@ describe('Objects controller', () => { const vacResponse = { data: { vacs: { data: vacData } } }; fetchMock.mockResponseOnce(JSON.stringify({ data: { products: { data: kennisartikelData } } })); fetchMock.mockResponseOnce(JSON.stringify(vacResponse)); - await request(app).get('/api/v2/objects').set('Authorization', 'Token YOUR_API_TOKEN'); - const consoleSpyKennisartikelValue = consoleSpy.mock.calls[0][1].filter( - (item: any) => item.path === '/response/results/0/vertalingen/0/titel', - ); - const consoleSpayVacValue = consoleSpy.mock.calls[0][1].filter( - (item: any) => item.path === '/response/results/0/vraag', + const consoleSpyKennisartikelValue = consoleSpy.mock.calls[0][1].find( + (item: any) => item.path === '/response/results/0/record/data/vertalingen/0/titel', ); - expect(consoleSpyKennisartikelValue).toEqual([ - { - path: '/response/results/0/vertalingen/0/titel', - message: 'must be string', - errorCode: 'type.openapi.validation', - }, - ]); - expect(consoleSpayVacValue).toEqual([ - { - path: '/response/results/0/vraag', - message: "must have required property 'vraag'", - errorCode: 'required.openapi.validation', - }, - ]); + const consoleSpayVacValue = consoleSpy.mock.calls[0][1].find( + (item: any) => item.path === '/response/results/0/record/data/vraag', + ); + + expect(consoleSpyKennisartikelValue).toEqual({ + path: '/response/results/0/record/data/vertalingen/0/titel', + message: 'must be string', + errorCode: 'type.openapi.validation', + }); + expect(consoleSpayVacValue).toEqual({ + path: '/response/results/0/record/data/vraag', + message: "must have required property 'vraag'", + errorCode: 'required.openapi.validation', + }); consoleSpy.mockRestore(); }); }); diff --git a/apps/overige-objecten-api/src/controllers/objects/index.ts b/apps/overige-objecten-api/src/controllers/objects/index.ts index b5e7c73d..5aee36eb 100644 --- a/apps/overige-objecten-api/src/controllers/objects/index.ts +++ b/apps/overige-objecten-api/src/controllers/objects/index.ts @@ -2,7 +2,6 @@ import type { RequestHandler } from 'express'; import { GET_ALL_PRODUCTS, GET_ALL_VAC_ITEMS, GET_PRODUCT_BY_UUID, GET_VAC_ITEM_BY_UUID } from '../../queries'; import type { StrapiProductType, VACSData } from '../../strapi-product-type'; import { fetchData, generateKennisartikelObject, getPaginatedResponse, getTheServerURL } from '../../utils'; - export const getAllObjectsController: RequestHandler = async (req, res, next) => { try { const locale = req.query?.locale || 'nl'; @@ -10,7 +9,6 @@ export const getAllObjectsController: RequestHandler = async (req, res, next) => const isAuthHasToken = req.headers?.authorization?.startsWith('Token'); const tokenAuth = isAuthHasToken ? req.headers?.authorization?.split(' ')[1] : req.headers?.authorization; const serverURL = getTheServerURL(req); - const kennisartikelSchemaURL = new URL('api/v2/objecttypes/kennisartikel', serverURL).href; const vacSchemaURL = new URL('api/v2/objecttypes/vac', serverURL).href; const graphqlURL = new URL('/graphql', process.env.STRAPI_PRIVATE_URL); // default pagination prams @@ -45,7 +43,27 @@ export const getAllObjectsController: RequestHandler = async (req, res, next) => Authorization: `Bearer ${tokenAuth}`, }, }); - const vac = vacData?.vacs?.data?.map((item) => ({ ...item.attributes.vac, url: vacSchemaURL })); + + const vac = vacData?.vacs?.data?.map((item) => { + const vacUrl = new URL(`/api/v2/objects/${item.attributes.vac.uuid}`, serverURL).href; + return { + uuid: item.attributes.vac.uuid, + type: vacSchemaURL, + url: vacUrl, + record: { + index: parseInt(item.id, 10), + startAt: item.attributes.createdAt, + typeVersion: 1, + data: { + ...item.attributes.vac, + url: vacUrl, + }, + geometry: null, + endAt: null, + registrationAt: item.attributes.createdAt, + }, + }; + }); const pagination = await getPaginatedResponse(req, data?.products); @@ -53,17 +71,17 @@ export const getAllObjectsController: RequestHandler = async (req, res, next) => const products = data?.products?.data || []; if (products.length === 0) return res.status(200).json({ results: [] }); - const kennisartikel = products.map(({ attributes }) => - generateKennisartikelObject({ attributes, url: kennisartikelSchemaURL }), + const kennisartikel = products.map(({ attributes, id }) => + generateKennisartikelObject({ attributes, url: serverURL, id }), ); // Set response content type res.set('Content-Type', 'application/json'); // Send results based on the requested type - if (type.endsWith('kennisartikel')) return res.status(200).json(kennisartikel); + if (type.endsWith('kennisartikel')) return res.status(200).json({ ...pagination, results: kennisartikel }); - if (type.endsWith('vac')) return res.status(200).json(vac); + if (type.endsWith('vac')) return res.status(200).json({ results: vac }); // If no specific type, return both kennisartikel and vac objects if (vac.length > 0 && kennisartikel.length > 0) @@ -92,10 +110,9 @@ export const getObjectByUUIDController: RequestHandler = async (req, res, next) const serverURL = getTheServerURL(req); const isAuthHasToken = req.headers?.authorization?.startsWith('Token'); const tokenAuth = isAuthHasToken ? req.headers?.authorization?.split(' ')[1] : req.headers?.authorization; - const kennisartikelSchemaURL = new URL('api/v2/objecttypes/kennisartikel', serverURL).href; const vacSchemaURL = new URL('api/v2/objecttypes/vac', serverURL).href; // Fetch product data from GraphQL - const { data } = await fetchData({ + const { data } = await fetchData({ url: graphqlURL.href, query: GET_PRODUCT_BY_UUID, variables: { locale, uuid }, @@ -117,7 +134,7 @@ export const getObjectByUUIDController: RequestHandler = async (req, res, next) // Handle the case for a knowledge article (kennisartikel) const products = data?.products?.data || []; const kennisartikel = products - .map(({ attributes }) => generateKennisartikelObject({ attributes, url: kennisartikelSchemaURL })) + .map(({ attributes, id }: any) => generateKennisartikelObject({ attributes, url: serverURL, id })) .find((item: { uuid: string }) => item.uuid === uuid); if (kennisartikel) { @@ -126,9 +143,26 @@ export const getObjectByUUIDController: RequestHandler = async (req, res, next) // Handle the case for VAC data if (Array.isArray(vacData?.vacs?.data) && vacData.vacs.data.length > 0) { - const vac = vacData.vacs.data.map((item) => { - return { ...item.attributes.vac, url: vacSchemaURL }; - }); + const vac = vacData?.vacs?.data?.map((item) => { + const vacUrl = new URL(`/api/v2/objects/${item.attributes.vac.uuid}`, serverURL).href; + return { + uuid: item.attributes.vac.uuid, + type: vacSchemaURL, + url: vacUrl, + record: { + index: parseInt(item.id, 10), + startAt: item.attributes.createdAt, + typeVersion: 1, + data: { + ...item.attributes.vac, + url: vacUrl, + }, + geometry: null, + endAt: null, + registrationAt: item.attributes.createdAt, + }, + }; + })[0]; return res.status(200).json(vac); // Return to prevent further execution } diff --git a/apps/overige-objecten-api/src/docs/openapi.yaml b/apps/overige-objecten-api/src/docs/openapi.yaml index 9284a2d9..61027866 100644 --- a/apps/overige-objecten-api/src/docs/openapi.yaml +++ b/apps/overige-objecten-api/src/docs/openapi.yaml @@ -17,7 +17,7 @@ paths: parameters: - in: query name: type - required: false # Make 'type' optional + required: false schema: type: string format: uri @@ -46,117 +46,77 @@ paths: content: application/json: schema: - oneOf: # Use oneOf to allow either kennisartikel or vac - - type: array - items: - $ref: "#/components/schemas/kennisartikel" - - type: array - items: - $ref: "#/components/schemas/vac" - - type: array + type: object + properties: + count: + type: integer + example: 127 + next: + type: string + format: uri + nullable: true + example: "http://localhost:4001/api/v2/objects?page=2&pageSize=10" + previous: + type: string + format: uri + nullable: true + example: null + results: + type: array items: - type: object - additionalProperties: false - - type: object - properties: - page: - type: integer - example: 1 - pageSize: - type: integer - example: 1 - count: - type: integer - example: 284 - total: - type: integer - example: 284 - next: - type: string - format: uri - nullable: true - example: "http://localhost:4001/api/v2/objects?type=http%3A%2F%2Flocalhost%3A4001%2Fapi%2Fv2%2Fobjecttypes%2Fkennisartikel&page=2&pageSize=1" - previous: - type: string - format: uri - nullable: true - example: null - results: - type: array - items: - oneOf: - - $ref: "#/components/schemas/kennisartikel" - - $ref: "#/components/schemas/vac" + $ref: "#/components/schemas/ObjectData" example: - page: 1 - pageSize: 10 - count: 29 - total: 284 + count: 127 next: "http://localhost:4001/api/v2/objects?page=2&pageSize=10" previous: null results: - url: "http://localhost:4001/api/v2/objecttypes/kennisartikel" uuid: "123e4567-e89b-12d3-a456-426614174000" - upnUri: "http://example.com/upn/1" - publicatieDatum: "2023-01-01" - productAanwezig: true - verantwoordelijkeOrganisatie: - url: "http://example.com/organisatie/1" - owmsIdentifier: "http://example.com/owms/1" - owmsEndDate: "2024-01-01T00:00:00Z" - locaties: ["Locatie 1", "Locatie 2"] - doelgroep: "eu-burger" - afdelingen: - - afdelingId: "1" - afdelingNaam: "Burgerzaken" - vertalingen: - - taal: "nl" - titel: "Kennisartikel Titel" - tekst: "Dit is de inleiding van het kennisartikel." - datumWijziging: "2023-02-01T00:00:00Z" - - vraag: "Wat is het proces om een paspoort aan te vragen?" - status: "actief" - antwoord: "U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren." + type: "http://localhost:4001/api/v2/objecttypes/kennisartikel" + record: + index: 1 + typeVersion: 3 + data: + url: "http://example.com" + uuid: "123e4567-e89b-12d3-a456-426614174000" + upnUri: "http://example.com/upn/1" + locaties: null doelgroep: "eu-burger" afdelingen: - - afdelingId: "1" - afdelingNaam: "Burgerzaken" - toelichting: "Deze VAC biedt informatie over het aanvragen van een paspoort in Nederland." - trefwoorden: - - trefwoord: "paspoort" - - trefwoord: "aanvragen" - gerelateerdeVACs: [] - gerelateerdeProducten: [] - "401": - description: Unauthorized - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: "Unauthorized" - "403": - description: Forbidden - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: "Forbidden" - "500": - description: Internal Server Error - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: "Internal Server Error" + - afdelingNaam: "Burgerzaken" + vertalingen: + - taal: "nl" + tekst: "Sample text" + titel: "Sample title" + notice: "Sample notice" + contact: "Contact details" + deskMemo: "Internal notes" + vereisten: "Requirements" + trefwoorden: + - trefwoord: "paspoort" + datumWijziging: "2024-08-05" + bezwaarEnBeroep: "Procedure description" + uitersteTermijn: "2024-12-31" + wtdBijGeenReactie: "Action if no response" + procedureBeschrijving: "Description of procedure" + kostenEnBetaalmethoden: "Payment methods and costs" + productAanwezig: true + publicatieDatum: "2023-01-01" + beschikbareTalen: + - "nl" + productValtOnder: null + verantwoordelijkeOrganisatie: + url: "http://example.com/organisatie/1" + owmsEndDate: "2024-01-01T00:00:00Z" + owmsPrefLabel: "Organization Label" + owmsIdentifier: "http://example.com/owms/1" + geometry: null + startAt: "2024-08-05" + endAt: null + registrationAt: "2024-08-05" + correctionFor: null + correctedBy: null + /objects/{uuid}: get: security: @@ -181,19 +141,20 @@ paths: - $ref: "#/components/schemas/vac" example: url: "http://localhost:4001/api/v2/objecttypes/vac" - vraag: "Wat is het proces om een paspoort aan te vragen?" - status: "actief" - antwoord: "U moet een afspraak maken bij de gemeente, uw identiteitsbewijs meenemen en een recente pasfoto aanleveren." - doelgroep: "eu-burger" - afdelingen: - - afdelingId: "1" - afdelingNaam: "Burgerzaken" - toelichting: "Deze VAC biedt informatie over het aanvragen van een paspoort in Nederland." - trefwoorden: - - trefwoord: "paspoort" - - trefwoord: "aanvragen" - gerelateerdeVACs: [] - gerelateerdeProducten: [] + uuid: "3fa85f64-5717-4562-b3fc-2c963f66afa6" + type: "http://localhost:4001/api/v2/objecttypes/vac" + record: + index: 0 + typeVersion: 32767 + data: "string" + geometry: + type: "Point" + coordinates: [0, 0] + startAt: "2024-11-08" + endAt: "2024-11-08" + registrationAt: "2024-11-08" + correctionFor: 2147483647 + correctedBy: 2147483647 "404": description: Object not found content: @@ -224,6 +185,7 @@ paths: error: type: string example: "Internal Server Error" + components: securitySchemes: TokenAuth: @@ -231,6 +193,75 @@ components: in: header name: Authorization schemas: + ObjectData: + type: object + properties: + url: + type: string + format: uri + uuid: + type: string + format: uuid + type: + type: string + format: uri + record: + type: object + properties: + index: + type: integer + readOnly: true + description: Incremental index number of the object record. + typeVersion: + type: integer + maximum: 32767 + minimum: 0 + description: Version of the OBJECTTYPE for data in the object record + data: + description: Object data, based on OBJECTTYPE + oneOf: + - $ref: "#/components/schemas/kennisartikel" + - $ref: "#/components/schemas/vac" + geometry: + allOf: + - $ref: "#/components/schemas/GeoJSONGeometry" + nullable: true + type: object + description: + Point, linestring or polygon object which represents the coordinates + of the object. Geometry can be added only if the related OBJECTTYPE allows + this (`OBJECTTYPE.allowGeometry = true` or `OBJECTTYPE.allowGeometry` + doesn't exist) + startAt: + type: string + format: date + description: Legal start date of the object record + endAt: + type: string + format: date + readOnly: true + nullable: true + description: Legal end date of the object record + registrationAt: + type: string + format: date + readOnly: true + description: The date when the record was registered in the system + correctionFor: + type: integer + maximum: 2147483647 + minimum: 0 + description: Index of the record corrected by the current record + readOnly: true + correctedBy: + type: integer + maximum: 2147483647 + minimum: 0 + description: Index of the record, which corrects the current record + readOnly: true + required: + - startAt + - typeVersion kennisartikel: type: object title: SDG Kennisartikel @@ -446,7 +477,6 @@ components: description: Alle beschikbare talen. items: type: string - vac: type: object title: VAC @@ -548,3 +578,154 @@ components: description: De naam van het gerelateerde product. title: Gerelateerde Producten description: Producten die gerelateerd zijn aan de VAC. + GeoJSONGeometry: + oneOf: + - $ref: "#/components/schemas/Point" + - $ref: "#/components/schemas/MultiPoint" + - $ref: "#/components/schemas/LineString" + - $ref: "#/components/schemas/MultiLineString" + - $ref: "#/components/schemas/Polygon" + - $ref: "#/components/schemas/MultiPolygon" + - $ref: "#/components/schemas/GeometryCollection" + discriminator: + propertyName: type + mapping: + Point: "#/components/schemas/Point" + MultiPoint: "#/components/schemas/MultiPoint" + LineString: "#/components/schemas/LineString" + MultiLineString: "#/components/schemas/MultiLineString" + Polygon: "#/components/schemas/Polygon" + MultiPolygon: "#/components/schemas/MultiPolygon" + GeometryCollection: "#/components/schemas/GeometryCollection" + Point: + type: object + description: GeoJSON point geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.2 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + $ref: "#/components/schemas/Point2D" + Geometry: + type: object + title: Geometry + description: GeoJSON geometry + required: + - type + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1 + properties: + type: + type: string + description: The geometry type + Point2D: + type: array + title: Point2D + description: A 2D point + items: + type: number + maxItems: 2 + minItems: 2 + MultiPoint: + type: object + description: GeoJSON multi-point geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.3 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + type: array + items: + $ref: "#/components/schemas/Point2D" + LineString: + type: object + description: GeoJSON line-string geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.4 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + type: array + items: + $ref: "#/components/schemas/Point2D" + minItems: 2 + MultiLineString: + type: object + description: GeoJSON multi-line-string geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.5 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + type: array + items: + type: array + items: + $ref: "#/components/schemas/Point2D" + Polygon: + type: object + description: GeoJSON polygon geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.6 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + type: array + items: + type: array + items: + $ref: "#/components/schemas/Point2D" + MultiPolygon: + type: object + description: GeoJSON multi-polygon geometry + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.7 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - coordinates + properties: + coordinates: + type: array + items: + type: array + items: + type: array + items: + $ref: "#/components/schemas/Point2D" + GeometryCollection: + type: object + description: GeoJSON geometry collection + externalDocs: + url: https://tools.ietf.org/html/rfc7946#section-3.1.8 + allOf: + - $ref: "#/components/schemas/Geometry" + - type: object + required: + - geometries + properties: + geometries: + type: array + items: + $ref: "#/components/schemas/Geometry" diff --git a/apps/overige-objecten-api/src/queries/index.ts b/apps/overige-objecten-api/src/queries/index.ts index 37461a0e..6851e587 100644 --- a/apps/overige-objecten-api/src/queries/index.ts +++ b/apps/overige-objecten-api/src/queries/index.ts @@ -140,6 +140,8 @@ query getAllVacItems($page: Int, $pageSize: Int, $start: Int, $limit: Int) { data { id attributes { + createdAt + updatedAt vac { uuid vraag: label @@ -168,6 +170,8 @@ query getVacItemByUUID($uuid: String) { data { id attributes { + createdAt + updatedAt vac { uuid vraag: label diff --git a/apps/overige-objecten-api/src/strapi-product-type.ts b/apps/overige-objecten-api/src/strapi-product-type.ts index 3969a7b7..497f2761 100644 --- a/apps/overige-objecten-api/src/strapi-product-type.ts +++ b/apps/overige-objecten-api/src/strapi-product-type.ts @@ -10,11 +10,14 @@ export interface VacItem { } export interface AttributesVacItem { + createdAt: string; + updatedAt: string; vac: VacItem; } export interface DataVacItem { attributes: AttributesVacItem; + id: string; } export interface RootObjectVacItem { diff --git a/apps/overige-objecten-api/src/utils/generateKennisartikelObject.ts b/apps/overige-objecten-api/src/utils/generateKennisartikelObject.ts index dfa8ee32..1f3636a4 100644 --- a/apps/overige-objecten-api/src/utils/generateKennisartikelObject.ts +++ b/apps/overige-objecten-api/src/utils/generateKennisartikelObject.ts @@ -7,9 +7,10 @@ import { components } from '../types/openapi'; interface GenerateKennisartikelObjectTypes { attributes: Attributes; url: string; + id: string; } -export const generateKennisartikelObject = ({ attributes, url }: GenerateKennisartikelObjectTypes) => { +export const generateKennisartikelObject = ({ attributes, url, id }: GenerateKennisartikelObjectTypes) => { const metaTags = attributes?.metaTags; const trefwoorden = metaTags?.keymatch?.split(', ').map((trefwoord: string) => ({ trefwoord })) || []; const kennisartikelMetadata = attributes.kennisartikelMetadata; @@ -36,24 +37,37 @@ export const generateKennisartikelObject = ({ attributes, url }: GenerateKennisa }, ]; - const data: components['schemas']['kennisartikel'] = { - url, + const data: components['schemas']['ObjectData'] = { + url: `${url}/api/v2/objects/${attributes.uuid}`, uuid: attributes.uuid, - upnUri: kennisartikelMetadata?.upnUri, - publicatieDatum, - productAanwezig: kennisartikelMetadata?.productAanwezig, - productValtOnder: kennisartikelMetadata?.productValtOnder, // we need an extra field for this - verantwoordelijkeOrganisatie: { - url: `${url}#verantwoordelijkeOrganisatie`, - owmsIdentifier: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsIdentifier, - owmsPrefLabel: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsPrefLabel, - owmsEndDate: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsEndDate, + type: new URL('api/v2/objecttypes/kennisartikel', url).href, + record: { + index: parseInt(id, 10), + startAt: attributes.createdAt, + typeVersion: 3, + data: { + url: `${url}/api/v2/objects/${attributes.uuid}`, + uuid: attributes.uuid, + upnUri: kennisartikelMetadata?.upnUri, + publicatieDatum, + productAanwezig: kennisartikelMetadata?.productAanwezig, + productValtOnder: kennisartikelMetadata?.productValtOnder, // we need an extra field for this + verantwoordelijkeOrganisatie: { + url: `${new URL('api/v2/objecttypes/kennisartikel', url).href}#verantwoordelijkeOrganisatie`, + owmsIdentifier: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsIdentifier, + owmsPrefLabel: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsPrefLabel, + owmsEndDate: kennisartikelMetadata?.verantwoordelijkeOrganisatie?.owmsEndDate, + }, + locaties: null, //Een lijst met locaties waarop dit product beschikbaar is. Deze is nog niet nodig voor KISS en mag null zijn. Dit obecjt is dus nog niet opgenomen in dit schema + doelgroep: kennisartikelMetadata?.doelgroep?.replace('_', '-') as 'eu-burger' | 'eu-bedrijf', + afdelingen: kennisartikelMetadata?.afdelingen, + beschikbareTalen: [attributes?.locale], + vertalingen, + }, + geometry: null, + endAt: null, + registrationAt: attributes.createdAt, }, - locaties: null, //Een lijst met locaties waarop dit product beschikbaar is. Deze is nog niet nodig voor KISS en mag null zijn. Dit obecjt is dus nog niet opgenomen in dit schema - doelgroep: kennisartikelMetadata?.doelgroep?.replace('_', '-') as 'eu-burger' | 'eu-bedrijf', - afdelingen: kennisartikelMetadata?.afdelingen, - beschikbareTalen: [attributes?.locale], - vertalingen, }; return data;