From 1ddb7d489a318a66baf67798ad8c325dfecf0bba Mon Sep 17 00:00:00 2001 From: mtraynham Date: Wed, 1 Nov 2017 11:40:50 -0400 Subject: [PATCH] Add types for json-query --- types/json-query/index.d.ts | 58 +++++++++++++ types/json-query/json-query-tests.ts | 123 +++++++++++++++++++++++++++ types/json-query/tsconfig.json | 23 +++++ types/json-query/tslint.json | 1 + 4 files changed, 205 insertions(+) create mode 100644 types/json-query/index.d.ts create mode 100644 types/json-query/json-query-tests.ts create mode 100644 types/json-query/tsconfig.json create mode 100644 types/json-query/tslint.json diff --git a/types/json-query/index.d.ts b/types/json-query/index.d.ts new file mode 100644 index 0000000000..929ab738ae --- /dev/null +++ b/types/json-query/index.d.ts @@ -0,0 +1,58 @@ +// Type definitions for json-query 2.2 +// Project: http://github.com/mmckegg/json-query#readme +// Definitions by: Matt Traynham +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export = JsonQuery; + +declare function JsonQuery( + selector: JsonQuery.Selector | JsonQuery.SelectorWithQueryParams, + options: JsonQuery.Options +): JsonQuery.Result; + +declare namespace JsonQuery { + type Selector = string; + + type QueryParam = any; + // No way to support [Selector, ...QueryParam[]]? + // 10 params should be more than enough, hopefully. + type SelectorWithQueryParams = + [Selector, QueryParam] + | [Selector, QueryParam] + | [Selector, QueryParam] + | [Selector, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam] + | [Selector, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam, QueryParam]; + + type Context = any; + + type Filter = (input: Context, ...args: any[]) => Context; + interface Locals { + [filterName: string]: Filter; + } + + interface Options { + data?: Context; + rootContext?: Context; + source?: Context; + context?: Context; + parent?: Context; + locals?: Locals; + globals?: boolean; + force?: boolean; + allowRegexp?: boolean; + } + + interface Result { + value: any; + key: string; + references: any[]; + parents: string[]; + } +} diff --git a/types/json-query/json-query-tests.ts b/types/json-query/json-query-tests.ts new file mode 100644 index 0000000000..5da1ca9e78 --- /dev/null +++ b/types/json-query/json-query-tests.ts @@ -0,0 +1,123 @@ +import jsonQuery = require('json-query'); + +// API +let data: jsonQuery.Context = { + people: [ + {name: 'Matt', country: 'NZ'}, + {name: 'Pete', country: 'AU'}, + {name: 'Mikey', country: 'NZ'} + ] +}; +jsonQuery('people[country=NZ].name', {data}); // => {value: 'Matt', parents: [...], key: 0} ... etc + +// Deep Queries +data = { + grouped_people: { + friends: [ + {name: 'Steve', country: 'NZ'}, + {name: 'Jane', country: 'US'}, + {name: 'Mike', country: 'AU'}, + {name: 'Mary', country: 'NZ'} + ], + enemies: [ + {name: 'Evil Steve', country: 'AU'}, + {name: 'Betty', country: 'NZ'} + ] + } +}; +const result: any = jsonQuery('grouped_people[**][*country=NZ]', {data}).value; + +// Inner Queries +data = { + page: { + id: 'page_1', + title: 'Test' + }, + comments_lookup: { + page_1: [ + {id: 'comment_1', parent_id: 'page_1', content: "I am a comment"} + ] + } +}; +jsonQuery('comments_lookup[{page.id}]', {data}); + +// Local functions (helpers) +const locals: jsonQuery.Locals = { + greetingName: (input: jsonQuery.Context) => { + if (input.known_as) { + return input.known_as; + } else { + return input.name; + } + }, + and: (inputA: jsonQuery.Context, inputB: boolean) => { + return inputA && inputB; + }, + text: (input: jsonQuery.Context, text: string) => { + return text; + }, + then: (input: jsonQuery.Context, thenValue: string, elseValue: string) => { + if (input) { + return thenValue; + } else { + return elseValue; + } + } +}; +data = { + is_fullscreen: true, + is_playing: false, + user: { + name: "Matthew McKegg", + known_as: "Matt" + } +}; +jsonQuery('user:greetingName', {data, locals}).value; // => "Matt" +jsonQuery(['is_fullscreen:and({is_playing}):then(?, ?)', "Playing big!", "Not so much"], {data, locals}).value; // => "Not so much" +jsonQuery(':text(This displays text cos we made it so)', {locals}).value; // => "This displays text cos we made it so" +jsonQuery('people:select(name, country)', { + data, + locals: { + select: (input: jsonQuery.Context, ...keys: string[]) => { + if (Array.isArray(input)) { + return input.map((item: any) => { + return Object.keys(item).reduce((result: {[p: string]: any}, key: string) => { + if (~keys.indexOf(key)) { + result[key] = item[key]; + } + return result; + }, {}); + }); + } + } + } +}); +jsonQuery('people[*:recentlyUpdated]', { + data, + locals: { + recentlyUpdated: (item: {updatedAt: number}) => { + return item.updatedAt < Date.now() - (30 * 24 * 60 * 60 * 1000); + } + } +}); + +// Context +data = { + styles: { + bold: 'font-weight:strong', + red: 'color: red' + }, + paragraphs: [ + {content: "I am a red paragraph", style: 'red'}, + {content: "I am a bold paragraph", style: 'bold'}, + ], +}; +let pageHtml = ''; +data.paragraphs.forEach((paragraph: {content: string, style: string}) => { + const style = jsonQuery('styles[{.style}]', {data, source: paragraph}).value; + const content = jsonQuery('.content', {data, source: paragraph}).value; // pretty pointless :) + pageHtml += `

${content}

`; +}); + +// Query Params +jsonQuery(['people[country=?]', 'NZ'], {data}); diff --git a/types/json-query/tsconfig.json b/types/json-query/tsconfig.json new file mode 100644 index 0000000000..9a317f4d83 --- /dev/null +++ b/types/json-query/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "json-query-tests.ts" + ] +} \ No newline at end of file diff --git a/types/json-query/tslint.json b/types/json-query/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/json-query/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }