-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(create): adds collection, scope, and services
- Loading branch information
Showing
10 changed files
with
281 additions
and
7 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { CollectionTree } from '~/types'; | ||
|
||
export function emptyCollection(): CollectionTree { | ||
return { | ||
types: { error: {}, request: {}, response: {} }, | ||
services: { query: {}, mutation: {}, subscription: {} }, | ||
scopes: {} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { CollectionTree, Service, Tree, ServiceItem, InputHook } from '~/types'; | ||
import { query, mutation, subscription } from '../service'; | ||
import { services as createServices } from '../services'; | ||
import { mergeCollectionArray } from './merge'; | ||
import { emptyCollection } from './empty'; | ||
|
||
export function setCollectionHooks( | ||
collection: CollectionTree, | ||
hooks: InputHook | InputHook[] | ||
): CollectionTree { | ||
const empty = emptyCollection(); | ||
|
||
return mergeCollectionArray([ | ||
{ ...empty, ...collection, services: empty.services }, | ||
setServicesHooks('query', collection.services.query, hooks), | ||
setServicesHooks('mutation', collection.services.mutation, hooks), | ||
setServicesHooks('subscription', collection.services.subscription, hooks), | ||
...Object.entries(collection.scopes).map(([name, scope]) => { | ||
const { types, ...other } = setCollectionHooks( | ||
{ ...empty, ...scope }, | ||
hooks | ||
); | ||
return { ...empty, types, scopes: { [name]: other } }; | ||
}) | ||
]); | ||
} | ||
|
||
export function setServicesHooks<T extends Service>( | ||
kind: keyof Tree['services'], | ||
services: { [key: string]: T }, | ||
hooks: InputHook | InputHook[] | ||
): CollectionTree { | ||
const entries = Object.entries(services); | ||
return createServices( | ||
entries.reduce( | ||
(acc: { [key: string]: ServiceItem }, [name, service]) => | ||
Object.assign(acc, { [name]: setServiceHooks(kind, service, hooks) }), | ||
{} | ||
) | ||
); | ||
} | ||
|
||
export function setServiceHooks<T extends Service>( | ||
kind: keyof Tree['services'], | ||
service: T, | ||
hooks: InputHook | InputHook[] | ||
): ServiceItem<T> { | ||
switch (kind) { | ||
case 'query': | ||
return query(service, hooks) as ServiceItem<T>; | ||
case 'mutation': | ||
return mutation(service, hooks) as ServiceItem<T>; | ||
case 'subscription': | ||
return subscription(service, hooks) as ServiceItem<T>; | ||
default: | ||
throw Error(`Invalid service kind`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { CollectionTree, InputHook } from '~/types'; | ||
import { mergeCollectionArray } from './merge'; | ||
import { emptyCollection } from './empty'; | ||
import { setCollectionHooks } from './hooks'; | ||
|
||
export function collection( | ||
collections?: CollectionTree | CollectionTree[], | ||
hooks?: InputHook | InputHook[] | ||
): CollectionTree { | ||
const collection = Array.isArray(collections) | ||
? mergeCollectionArray(collections) | ||
: collections || emptyCollection(); | ||
|
||
return hooks ? setCollectionHooks(collection, hooks) : collection; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { CollectionTree, ScopeTree } from '~/types'; | ||
import { emptyCollection } from './empty'; | ||
|
||
export function mergeCollectionArray( | ||
collections: CollectionTree[] | ||
): CollectionTree { | ||
return collections.reduce( | ||
(acc, collection) => mergeCollections(acc, collection), | ||
emptyCollection() | ||
); | ||
} | ||
|
||
export function mergeCollections( | ||
a: CollectionTree, | ||
b: CollectionTree | ||
): CollectionTree { | ||
const { types: aTypes, ...aScope } = a; | ||
const { types: bTypes, ...bScope } = b; | ||
return { | ||
types: { | ||
error: { ...aTypes.error, ...bTypes.error }, | ||
request: { ...aTypes.request, ...bTypes.request }, | ||
response: { ...aTypes.response, ...bTypes.response } | ||
}, | ||
...mergeScopes(aScope, bScope) | ||
}; | ||
} | ||
|
||
export function mergeScopes(a: ScopeTree, b: ScopeTree): ScopeTree { | ||
const scopeKeys = { | ||
a: Object.keys(a.scopes), | ||
b: Object.keys(b.scopes) | ||
}; | ||
const nonUniqueScopeKeys = scopeKeys.a.filter( | ||
(x) => scopeKeys.b.indexOf(x) !== -1 | ||
); | ||
|
||
return { | ||
services: { | ||
query: { ...a.services.query, ...b.services.query }, | ||
mutation: { ...a.services.mutation, ...b.services.mutation }, | ||
subscription: { ...a.services.subscription, ...b.services.subscription } | ||
}, | ||
scopes: { | ||
...a.scopes, | ||
...b.scopes, | ||
...nonUniqueScopeKeys.reduce( | ||
(acc: { [key: string]: ScopeTree }, x) => | ||
Object.assign(acc, mergeScopes(a.scopes[x], b.scopes[x])), | ||
{} | ||
) | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
export * from './collection'; | ||
export * from './service'; | ||
export * from './services'; | ||
export * from './schema'; | ||
export * from './scope'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { CollectionTree, InputHook } from '~/types'; | ||
import { collection as createCollection } from './collection'; | ||
|
||
export function scope( | ||
name: string, | ||
collection: CollectionTree, | ||
hooks?: InputHook | InputHook[] | ||
): CollectionTree { | ||
const { types, ...other } = collection; | ||
const tree = createCollection(); | ||
tree.types = types; | ||
tree.scopes[name] = other; | ||
|
||
return hooks ? createCollection(tree, hooks) : tree; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { CollectionTree, InputHook, InputServices } from '~/types'; | ||
import { itemToCollection } from './item-to-collection'; | ||
import { collection } from '../collection'; | ||
import { scope as createScope } from '../scope'; | ||
|
||
export function services( | ||
services: InputServices, | ||
hooks?: InputHook | InputHook[] | ||
): CollectionTree; | ||
export function services( | ||
name: string, | ||
services: InputServices, | ||
hooks?: InputHook | InputHook[] | ||
): CollectionTree; | ||
export function services( | ||
name: string, | ||
scope: boolean, | ||
services: InputServices, | ||
hooks?: InputHook | InputHook[] | ||
): CollectionTree; | ||
export function services(...args: any[]): CollectionTree { | ||
const hasName = typeof args[0] === 'string'; | ||
const hasScope = typeof args[1] === 'boolean'; | ||
const name: string = hasName ? args[0] : ''; | ||
const scope: boolean = hasScope ? args[1] : false; | ||
const services: InputServices = hasScope | ||
? args[2] | ||
: hasName | ||
? args[1] | ||
: args[0]; | ||
const hooks: InputHook | InputHook[] | undefined = hasScope | ||
? args[3] | ||
: hasName | ||
? args[2] | ||
: args[1]; | ||
|
||
const collections: CollectionTree[] = []; | ||
const entries = Object.entries(services); | ||
for (const [key, item] of entries) { | ||
collections.push(itemToCollection(name, key, item)); | ||
} | ||
|
||
return scope | ||
? createScope(name, collection(collections, hooks)) | ||
: collection(collections, hooks); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { ServiceItem, CollectionTree } from '~/types'; | ||
import { collection } from '../collection'; | ||
import camelcase from 'camelcase'; | ||
import { request, response, error } from '../type'; | ||
|
||
export function itemToCollection( | ||
prefix: string, | ||
name: string, | ||
item: ServiceItem | ||
): CollectionTree { | ||
const collections: CollectionTree[] = []; | ||
const service = { | ||
...item.service, | ||
types: { ...item.service.types } | ||
}; | ||
|
||
const pre = | ||
camelcase(prefix, { pascalCase: true }) + | ||
camelcase(name, { pascalCase: true }); | ||
if (item.types.request) { | ||
collections.push(request(pre + 'Request', { schema: item.types.request })); | ||
service.types.request = pre + 'Request'; | ||
} | ||
if (item.types.response) { | ||
collections.push( | ||
response(pre + 'Response', { schema: item.types.response }) | ||
); | ||
service.types.response = pre + 'Response'; | ||
} | ||
if (item.types.errors) { | ||
for (const { name: id, ...other } of item.types.errors) { | ||
collections.push(error(pre + id, other)); | ||
service.types.errors.push(pre + id); | ||
} | ||
} | ||
|
||
const tree = collection(); | ||
tree.services[item.kind][name] = service; | ||
collections.push(tree); | ||
|
||
return collection(collections); | ||
} |