Skip to content

Commit

Permalink
Better date support
Browse files Browse the repository at this point in the history
  • Loading branch information
ingalls committed Nov 7, 2023
1 parent 76434ac commit 93df5bf
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 104 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@

## Version History

### v5.0.0

- :tada: Support the `format` tag in the Schema for Dates
- :rocket: Return Dates as ISO formatted strings to conform to schema

### v4.6.2

- :bug: Fix the way headers were appended
Expand Down
27 changes: 18 additions & 9 deletions dist/lib/geometry.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/lib/geometry.js.map

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions dist/lib/schema.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/lib/schema.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 22 additions & 11 deletions lib/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import EventEmitter from 'node:events';
import Err from '@openaddresses/batch-error';
import rings2geojson from './rings2geojson.js';
import Fetch from './fetch.js';
import { Feature } from 'geojson';
import { Feature, GeoJsonProperties } from 'geojson';
import Schema from './schema.js'
import { JSONSchema6, JSONSchema6Definition } from 'json-schema';
import {
EsriDumpConfig,
EsriDumpConfigApproach
Expand All @@ -28,7 +30,8 @@ export default class Geometry extends EventEmitter {
maxRecords: null | number;
set: Set<number>;
oidField: string;
paths: Path[]
paths: Path[];
schema: JSONSchema6;

constructor(url: URL, metadata: any) {
super();
Expand All @@ -40,6 +43,7 @@ export default class Geometry extends EventEmitter {
this.maxRecords = metadata.maxRecordCount || null;
this.set = new Set();
this.oidField = Geometry.findOidField(metadata.fields);
this.schema = Schema(metadata);
}

async fetch(config: EsriDumpConfig) {
Expand Down Expand Up @@ -182,28 +186,35 @@ export default class Geometry extends EventEmitter {
}

toGeoJSON(esrifeature: any): Feature {
const id = esrifeature.attributes[this.oidField];
const type = 'Feature';
const properties: GeoJsonProperties = {}
for (const prop in esrifeature.attributes) {
const schema: JSONSchema6Definition = this.schema.properties[prop];

if (typeof schema !== 'boolean' && schema.format === 'date-time') {
properties[prop] = new Date(esrifeature.attributes[prop]).toISOString();
} else {
properties[prop] = esrifeature.attributes[prop];
}
}

if (this.geomType === 'esriGeometryPolygon') {
return {
id: esrifeature.attributes[this.oidField],
type: 'Feature',
properties: esrifeature.attributes,
id, type, properties,
geometry: rings2geojson(esrifeature.geometry.rings)
};
} else if (this.geomType === 'esriGeometryPolyline') {
return {
id: esrifeature.attributes[this.oidField],
type: 'Feature',
properties: esrifeature.attributes,
id, type, properties,
geometry: {
type: 'MultiLineString',
coordinates: esrifeature.geometry.paths
}
};
} else if (this.geomType === 'esriGeometryPoint') {
return {
id: esrifeature.attributes[this.oidField],
type: 'Feature',
properties: esrifeature.attributes,
id, type, properties,
geometry: {
type: 'Point',
coordinates: [esrifeature.geometry.x, esrifeature.geometry.y]
Expand Down
41 changes: 19 additions & 22 deletions lib/schema.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import {
JSONSchema6,
JSONSchema6TypeName
} from 'json-schema';
import { JSONSchema6 } from 'json-schema';

// Ref: https://help.arcgis.com/en/sdk/10.0/java_ao_adf/api/arcgiswebservices/com/esri/arcgisws/EsriFieldType.html
const Types: Map<string, JSONSchema6TypeName> = new Map([
['esriFieldTypeDate', 'string'],
['esriFieldTypeString', 'string'],
['esriFieldTypeDouble', 'number'],
['esriFieldTypeSingle', 'number'],
['esriFieldTypeOID', 'number'],
['esriFieldTypeInteger', 'integer'],
['esriFieldTypeSmallInteger', 'integer'],
['esriFieldTypeGeometry', 'object'],
['esriFieldTypeBlob', 'object'],
['esriFieldTypeGlobalID', 'string'],
['esriFieldTypeRaster', 'object'],
['esriFieldTypeGUID', 'string'],
['esriFieldTypeXML', 'string'],
const Types: Map<string, JSONSchema6> = new Map([
['esriFieldTypeDate', { type: 'string', format: 'date-time' }],
['esriFieldTypeString', { type: 'string' }],
['esriFieldTypeDouble', { type: 'number' }],
['esriFieldTypeSingle', { type: 'number' }],
['esriFieldTypeOID', { type: 'number' }],
['esriFieldTypeInteger', { type: 'integer' }],
['esriFieldTypeSmallInteger', { type: 'integer' }],
['esriFieldTypeGeometry', { type: 'object' }],
['esriFieldTypeBlob', { type: 'object' }],
['esriFieldTypeGlobalID', { type: 'string' }],
['esriFieldTypeRaster', { type: 'object' }],
['esriFieldTypeGUID', { type: 'string' }],
['esriFieldTypeXML', { type: 'string' }],
]);

export default function FieldToSchema(metadata: any) {
export default function FieldToSchema(metadata: any): JSONSchema6 {
const doc: JSONSchema6 = {
type: 'object',
required: [],
Expand All @@ -35,13 +32,13 @@ export default function FieldToSchema(metadata: any) {
for (const field of metadata.fields) {
const name = String(field.name);

const type: JSONSchema6TypeName = Types.has(field.type) ? Types.get(field.type) : 'string';
const type: JSONSchema6 = Types.has(field.type) ? Types.get(field.type) : { type: 'string' };

const prop: JSONSchema6 = doc.properties[name] = {
type
...JSON.parse(JSON.stringify(type))
}

if (!isNaN(field.length) && type === 'string') {
if (!isNaN(field.length) && type.type === 'string') {
prop.maxLength = field.length;
}
}
Expand Down
Loading

0 comments on commit 93df5bf

Please sign in to comment.