Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Ensure isomorphism in @truffle/db input/output
Browse files Browse the repository at this point in the history
So that queries and mutations that accept a list of inputs thus return a
list of outputs that one-to-one correspond to the inputs.

This allows filtering for lists of IDs, some of which may be unknown
resources, and it allows mutating multiple resources, some of which may
be repeated in the list or cause errors
  • Loading branch information
g. nicholas d'andrea committed Nov 4, 2020
1 parent 3ba09e4 commit c4a8ed1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
14 changes: 10 additions & 4 deletions packages/db/src/graphql/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class DefinitionsSchema<C extends Collections> {
}
input QueryFilter {
ids: [ID!]
ids: [ID]!
}
type Query
Expand Down Expand Up @@ -234,14 +234,20 @@ abstract class DefinitionSchema<
if (filter) {
logFilter("Filtering for ids: %o...", filter.ids);

const result = await workspace.find(resources, {
const results = await workspace.find(resources, {
selector: {
id: { $in: filter.ids }
id: { $in: filter.ids.filter(id => id) }
}
});

const byId = results
.map(result => ({
[result.id]: result
}))
.reduce((a, b) => ({ ...a, ...b }), {});

logFilter("Filtered for ids: %o", filter.ids);
return result;
return filter.ids.map(id => (id ? byId[id] : undefined));
} else {
logAll("Fetching all...");

Expand Down
45 changes: 33 additions & 12 deletions packages/db/src/pouch/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
): PouchDB.Database;

private async initialize() {
for (const [collectionName, definition] of Object.entries(this.definitions)) {
await this.initializeCollection(collectionName, definition)
};
for (const [collectionName, definition] of Object.entries(
this.definitions
)) {
await this.initializeCollection(collectionName, definition);
}

debug("Databases ready.");
}
Expand All @@ -74,7 +76,6 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
for (let index of createIndexes || []) {
await collection.createIndex({ index });
}

}

public async all<N extends CollectionName<C>>(
Expand Down Expand Up @@ -160,15 +161,18 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
const log = debug.extend(`${collectionName}:add`);
log("Adding...");

const resourceInputIds = input[collectionName].map(resourceInput =>
this.generateId(collectionName, resourceInput)
);

const resourceInputById = input[collectionName]
.map(resourceInput => ({
[this.generateId(collectionName, resourceInput)]: resourceInput
.map((resourceInput, index) => ({
[resourceInputIds[index]]: resourceInput
}))
.reduce((a, b) => ({ ...a, ...b }), {});

const resources = await Promise.all(
Object.entries(resourceInputById).map(async ([ id, resourceInput ]) => {
Object.entries(resourceInputById).map(async ([id, resourceInput]) => {
// check for existing
const resource = await this.get(collectionName, id);
if (resource) {
Expand All @@ -187,12 +191,19 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
})
);

const resourcesById = resources
.map(resource => ({
[resource.id as string]: resource
}))
.reduce((a, b) => ({ ...a, ...b }), {});

log(
"Added ids: %o",
resources.map(({ id }) => id)
);

return ({
[collectionName]: resources
[collectionName]: resourceInputIds.map(id => resourcesById[id])
} as unknown) as MutationPayload<C, N>;
}

Expand All @@ -205,14 +216,18 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
const log = debug.extend(`${collectionName}:update`);
log("Updating...");

const resourceInputIds = input[collectionName].map(resourceInput =>
this.generateId(collectionName, resourceInput)
);

const resourceInputById = input[collectionName]
.map(resourceInput => ({
[this.generateId(collectionName, resourceInput)]: resourceInput
.map((resourceInput, index) => ({
[resourceInputIds[index]]: resourceInput
}))
.reduce((a, b) => ({ ...a, ...b }), {});

const resources = await Promise.all(
Object.entries(resourceInputById).map(async ([ id, resourceInput ]) => {
Object.entries(resourceInputById).map(async ([id, resourceInput]) => {
// check for existing
const resource = await this.get(collectionName, id);
const { _rev = undefined } = resource ? resource : {};
Expand All @@ -230,12 +245,18 @@ export abstract class Databases<C extends Collections> implements Workspace<C> {
})
);

const resourcesById = resources
.map(resource => ({
[resource.id as string]: resource
}))
.reduce((a, b) => ({ ...a, ...b }), {});

log(
"Updated ids: %o",
resources.map(({ id }) => id)
);
return ({
[collectionName]: resources
[collectionName]: resourceInputIds.map(id => resourcesById[id])
} as unknown) as MutationPayload<C, M>;
}

Expand Down

0 comments on commit c4a8ed1

Please sign in to comment.