-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add a situation (and foldedSteps) migration function
- Loading branch information
Showing
9 changed files
with
355 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './commons' | ||
export * from './serializeParsedRules' | ||
export * from './migrations' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './migrateSituation' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { DottedName, MigrationType, Situation } from '../../types/types' | ||
import { handleSituationKeysMigration } from './migrateSituation/handleSituationKeysMigration' | ||
import { handleSituationValuesMigration } from './migrateSituation/handleSituationValuesMigration' | ||
import { handleSpecialCases } from './migrateSituation/handleSpecialCases' | ||
|
||
type Props = { | ||
situation: Situation | ||
foldedSteps?: DottedName[] | ||
migrationInstructions: MigrationType | ||
} | ||
|
||
export function migrateSituation({ | ||
situation, | ||
foldedSteps = [], | ||
migrationInstructions, | ||
}: Props) { | ||
let situationMigrated = { ...situation } | ||
let foldedStepsMigrated = [...foldedSteps] | ||
|
||
Object.entries(situationMigrated).map(([ruleName, nodeValue]) => { | ||
const situationUpdated = handleSpecialCases({ | ||
ruleName, | ||
nodeValue, | ||
situation: situationMigrated, | ||
}) | ||
|
||
situationMigrated = situationUpdated | ||
|
||
// We check if the non supported ruleName is a key to migrate. | ||
// Ex: "logement . chauffage . bois . type . bûche . consommation": "xxx" which is now ""logement . chauffage . bois . type . bûches . consommation": "xxx" | ||
if (Object.keys(migrationInstructions.keysToMigrate).includes(ruleName)) { | ||
const result = handleSituationKeysMigration({ | ||
ruleName, | ||
nodeValue, | ||
situation: situationMigrated, | ||
foldedSteps: foldedStepsMigrated, | ||
migrationInstructions, | ||
}) | ||
|
||
situationMigrated = result.situationMigrated | ||
foldedStepsMigrated = result.foldedStepsMigrated | ||
} | ||
|
||
const matchingValueToMigrateObject = | ||
migrationInstructions.valuesToMigrate[ | ||
Object.keys(migrationInstructions.valuesToMigrate).find((key) => | ||
ruleName.includes(key), | ||
) as any | ||
] | ||
|
||
const formattedNodeValue = | ||
typeof nodeValue === 'string' && | ||
nodeValue.startsWith("'") && | ||
nodeValue !== 'oui' && | ||
nodeValue !== 'non' | ||
? nodeValue.slice(1, -1) | ||
: (nodeValue as string) | ||
|
||
if ( | ||
// We check if the value of the non supported ruleName value is a value to migrate. | ||
// Ex: answer "logement . chauffage . bois . type": "bûche" changed to "bûches" | ||
// If a value is specified but empty, we consider it to be deleted (we need to ask the question again) | ||
// Ex: answer "transport . boulot . commun . type": "vélo" | ||
matchingValueToMigrateObject && | ||
Object.keys(matchingValueToMigrateObject).includes( | ||
// If the string start with a ', we remove it along with the last character | ||
// Ex: "'bûche'" => "bûche" | ||
formattedNodeValue, | ||
) | ||
) { | ||
const result = handleSituationValuesMigration({ | ||
ruleName, | ||
nodeValue: formattedNodeValue, | ||
situation: situationMigrated, | ||
foldedSteps: foldedStepsMigrated, | ||
migrationInstructions, | ||
}) | ||
|
||
situationMigrated = result.situationMigrated | ||
foldedStepsMigrated = result.foldedStepsMigrated | ||
} | ||
}) | ||
|
||
return { situationMigrated, foldedStepsMigrated } | ||
} |
18 changes: 18 additions & 0 deletions
18
source/migrations/migrateSituation/deleteKeyFromSituationAndFoldedSteps.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { DottedName, Situation } from '../../../types/types' | ||
|
||
export function deleteKeyFromSituationAndFoldedSteps({ | ||
ruleName, | ||
situation, | ||
foldedSteps, | ||
}: { | ||
ruleName: string | ||
situation: Situation | ||
foldedSteps: DottedName[] | ||
}) { | ||
delete situation[ruleName] | ||
const index = foldedSteps?.indexOf(ruleName) | ||
|
||
if (index > -1) { | ||
foldedSteps.splice(index, 1) | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
source/migrations/migrateSituation/handleSituationKeysMigration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { | ||
DottedName, | ||
MigrationType, | ||
NodeValue, | ||
Situation, | ||
} from '../../../types/types' | ||
import { deleteKeyFromSituationAndFoldedSteps } from './deleteKeyFromSituationAndFoldedSteps' | ||
|
||
type Props = { | ||
ruleName: string | ||
nodeValue: NodeValue | ||
situation: Situation | ||
foldedSteps: DottedName[] | ||
migrationInstructions: MigrationType | ||
} | ||
|
||
function updateKeyInSituationAndFoldedSteps({ | ||
ruleName, | ||
nodeValue, | ||
situation, | ||
foldedSteps, | ||
migrationInstructions, | ||
}: { | ||
ruleName: string | ||
nodeValue: NodeValue | ||
situation: Situation | ||
foldedSteps: DottedName[] | ||
migrationInstructions: MigrationType | ||
}) { | ||
situation[migrationInstructions.keysToMigrate[ruleName]] = | ||
(nodeValue as any)?.valeur ?? nodeValue | ||
|
||
delete situation[ruleName] | ||
|
||
const index = foldedSteps?.indexOf(ruleName) | ||
|
||
if (index > -1) { | ||
foldedSteps[index] = migrationInstructions.keysToMigrate[ruleName] | ||
} | ||
} | ||
|
||
export function handleSituationKeysMigration({ | ||
ruleName, | ||
nodeValue, | ||
situation, | ||
foldedSteps, | ||
migrationInstructions, | ||
}: Props) { | ||
const situationMigrated = { ...situation } | ||
const foldedStepsMigrated = [...foldedSteps] | ||
|
||
// The key is not a key to migrate but a key to delete | ||
if (migrationInstructions.keysToMigrate[ruleName] === '') { | ||
deleteKeyFromSituationAndFoldedSteps({ | ||
ruleName, | ||
situation: situationMigrated, | ||
foldedSteps: foldedStepsMigrated, | ||
}) | ||
return { situationMigrated, foldedStepsMigrated } | ||
} | ||
|
||
if (!migrationInstructions.keysToMigrate[ruleName]) { | ||
return | ||
} | ||
|
||
// The key is renamed and needs to be migrated | ||
updateKeyInSituationAndFoldedSteps({ | ||
ruleName, | ||
nodeValue, | ||
situation: situationMigrated, | ||
foldedSteps: foldedStepsMigrated, | ||
migrationInstructions, | ||
}) | ||
|
||
return { situationMigrated, foldedStepsMigrated } | ||
} |
92 changes: 92 additions & 0 deletions
92
source/migrations/migrateSituation/handleSituationValuesMigration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { | ||
DottedName, | ||
MigrationType, | ||
NodeValue, | ||
Situation, | ||
} from '../../../types/types' | ||
import { deleteKeyFromSituationAndFoldedSteps } from './deleteKeyFromSituationAndFoldedSteps' | ||
|
||
type Props = { | ||
ruleName: DottedName | ||
nodeValue: NodeValue | ||
situation: Situation | ||
foldedSteps: DottedName[] | ||
migrationInstructions: MigrationType | ||
} | ||
|
||
function getMigratedValue({ | ||
ruleName, | ||
nodeValue, | ||
migrationInstructions, | ||
}: { | ||
ruleName: DottedName | ||
nodeValue: NodeValue | ||
migrationInstructions: MigrationType | ||
}): string | number { | ||
if ( | ||
typeof migrationInstructions.valuesToMigrate[ruleName][ | ||
nodeValue as string | ||
] === 'string' && | ||
migrationInstructions.valuesToMigrate[ruleName][nodeValue as string] !== | ||
'oui' && | ||
migrationInstructions.valuesToMigrate[ruleName][nodeValue as string] !== | ||
'non' | ||
) { | ||
return `'${migrationInstructions.valuesToMigrate[ruleName][nodeValue as string]}'` | ||
} | ||
|
||
if ( | ||
( | ||
migrationInstructions.valuesToMigrate[ruleName][nodeValue as string] as { | ||
valeur: number | ||
} | ||
)?.valeur !== undefined | ||
) { | ||
return ( | ||
migrationInstructions.valuesToMigrate[ruleName][nodeValue as string] as { | ||
valeur: number | ||
} | ||
).valeur | ||
} | ||
|
||
return migrationInstructions.valuesToMigrate[ruleName][ | ||
nodeValue as string | ||
] as string | number | ||
} | ||
|
||
export function handleSituationValuesMigration({ | ||
ruleName, | ||
nodeValue, | ||
situation, | ||
foldedSteps, | ||
migrationInstructions, | ||
}: Props) { | ||
if (!migrationInstructions.valuesToMigrate[ruleName]) { | ||
return | ||
} | ||
|
||
const situationMigrated = { ...situation } | ||
const foldedStepsMigrated = [...foldedSteps] | ||
|
||
// The value is not a value to migrate and the key has to be deleted | ||
if ( | ||
migrationInstructions.valuesToMigrate[ruleName][nodeValue as string] === '' | ||
) { | ||
deleteKeyFromSituationAndFoldedSteps({ | ||
ruleName, | ||
situation: situationMigrated, | ||
foldedSteps: foldedStepsMigrated, | ||
}) | ||
|
||
return { situationMigrated, foldedStepsMigrated } | ||
} | ||
|
||
// The value is renamed and needs to be migrated | ||
situationMigrated[ruleName] = getMigratedValue({ | ||
ruleName, | ||
nodeValue, | ||
migrationInstructions, | ||
}) | ||
|
||
return { situationMigrated, foldedStepsMigrated } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
type Props = { | ||
ruleName: string | ||
nodeValue: any | ||
situation: any | ||
} | ||
|
||
// Handle migration of old value format : an object { valeur: number, unité: string } | ||
export function handleSpecialCases({ ruleName, nodeValue, situation }: Props) { | ||
const situationUpdated = { ...situation } | ||
|
||
// Special case, number store as a string, we have to convert it to a number | ||
if ( | ||
nodeValue && | ||
typeof nodeValue === 'string' && | ||
!isNaN(parseFloat(nodeValue)) | ||
) { | ||
situationUpdated[ruleName] = parseFloat(nodeValue) | ||
} | ||
|
||
// Special case : wrong value format, legacy from previous publicodes version | ||
// handle the case where valeur is a string "2.33" | ||
if (nodeValue && nodeValue.valeur !== undefined) { | ||
situationUpdated[ruleName] = | ||
typeof nodeValue.valeur === 'string' && | ||
!isNaN(parseFloat(nodeValue.valeur)) | ||
? parseFloat(nodeValue.valeur) | ||
: (nodeValue.valeur as number) | ||
} | ||
// Special case : other wrong value format, legacy from previous publicodes version | ||
// handle the case where nodeValue is a string "2.33" | ||
if (nodeValue && nodeValue.nodeValue !== undefined) { | ||
situationUpdated[ruleName] = | ||
typeof nodeValue.nodeValue === 'string' && | ||
!isNaN(parseFloat(nodeValue.nodeValue)) | ||
? parseFloat(nodeValue.nodeValue) | ||
: (nodeValue.nodeValue as number) | ||
} | ||
|
||
return situationUpdated | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Evaluation } from 'publicodes' | ||
|
||
export type Situation = { | ||
[key: string]: string | number | ||
} | ||
|
||
export type DottedName = string | ||
|
||
export type MigrationType = { | ||
keysToMigrate: Record<DottedName, DottedName> | ||
valuesToMigrate: Record<DottedName, Record<string, NodeValue>> | ||
} | ||
|
||
export type NodeValue = Evaluation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters