@memberjunction/server 3.0.0 → 3.1.0

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 (34) hide show
  1. package/dist/config.d.ts +16 -0
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +3 -3
  4. package/dist/config.js.map +1 -1
  5. package/dist/generated/generated.d.ts +481 -4
  6. package/dist/generated/generated.d.ts.map +1 -1
  7. package/dist/generated/generated.js +3304 -334
  8. package/dist/generated/generated.js.map +1 -1
  9. package/dist/generic/ResolverBase.d.ts.map +1 -1
  10. package/dist/generic/ResolverBase.js +5 -2
  11. package/dist/generic/ResolverBase.js.map +1 -1
  12. package/dist/generic/RunViewResolver.d.ts +5 -0
  13. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  14. package/dist/generic/RunViewResolver.js +53 -4
  15. package/dist/generic/RunViewResolver.js.map +1 -1
  16. package/dist/resolvers/RunTestResolver.d.ts +2 -2
  17. package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
  18. package/dist/resolvers/RunTestResolver.js +33 -11
  19. package/dist/resolvers/RunTestResolver.js.map +1 -1
  20. package/package.json +51 -45
  21. package/src/__tests__/setup.ts +21 -0
  22. package/src/config.ts +3 -3
  23. package/src/generated/generated.ts +1894 -21
  24. package/src/generic/ResolverBase.ts +6 -2
  25. package/src/generic/RunViewResolver.ts +55 -5
  26. package/src/resolvers/RunTestResolver.ts +25 -0
  27. package/dist/apolloServer/TransactionPlugin.d.ts +0 -4
  28. package/dist/apolloServer/TransactionPlugin.d.ts.map +0 -1
  29. package/dist/apolloServer/TransactionPlugin.js +0 -46
  30. package/dist/apolloServer/TransactionPlugin.js.map +0 -1
  31. package/dist/auth/__tests__/backward-compatibility.test.d.ts +0 -2
  32. package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +0 -1
  33. package/dist/auth/__tests__/backward-compatibility.test.js +0 -135
  34. package/dist/auth/__tests__/backward-compatibility.test.js.map +0 -1
@@ -891,8 +891,12 @@ export class ResolverBase {
891
891
  // MapFieldNamesToCodeNames now handles encryption filtering as well
892
892
  return await this.MapFieldNamesToCodeNames(entityName, entityObject.GetAll(), contextUser);
893
893
  }
894
- // save failed, return null
895
- else throw entityObject.LatestResult?.Message;
894
+ // save failed, throw error with message
895
+ else {
896
+ throw new GraphQLError(entityObject.LatestResult?.CompleteMessage ?? 'Unknown error creating record', {
897
+ extensions: { code: 'CREATE_ENTITY_ERROR', entityName },
898
+ });
899
+ }
896
900
  } else return null;
897
901
  }
898
902
 
@@ -409,24 +409,43 @@ export class RunViewWithCacheCheckInput {
409
409
  cacheStatus?: RunViewCacheStatusInput;
410
410
  }
411
411
 
412
+ @ObjectType()
413
+ export class DifferentialDataOutput {
414
+ @Field(() => [RunViewGenericResultRow], {
415
+ description: 'Records that have been created or updated since the client\'s maxUpdatedAt'
416
+ })
417
+ updatedRows: RunViewGenericResultRow[];
418
+
419
+ @Field(() => [String], {
420
+ description: 'Primary key values (as concatenated strings) of records that have been deleted'
421
+ })
422
+ deletedRecordIDs: string[];
423
+ }
424
+
412
425
  @ObjectType()
413
426
  export class RunViewWithCacheCheckResultOutput {
414
427
  @Field(() => Int, { description: 'The index of this view in the batch request' })
415
428
  viewIndex: number;
416
429
 
417
- @Field(() => String, { description: "'current', 'stale', or 'error'" })
430
+ @Field(() => String, { description: "'current', 'differential', 'stale', or 'error'" })
418
431
  status: string;
419
432
 
420
433
  @Field(() => [RunViewGenericResultRow], {
421
434
  nullable: true,
422
- description: 'Fresh results - only populated when status is stale'
435
+ description: 'Fresh results - only populated when status is stale (full refresh)'
423
436
  })
424
437
  Results?: RunViewGenericResultRow[];
425
438
 
426
- @Field(() => String, { nullable: true, description: 'Max __mj_UpdatedAt from results when stale' })
439
+ @Field(() => DifferentialDataOutput, {
440
+ nullable: true,
441
+ description: 'Differential update data - only populated when status is differential'
442
+ })
443
+ differentialData?: DifferentialDataOutput;
444
+
445
+ @Field(() => String, { nullable: true, description: 'Max __mj_UpdatedAt from results when stale or differential' })
427
446
  maxUpdatedAt?: string;
428
447
 
429
- @Field(() => Int, { nullable: true, description: 'Row count of results when stale' })
448
+ @Field(() => Int, { nullable: true, description: 'Row count of results when stale or differential (total after applying delta)' })
430
449
  rowCount?: number;
431
450
 
432
451
  @Field(() => String, { nullable: true, description: 'Error message if status is error' })
@@ -886,13 +905,43 @@ export class RunViewResolver extends ResolverBase {
886
905
  const inputItem = input[index];
887
906
  const entity = provider.Entities.find(e => e.Name === inputItem.params.EntityName);
888
907
 
908
+ // If we have differential data but no entity, that's a configuration error
909
+ if (result.status === 'differential' && result.differentialData && !entity) {
910
+ throw new Error(
911
+ `Entity '${inputItem.params.EntityName}' not found in provider metadata but server returned differential data. ` +
912
+ `This may indicate a metadata sync issue.`
913
+ );
914
+ }
915
+
916
+ if (result.status === 'differential' && result.differentialData && entity) {
917
+ // Process differential data into GraphQL-compatible format
918
+ const processedUpdatedRows = this.processRawData(
919
+ result.differentialData.updatedRows as Record<string, unknown>[],
920
+ entity.ID,
921
+ entity
922
+ );
923
+ return {
924
+ viewIndex: result.viewIndex,
925
+ status: result.status,
926
+ Results: undefined,
927
+ differentialData: {
928
+ updatedRows: processedUpdatedRows,
929
+ deletedRecordIDs: result.differentialData.deletedRecordIDs,
930
+ },
931
+ maxUpdatedAt: result.maxUpdatedAt,
932
+ rowCount: result.rowCount,
933
+ errorMessage: result.errorMessage,
934
+ };
935
+ }
936
+
889
937
  if (result.status === 'stale' && result.results && entity) {
890
- // Process raw data into GraphQL-compatible format
938
+ // Process raw data into GraphQL-compatible format (full refresh)
891
939
  const processedRows = this.processRawData(result.results as Record<string, unknown>[], entity.ID, entity);
892
940
  return {
893
941
  viewIndex: result.viewIndex,
894
942
  status: result.status,
895
943
  Results: processedRows,
944
+ differentialData: undefined,
896
945
  maxUpdatedAt: result.maxUpdatedAt,
897
946
  rowCount: result.rowCount,
898
947
  errorMessage: result.errorMessage,
@@ -903,6 +952,7 @@ export class RunViewResolver extends ResolverBase {
903
952
  viewIndex: result.viewIndex,
904
953
  status: result.status,
905
954
  Results: undefined,
955
+ differentialData: undefined,
906
956
  maxUpdatedAt: result.maxUpdatedAt,
907
957
  rowCount: result.rowCount,
908
958
  errorMessage: result.errorMessage,
@@ -16,6 +16,7 @@ import { LogError, LogStatus } from '@memberjunction/core';
16
16
  import { TestEngine } from '@memberjunction/testing-engine';
17
17
  import { ResolverBase } from '../generic/ResolverBase.js';
18
18
  import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
19
+ import { TestRunVariables } from '@memberjunction/testing-engine-base';
19
20
 
20
21
  // ===== GraphQL Types =====
21
22
 
@@ -105,6 +106,7 @@ export class RunTestResolver extends ResolverBase {
105
106
  @Arg('verbose', { nullable: true }) verbose: boolean = true,
106
107
  @Arg('environment', { nullable: true }) environment?: string,
107
108
  @Arg('tags', { nullable: true }) tags?: string,
109
+ @Arg('variables', { nullable: true }) variables?: string,
108
110
  @PubSub() pubSub?: PubSubEngine,
109
111
  @Ctx() { userPayload }: AppContext = {} as AppContext
110
112
  ): Promise<TestRunResult> {
@@ -129,11 +131,22 @@ export class RunTestResolver extends ResolverBase {
129
131
  this.createProgressCallback(pubSub, userPayload, testId) :
130
132
  undefined;
131
133
 
134
+ // Parse variables from JSON string if provided
135
+ let parsedVariables: TestRunVariables | undefined;
136
+ if (variables) {
137
+ try {
138
+ parsedVariables = JSON.parse(variables);
139
+ } catch (e) {
140
+ LogError(`[RunTestResolver] Failed to parse variables: ${variables}`);
141
+ }
142
+ }
143
+
132
144
  // Run the test
133
145
  const options = {
134
146
  verbose,
135
147
  environment,
136
148
  tags,
149
+ variables: parsedVariables,
137
150
  progressCallback
138
151
  };
139
152
 
@@ -213,6 +226,7 @@ export class RunTestResolver extends ResolverBase {
213
226
  @Arg('environment', { nullable: true }) environment?: string,
214
227
  @Arg('parallel', { nullable: true }) parallel: boolean = false,
215
228
  @Arg('tags', { nullable: true }) tags?: string,
229
+ @Arg('variables', { nullable: true }) variables?: string,
216
230
  @Arg('selectedTestIds', { nullable: true }) selectedTestIds?: string,
217
231
  @Arg('sequenceStart', () => Int, { nullable: true }) sequenceStart?: number,
218
232
  @Arg('sequenceEnd', () => Int, { nullable: true }) sequenceEnd?: number,
@@ -247,11 +261,22 @@ export class RunTestResolver extends ResolverBase {
247
261
  }
248
262
  }
249
263
 
264
+ // Parse variables from JSON string if provided
265
+ let parsedVariables: TestRunVariables | undefined;
266
+ if (variables) {
267
+ try {
268
+ parsedVariables = JSON.parse(variables);
269
+ } catch (e) {
270
+ LogError(`[RunTestResolver] Failed to parse variables: ${variables}`);
271
+ }
272
+ }
273
+
250
274
  const options = {
251
275
  verbose,
252
276
  environment,
253
277
  parallel,
254
278
  tags,
279
+ variables: parsedVariables,
255
280
  selectedTestIds: parsedSelectedTestIds,
256
281
  sequenceStart,
257
282
  sequenceEnd,
@@ -1,4 +0,0 @@
1
- import { ApolloServerPlugin } from '@apollo/server';
2
- import { AppContext } from '../types.js';
3
- export declare const TransactionPlugin: ApolloServerPlugin<AppContext>;
4
- //# sourceMappingURL=TransactionPlugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TransactionPlugin.d.ts","sourceRoot":"","sources":["../../src/apolloServer/TransactionPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgF,MAAM,gBAAgB,CAAC;AAElI,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,UAAU,CAgD5D,CAAC"}
@@ -1,46 +0,0 @@
1
- import sql from 'mssql';
2
- export const TransactionPlugin = {
3
- async requestDidStart(requestContext) {
4
- const start = Date.now();
5
- const query = requestContext.request.query || '';
6
- const isMutation = /^\s*mutation\b/i.test(query);
7
- if (!isMutation) {
8
- return null;
9
- }
10
- const pool = requestContext.contextValue.dataSource;
11
- const transaction = new sql.Transaction(pool);
12
- requestContext.contextValue.transaction = transaction;
13
- console.log('Starting transaction wrapper, time spent: ', Date.now() - start, 'ms ');
14
- await transaction.begin();
15
- return {
16
- didEncounterErrors: async (requestContext) => {
17
- console.log('Error in transaction wrapper: ' + requestContext.errors, 'time spent: ', Date.now() - start, 'ms');
18
- },
19
- executionDidStart: async () => {
20
- return {
21
- executionDidEnd: async (err) => {
22
- try {
23
- if (err) {
24
- console.log('Error in transaction, rolling back, time spent: ', Date.now() - start, 'ms ');
25
- console.error('Rolling back transaction', err);
26
- await transaction.rollback();
27
- }
28
- else {
29
- console.log('Committing transaction, time spent: ', Date.now() - start, 'ms ');
30
- await transaction.commit();
31
- }
32
- }
33
- catch (execErr) {
34
- console.log('Execution Error, time spent: ', Date.now() - start, 'ms ');
35
- console.error(execErr);
36
- }
37
- finally {
38
- console.log('Transaction complete, time spent: ', Date.now() - start, 'ms ');
39
- }
40
- },
41
- };
42
- },
43
- };
44
- },
45
- };
46
- //# sourceMappingURL=TransactionPlugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TransactionPlugin.js","sourceRoot":"","sources":["../../src/apolloServer/TransactionPlugin.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,OAAO,CAAC;AAGxB,MAAM,CAAC,MAAM,iBAAiB,GAAmC;IAC/D,KAAK,CAAC,eAAe,CAAC,cAAc;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QAKD,MAAM,IAAI,GAAuB,cAAc,CAAC,YAAY,CAAC,UAAU,CAAC;QACxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAG7C,cAAc,CAAC,YAAoB,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;QACrF,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QAE1B,OAAO;YACL,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;gBAC3C,OAAO,CAAC,GAAG,CAAC,gCAAgC,GAAG,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;YAClH,CAAC;YACD,iBAAiB,EAAE,KAAK,IAAI,EAAE;gBAC5B,OAAO;oBACL,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;wBAC7B,IAAI,CAAC;4BACH,IAAI,GAAG,EAAE,CAAC;gCACR,OAAO,CAAC,GAAG,CAAC,kDAAkD,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;gCAC3F,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;gCAC/C,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;4BAC/B,CAAC;iCAAM,CAAC;gCACN,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;gCAC/E,MAAM,WAAW,CAAC,MAAM,EAAE,CAAC;4BAC7B,CAAC;wBACH,CAAC;wBAAC,OAAO,OAAO,EAAE,CAAC;4BACjB,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;4BACxE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;gCAAS,CAAC;4BACT,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;wBAC/E,CAAC;oBACH,CAAC;iBACF,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=backward-compatibility.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"backward-compatibility.test.d.ts","sourceRoot":"","sources":["../../../src/auth/__tests__/backward-compatibility.test.ts"],"names":[],"mappings":""}
@@ -1,135 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
2
- import { AuthProviderFactory } from '../AuthProviderFactory';
3
- import { initializeAuthProviders } from '../initializeProviders';
4
- describe('Authentication Provider Backward Compatibility', () => {
5
- let factory;
6
- beforeEach(() => {
7
- factory = AuthProviderFactory.getInstance();
8
- factory.clear();
9
- });
10
- afterEach(() => {
11
- factory.clear();
12
- });
13
- describe('Legacy Configuration Support', () => {
14
- it('should create MSAL provider from legacy config', () => {
15
- process.env.TENANT_ID = 'test-tenant-id';
16
- process.env.WEB_CLIENT_ID = 'test-client-id';
17
- initializeAuthProviders();
18
- const msalProvider = factory.getByName('msal');
19
- expect(msalProvider).toBeDefined();
20
- expect(msalProvider?.issuer).toContain('test-tenant-id');
21
- expect(msalProvider?.audience).toBe('test-client-id');
22
- });
23
- it('should create Auth0 provider from legacy config', () => {
24
- process.env.AUTH0_DOMAIN = 'test.auth0.com';
25
- process.env.AUTH0_CLIENT_ID = 'auth0-client-id';
26
- process.env.AUTH0_CLIENT_SECRET = 'auth0-secret';
27
- initializeAuthProviders();
28
- const auth0Provider = factory.getByName('auth0');
29
- expect(auth0Provider).toBeDefined();
30
- expect(auth0Provider?.issuer).toBe('https://test.auth0.com/');
31
- expect(auth0Provider?.audience).toBe('auth0-client-id');
32
- });
33
- });
34
- describe('Provider Registry Functionality', () => {
35
- it('should find providers by issuer with different formats', () => {
36
- const testProvider = {
37
- name: 'test',
38
- issuer: 'https://test.provider.com/oauth2',
39
- audience: 'test-audience',
40
- jwksUri: 'https://test.provider.com/.well-known/jwks.json',
41
- validateConfig: () => true,
42
- getSigningKey: jest.fn(),
43
- extractUserInfo: jest.fn(),
44
- matchesIssuer: (issuer) => {
45
- const normalized = issuer.toLowerCase().replace(/\/$/, '');
46
- return normalized === 'https://test.provider.com/oauth2';
47
- }
48
- };
49
- factory.register(testProvider);
50
- expect(factory.getByIssuer('https://test.provider.com/oauth2')).toBe(testProvider);
51
- expect(factory.getByIssuer('https://test.provider.com/oauth2/')).toBe(testProvider);
52
- expect(factory.getByIssuer('https://TEST.PROVIDER.COM/oauth2')).toBe(testProvider);
53
- });
54
- it('should cache issuer lookups for performance', () => {
55
- const testProvider = {
56
- name: 'test',
57
- issuer: 'https://test.provider.com',
58
- audience: 'test',
59
- jwksUri: 'https://test.provider.com/jwks',
60
- validateConfig: () => true,
61
- getSigningKey: jest.fn(),
62
- extractUserInfo: jest.fn(),
63
- matchesIssuer: jest.fn((issuer) => issuer === 'https://test.provider.com')
64
- };
65
- factory.register(testProvider);
66
- factory.getByIssuer('https://test.provider.com');
67
- expect(testProvider.matchesIssuer).toHaveBeenCalledTimes(1);
68
- factory.getByIssuer('https://test.provider.com');
69
- expect(testProvider.matchesIssuer).toHaveBeenCalledTimes(1);
70
- });
71
- });
72
- describe('User Info Extraction', () => {
73
- it('should extract user info from different token formats', () => {
74
- const msalPayload = {
75
- iss: 'https://login.microsoftonline.com/tenant/v2.0',
76
- email: 'user@example.com',
77
- given_name: 'John',
78
- family_name: 'Doe',
79
- name: 'John Doe',
80
- preferred_username: 'john.doe@example.com'
81
- };
82
- const auth0Payload = {
83
- iss: 'https://test.auth0.com/',
84
- email: 'user@example.com',
85
- given_name: 'Jane',
86
- family_name: 'Smith',
87
- name: 'Jane Smith'
88
- };
89
- const oktaPayload = {
90
- iss: 'https://test.okta.com/oauth2/default',
91
- email: 'user@example.com',
92
- given_name: 'Bob',
93
- family_name: 'Johnson',
94
- name: 'Bob Johnson',
95
- preferred_username: 'bob.johnson'
96
- };
97
- initializeAuthProviders();
98
- const msalProvider = factory.getByIssuer(msalPayload.iss);
99
- if (msalProvider) {
100
- const msalUserInfo = msalProvider.extractUserInfo(msalPayload);
101
- expect(msalUserInfo.email).toBe('user@example.com');
102
- expect(msalUserInfo.firstName).toBe('John');
103
- expect(msalUserInfo.lastName).toBe('Doe');
104
- }
105
- const auth0Provider = factory.getByIssuer(auth0Payload.iss);
106
- if (auth0Provider) {
107
- const auth0UserInfo = auth0Provider.extractUserInfo(auth0Payload);
108
- expect(auth0UserInfo.email).toBe('user@example.com');
109
- expect(auth0UserInfo.firstName).toBe('Jane');
110
- expect(auth0UserInfo.lastName).toBe('Smith');
111
- }
112
- });
113
- });
114
- describe('Error Handling', () => {
115
- it('should handle missing provider gracefully', () => {
116
- const unknownIssuer = 'https://unknown.provider.com';
117
- const provider = factory.getByIssuer(unknownIssuer);
118
- expect(provider).toBeUndefined();
119
- });
120
- it('should validate provider configuration', () => {
121
- const invalidProvider = {
122
- name: 'invalid',
123
- issuer: '',
124
- audience: 'test',
125
- jwksUri: 'https://test.com/jwks',
126
- validateConfig: () => false,
127
- getSigningKey: jest.fn(),
128
- extractUserInfo: jest.fn(),
129
- matchesIssuer: jest.fn()
130
- };
131
- expect(() => factory.register(invalidProvider)).toThrow();
132
- });
133
- });
134
- });
135
- //# sourceMappingURL=backward-compatibility.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"backward-compatibility.test.js","sourceRoot":"","sources":["../../../src/auth/__tests__/backward-compatibility.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,IAAI,OAA4B,CAAC;IAEjC,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,mBAAmB,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YAExD,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,gBAAgB,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,gBAAgB,CAAC;YAG7C,uBAAuB,EAAE,CAAC;YAG1B,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YACnC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YACzD,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YAEzD,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,gBAAgB,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,iBAAiB,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,cAAc,CAAC;YAGjD,uBAAuB,EAAE,CAAC;YAG1B,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;YACpC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YAC9D,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAGH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC/C,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAEhE,MAAM,YAAY,GAAG;gBACnB,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,kCAAkC;gBAC1C,QAAQ,EAAE,eAAe;gBACzB,OAAO,EAAE,iDAAiD;gBAC1D,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;gBAC1B,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;gBACxB,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE;gBAC1B,aAAa,EAAE,CAAC,MAAc,EAAE,EAAE;oBAChC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC3D,OAAO,UAAU,KAAK,kCAAkC,CAAC;gBAC3D,CAAC;aACe,CAAC;YAEnB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAG/B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAGnF,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAGpF,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,YAAY,GAAG;gBACnB,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,gCAAgC;gBACzC,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;gBAC1B,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;gBACxB,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE;gBAC1B,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAc,EAAW,EAAE,CAAC,MAAM,KAAK,2BAA2B,CAAC;aAC3E,CAAC;YAEnB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAG/B,OAAO,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;YACjD,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAG5D,OAAO,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;YACjD,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAE/D,MAAM,WAAW,GAAG;gBAClB,GAAG,EAAE,+CAA+C;gBACpD,KAAK,EAAE,kBAAkB;gBACzB,UAAU,EAAE,MAAM;gBAClB,WAAW,EAAE,KAAK;gBAClB,IAAI,EAAE,UAAU;gBAChB,kBAAkB,EAAE,sBAAsB;aAC3C,CAAC;YAGF,MAAM,YAAY,GAAG;gBACnB,GAAG,EAAE,yBAAyB;gBAC9B,KAAK,EAAE,kBAAkB;gBACzB,UAAU,EAAE,MAAM;gBAClB,WAAW,EAAE,OAAO;gBACpB,IAAI,EAAE,YAAY;aACnB,CAAC;YAGF,MAAM,WAAW,GAAG;gBAClB,GAAG,EAAE,sCAAsC;gBAC3C,KAAK,EAAE,kBAAkB;gBACzB,UAAU,EAAE,KAAK;gBACjB,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,aAAa;gBACnB,kBAAkB,EAAE,aAAa;aAClC,CAAC;YAGF,uBAAuB,EAAE,CAAC;YAG1B,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC1D,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;gBAC/D,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACpD,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC5C,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5D,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,aAAa,GAAG,aAAa,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;gBAClE,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACrD,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,aAAa,GAAG,8BAA8B,CAAC;YACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;YACpD,MAAM,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,eAAe,GAAG;gBACtB,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,uBAAuB;gBAChC,cAAc,EAAE,GAAG,EAAE,CAAC,KAAK;gBAC3B,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;gBACxB,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE;gBAC1B,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;aACR,CAAC;YAEnB,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}