From 5df1d8b0532648d16fd42a00da4d2cd5c2b6c64e Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 27 Jan 2026 11:10:04 +0000 Subject: [PATCH 1/6] Add Deactivated -> deletedAt mapping for USCH resources --- .../lambdas/s3-importer/src/uschMappings.ts | 8 +++- .../tests/fixtures/sampleResources.ts | 1 + .../tests/unit/uschMappings.test.ts | 47 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/resources-domain/lambdas/s3-importer/src/uschMappings.ts b/resources-domain/lambdas/s3-importer/src/uschMappings.ts index bd34e35c4..e6e879978 100644 --- a/resources-domain/lambdas/s3-importer/src/uschMappings.ts +++ b/resources-domain/lambdas/s3-importer/src/uschMappings.ts @@ -163,12 +163,14 @@ export type UschCsvResource = { Coverage: string; Comment: string; HoursFormatted: string; + Deactivated: string; }; export type UschExpandedResource = Partial< - Omit & { + Omit & { Categories: string[]; Coverage: string[]; + Deactivated: boolean; } >; @@ -202,6 +204,7 @@ export const expandCsvLine = (csv: UschCsvResource): UschExpandedResource => { ...csv, Categories: csv.Categories?.split(';').filter(Boolean), Coverage: csv.Coverage?.split(';').filter(Boolean), + Deactivated: Boolean(csv.Deactivated && csv.Deactivated.toLowerCase() === 'true'), }; for (const key in expanded) { const validKey = key as keyof UschExpandedResource; @@ -215,6 +218,9 @@ export const expandCsvLine = (csv: UschCsvResource): UschExpandedResource => { export const USCH_MAPPING_NODE: MappingNode = { ResourceID: resourceFieldMapping('id'), Name: resourceFieldMapping('name'), + Deactivated: resourceFieldMapping('deletedAt', context => + context.currentValue ? new Date().toISOString() : '', + ), AlternateName: translatableAttributeMapping('alternateName', { language: 'en' }), Address: attributeMapping('stringAttributes', 'address/street'), City: attributeMapping('stringAttributes', 'address/city', { diff --git a/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts b/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts index 5cdfd781b..36bd9f78e 100644 --- a/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts +++ b/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts @@ -65,4 +65,5 @@ export const EMPTY_CSV_LINE: UschCsvResource = { StateProvince: '', UpdatedOn: '', WebsiteAddress: '', + Deactivated: '', }; diff --git a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts index 8557bf9fc..b5f24bd3c 100644 --- a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts +++ b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts @@ -33,6 +33,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: [], + Deactivated: false, }); }); test('Csv line with single category - outputs expanded resource with single item category array', async () => { @@ -45,6 +46,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: ['One category'], + Deactivated: false, }); }); test('Csv line with multiple categories seperated by semi-colons - outputs expanded resource with category array without trimming', async () => { @@ -57,6 +59,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: ['A ', 'few', ' categories'], + Deactivated: false, }); }); test('Csv line with single coverage item - outputs expanded resource with single item coverage array', async () => { @@ -69,6 +72,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: ['One coverage'], Categories: [], + Deactivated: false, }); }); test('Csv line with multiple coverage seperated by semi-colons - outputs expanded resource with coverage array without trimming', async () => { @@ -81,8 +85,43 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: ['A ', 'few', ' coverages'], Categories: [], + Deactivated: false, }); }); + test('Csv line with Deactivated set false, sets Deactivated as false', async () => { + const result: UschExpandedResource = expandCsvLine({ + ...EMPTY_CSV_LINE, + ResourceID: TEST_RESOURCE_ID, + Deactivated: 'false', + }); + expect(result).toStrictEqual({ + ResourceID: TEST_RESOURCE_ID, + Coverage: [], + Categories: [], + Deactivated: false, + }); + }); + each([ + { deactivatedCsvValue: 'true' }, + { deactivatedCsvValue: 'TRUE' }, + { deactivatedCsvValue: 'True' }, + { deactivatedCsvValue: 'tRuE' }, + ]).test( + "Csv line with Deactivated set '$deactivatedCsvValue', sets Deactivated as true", + async ({ deactivatedCsvValue }) => { + const result: UschExpandedResource = expandCsvLine({ + ...EMPTY_CSV_LINE, + ResourceID: TEST_RESOURCE_ID, + Deactivated: deactivatedCsvValue, + }); + expect(result).toStrictEqual({ + ResourceID: TEST_RESOURCE_ID, + Coverage: [], + Categories: [], + Deactivated: true, + }); + }, + ); }); /** @@ -154,6 +193,14 @@ describe('Mapping valid sample resources should produce no warnings', () => { Coverage: ['COVERAGE 1', 'COVERAGE 2', 'COVERAGE 3'], }, }, + { + description: 'Resource with coverage', + resource: { + ResourceID: 'EMPTY_RESOURCE', + Coverage: ['COVERAGE 1', 'COVERAGE 2', 'COVERAGE 3'], + Deactivated: true, + }, + }, ]; each(testCases).test('$description has no warnings', ({ resource }) => { From ca27a86059fb9e13b6a491c5e63499b41c1dc511 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 27 Jan 2026 13:53:56 +0000 Subject: [PATCH 2/6] Update resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../lambdas/s3-importer/tests/unit/uschMappings.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts index b5f24bd3c..c42dbc837 100644 --- a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts +++ b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts @@ -194,7 +194,7 @@ describe('Mapping valid sample resources should produce no warnings', () => { }, }, { - description: 'Resource with coverage', + description: 'Resource with coverage and deactivated flag', resource: { ResourceID: 'EMPTY_RESOURCE', Coverage: ['COVERAGE 1', 'COVERAGE 2', 'COVERAGE 3'], From c2b5db750f91bbd6d5c1466468a17fbe1a684d7d Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 27 Jan 2026 14:12:46 +0000 Subject: [PATCH 3/6] Add another create-db.js retryable startup error type --- resources-domain/resources-service/create-db.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources-domain/resources-service/create-db.js b/resources-domain/resources-service/create-db.js index b8309aeab..cddbb1d49 100644 --- a/resources-domain/resources-service/create-db.js +++ b/resources-domain/resources-service/create-db.js @@ -65,7 +65,11 @@ async function create() { break; } catch (err) { // Catch and ECONNRESET, ECONNREFUSED or messages with 'connection' / 'connect' in. Cast a broad net! - if (err.message?.toLowerCase()?.includes('conn')) { + const errorMessage = err.message?.toLowerCase() ?? ''; + if ( + errorMessage.includes('conn') || + errorMessage.includes('the database system is starting up') + ) { console.debug( "Creation failed connecting to DB, assuming it's not ready yet & retrying...", ); From ec919d3a5f1825635fdd7afbd0080aabb24f5016 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 27 Jan 2026 15:09:48 +0000 Subject: [PATCH 4/6] Change deactivated csv field to inactive --- .../lambdas/s3-importer/src/uschMappings.ts | 8 ++--- .../tests/fixtures/sampleResources.ts | 2 +- .../tests/unit/uschMappings.test.ts | 36 +++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/resources-domain/lambdas/s3-importer/src/uschMappings.ts b/resources-domain/lambdas/s3-importer/src/uschMappings.ts index e6e879978..edc2adb93 100644 --- a/resources-domain/lambdas/s3-importer/src/uschMappings.ts +++ b/resources-domain/lambdas/s3-importer/src/uschMappings.ts @@ -163,14 +163,14 @@ export type UschCsvResource = { Coverage: string; Comment: string; HoursFormatted: string; - Deactivated: string; + Inactive: string; }; export type UschExpandedResource = Partial< - Omit & { + Omit & { Categories: string[]; Coverage: string[]; - Deactivated: boolean; + Inactive: boolean; } >; @@ -204,7 +204,7 @@ export const expandCsvLine = (csv: UschCsvResource): UschExpandedResource => { ...csv, Categories: csv.Categories?.split(';').filter(Boolean), Coverage: csv.Coverage?.split(';').filter(Boolean), - Deactivated: Boolean(csv.Deactivated && csv.Deactivated.toLowerCase() === 'true'), + Deactivated: Boolean(csv.Inactive && csv.Inactive.toLowerCase() === 'true'), }; for (const key in expanded) { const validKey = key as keyof UschExpandedResource; diff --git a/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts b/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts index 36bd9f78e..7d8473025 100644 --- a/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts +++ b/resources-domain/lambdas/s3-importer/tests/fixtures/sampleResources.ts @@ -65,5 +65,5 @@ export const EMPTY_CSV_LINE: UschCsvResource = { StateProvince: '', UpdatedOn: '', WebsiteAddress: '', - Deactivated: '', + Inactive: '', }; diff --git a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts index c42dbc837..f3825bb2e 100644 --- a/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts +++ b/resources-domain/lambdas/s3-importer/tests/unit/uschMappings.test.ts @@ -33,7 +33,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: [], - Deactivated: false, + Inactive: false, }); }); test('Csv line with single category - outputs expanded resource with single item category array', async () => { @@ -46,7 +46,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: ['One category'], - Deactivated: false, + Inactive: false, }); }); test('Csv line with multiple categories seperated by semi-colons - outputs expanded resource with category array without trimming', async () => { @@ -59,7 +59,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: ['A ', 'few', ' categories'], - Deactivated: false, + Inactive: false, }); }); test('Csv line with single coverage item - outputs expanded resource with single item coverage array', async () => { @@ -72,7 +72,7 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: ['One coverage'], Categories: [], - Deactivated: false, + Inactive: false, }); }); test('Csv line with multiple coverage seperated by semi-colons - outputs expanded resource with coverage array without trimming', async () => { @@ -85,40 +85,40 @@ describe('expandCsvLine', () => { ResourceID: TEST_RESOURCE_ID, Coverage: ['A ', 'few', ' coverages'], Categories: [], - Deactivated: false, + Inactive: false, }); }); - test('Csv line with Deactivated set false, sets Deactivated as false', async () => { + test('Csv line with Inactive set false, sets Inactive as false', async () => { const result: UschExpandedResource = expandCsvLine({ ...EMPTY_CSV_LINE, ResourceID: TEST_RESOURCE_ID, - Deactivated: 'false', + Inactive: 'false', }); expect(result).toStrictEqual({ ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: [], - Deactivated: false, + Inactive: false, }); }); each([ - { deactivatedCsvValue: 'true' }, - { deactivatedCsvValue: 'TRUE' }, - { deactivatedCsvValue: 'True' }, - { deactivatedCsvValue: 'tRuE' }, + { inactiveCsvValue: 'true' }, + { inactiveCsvValue: 'TRUE' }, + { inactiveCsvValue: 'True' }, + { inactiveCsvValue: 'tRuE' }, ]).test( - "Csv line with Deactivated set '$deactivatedCsvValue', sets Deactivated as true", - async ({ deactivatedCsvValue }) => { + "Csv line with Inactive set '$inactiveCsvValue', sets Inactive as true", + async ({ inactiveCsvValue }) => { const result: UschExpandedResource = expandCsvLine({ ...EMPTY_CSV_LINE, ResourceID: TEST_RESOURCE_ID, - Deactivated: deactivatedCsvValue, + Inactive: inactiveCsvValue, }); expect(result).toStrictEqual({ ResourceID: TEST_RESOURCE_ID, Coverage: [], Categories: [], - Deactivated: true, + Inactive: true, }); }, ); @@ -194,11 +194,11 @@ describe('Mapping valid sample resources should produce no warnings', () => { }, }, { - description: 'Resource with coverage and deactivated flag', + description: 'Resource with coverage and inactive flag', resource: { ResourceID: 'EMPTY_RESOURCE', Coverage: ['COVERAGE 1', 'COVERAGE 2', 'COVERAGE 3'], - Deactivated: true, + Inactive: true, }, }, ]; From f859bbe70c69bc55339b46589d38e614768b3495 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Tue, 27 Jan 2026 15:18:30 +0000 Subject: [PATCH 5/6] Change deactivated csv field to inactive --- resources-domain/lambdas/s3-importer/src/uschMappings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/lambdas/s3-importer/src/uschMappings.ts b/resources-domain/lambdas/s3-importer/src/uschMappings.ts index edc2adb93..dced975ff 100644 --- a/resources-domain/lambdas/s3-importer/src/uschMappings.ts +++ b/resources-domain/lambdas/s3-importer/src/uschMappings.ts @@ -204,7 +204,7 @@ export const expandCsvLine = (csv: UschCsvResource): UschExpandedResource => { ...csv, Categories: csv.Categories?.split(';').filter(Boolean), Coverage: csv.Coverage?.split(';').filter(Boolean), - Deactivated: Boolean(csv.Inactive && csv.Inactive.toLowerCase() === 'true'), + Inactive: Boolean(csv.Inactive && csv.Inactive.toLowerCase() === 'true'), }; for (const key in expanded) { const validKey = key as keyof UschExpandedResource; From f8c6f0d99bec3e7ebcff6305a9f7a10f48e4bbc3 Mon Sep 17 00:00:00 2001 From: Stephen Hand Date: Wed, 28 Jan 2026 10:02:03 +0000 Subject: [PATCH 6/6] Fix name mismatch in mapping --- resources-domain/lambdas/s3-importer/src/uschMappings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-domain/lambdas/s3-importer/src/uschMappings.ts b/resources-domain/lambdas/s3-importer/src/uschMappings.ts index dced975ff..9be54f1b5 100644 --- a/resources-domain/lambdas/s3-importer/src/uschMappings.ts +++ b/resources-domain/lambdas/s3-importer/src/uschMappings.ts @@ -218,7 +218,7 @@ export const expandCsvLine = (csv: UschCsvResource): UschExpandedResource => { export const USCH_MAPPING_NODE: MappingNode = { ResourceID: resourceFieldMapping('id'), Name: resourceFieldMapping('name'), - Deactivated: resourceFieldMapping('deletedAt', context => + Inactive: resourceFieldMapping('deletedAt', context => context.currentValue ? new Date().toISOString() : '', ), AlternateName: translatableAttributeMapping('alternateName', { language: 'en' }),