mad-data-parser 0.0.1 → 0.0.2-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.vscode/launch.json +40 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/mad-data-parser-0.0.2-beta.12.tgz +0 -0
  5. package/dist/package.json +28 -0
  6. package/dist/parser/parseJsonPaths.d.ts +11 -3
  7. package/dist/parser/parseJsonPaths.d.ts.map +1 -1
  8. package/dist/parser/parseJsonPaths.js +127 -68
  9. package/dist/parser/parseJsonPaths.js.map +1 -1
  10. package/dist/utils/graphql/index.d.ts +2 -2
  11. package/dist/utils/graphql/index.d.ts.map +1 -1
  12. package/dist/utils/graphql/index.js +2 -1
  13. package/dist/utils/graphql/index.js.map +1 -1
  14. package/dist/utils/graphql-tag/collocated/gql.d.ts +47 -0
  15. package/dist/utils/graphql-tag/collocated/gql.d.ts.map +1 -0
  16. package/dist/utils/graphql-tag/collocated/gql.js +133 -0
  17. package/dist/utils/graphql-tag/collocated/gql.js.map +1 -0
  18. package/dist/utils/graphql-tag/collocated/guards.d.ts +4 -0
  19. package/dist/utils/graphql-tag/collocated/guards.d.ts.map +1 -0
  20. package/dist/utils/graphql-tag/collocated/guards.js +13 -0
  21. package/dist/utils/graphql-tag/collocated/guards.js.map +1 -0
  22. package/dist/utils/graphql-tag/collocated/stringifyDocument.d.ts +2 -0
  23. package/dist/utils/graphql-tag/collocated/stringifyDocument.d.ts.map +1 -0
  24. package/dist/utils/graphql-tag/collocated/stringifyDocument.js +38 -0
  25. package/dist/utils/graphql-tag/collocated/stringifyDocument.js.map +1 -0
  26. package/dist/utils/graphql-tag/collocated/types.d.ts +19 -0
  27. package/dist/utils/graphql-tag/collocated/types.d.ts.map +1 -0
  28. package/dist/utils/graphql-tag/collocated/types.js +2 -0
  29. package/dist/utils/graphql-tag/collocated/types.js.map +1 -0
  30. package/dist/utils/graphql-tag/index.d.ts +5 -0
  31. package/dist/utils/graphql-tag/index.d.ts.map +1 -0
  32. package/dist/utils/graphql-tag/index.js +5 -0
  33. package/dist/utils/graphql-tag/index.js.map +1 -0
  34. package/dist/utils/jsonPath/guards.d.ts +1 -1
  35. package/dist/utils/jsonPath/index.d.ts +3 -3
  36. package/dist/utils/jsonPath/index.js +3 -3
  37. package/dist/utils/jsonPath/visitor.d.ts +2 -2
  38. package/dist/utils/jsonPath/visitor.js +3 -3
  39. package/dist/version.txt +1 -0
  40. package/nodemon.json +1 -1
  41. package/package.json +24 -11
  42. package/var/cache/schema.graphql +35655 -0
  43. package/.swcrc +0 -27
  44. package/example/data/__tests__/output.ts +0 -57
  45. package/example/data/data.ts +0 -226
  46. package/example/data/output.ts +0 -74
  47. package/example/data/types.ts +0 -92
  48. package/example/example.ts +0 -26
  49. package/example/jsonPaths.data.ts +0 -13
  50. package/example/loadSchema.ts +0 -32
  51. package/src/index.ts +0 -2
  52. package/src/parser/parseJsonPaths.ts +0 -136
  53. package/src/utils/graphql/index.ts +0 -51
  54. package/src/utils/jsonPath/guards.ts +0 -37
  55. package/src/utils/jsonPath/index.ts +0 -3
  56. package/src/utils/jsonPath/types.ts +0 -56
  57. package/src/utils/jsonPath/visitor.ts +0 -108
  58. package/src/utils/ts/helpers.ts +0 -13
@@ -1,136 +0,0 @@
1
- import { getNamedType, GraphQLSchema, isObjectType, isUnionType } from "graphql"
2
- import type { DocumentNode, GraphQLObjectType, GraphQLOutputType, SelectionSetNode, FragmentDefinitionNode, FieldNode, InlineFragmentNode } from "graphql"
3
-
4
- import { createFieldNode, createInlineFragment, findFieldNode, isPrimitiveType } from "~/utils/graphql"
5
- import { Kind } from "graphql"
6
- import * as JSONPath from '~/utils/jsonPath'
7
-
8
-
9
- type StackItem = {type: GraphQLOutputType, selectionSet: SelectionSetNode, parent: StackItem|null}
10
- const typeNameFieldNode = createFieldNode('__typename')
11
-
12
- export function parseJsonPaths(jsonPaths:Array<JSONPath.ASTNode[]>, rootType: GraphQLObjectType, fragmentName?: string): DocumentNode {
13
- fragmentName = fragmentName ?? `autoGen${rootType.name}`
14
-
15
- const rootFragment:FragmentDefinitionNode = {
16
- kind: Kind.FRAGMENT_DEFINITION,
17
- typeCondition: { kind: Kind.NAMED_TYPE, name: { kind: Kind.NAME, value: rootType.name } },
18
- name: { kind: Kind.NAME, value: fragmentName },
19
- selectionSet: {
20
- kind: Kind.SELECTION_SET,
21
- selections: [typeNameFieldNode],
22
- } satisfies SelectionSetNode,
23
- }
24
-
25
- const doc: DocumentNode = {
26
- kind: Kind.DOCUMENT,
27
- definitions: [rootFragment],
28
- }
29
- const stack: Array<StackItem[]> = []
30
- const visitor: JSONPath.NodeVisitor = {
31
- Root() {
32
- stack.push([{type: rootType, selectionSet: rootFragment.selectionSet!, parent: null}])
33
- return
34
- },
35
- Identifier(node) {
36
- const stackItems = stack[stack.length - 1]!
37
- const passStackItems = processStackItems(stackItems, {fieldName: node.expression.value!, value: undefined, condition: undefined})
38
- stack.push(passStackItems)
39
- return
40
- },
41
- FilterExpression(node) {
42
- const stackItems = stack[stack.length - 1]!
43
- const regex = /\?\(@\.(?<field>\w+)(\s*(?<condition>(?:==|!=)=?)\s*(?<quote>'|")(?<value>.*?)(\4))?/
44
- const matches = node.expression.value!.match(regex)
45
- const fieldName = matches?.groups?.field ?? '__typename'
46
- const condition = matches?.groups?.condition
47
- const value = matches?.groups?.value
48
- const passStackItems = processStackItems(stackItems, {fieldName, value, condition})
49
- stack.push(passStackItems)
50
- return
51
- },
52
- leave(node, parent, path, ancestors) {
53
- if(needProcess(node)) {
54
- stack.pop()
55
- }
56
- }
57
- }
58
- JSONPath.visit(jsonPaths, visitor)
59
- return doc
60
- }
61
-
62
- function needProcess(node:JSONPath.ASTNode):boolean {
63
- return JSONPath.isRootNode(node) || JSONPath.isIdentifierNode(node) || JSONPath.isFilterExpressionNode(node)
64
- }
65
-
66
-
67
-
68
-
69
- function processStackItems(stackItems: StackItem[], {fieldName, value, condition}: {fieldName: string, value?: string, condition?: string}) {
70
- const passStackItems: StackItem[] = []
71
- stackItems.forEach(stackItem => {
72
- const parentType = stackItem.type
73
- if(isPrimitiveType(parentType)) {
74
- return
75
- }
76
- const selSet = stackItem.selectionSet
77
- if (isUnionType(parentType)) {
78
- const filterField = (type: GraphQLObjectType) => fieldName === '__typename'? type.name === value : Boolean(type.getFields()[fieldName!])
79
- const filter = condition && !condition.includes('!')
80
- ? (type: GraphQLObjectType) => filterField(type)
81
- : (type: GraphQLObjectType) => !filterField(type)
82
- const possibleTypes = parentType.getTypes().filter(filter)
83
- possibleTypes.forEach(type => {
84
- let inlineFragment:InlineFragmentNode|undefined = selSet.selections.find(
85
- selection => selection.kind === Kind.INLINE_FRAGMENT
86
- && (selection.typeCondition?.name.value === type.name)
87
- ) as InlineFragmentNode|undefined
88
-
89
- if (!inlineFragment) {
90
- inlineFragment = createInlineFragment(type, '__typename')
91
- ;(selSet.selections as any[]).push(inlineFragment)
92
- }
93
- const fragmentStackItem = {type: type, selectionSet: inlineFragment.selectionSet!, parent: stackItem}
94
- const appendFieldType = type.getFields()[fieldName!]?.type
95
- if(!appendFieldType) {
96
- if (fieldName === '__typename') {
97
- passStackItems.push(fragmentStackItem)
98
- }
99
- return
100
- }
101
- const newStackItem = processGraphqlObjectType(fragmentStackItem, appendFieldType, fieldName!)
102
- passStackItems.push(newStackItem)
103
- })
104
- return;
105
- }
106
- const parentObjectType = isObjectType(parentType) ? parentType : stackItem.parent?.type as GraphQLObjectType|undefined
107
- if (!parentObjectType) return;
108
- const field = parentObjectType.getFields()[fieldName!]
109
- if(!field) {
110
- return
111
- }
112
- const newStackItem = processGraphqlObjectType(stackItem, field.type, fieldName!)
113
- passStackItems.push(newStackItem)
114
-
115
- })
116
- return passStackItems
117
- }
118
-
119
-
120
-
121
- function processGraphqlObjectType(stackItem: StackItem, fieldType: GraphQLOutputType, fieldName: string): StackItem {
122
- const selSet = stackItem.selectionSet
123
- if(!selSet){
124
- throw new Error('Selection set not found')
125
- }
126
- const realFieldType = getNamedType(fieldType)
127
- const subFieldsSelections = [isPrimitiveType(realFieldType) ? undefined : typeNameFieldNode].filter(Boolean) as FieldNode[]
128
- let fieldNode = findFieldNode(selSet, fieldName)
129
- if(!fieldNode) {
130
- fieldNode = createFieldNode(fieldName, subFieldsSelections.map(selection => selection.name.value!))
131
- ;(selSet.selections as any[]).push(fieldNode)
132
- }
133
- return {type: realFieldType, selectionSet: fieldNode.selectionSet!, parent: stackItem}
134
- }
135
-
136
-
@@ -1,51 +0,0 @@
1
- import { getNamedType, isScalarType, isEnumType, Kind } from "graphql"
2
- import type { GraphQLOutputType, SelectionSetNode, FieldNode, InlineFragmentNode, GraphQLNamedOutputType, SelectionNode } from "graphql"
3
-
4
-
5
- export function isPrimitiveType(type: GraphQLOutputType): boolean {
6
- const namedType = getNamedType(type)
7
- return isScalarType(namedType) || isEnumType(namedType)
8
- }
9
-
10
- export function findFieldNode(selectionSet: SelectionSetNode, fieldName: string):FieldNode|undefined {
11
- return selectionSet?.selections.find(selection => selection.kind === Kind.FIELD && selection.name.value === fieldName) as FieldNode|undefined
12
- }
13
-
14
-
15
- export function createFieldNode(fieldName: string, children?: string[]):FieldNode {
16
- let selectionSet: SelectionSetNode|undefined = undefined
17
- if(children?.length) {
18
- selectionSet = {
19
- kind: Kind.SELECTION_SET,
20
- selections: children.map(child => createFieldNode(child)),
21
- } satisfies SelectionSetNode
22
- }
23
- return {
24
- kind: Kind.FIELD,
25
- name: { kind: Kind.NAME, value: fieldName },
26
- selectionSet
27
- }
28
- }
29
-
30
-
31
-
32
- export function createFieldSelectionSet(outputType: GraphQLNamedOutputType, fieldName?: string):SelectionSetNode {
33
- const ret = {
34
- kind: Kind.SELECTION_SET,
35
- selections: [fieldName ? createFieldNode(fieldName): undefined].filter(Boolean) as SelectionNode[],
36
- } satisfies SelectionSetNode
37
-
38
- if (!isPrimitiveType(outputType) && !ret.selections.find(selection => selection.kind === Kind.FIELD && selection.name.value === '__typename')) {
39
- ret.selections.unshift(createFieldNode('__typename'))
40
- }
41
- return ret
42
- }
43
-
44
-
45
- export function createInlineFragment(outputType: GraphQLNamedOutputType, fieldName: string):InlineFragmentNode {
46
- return {
47
- kind: Kind.INLINE_FRAGMENT,
48
- typeCondition: { kind: Kind.NAMED_TYPE, name: { kind: Kind.NAME, value: outputType.name } },
49
- selectionSet: createFieldSelectionSet(outputType, fieldName),
50
- } satisfies InlineFragmentNode
51
- }
@@ -1,37 +0,0 @@
1
-
2
- import type { BaseNode, IdentifierNode, ASTNode, NumericLiteralNode, FilterExpressionNode, ScriptExpressionNode, StringLiteralNode, WildcardNode, SliceNode, RootNode } from "./types"
3
-
4
- export function isAstNode(node: unknown): node is ASTNode {
5
- return typeof node === 'object' && node !== null && 'expression' in node && typeof node.expression === 'object' && node.expression !== null && 'type' in node.expression && typeof node.expression.type === 'string'
6
- }
7
- export function isBaseNode(node: ASTNode): node is BaseNode {
8
- return isAstNode(node) && 'operation' in node && typeof node.operation === 'string' && 'scope' in node && typeof node.scope === 'string'
9
- }
10
- export function isIdentifierNode(node: ASTNode): node is IdentifierNode {
11
- return isBaseNode(node) && node.operation === 'member' && node.expression.type === 'identifier'
12
- }
13
- export function isNumericLiteralNode(node: ASTNode): node is NumericLiteralNode {
14
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'numeric_literal'
15
- }
16
- export function isFilterExpressionNode(node: ASTNode): node is FilterExpressionNode {
17
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'filter_expression'
18
- }
19
- export function isScriptExpressionNode(node: ASTNode): node is ScriptExpressionNode {
20
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'script_expression'
21
- }
22
- export function isStringLiteralNode(node: ASTNode): node is StringLiteralNode {
23
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'string_literal'
24
- }
25
- export function isWildcardNode(node: ASTNode): node is WildcardNode {
26
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'wildcard'
27
- }
28
- export function isSliceNode(node: ASTNode): node is SliceNode {
29
- return isBaseNode(node) && node.operation === 'subscript' && node.expression.type === 'slice'
30
- }
31
- export function isRootNode(node: ASTNode): node is RootNode {
32
- return isAstNode(node) && node.expression.type === 'root' && node.expression.value === '$'
33
- }
34
-
35
- export function isJSONPath(nodes: unknown): nodes is ASTNode[] {
36
- return Array.isArray(nodes) && nodes.every(node => isAstNode(node))
37
- }
@@ -1,3 +0,0 @@
1
- export * from './types'
2
- export * from './guards'
3
- export * from './visitor'
@@ -1,56 +0,0 @@
1
- export interface ASTNode {
2
- expression: Expression
3
- }
4
-
5
- export type ExpressionType = 'root' | 'identifier' | 'numeric_literal' | 'filter_expression' | 'script_expression' | 'string_literal' | 'wildcard' | 'slice'
6
- export type ExpressionValue = string | number | undefined
7
-
8
- interface BuildExpression<T extends ExpressionType = ExpressionType, V extends ExpressionValue = ExpressionValue> {
9
- type: T
10
- value: V
11
- }
12
- /** expression types */
13
- export type Expression = BuildExpression<ExpressionType, ExpressionValue>
14
- export type RootExpression = BuildExpression<'root', '$'>
15
- export type IdentifierExpression = BuildExpression<'identifier', string>
16
- export type NumericLiteralExpression = BuildExpression<'numeric_literal', number>
17
- export type FilterExpressionExpression = BuildExpression<'filter_expression', `?(${string})`>
18
- export type ScriptExpressionExpression = BuildExpression<'script_expression', string>
19
- export type StringLiteralExpression = BuildExpression<'string_literal', string>
20
- export type WildcardExpression = BuildExpression<'wildcard', '*'>
21
- export type SliceExpression = BuildExpression<'slice', `${number|''}:${number|''}`>
22
-
23
- /** node types */
24
- export interface RootNode extends ASTNode {
25
- expression: RootExpression
26
- }
27
- export interface BaseNode<T extends 'member' | 'subscript' = 'member'|'subscript'> extends ASTNode {
28
- operation: T
29
- scope: 'child' | 'descendant' | 'parent'
30
- }
31
- export interface IdentifierNode extends BaseNode<'member'> {
32
- expression: IdentifierExpression
33
- }
34
- export interface NumericLiteralNode extends BaseNode<'subscript'> {
35
- expression: NumericLiteralExpression
36
- }
37
- export interface FilterExpressionNode extends BaseNode<'subscript'> {
38
- expression: FilterExpressionExpression
39
- }
40
- export interface ScriptExpressionNode extends BaseNode<'subscript'> {
41
- expression: ScriptExpressionExpression
42
- }
43
- export interface StringLiteralNode extends BaseNode<'subscript'> {
44
- expression: StringLiteralExpression
45
- }
46
- export interface WildcardNode extends BaseNode<'subscript'> {
47
- expression: WildcardExpression
48
- }
49
- export interface SliceNode extends BaseNode<'subscript'> {
50
- expression: SliceExpression
51
- }
52
-
53
-
54
-
55
-
56
-
@@ -1,108 +0,0 @@
1
- import type { ASTNode, ExpressionType, RootNode, IdentifierNode, NumericLiteralNode, FilterExpressionNode, ScriptExpressionNode, StringLiteralNode, WildcardNode, SliceNode } from "./types"
2
- import { isJSONPath } from "./guards"
3
- import { isAstNode } from "./guards"
4
- import { snakeToPascalCase, type SnakeToPascalCase } from "~/utils/ts/helpers"
5
-
6
- export const BREAK = Symbol('BREAK')
7
-
8
- type Kind = {
9
- root: RootNode
10
- identifier: IdentifierNode
11
- numeric_literal: NumericLiteralNode
12
- filter_expression: FilterExpressionNode
13
- script_expression: ScriptExpressionNode
14
- string_literal: StringLiteralNode
15
- wildcard: WildcardNode
16
- slice: SliceNode
17
- }
18
-
19
-
20
- /** visitor types */
21
- export type VisitorFn = (node: ASTNode, parent: ASTNode|null, index: Array<number>, ancestors: ASTNode[]) => ASTNode|typeof BREAK|undefined|null|void
22
- export type TypedVisitorFn<T extends ExpressionType = ExpressionType> = (node: Kind[T], parent: ASTNode|null, index: Array<number>, ancestors: ASTNode[]) => ASTNode|typeof BREAK|undefined|null|void
23
- export interface IVisitor {
24
- enter?:VisitorFn;
25
- leave?:VisitorFn;
26
- }
27
- export type NodeVisitor = {
28
- [T in ExpressionType as `${'leave' | ''}${SnakeToPascalCase<T>}`]?: TypedVisitorFn<T>;
29
- } & IVisitor
30
-
31
- function doVisit(nodes: ASTNode[]|Array<ASTNode[]>, visitor: IVisitor):void {
32
- if (isJSONPath(nodes)){
33
- nodes = [nodes]
34
- }
35
- for (const jsonPath of nodes) {
36
- let parent: ASTNode|null = null
37
- let ancestors: ASTNode[] = []
38
- let path: Array<number> = []
39
- for (let i = 0; i < jsonPath.length; i++) {
40
- const _node = jsonPath[i]!
41
- let node: ASTNode = _node
42
- path.push(i)
43
- const enterResult = visitor.enter?.(node, parent, path, ancestors)
44
- if(enterResult === BREAK) {
45
- break
46
- }
47
- if(isAstNode(enterResult)) {
48
- node = enterResult
49
- }
50
- parent = node
51
- ancestors.push(node)
52
- jsonPath[i] = node
53
- }
54
- parent = ancestors.pop() ?? null
55
- path.pop()
56
- for (let i = jsonPath.length - 1; i >= 0; i--) {
57
- const _node = jsonPath[i]!
58
- let node: ASTNode = _node
59
- parent = ancestors.pop() ?? null
60
- path.pop()
61
- const leaveResult = visitor.leave?.(node, parent, path, ancestors)
62
- if(leaveResult === BREAK) {
63
- break;
64
- }
65
- if(isAstNode(leaveResult)) {
66
- node = leaveResult
67
- }
68
- jsonPath[i] = node
69
- }
70
- }
71
- }
72
-
73
-
74
- function makeVisitor(visitor: NodeVisitor): IVisitor {
75
- const visitorCall = function (type:'enter'|'leave', ...[node, ...rest]: Parameters<TypedVisitorFn>): ReturnType<TypedVisitorFn> {
76
- let result: ReturnType<TypedVisitorFn>
77
- //call leave node method
78
- if (type === 'leave') {
79
- const methodName = `${type}${snakeToPascalCase(node.expression.type) as SnakeToPascalCase<ExpressionType>}` as keyof NodeVisitor
80
- result = visitor[methodName]?.(node as any,...rest)
81
- if(result === BREAK) {
82
- return result
83
- }
84
- }
85
- //call original visitor
86
- if (type in visitor) {
87
- result = (visitor as IVisitor)[type as keyof IVisitor]?.(node, ...rest)
88
- if(result === BREAK) {
89
- return result
90
- }
91
- }
92
- //call enter enter node method
93
- if (type === 'enter') {
94
- const methodName = `${snakeToPascalCase(node.expression.type) as SnakeToPascalCase<ExpressionType>}` as keyof NodeVisitor
95
- result = visitor[methodName]?.(node as any,...rest)
96
- }
97
- return result
98
- }
99
- const result: IVisitor = {
100
- enter: visitorCall.bind(null, 'enter') as VisitorFn,
101
- leave: visitorCall.bind(null, 'leave') as VisitorFn,
102
- }
103
- return result
104
- }
105
-
106
- export function visit(nodes: ASTNode[]|Array<ASTNode[]>, visitor: NodeVisitor):void{
107
- doVisit(nodes, makeVisitor(visitor))
108
- }
@@ -1,13 +0,0 @@
1
- export type SnakeToCamelCase<S extends string> = S extends `${infer T}_${infer U}` ?
2
- `${T}${Capitalize<SnakeToCamelCase<U>>}` : S
3
- export type SnakeToPascalCase<S extends string> = Capitalize<SnakeToCamelCase<S>>
4
-
5
-
6
- export function snakeToCamelCase(str: string): SnakeToCamelCase<string>
7
- {
8
- return str.split('_').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('') as SnakeToCamelCase<string>
9
- }
10
- export function snakeToPascalCase(str: string): SnakeToPascalCase<string>
11
- {
12
- return snakeToCamelCase(str).charAt(0).toUpperCase() + snakeToCamelCase(str).slice(1) as SnakeToPascalCase<string>
13
- }