Skip to content

Commit

Permalink
Better error handeling for name colisions in cli #983
Browse files Browse the repository at this point in the history
  • Loading branch information
Polleps authored and joepio committed Oct 10, 2024
1 parent 5e2445f commit 779c268
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 27 deletions.
4 changes: 4 additions & 0 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This changelog covers all five packages, as they are (for now) updated as a whol

- [#981](https://github.com/atomicdata-dev/atomic-server/issues/981) Fix bug where the service worker would not update cache with updated code.

### @tomic/cli

- [#983](https://github.com/atomicdata-dev/atomic-server/issues/983) Give clear error when name collisions are found in an ontology.

## [v0.40.0] - 2024-10-07

### Atomic Browser
Expand Down
42 changes: 33 additions & 9 deletions browser/cli/src/generateBaseObject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { core, Resource } from '@tomic/lib';
import { Resource, type Core } from '@tomic/lib';
import { store } from './store.js';
import { camelCaseify, dedupe } from './utils.js';
import chalk from 'chalk';

export type ReverseMapping = Record<string, string>;

Expand All @@ -10,21 +11,19 @@ type BaseObject = {
};

export const generateBaseObject = async (
ontology: Resource,
ontology: Resource<Core.Ontology>,
): Promise<[string, ReverseMapping]> => {
if (ontology.error) {
throw ontology.error;
}

const classes = dedupe(ontology.get(core.properties.classes)) as string[];
const properties = dedupe(
ontology.get(core.properties.properties),
) as string[];
const classes = dedupe(ontology.props.classes ?? []);
const properties = dedupe(ontology.props.properties ?? []);
const name = camelCaseify(ontology.title);

const baseObj = {
classes: await listToObj(classes),
properties: await listToObj(properties),
classes: await listToObj(classes, 'classes'),
properties: await listToObj(properties, 'properties'),
};

const objStr = `export const ${name} = {
Expand All @@ -35,7 +34,10 @@ export const generateBaseObject = async (
return [objStr, createReverseMapping(name, baseObj)];
};

const listToObj = async (list: string[]): Promise<Record<string, string>> => {
const listToObj = async (
list: string[],
type: string,
): Promise<Record<string, string>> => {
const entries = await Promise.all(
list.map(async subject => {
const resource = await store.getResource(subject);
Expand All @@ -44,6 +46,28 @@ const listToObj = async (list: string[]): Promise<Record<string, string>> => {
}),
);

// check for duplicates and throw an error if there are any.
const duplicates = entries.filter(
(entry, index) => entries.findIndex(e => e[0] === entry[0]) !== index,
);

if (duplicates.length > 0) {
// eslint-disable-next-line no-console
console.log(
chalk.red(`ERROR: Found ${type} with the same name: `),
duplicates.map(e => e[0]).join(', '),
);

// eslint-disable-next-line no-console
console.log(
chalk.red(
'Properties with the same name will conflict in the generated ontology. Try to reuse properties where possible or rename the duplicate to prevent a conflict.',
),
);

process.exit(1);
}

return Object.fromEntries(entries);
};

Expand Down
6 changes: 3 additions & 3 deletions browser/cli/src/generateOntology.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { generateBaseObject } from './generateBaseObject.js';
import { generateClasses } from './generateClasses.js';
import { store } from './store.js';
import { camelCaseify } from './utils.js';
import { camelCaseify, dedupe } from './utils.js';
import { generatePropTypeMapping } from './generatePropTypeMapping.js';
import { generateSubjectToNameMapping } from './generateSubjectToNameMapping.js';
import { generateClassExports } from './generateClassExports.js';
Expand Down Expand Up @@ -47,9 +47,9 @@ export const generateOntology = async (
filename: string;
content: string;
}> => {
const ontology = await store.getResourceAsync<Core.Ontology>(subject);
const ontology = await store.getResource<Core.Ontology>(subject);

const properties = ontology.props.properties ?? [];
const properties = dedupe(ontology.props.properties ?? []);

for (const prop of properties) {
propertyRecord.repordPropertyDefined(prop);
Expand Down
15 changes: 6 additions & 9 deletions browser/cli/src/generatePropTypeMapping.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Datatype, Resource } from '@tomic/lib';
import { Datatype, Resource, type Core } from '@tomic/lib';
import { store } from './store.js';
import { ReverseMapping } from './generateBaseObject.js';
import { DatatypeToTSTypeMap } from './DatatypeToTSTypeMap.js';
import { dedupe } from './utils.js';

export const generatePropTypeMapping = (
ontology: Resource,
ontology: Resource<Core.Ontology>,
reverseMapping: ReverseMapping,
): string => {
const properties = (ontology.get(
'https://atomicdata.dev/properties/properties',
) ?? []) as string[];
const properties = dedupe(ontology.props.properties ?? []);

const lines = properties
.map(subject => generateLine(subject, reverseMapping))
Expand All @@ -21,10 +20,8 @@ export const generatePropTypeMapping = (
};

const generateLine = (subject: string, reverseMapping: ReverseMapping) => {
const resource = store.getResourceLoading(subject);
const datatype = resource.get(
'https://atomicdata.dev/properties/datatype',
) as Datatype;
const resource = store.getResourceLoading<Core.Property>(subject);
const datatype = resource.props.datatype as Datatype;

return `[${reverseMapping[subject]}]: ${DatatypeToTSTypeMap[datatype]}`;
};
16 changes: 10 additions & 6 deletions browser/cli/src/generateSubjectToNameMapping.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { Resource } from '@tomic/lib';
import { Resource, core } from '@tomic/lib';
import { ReverseMapping } from './generateBaseObject.js';

export function generateSubjectToNameMapping(
ontology: Resource,
reverseMapping: ReverseMapping,
) {
const properties = ontology.getArray(
'https://atomicdata.dev/properties/properties',
) as string[];
const properties = ontology.getArray(core.properties.properties) as string[];

const lines = properties.map(prop => propLine(prop, reverseMapping));
const lines = properties
.map(prop => propLine(prop, reverseMapping))
.filter(line => line);

return `interface PropSubjectToNameMapping {
${lines.join('\n')}
}`;
}

const propLine = (subject: string, reverseMapping: ReverseMapping) => {
const name = reverseMapping[subject].split('.')[2];
const name = reverseMapping[subject]?.split('.')[2];

if (!name) {
return undefined;
}

return `[${reverseMapping[subject]}]: '${name}',`;
};

0 comments on commit 779c268

Please sign in to comment.