diff --git a/apps/omsorgspengerutbetaling-soknad/vitest.config.ts b/apps/omsorgspengerutbetaling-soknad/vitest.config.ts index a48a8ae26..e1dfa3545 100644 --- a/apps/omsorgspengerutbetaling-soknad/vitest.config.ts +++ b/apps/omsorgspengerutbetaling-soknad/vitest.config.ts @@ -5,7 +5,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { - exclude: ['./e2e/**/*', './build/**/*', './dist/**/*', '**/*.spec.tsx', '**/*.spec.ts'], + exclude: ['./e2e/**/*', './build/**/*', './dist/**/*', '**/*.spec.tsx', '**/*.spec.ts', 'node_modules'], globals: true, environment: 'jsdom', css: false, diff --git a/apps/omsorgspengesoknad/package.json b/apps/omsorgspengesoknad/package.json index 8148fe261..8782f324e 100644 --- a/apps/omsorgspengesoknad/package.json +++ b/apps/omsorgspengesoknad/package.json @@ -13,7 +13,7 @@ "@navikt/ds-react": "7.0.1", "@navikt/ds-tailwind": "7.0.1", "@navikt/sif-app-register": "*", - "@navikt/sif-common": "workspace:*", + "@navikt/sif-common": "*", "@navikt/sif-common-amplitude": "*", "@navikt/sif-common-core-ds": "*", "@navikt/sif-common-formik-ds": "*", diff --git "a/apps/sif-demo-app/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" new file mode 100644 index 000000000..dc67d6c18 --- /dev/null +++ "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" @@ -0,0 +1,29 @@ +{ + "organisasjoner": [ + { "navn": "SJOKKERENDE ELEKTRIKER", "organisasjonsnummer": "947064649", "ansattFom": "2002-04-20" } + ], + "frilansoppdrag": [ + { + "type": "type oppdrag", + "organisasjonsnummer": "991012133", + "navn": "Hurdal frilanssenter", + "ansattFom": "2022-01-01", + "ansattTom": "2022-01-15" + }, + { + "type": "type oppdrag", + "organisasjonsnummer": "991012134", + "navn": "Svandalen frilanssenter", + "ansattFom": "2022-01-01", + "ansattTom": "2022-01-15" + } + ], + "privatarbeidsgiver": [ + { + "navn": "Jon Jonsen", + "ansattFom": "2021-01-01", + "ansattTom": "2021-12-31", + "offentligIdent": "12345678910" + } + ] +} diff --git "a/apps/sif-demo-app/api-mock/data/s\303\270ker1/barn-mock.json" "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/barn-mock.json" new file mode 100644 index 000000000..f2f0f8d84 --- /dev/null +++ "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/barn-mock.json" @@ -0,0 +1,19 @@ +{ + "barn": [ + { + "fornavn": "ALFABETISK", + "etternavn": "FAGGOTT", + "aktørId": "2811762539343", + "fødselsdato": "2019-06-08", + "fødselsnummer": "08861999573" + }, + { + "fornavn": "Barn", + "mellomnavn": "Barne", + "etternavn": "Barnesen", + "fødselsdato": "2020-04-20", + "aktørId": "123" + }, + { "fødselsdato": "2015-01-02", "fornavn": "Mock", "etternavn": "Mocknes", "aktørId": "2", "mellomnavn": "" } + ] +} diff --git "a/apps/sif-demo-app/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" new file mode 100644 index 000000000..70f748b17 --- /dev/null +++ "b/apps/sif-demo-app/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" @@ -0,0 +1,8 @@ +{ + "aktørId": "2320509955297", + "fødselsdato": "1995-06-02", + "fødselsnummer": "02869599259", + "fornavn": "PRESENTABEL", + "mellomnavn": null, + "etternavn": "HOFTE" +} diff --git a/apps/sif-demo-app/api-mock/mock-server.cjs b/apps/sif-demo-app/api-mock/mock-server.cjs new file mode 100644 index 000000000..b7316b05f --- /dev/null +++ b/apps/sif-demo-app/api-mock/mock-server.cjs @@ -0,0 +1,188 @@ +/* eslint-disable no-console */ +const express = require('express'); +const helmet = require('helmet'); +const busboyCons = require('busboy'); +const os = require('os'); +const fs = require('fs'); +const cors = require('cors'); + +const server = express(); + +server.use(express.json()); +server.use( + helmet({ + contentSecurityPolicy: true, + crossOriginEmbedderPolicy: false, + crossOriginResourcePolicy: false, + }), +); + +server.use( + cors({ + origin: 'http://localhost:8080', + methods: ['GET', 'POST', 'DELETE', 'PUT', 'OPTIONS'], + allowedHeaders: ['content-type', 'X-Brukerdialog-Git-Sha', 'x_correlation_id'], + credentials: true, + }), +); +server.options('*', cors()); + +const MELLOMLAGRING_JSON = `${os.tmpdir()}/omsorgspengesoknad-mellomlagring.json`; + +const isJSON = (str) => { + try { + return JSON.parse(str) && !!str; + } catch (e) { + return false; + } +}; + +const writeFileAsync = async (path, text) => { + return new Promise((resolve, reject) => { + fs.writeFile(path, text, 'utf8', (err) => { + if (err) reject(err); + else resolve(); + }); + }); +}; + +const readFileSync = (path) => { + return fs.readFileSync(path, 'utf8'); +}; + +const existsSync = (path) => fs.existsSync(path); + +const mockPath = `${__dirname}/data`; +const soker = 'søker1'; + +const søkerFileName = `søker-mock.json`; +const barnFileName = `barn-mock.json`; +const arbeidsgivereFileName = `arbeidsgivere-mock.json`; +const innvilgetVedtakFileName = `innvilget-vedtak-mock.json`; +const ikkeInnvilgetVedtakFileName = `ikke-innvilget-vedtak-mock.json`; + +const readMockFile = (file, responseObject) => { + const filePath = `${mockPath}/${soker}/${file}`; + if (existsSync(filePath)) { + const body = readFileSync(filePath); + responseObject.send(JSON.parse(body)); + } else { + responseObject.send({}); + } +}; + +const startExpressServer = () => { + const port = process.env.PORT || 8099; + + server.get('/oppslag/soker', (req, res) => { + setTimeout(() => { + readMockFile(søkerFileName, res); + }, 250); + }); + + server.get('/oppslag/barn', (req, res) => { + setTimeout(() => { + readMockFile(barnFileName, res); + }, 250); + }); + + server.get('/oppslag/arbeidsgiver', (req, res) => { + setTimeout(() => { + readMockFile(arbeidsgivereFileName, res); + }, 250); + }); + + /** --- Send søknad ---------- */ + + server.post('/omsorgspenger-utvidet-rett/innsending', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + res.sendStatus(200); + }, 2500); + }); + + const errorResponse = { + type: '/problem-details/invalid-request-parameters', + title: 'invalid-request-parameters', + status: 400, + detail: 'Requesten inneholder ugyldige paramtere.', + instance: 'about:blank', + invalid_parameters: [ + 'høyereRisikoForFraværBeskrivelse matcher ikke tilatt møønster: ^[\\p{Punct}\\p{L}\\p{M}\\p{N}\\p{Sc}\\p{Space}«»–§�\\u2018\\u2019\\u201a\\u201b\\u201c\\u201d\\u201e\\u201f\\u00b4\\u2026]*$', + ], + }; + server.post('/omsorgspenger-utvidet-rett/innsending-error', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + res.status(400).send(errorResponse); + }, 100); + }); + + /** --- Vedlegg ---------- */ + + server.post('/vedlegg', (req, res) => { + res.set('Access-Control-Expose-Headers', 'Location'); + res.set('Location', 'nav.no'); + const busboy = busboyCons({ headers: req.headers }); + busboy.on('finish', () => { + res.writeHead(200, { + Location: 'http://localhost:8089/vedlegg/eyJraWQiOiIxIiwidHlwIjoiSldUIiwiYWxnIjoibm9uZSJ9.eyJqdG', + }); + res.end(); + }); + req.pipe(busboy); + }); + + server.delete('/vedlegg', (req, res) => { + res.sendStatus(200); + }); + + /** --- Mellomlagring ---------- */ + + server.get('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + if (existsSync(MELLOMLAGRING_JSON)) { + const body = readFileSync(MELLOMLAGRING_JSON); + res.send(JSON.parse(body)); + } else { + res.send({}); + } + }); + server.post('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + const body = req.body; + const jsBody = isJSON(body) ? JSON.parse(body) : body; + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify(jsBody, null, 2)); + res.sendStatus(200); + }); + server.put('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + const body = req.body; + const jsBody = isJSON(body) ? JSON.parse(body) : body; + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify(jsBody, null, 2)); + res.sendStatus(200); + }); + server.delete('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify({}, null, 2)); + res.sendStatus(200); + }); + + server.listen(port, () => { + console.log(`Express mock-api server listening on port: ${port}`); + }); + + /** --- Sjekk tidligere innvilget vedtak ---------- */ + + server.post('/k9-sak-innsyn-api/k9sak/omsorgsdager-kronisk-sykt-barn/har-gyldig-vedtak', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + if (body.pleietrengendeAktørId === '2') { + readMockFile(innvilgetVedtakFileName, res); + } else { + readMockFile(ikkeInnvilgetVedtakFileName, res); + } + }, 2500); + }); +}; + +startExpressServer(); diff --git a/apps/sif-demo-app/package.json b/apps/sif-demo-app/package.json index 07fe2f0a7..7edab7ae1 100644 --- a/apps/sif-demo-app/package.json +++ b/apps/sif-demo-app/package.json @@ -5,6 +5,7 @@ "version": "0.1.1", "scripts": { "dev": "node ./dev-server.cjs", + "dev-api": "PORT=8089 node ./api-mock/mock-server.cjs", "dev:vite": "vite", "dev:debug": "vite --debug", "build": "vite build --base=/familie/sykdom-i-familien/soknad/sif-demo-app", @@ -18,6 +19,10 @@ "@navikt/ds-react": "7.0.1", "@navikt/ds-tailwind": "7.0.1", "@navikt/nav-dekoratoren-moduler": "3.1.0", + "@navikt/sif-common": "*", + "@navikt/sif-common-core-ds": "*", + "@navikt/sif-common-soknad-ds": "*", + "@navikt/sif-common-ui": "*", "clsx": "2.1.1", "date-fns": "4.1.0", "react": "18.3.1", diff --git a/apps/sif-demo-app/src/App.tsx b/apps/sif-demo-app/src/App.tsx index 30a1f67c9..7e1bf8154 100644 --- a/apps/sif-demo-app/src/App.tsx +++ b/apps/sif-demo-app/src/App.tsx @@ -1,7 +1,52 @@ +import { Box, Tabs } from '@navikt/ds-react'; +import LoadingSpinner from '@navikt/sif-common-core-ds/src/atoms/loading-spinner/LoadingSpinner'; +import Page from '@navikt/sif-common-core-ds/src/components/page/Page'; +import SøkerInfo from './components/SøkerInfo'; +import { useInitialData } from './hooks/useInitialData'; import '@navikt/ds-css'; +import BarnInfo from './components/BarnInfo'; +import ArbeidsgiverInfo from './components/ArbeidsgiverInfo'; const App = () => { - return

Demo app

; + const { initialData, isLoading } = useInitialData(); + + if (isLoading || !initialData) { + return ( + +
+ +
+
+ ); + } + + const { søker, barn, arbeidsgivere } = initialData; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + ); }; export default App; diff --git a/apps/sif-demo-app/src/components/ArbeidsgiverInfo.tsx b/apps/sif-demo-app/src/components/ArbeidsgiverInfo.tsx new file mode 100644 index 000000000..d29100ecf --- /dev/null +++ b/apps/sif-demo-app/src/components/ArbeidsgiverInfo.tsx @@ -0,0 +1,33 @@ +import { Heading, VStack } from '@navikt/ds-react'; +import { Arbeidsgivere } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; + +interface Props { + arbeidsgivere: Arbeidsgivere; +} + +const Organisasjon = ({ organisasjon }: { organisasjon: Arbeidsgivere['organisasjoner'][0] }) => { + return ( + + + + {organisasjon.navn} + + + + ); +}; + +const ArbeidsgiverInfo = ({ arbeidsgivere: { organisasjoner } }: Props) => { + return ( + + {organisasjoner.length > 0 ? ( + organisasjoner.map((o) => ) + ) : ( + Ingen arbeidsgiver registrert + )} + + ); +}; + +export default ArbeidsgiverInfo; diff --git a/apps/sif-demo-app/src/components/BarnInfo.tsx b/apps/sif-demo-app/src/components/BarnInfo.tsx new file mode 100644 index 000000000..10ea48ea0 --- /dev/null +++ b/apps/sif-demo-app/src/components/BarnInfo.tsx @@ -0,0 +1,54 @@ +import { Heading, Table, VStack } from '@navikt/ds-react'; +import { RegistrertBarn } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; +import { dateFormatter } from '@navikt/sif-common-utils'; + +interface Props { + barn: RegistrertBarn[]; +} + +const BarnInfo = ({ barn: registrerteBarn }: Props) => { + return ( + + {registrerteBarn.map((barn, index) => ( + + + + Barn {index + 1} + + + + Felt + Verdi + + + + AktørID + {barn.aktørId} + + + Fødselsdato + {dateFormatter.compact(barn.fødselsdato)} + + + Fornavn + {barn.fornavn} + + + Mellomnavn + {barn.mellomnavn} + + + Etternavn + {barn.etternavn} + + +
+
+
+ ))} +
+ ); +}; + +export default BarnInfo; diff --git a/apps/sif-demo-app/src/components/ShadowBox.tsx b/apps/sif-demo-app/src/components/ShadowBox.tsx new file mode 100644 index 000000000..7793807f3 --- /dev/null +++ b/apps/sif-demo-app/src/components/ShadowBox.tsx @@ -0,0 +1,11 @@ +import { Box } from '@navikt/ds-react'; + +const ShadowBox = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +export default ShadowBox; diff --git "a/apps/sif-demo-app/src/components/S\303\270kerInfo.tsx" "b/apps/sif-demo-app/src/components/S\303\270kerInfo.tsx" new file mode 100644 index 000000000..fcf028b8d --- /dev/null +++ "b/apps/sif-demo-app/src/components/S\303\270kerInfo.tsx" @@ -0,0 +1,56 @@ +import { Heading, Table, VStack } from '@navikt/ds-react'; +import { Søker } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; +import { dateFormatter } from '@navikt/sif-common-utils'; + +interface Props { + søker: Søker; +} + +const SøkerInfo = ({ søker }: Props) => { + return ( + + + + Søker + + + + + Felt + Verdi + + + + + AktørID + {søker.aktørId} + + + Fødselsnummer + {søker.fødselsnummer} + + + Fødselsdato + {dateFormatter.compact(søker.fødselsdato)} + + + Fornavn + {søker.fornavn} + + + Mellomnavn + {søker.mellomnavn} + + + Etternavn + {søker.etternavn} + + +
+
+
+ ); +}; + +export default SøkerInfo; diff --git a/apps/sif-demo-app/src/hooks/useInitialData.ts b/apps/sif-demo-app/src/hooks/useInitialData.ts new file mode 100644 index 000000000..0cd335f69 --- /dev/null +++ b/apps/sif-demo-app/src/hooks/useInitialData.ts @@ -0,0 +1,29 @@ +import { useState } from 'react'; +import { Arbeidsgivere, fetchArbeidsgivere, fetchBarn, fetchSøker, RegistrertBarn, Søker } from '@navikt/sif-common'; +import { useEffectOnce } from '@navikt/sif-common-hooks'; +import { ISODateRangeToDateRange } from '@navikt/sif-common-utils'; + +type InitialData = { + barn: RegistrertBarn[]; + søker: Søker; + arbeidsgivere: Arbeidsgivere; +}; + +export const useInitialData = () => { + const [initialData, setInitialData] = useState(); + const [isLoading, setIsLoading] = useState(true); + + const fetchInitialData = async () => { + const søker = await fetchSøker(); + const barn = await fetchBarn(); + const arbeidsgivere = await fetchArbeidsgivere(ISODateRangeToDateRange('2020-01-01/2020-01-31')); + setInitialData({ søker, barn, arbeidsgivere }); + setIsLoading(false); + }; + + useEffectOnce(() => { + fetchInitialData(); + }); + + return { initialData, isLoading }; +}; diff --git a/packages/sif-common/README.md b/packages/sif-common/README.md new file mode 100644 index 000000000..99b268506 --- /dev/null +++ b/packages/sif-common/README.md @@ -0,0 +1,3 @@ +# sif-common + +Pakke for samling av komponenter som i dag ligger spredd i flere common pakker. Formål er å forenkle og forbedre struktur og kode. diff --git a/packages/sif-common/src/api/schemas/arbeidsgivereSchema.ts b/packages/sif-common/src/api/schemas/arbeidsgivereSchema.ts index 787d99163..6b24eb185 100644 --- a/packages/sif-common/src/api/schemas/arbeidsgivereSchema.ts +++ b/packages/sif-common/src/api/schemas/arbeidsgivereSchema.ts @@ -18,7 +18,7 @@ export const arbeidsgiverPrivatSchema = z.object({ export const arbeidsgiverFrilansoppdragSchema = z.object({ type: z.string(), organisasjonsnummer: z.string().nullable(), - offentligIdent: z.string().nullable(), + offentligIdent: z.string().optional().nullable(), navn: z.string(), ansattFom: z.preprocess(parseMaybeDateStringToDate, z.date()).or(z.undefined()).or(z.null()), ansattTom: z.preprocess(parseMaybeDateStringToDate, z.date()).or(z.undefined()).or(z.null()), diff --git a/packages/sif-common/src/api/schemas/barnSchema.ts b/packages/sif-common/src/api/schemas/barnSchema.ts index 404331670..e33d9c482 100644 --- a/packages/sif-common/src/api/schemas/barnSchema.ts +++ b/packages/sif-common/src/api/schemas/barnSchema.ts @@ -7,7 +7,7 @@ export const barnSchema = z.object({ etternavn: z.string(), mellomnavn: z .string() - // .optional() + .optional() .nullable() .transform((v) => (v === null ? undefined : v)), fødselsdato: z.preprocess(parseMaybeDateStringToDate, z.date()), diff --git a/packages/sif-common/src/api/services/arbeidsgivereService.ts b/packages/sif-common/src/api/services/arbeidsgivereService.ts index 999c63afd..cdc0ecc4f 100644 --- a/packages/sif-common/src/api/services/arbeidsgivereService.ts +++ b/packages/sif-common/src/api/services/arbeidsgivereService.ts @@ -1,11 +1,21 @@ +import getSentryLoggerForApp from '@navikt/sif-common-sentry'; import { dateToISODate } from '@navikt/sif-common-utils'; import { k9BrukerdialogApiClient } from '../apiClient'; -import { Arbeidsgivere } from '../types'; import { arbeidsgivereResponseSchema } from '../schemas/arbeidsgivereSchema'; +import { Arbeidsgivere } from '../types'; export const fetchArbeidsgivere = async ({ from, to }: { from: Date; to: Date }): Promise => { - const response = await k9BrukerdialogApiClient.get(`/oppslag/arbeidsgivere`, { + const response = await k9BrukerdialogApiClient.get(`/oppslag/arbeidsgiver`, { params: { fra_og_med: dateToISODate(from), til_og_med: dateToISODate(to) }, }); - return arbeidsgivereResponseSchema.parse(response.data); + try { + return arbeidsgivereResponseSchema.parse(response.data); + } catch (e) { + getSentryLoggerForApp('sif-common', []).logError('ZOD parse error', e); + return { + organisasjoner: [], + privatarbeidsgiver: [], + frilansoppdrag: [], + }; + } }; diff --git a/packages/sif-common/src/api/services/barnService.ts b/packages/sif-common/src/api/services/barnService.ts index 9cd02390e..b20e31738 100644 --- a/packages/sif-common/src/api/services/barnService.ts +++ b/packages/sif-common/src/api/services/barnService.ts @@ -1,7 +1,7 @@ +import getSentryLoggerForApp from '@navikt/sif-common-sentry'; import { k9BrukerdialogApiClient } from '../apiClient'; import { barnResponseSchema } from '../schemas/barnSchema'; import { RegistrertBarn } from '../types'; -import getSentryLoggerForApp from '@navikt/sif-common-sentry'; export const fetchBarn = async (): Promise => { const response = await k9BrukerdialogApiClient.get(`/oppslag/barn`); @@ -9,7 +9,7 @@ export const fetchBarn = async (): Promise => { const barn = barnResponseSchema.parse(response.data).barn; return barn; } catch (e) { - getSentryLoggerForApp('sif-common', []).logApiError(e); + getSentryLoggerForApp('sif-common', []).logError('ZOD parse error', e); throw e; } }; diff --git "a/packages/sif-common/src/api/services/s\303\270kerService.ts" "b/packages/sif-common/src/api/services/s\303\270kerService.ts" index 7d2e664e9..08d5f2907 100644 --- "a/packages/sif-common/src/api/services/s\303\270kerService.ts" +++ "b/packages/sif-common/src/api/services/s\303\270kerService.ts" @@ -1,10 +1,16 @@ +import getSentryLoggerForApp from '@navikt/sif-common-sentry'; import { k9BrukerdialogApiClient } from '../apiClient'; -import { Søker } from '../types'; import { søkerResponseSchema } from '../schemas/søkerSchema'; +import { Søker } from '../types'; export const fetchSøker = async (): Promise => { const response = await k9BrukerdialogApiClient.get(`/oppslag/soker`); - return søkerResponseSchema.parse(response.data); + try { + return søkerResponseSchema.parse(response.data); + } catch (e) { + getSentryLoggerForApp('sif-common', []).logError('ZOD parse error', e); + throw e; + } }; export const fetchSøkerId = async (): Promise => { diff --git a/yarn.lock b/yarn.lock index cd04b98de..0b8f283aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4728,7 +4728,7 @@ __metadata: "@navikt/ds-react": "npm:7.0.1" "@navikt/ds-tailwind": "npm:7.0.1" "@navikt/sif-app-register": "npm:*" - "@navikt/sif-common": "workspace:*" + "@navikt/sif-common": "npm:*" "@navikt/sif-common-amplitude": "npm:*" "@navikt/sif-common-core-ds": "npm:*" "@navikt/sif-common-formik-ds": "npm:*" @@ -5404,7 +5404,7 @@ __metadata: languageName: unknown linkType: soft -"@navikt/sif-common@workspace:*, @navikt/sif-common@workspace:packages/sif-common": +"@navikt/sif-common@npm:*, @navikt/sif-common@workspace:packages/sif-common": version: 0.0.0-use.local resolution: "@navikt/sif-common@workspace:packages/sif-common" dependencies: @@ -5461,6 +5461,10 @@ __metadata: "@navikt/ds-react": "npm:7.0.1" "@navikt/ds-tailwind": "npm:7.0.1" "@navikt/nav-dekoratoren-moduler": "npm:2.1.6" + "@navikt/sif-common": "npm:*" + "@navikt/sif-common-core-ds": "npm:*" + "@navikt/sif-common-soknad-ds": "npm:*" + "@navikt/sif-common-ui": "npm:*" "@types/node": "npm:22.5.5" "@types/react": "npm:18.3.8" "@types/react-dom": "npm:18.3.0"