Skip to content
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

Better error handeling for name colisions in cli #983 #988

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}',`;
};
Loading