-
Notifications
You must be signed in to change notification settings - Fork 0
feat: canonical export-name converter for GeoPackage columns (MAPCO-10823) #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: alpha
Are you sure you want to change the base?
Changes from all commits
259c0cb
f9a860f
415b7f8
ba71e67
3d3f8ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||
| import { snakeCase } from 'change-case'; | ||||||
|
|
||||||
| /** Export column names that differ from plain `snakeCase` (e.g. `resolution_degree` -> `resolution_deg`). */ | ||||||
| export const EXPORT_COLUMN_NAME_OVERRIDES: Record<string, string> = { | ||||||
| resolutionDegree: 'resolution_deg', | ||||||
| }; | ||||||
|
|
||||||
| /** Maps a camelCase property to its GeoPackage export column name: an override if present, else `snakeCase`. */ | ||||||
| export const toExportColumnName = (propertyName: string): string => { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| return EXPORT_COLUMN_NAME_OVERRIDES[propertyName] ?? snakeCase(propertyName); | ||||||
| }; | ||||||
|
|
||||||
| /** Renames an object's keys to their export column names, preserving values (incl. `null`). */ | ||||||
| export const convertKeysToExportColumns = (obj: Record<string, unknown>): Record<string, unknown> => { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| const result = Object.create(null) as Record<string, unknown>; // null-proto: a `__proto__` key stays a plain own property | ||||||
| for (const [key, value] of Object.entries(obj)) { | ||||||
| result[toExportColumnName(key)] = value; | ||||||
| } | ||||||
| return result; | ||||||
| }; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| export * from './export.utils'; | ||
| export * from './geo.utils'; | ||
| export * from './helpers.utils'; | ||
| export * from './layer.utils'; |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can avoid testing the |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { EXPORT_COLUMN_NAME_OVERRIDES, convertKeysToExportColumns } from '../../src/utils/export.utils'; | ||
|
|
||
| describe('export-name converter', () => { | ||
| describe('convertKeysToExportColumns', () => { | ||
| it('renames camelCase keys to snake_case export columns, applying overrides and preserving values', () => { | ||
| const input = { | ||
| id: 'abc', // single-word key is unchanged | ||
| sensors: ['a', 'b'], | ||
| sourceName: 'src', // plain camelCase -> snake_case | ||
| horizontalAccuracyCE90: 3, // acronym + number kept together | ||
| imagingTimeBeginUTC: '2020-01-01', // trailing acronym (UTC) | ||
| ingestionDateUTC: '2021-02-03', | ||
| resolutionDegree: 0.5, // override -> resolution_deg (not resolution_degree) | ||
| resolutionMeter: 12, // not overridden | ||
| maxResolutionDeg: 0.7, // already abbreviated, no override needed | ||
| }; | ||
|
|
||
| // toEqual (not toStrictEqual): the result intentionally has a null prototype for safety. | ||
| /* eslint-disable @typescript-eslint/naming-convention -- snake_case keys are the expected export column names */ | ||
| expect(convertKeysToExportColumns(input)).toEqual({ | ||
| id: 'abc', | ||
| sensors: ['a', 'b'], | ||
| source_name: 'src', | ||
| horizontal_accuracy_ce90: 3, | ||
| imaging_time_begin_utc: '2020-01-01', | ||
| ingestion_date_utc: '2021-02-03', | ||
| resolution_deg: 0.5, | ||
| resolution_meter: 12, | ||
| max_resolution_deg: 0.7, | ||
| }); | ||
| /* eslint-enable @typescript-eslint/naming-convention */ | ||
| }); | ||
|
|
||
| it('preserves null values (used for fixed-schema columns)', () => { | ||
| expect(convertKeysToExportColumns({ description: null, cities: null })).toEqual({ description: null, cities: null }); | ||
| }); | ||
|
|
||
| it('returns an object with no prototype to avoid prototype-chain writes', () => { | ||
| expect(Object.getPrototypeOf(convertKeysToExportColumns({ sourceName: 'x' }))).toBeNull(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('override table', () => { | ||
| it('declares resolutionDegree -> resolution_deg as its single entry', () => { | ||
| expect(EXPORT_COLUMN_NAME_OVERRIDES).toStrictEqual({ resolutionDegree: 'resolution_deg' }); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.