@mapeo/mock-data
Version:
Module and CLI to generate mock data for Mapeo
194 lines (175 loc) • 5.67 kB
JavaScript
import { JSONSchemaFaker } from 'json-schema-faker'
import { faker } from '@faker-js/faker'
import deref from 'dereference-json-schema'
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const Geometry = require('@comapeo/geometry/json/geometry.json')
/**
* @typedef {typeof import('@comapeo/schema').docSchemas[import('@comapeo/schema/dist/types.js').SchemaName]} ValidSchema
*/
/**
* @param {number} bytes
*/
function hexString(bytes) {
return faker.string.hexadecimal({
length: bytes * 2,
prefix: '',
casing: 'lower',
})
}
function versionId() {
return hexString(32) + '/' + faker.number.int(1000)
}
const FAKER_EXTENSIONS = /** @type {const} */ ({
mapeo: {
id: () => hexString(32),
versionId: () => versionId(),
links: () =>
faker.helpers.multiple(() => versionId(), {
count: {
min: 0,
max: 5,
},
}),
id8: () => hexString(8),
comver: () =>
`${Math.floor(Math.random() * 100)}.${Math.floor(Math.random() * 100)}`,
url: () => faker.internet.url(),
},
})
JSONSchemaFaker.extend('faker', () => {
return Object.assign(faker, FAKER_EXTENSIONS)
})
export { JSONSchemaFaker, createFakerSchema }
/**
* @param {ValidSchema} schema
*/
function createFakerSchema(schema) {
// TODO: Ideally uses structured clone but not supported in Node 16
/** @type {import('type-fest').WritableDeep<ValidSchema>} */
const s = JSON.parse(JSON.stringify(schema))
mutateWithFakerProperty(s.properties.docId, 'mapeo.id')
mutateWithFakerProperty(s.properties.versionId, 'mapeo.versionId')
mutateWithFakerProperty(s.properties.originalVersionId, 'mapeo.versionId')
mutateWithFakerProperty(s.properties.links, 'mapeo.links')
switch (s.title) {
case 'CoreOwnership': {
mutateWithFakerProperty(s.properties.authCoreId, 'mapeo.id')
mutateWithFakerProperty(s.properties.blobCoreId, 'mapeo.id')
mutateWithFakerProperty(s.properties.blobIndexCoreId, 'mapeo.id')
mutateWithFakerProperty(s.properties.configCoreId, 'mapeo.id')
mutateWithFakerProperty(s.properties.dataCoreId, 'mapeo.id')
return s
}
case 'DeviceInfo': {
mutateWithFakerProperty(
s.properties.selfHostedServerDetails.properties.baseUrl,
'mapeo.url',
)
return s
}
case 'Field': {
return s
}
case 'Observation': {
mutateWithFakerProperty(
s.definitions.position.properties.coords.properties.longitude,
'location.longitude',
)
mutateWithFakerProperty(
s.definitions.position.properties.coords.properties.latitude,
'location.latitude',
)
mutateWithFakerProperty(s.properties.lon, 'location.longitude')
mutateWithFakerProperty(s.properties.lat, 'location.latitude')
mutateWithFakerProperty(
s.properties.attachments.items.properties.driveDiscoveryId,
'mapeo.id',
)
mutateWithFakerProperty(
s.properties.attachments.items.properties.hash,
'mapeo.id',
)
mutateWithFakerProperty(
s.properties.attachments.items.properties.name,
'mapeo.id8',
)
mutateWithFakerProperty(
s.properties.presetRef.properties.docId,
'mapeo.id',
)
mutateWithFakerProperty(
s.properties.presetRef.properties.versionId,
'mapeo.versionId',
)
return s
}
case 'Preset': {
mutateWithFakerProperty(
s.properties.fieldRefs.items.properties.docId,
'mapeo.id',
)
mutateWithFakerProperty(
s.properties.fieldRefs.items.properties.versionId,
'mapeo.versionId',
)
mutateWithFakerProperty(s.properties.iconRef.properties.docId, 'mapeo.id')
mutateWithFakerProperty(
s.properties.iconRef.properties.versionId,
'mapeo.versionId',
)
return s
}
case 'ProjectSettings': {
mutateWithFakerProperty(
s.properties.configMetadata.properties.fileVersion,
'mapeo.comver',
)
return s
}
case 'Role': {
mutateWithFakerProperty(s.properties.roleId, 'mapeo.id8')
return s
}
case 'Icon': {
mutateWithFakerProperty(s.definitions.blobVersionId, 'mapeo.versionId')
return s
}
case 'Track': {
mutateWithFakerProperty(
s.properties.observationRefs.items.properties.docId,
'mapeo.id',
)
mutateWithFakerProperty(
s.properties.observationRefs.items.properties.versionId,
'mapeo.versionId',
)
return s
}
case 'translation': {
mutateWithFakerProperty(s.properties.docRef.properties.docId, 'mapeo.id')
mutateWithFakerProperty(
s.properties.docRef.properties.versionId,
'mapeo.versionId',
)
return s
}
case 'RemoteDetectionAlert':
// @ts-expect-error Dereferencing this causes a type error, but the data
// is generated correctly.
s.properties.geometry = deref.dereferenceSync(Geometry)
return s
}
}
/**
* @template {keyof typeof FAKER_EXTENSIONS} TCustomExtensionNamespace
* @template {keyof (typeof FAKER_EXTENSIONS)[keyof typeof FAKER_EXTENSIONS]} TCustomExtensionField
* @template {`${TCustomExtensionNamespace}.${TCustomExtensionField}`} TCustomExtensionId
* @template {`location.${Extract<keyof import("@faker-js/faker").LocationModule, 'latitude' | 'longitude'>}`} TLocationFakerId
* @param {object} property
* @param {TCustomExtensionId | TLocationFakerId} fakerId
*/
function mutateWithFakerProperty(property, fakerId) {
// @ts-expect-error
property.faker = fakerId
}