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

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 (90) hide show
  1. package/index.d.ts +2 -0
  2. package/index.js +2 -0
  3. package/mad-data-parser-0.0.2-beta.11.tgz +0 -0
  4. package/package.json +14 -38
  5. package/parser/parseJsonPaths.d.ts +12 -0
  6. package/parser/parseJsonPaths.d.ts.map +1 -0
  7. package/parser/parseJsonPaths.js +161 -0
  8. package/parser/parseJsonPaths.js.map +1 -0
  9. package/{dist/utils → utils}/graphql/index.d.ts +2 -2
  10. package/utils/graphql/index.d.ts.map +1 -0
  11. package/{dist/utils → utils}/graphql/index.js +2 -1
  12. package/utils/graphql/index.js.map +1 -0
  13. package/utils/graphql-tag/collocated/gql.d.ts +47 -0
  14. package/utils/graphql-tag/collocated/gql.d.ts.map +1 -0
  15. package/utils/graphql-tag/collocated/gql.js +133 -0
  16. package/utils/graphql-tag/collocated/gql.js.map +1 -0
  17. package/utils/graphql-tag/collocated/guards.d.ts +4 -0
  18. package/utils/graphql-tag/collocated/guards.d.ts.map +1 -0
  19. package/utils/graphql-tag/collocated/guards.js +13 -0
  20. package/utils/graphql-tag/collocated/guards.js.map +1 -0
  21. package/utils/graphql-tag/collocated/stringifyDocument.d.ts +2 -0
  22. package/utils/graphql-tag/collocated/stringifyDocument.d.ts.map +1 -0
  23. package/utils/graphql-tag/collocated/stringifyDocument.js +38 -0
  24. package/utils/graphql-tag/collocated/stringifyDocument.js.map +1 -0
  25. package/utils/graphql-tag/collocated/types.d.ts +19 -0
  26. package/utils/graphql-tag/collocated/types.d.ts.map +1 -0
  27. package/utils/graphql-tag/collocated/types.js.map +1 -0
  28. package/utils/graphql-tag/index.d.ts +5 -0
  29. package/utils/graphql-tag/index.d.ts.map +1 -0
  30. package/utils/graphql-tag/index.js +5 -0
  31. package/utils/graphql-tag/index.js.map +1 -0
  32. package/{dist/utils → utils}/jsonPath/guards.d.ts +1 -1
  33. package/utils/jsonPath/index.d.ts +4 -0
  34. package/utils/jsonPath/index.js +4 -0
  35. package/utils/jsonPath/types.js +2 -0
  36. package/{dist/utils → utils}/jsonPath/visitor.d.ts +2 -2
  37. package/{dist/utils → utils}/jsonPath/visitor.js +3 -3
  38. package/version.txt +1 -0
  39. package/.env.example +0 -0
  40. package/.swcrc +0 -27
  41. package/dist/index.d.ts +0 -2
  42. package/dist/index.js +0 -2
  43. package/dist/parser/parseJsonPaths.d.ts +0 -4
  44. package/dist/parser/parseJsonPaths.d.ts.map +0 -1
  45. package/dist/parser/parseJsonPaths.js +0 -116
  46. package/dist/parser/parseJsonPaths.js.map +0 -1
  47. package/dist/utils/graphql/index.d.ts.map +0 -1
  48. package/dist/utils/graphql/index.js.map +0 -1
  49. package/dist/utils/jsonPath/index.d.ts +0 -4
  50. package/dist/utils/jsonPath/index.js +0 -4
  51. package/example/data/__tests__/output.ts +0 -57
  52. package/example/data/data.ts +0 -226
  53. package/example/data/output.ts +0 -74
  54. package/example/data/types.ts +0 -92
  55. package/example/example.ts +0 -26
  56. package/example/jsonPaths.data.ts +0 -13
  57. package/example/loadSchema.ts +0 -32
  58. package/jest.config.d.ts +0 -6
  59. package/jest.config.ts +0 -241
  60. package/nodemon.json +0 -27
  61. package/register.setup.jest.d.ts +0 -2
  62. package/register.setup.jest.ts +0 -19
  63. package/src/index.ts +0 -2
  64. package/src/parser/parseJsonPaths.ts +0 -136
  65. package/src/utils/graphql/index.ts +0 -51
  66. package/src/utils/jsonPath/guards.ts +0 -37
  67. package/src/utils/jsonPath/index.ts +0 -3
  68. package/src/utils/jsonPath/types.ts +0 -56
  69. package/src/utils/jsonPath/visitor.ts +0 -108
  70. package/src/utils/ts/helpers.ts +0 -13
  71. package/tsconfig.build.json +0 -19
  72. package/tsconfig.jest.json +0 -18
  73. package/tsconfig.json +0 -36
  74. /package/{dist/index.d.ts.map → index.d.ts.map} +0 -0
  75. /package/{dist/index.js.map → index.js.map} +0 -0
  76. /package/{dist/utils/jsonPath → utils/graphql-tag/collocated}/types.js +0 -0
  77. /package/{dist/utils → utils}/jsonPath/guards.d.ts.map +0 -0
  78. /package/{dist/utils → utils}/jsonPath/guards.js +0 -0
  79. /package/{dist/utils → utils}/jsonPath/guards.js.map +0 -0
  80. /package/{dist/utils → utils}/jsonPath/index.d.ts.map +0 -0
  81. /package/{dist/utils → utils}/jsonPath/index.js.map +0 -0
  82. /package/{dist/utils → utils}/jsonPath/types.d.ts +0 -0
  83. /package/{dist/utils → utils}/jsonPath/types.d.ts.map +0 -0
  84. /package/{dist/utils → utils}/jsonPath/types.js.map +0 -0
  85. /package/{dist/utils → utils}/jsonPath/visitor.d.ts.map +0 -0
  86. /package/{dist/utils → utils}/jsonPath/visitor.js.map +0 -0
  87. /package/{dist/utils → utils}/ts/helpers.d.ts +0 -0
  88. /package/{dist/utils → utils}/ts/helpers.d.ts.map +0 -0
  89. /package/{dist/utils → utils}/ts/helpers.js +0 -0
  90. /package/{dist/utils → utils}/ts/helpers.js.map +0 -0
@@ -1,92 +0,0 @@
1
-
2
-
3
-
4
-
5
- export type TableCellTypeT = 'text' | 'link' | 'currency' | 'number' | 'cta' | 'cta_secondary' | 'stock' | 'swatch' | 'icon' | 'image' | 'date'
6
- export type TableColumnSizeT = 'auto' | '80' | '92' | '100' | '120'
7
- export type TableColumnAlignT = 'left' | 'right' | 'center'
8
- export type TableColumnSortT = 'asc' | 'desc' | null
9
- export type UiStatusCode = 'INS' | 'LOW' | 'INT' | 'ARS' | 'MTO' | 'PRE'
10
- export type UiStampStatusT = 'Preview' | 'Limited' | 'New' | 'Updated' | 'Discontinued' | 'Unavailable' | 'Run-Out' | 'Seconds'
11
-
12
-
13
-
14
- export type OutputFormatTypeT = 'string' | 'unit' | 'currency' | 'date' | 'number' | 'media' //| 'date-distance'
15
- export type StringFormatTypeT = 'text' | 'html' | 'markdown'
16
- export type MediaFormatTypeT = 'images' | 'videos' | 'documents'
17
-
18
- export type CurrencyFormatTypeT = 'currency_01' | 'currency_02' | 'currency_03' | 'currency_04' | 'currency_05' | 'currency_06' | 'currency_07'
19
- export type DateFormatTypeT = 'iso_8601' | 'date_02' | 'date_03' | 'date_04' | 'date_05' | 'store_config'
20
- export type MediaAspectT = 'screen' | 'landscape_plus' | 'landscape' | 'square' | 'portrait_plus' | 'portrait' | 'banner' | 'original' | 'auto'
21
- export type SizeT = 'small' | 'medium' | 'large'
22
-
23
- interface DataSettingOutput {
24
- __typename: 'DataSettingOutput'
25
- type: OutputFormatTypeT
26
- fallback?: string
27
- stringFormat?: StringFormatTypeT
28
- mediaType?: MediaFormatTypeT
29
- aspectRatio?: MediaAspectT
30
- size?: SizeT
31
- unitSuffix?: string
32
- decimals?: number
33
- imperial?: boolean
34
- conversionFormula?: number
35
- unitSuffixImperial?: string
36
- decimalsImperial?: number
37
- currencyFormat?: CurrencyFormatTypeT
38
- dateFormat?: DateFormatTypeT
39
- }
40
-
41
- export type DataValue = string | number | Date | null | undefined
42
-
43
- export interface CellConfig {
44
- value: DataValue
45
- type?: TableCellTypeT
46
- swatch?: string
47
- icon?: string // Presence implies type: 'icon'
48
- stock?: UiStatusCode // Presence implies type: 'stock'
49
- status?: UiStampStatusT
50
- subheading?: boolean
51
- bold?: boolean
52
- imgSource?: string // Presence implies type: 'image'
53
- wrap?: boolean
54
- }
55
-
56
- export type CellValue = DataValue | CellConfig
57
-
58
- export interface TableColumn {
59
- label: string
60
- key: string
61
- align?: TableColumnAlignT
62
- sort?: TableColumnSortT
63
- type?: TableCellTypeT
64
- bold?: boolean
65
- wrap?: boolean
66
- columnSize?: TableColumnSizeT
67
- imgSource?: string
68
- outputFormat?: DataSettingOutput
69
- }
70
-
71
-
72
-
73
-
74
-
75
-
76
- export interface TableRow extends Record<string, CellValue> {
77
- id: string
78
- }
79
- export interface TableValues {
80
- subheading?: string | CellConfig
81
- rows: TableRow[]
82
- }
83
-
84
-
85
- export function isCellConfig(cell?: CellValue): cell is CellConfig {
86
- return typeof cell === 'object' && !!cell && 'value' in cell
87
- }
88
-
89
- export interface DataTable {
90
- columns: TableColumn[]
91
- values: TableValues[]
92
- }
@@ -1,26 +0,0 @@
1
-
2
- import {
3
-
4
- type GraphQLObjectType,
5
- print,
6
- } from 'graphql'
7
- import jp from 'jsonpath'
8
- import { loadRemoteSchema } from './loadSchema'
9
- import * as JSONPath from '../src/utils/jsonPath'
10
-
11
- import { parseJsonPaths } from '../src/parser/parseJsonPaths'
12
- import { jsonPathsData } from './jsonPaths.data'
13
- async function main() {
14
- const jsonPaths: Array<JSONPath.ASTNode[]> = jsonPathsData.map(jp.parse.bind(jp))
15
- const schema = await loadRemoteSchema({
16
- authToken: process.env.GRAPHQL_AUTH_TOKEN ,
17
- endpoint: process.env.GRAPHQL_ENDPOINT ?? '',
18
- })
19
- const rootType = schema.getType('PageProduct') as GraphQLObjectType
20
- const doc = parseJsonPaths(jsonPaths, rootType)
21
-
22
- console.log(print(doc))
23
- }
24
-
25
-
26
- void main()
@@ -1,13 +0,0 @@
1
- export const jsonPathsData = [
2
- '$.bundles[0].products[?(@.__typename == "PageProduct")].configPageInfo[-1:].internalName',
3
- '$.bundles[0].products[?(@.__typename == "PageProduct")].configPageInfo[*].mediaStudio',
4
- '$.bundles[0].products[?(@.__typename == "PageProduct")].configPageInfo[*].mediaStudio.metaproperties.nodes[?(@.name=="Asset_Type_1")].options[*].displayLabel',
5
- '$.modelSpecs[0].efficiency',
6
- '$.bundles[0].products[?(@.__typename == "PageProduct")].configPageInfo[0].mediaStudio.metaproperties.nodes[?(@.name=="Asset_Type_1")].options[*].displayLabel',
7
- '$.bundles[0].products[?(@.__typename == "PageProduct")].configPageInfo[1].mediaStudio.metaproperties.nodes[?(@.name=="Asset_Type_1")].options[*].displayLabel',
8
- '$.availableOn[*]',
9
- '$.modelSpecs[*].efficiency[?(@.__typename == "ContentDisclaimer")].disclaimer.raw',
10
- '$.modelSpecs[0].efficiency[?(@.__typename == "SpecEfficiency")].efficiency[0].burnerModel[?(@.__typename == "SpecEfficiencyEthanol")].burnTimeMax',
11
- "$.configPageInfo[?(@.internalName == 'foo')].internalName",
12
- '$.modelSpecs[0].efficiency[?(@.disclaimer === "foo")]'
13
- ]
@@ -1,32 +0,0 @@
1
- import { loadSchema, type LoadSchemaOptions } from '@graphql-tools/load'
2
- import { UrlLoader, type LoadFromUrlOptions } from '@graphql-tools/url-loader'
3
- import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
4
- import { printSchema } from 'graphql'
5
- import fs from 'fs'
6
-
7
- export async function loadRemoteSchema(options: {
8
- authToken?: string,
9
- endpoint: string,
10
- }) {
11
- const graphqlFile = process.cwd() + '/var/cache/schema.graphql'
12
- if(fs.existsSync(graphqlFile)) {
13
- const schema = await loadSchema(graphqlFile, { loaders: [new GraphQLFileLoader()] })
14
- return schema
15
- }
16
-
17
-
18
- const { authToken, endpoint } = options;
19
- const urlLoader = new UrlLoader()
20
- const initOpts: LoadFromUrlOptions & LoadSchemaOptions = {
21
- assumeValidSDL: true,
22
- assumeValid: true,
23
- noLocation: true,
24
- noSource: true,
25
- loaders: [urlLoader],
26
- // maxTokens: 1e3,
27
- // handleAsSDL: false,
28
- }
29
- const schema = await loadSchema(endpoint, initOpts)
30
- fs.writeFileSync(graphqlFile, printSchema(schema))
31
- return schema
32
- }
package/jest.config.d.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * For a detailed explanation regarding each configuration property, visit:
3
- * https://jestjs.io/docs/configuration
4
- */
5
- export {};
6
- //# sourceMappingURL=jest.config.d.ts.map
package/jest.config.ts DELETED
@@ -1,241 +0,0 @@
1
- /**
2
- * For a detailed explanation regarding each configuration property, visit:
3
- * https://jestjs.io/docs/configuration
4
- */
5
-
6
- const fs = require('node:fs')
7
- const { pathsToModuleNameMapper } = require('ts-jest')
8
- const JSON5 = require('json5')
9
-
10
-
11
- const jsonData = fs.readFileSync('./tsconfig.jest.json')
12
- const jscConfig = JSON5.parse(fs.readFileSync('./.swcrc').toString('utf-8'))
13
- const { compilerOptions } = JSON5.parse(jsonData.toString('utf-8'))
14
-
15
- const config = {
16
- // All imported modules in your tests should be mocked automatically
17
- // automock: false,
18
-
19
- // Stop running tests after `n` failures
20
- // bail: 0,
21
-
22
- // The directory where Jest should store its cached dependency information
23
- // cacheDirectory: "/tmp/jest_rs",
24
-
25
- // Automatically clear mock calls, instances, contexts and results before every test
26
- clearMocks: true,
27
-
28
- // Indicates whether the coverage information should be collected while executing the test
29
- collectCoverage: true,
30
-
31
- // An array of glob patterns indicating a set of files for which coverage information should be collected
32
- // collectCoverageFrom: undefined,
33
-
34
- // The directory where Jest should output its coverage files
35
- coverageDirectory: 'coverage',
36
-
37
- // An array of regexp pattern strings used to skip coverage collection
38
- coveragePathIgnorePatterns: [
39
- "/node_modules/",
40
-
41
- ],
42
-
43
- // Indicates which provider should be used to instrument code for coverage
44
- coverageProvider: 'v8',
45
-
46
- // A list of reporter names that Jest uses when writing coverage reports
47
- // coverageReporters: [
48
- // "json",
49
- // "text",
50
- // "lcov",
51
- // "clover"
52
- // ],
53
-
54
- // An object that configures minimum threshold enforcement for coverage results
55
- // coverageThreshold: undefined,
56
-
57
- // A path to a custom dependency extractor
58
- // dependencyExtractor: undefined,
59
-
60
- // Make calling deprecated APIs throw helpful error messages
61
- // errorOnDeprecated: false,
62
-
63
- // The default configuration for fake timers
64
- // fakeTimers: {
65
- // "enableGlobally": false
66
- // },
67
-
68
- // Force coverage collection from ignored files using an array of glob patterns
69
- // forceCoverageMatch: [],
70
-
71
- // A path to a module which exports an async function that is triggered once before all test suites
72
- // globalSetup: undefined,
73
-
74
- // A path to a module which exports an async function that is triggered once after all test suites
75
- // globalTeardown: undefined,
76
-
77
- // A set of global variables that need to be available in all test environments
78
- globals: {
79
-
80
- },
81
- transform: {
82
- // '^.+\\.tsx?$': ['ts-jest', {
83
- // // babel: true,
84
- // tsconfig: 'tsconfig.jest.json',
85
- // }],
86
- '^.+\\.(t|j)sx?$': ['@swc/jest',
87
- jscConfig
88
- ]
89
-
90
- },
91
-
92
- testEnvironment: 'node',
93
-
94
- // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
95
- // maxWorkers: "50%",
96
-
97
- // An array of directory names to be searched recursively up from the requiring module's location
98
- // moduleDirectories: [
99
- // "node_modules"
100
- // ],
101
-
102
- // An array of file extensions your modules use
103
- // moduleFileExtensions: [
104
- // "js",
105
- // "mjs",
106
- // "cjs",
107
- // "jsx",
108
- // "ts",
109
- // "tsx",
110
- // "json",
111
- // "node"
112
- // ],
113
-
114
- // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
115
- moduleNameMapper: {
116
- ...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
117
- '^~/(.*)$': '<rootDir>/src/$1',
118
- },
119
-
120
- // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
121
- // modulePathIgnorePatterns: [],
122
-
123
- // Activates notifications for test results
124
- notify: true,
125
-
126
- // An enum that specifies notification mode. Requires { notify: true }
127
- notifyMode: 'failure',
128
-
129
- // A preset that is used as a base for Jest's configuration
130
- preset: 'ts-jest',
131
-
132
- // Run tests from one or more projects
133
- // projects: undefined,
134
-
135
- // Use this configuration option to add custom reporters to Jest
136
- // reporters: undefined,
137
- reporters: [
138
- 'default',
139
- [
140
- '@jest-performance-reporter/core',
141
- {
142
- errorAfterMs: 1000,
143
- warnAfterMs: 50,
144
- logLevel: 'warn',
145
- maxItems: 1,
146
- // "jsonReportPath": "performance-report.json",
147
- // "csvReportPath": "performance-report.csv"
148
- },
149
- ],
150
- ],
151
-
152
- // Automatically reset mock state before every test
153
- // resetMocks: false,
154
-
155
- // Reset the module registry before running each individual test
156
- // resetModules: false,
157
-
158
- // A path to a custom resolver
159
- // resolver: undefined,
160
-
161
- // Automatically restore mock state and implementation before every test
162
- // restoreMocks: false,
163
-
164
- // The root directory that Jest should scan for tests and modules within
165
- rootDir: './',
166
-
167
- // A list of paths to directories that Jest should use to search for files in
168
- // roots: [
169
- // "<rootDir>"
170
- // ],
171
-
172
- // Allows you to use a custom runner instead of Jest's default test runner
173
- // runner: "jest-runner",
174
-
175
- // The paths to modules that run some code to configure or set up the testing environment before each test
176
- setupFiles: [
177
- "./register.setup.jest.ts"
178
- ],
179
-
180
- // A list of paths to modules that run some code to configure or set up the testing framework before each test
181
- // setupFilesAfterEnv: [],
182
-
183
- // The number of seconds after which a test is considered as slow and reported as such in the results.
184
- // slowTestThreshold: 5,
185
-
186
- // A list of paths to snapshot serializer modules Jest should use for snapshot testing
187
- // snapshotSerializers: [],
188
-
189
- // The test environment that will be used for testing
190
- // testEnvironment: "jest-environment-node",
191
-
192
- // Options that will be passed to the testEnvironment
193
- // testEnvironmentOptions: {},
194
-
195
- // Adds a location field to test results
196
- // testLocationInResults: false,
197
-
198
- // The glob patterns Jest uses to detect test files
199
- testMatch: [
200
- "**/src/**/__tests__/**/*.[jt]s?(x)",
201
- "**/src/**/?(*.)+(spec|test).[tj]s?(x)"
202
- ],
203
-
204
- // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
205
- testPathIgnorePatterns: [
206
- '/node_modules/',
207
- '/dist/',
208
- ],
209
-
210
- // The regexp pattern or array of patterns that Jest uses to detect test files
211
- // testRegex: [],
212
-
213
- // This option allows the use of a custom results processor
214
- // testResultsProcessor: undefined,
215
-
216
- // This option allows use of a custom test runner
217
- // testRunner: "jest-circus/runner",
218
-
219
- // A map from regular expressions to paths to transformers
220
- // transform: undefined,
221
-
222
- // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
223
- transformIgnorePatterns: [
224
- '/node_modules/',
225
- '\\.pnp\\.[^\\/]+$',
226
- ],
227
-
228
- // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
229
- // unmockedModulePathPatterns: undefined,
230
-
231
- // Indicates whether each individual test should be reported during the run
232
- // verbose: undefined,
233
-
234
- // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
235
- // watchPathIgnorePatterns: [],
236
-
237
- // Whether to use watchman for file crawling
238
- // watchman: true,
239
- }
240
-
241
- module.exports = config
package/nodemon.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "verbose": false,
3
- "ignore": [
4
- ".git",
5
- "node_modules",
6
- "./.*",
7
- "./var/**/*",
8
- "./docker-compose/**"
9
- ],
10
- "watch": [
11
- "**/*"
12
- ],
13
- "ext": "js ts gql",
14
- "signal": "SIGQUIT",
15
- "execMap": {
16
- "ts": "NODE_ENV=${NODE_ENV:-development} NODE_OPTIONS='--max-http-header-size=65535' UWS_HTTP_MAX_HEADERS_SIZE=65535 tsx --trace-warnings --trace-uncaught"
17
-
18
- },
19
- "spawn": false,
20
- "delay": "200",
21
- "legacyWatch": false,
22
-
23
- "events": {
24
-
25
- }
26
-
27
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=register.setup.jest.d.ts.map
@@ -1,19 +0,0 @@
1
-
2
- // import {jest} from '@jest/globals'
3
-
4
- import path from 'path'
5
-
6
-
7
-
8
-
9
- import glob from 'fast-glob'
10
- // jest.mock('~/config/AWS')
11
-
12
-
13
-
14
-
15
-
16
- glob.sync('src/**/__mock__/**/*.ts', {cwd: process.cwd()}).forEach(file => {
17
- require(path.join(process.cwd(), file))
18
- })
19
-
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from '~/parser/parseJsonPaths'
2
-
@@ -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
- }