@meshmakers/octo-services 3.4.1480 → 3.5.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.
package/README.md CHANGED
@@ -141,7 +141,9 @@ See [CLAUDE.md](CLAUDE.md) for development guidelines, CK ID types, GraphQL util
141
141
  ## Dependencies
142
142
 
143
143
  - **Angular 21** (core, common/http)
144
- - **Apollo Angular** / **@apollo/client** (GraphQL client)
144
+ - **Apollo Angular** (peer dependency, `^14.0.0`)
145
+ - **@apollo/client** (peer dependency, `^4.1.0` — the oldest 4.x line that has every API used here, so hosts on apollo-angular 14.1 / @apollo/client 4.1 keep installing; imported at runtime: `InMemoryCache`, `ApolloLink`, the error link)
146
+ - **graphql** (peer dependency, `^16.0.0 || ^17.0.0` like apollo-angular / @apollo/client; only the `DocumentNode` type is imported, which the public API exposes)
145
147
  - **tus-js-client** (resumable uploads)
146
148
  - **@meshmakers/shared-auth** (AuthorizeService for TUS uploads)
147
149
  - **@meshmakers/shared-services** (MessageService, PagedResultDto)
@@ -0,0 +1,127 @@
1
+ import { print, TypeInfo, visit, visitWithTypeInfo, getNamedType, buildSchema, parse } from 'graphql';
2
+ import { isCredentialLikeAttributeName } from '@meshmakers/octo-services';
3
+
4
+ const GENERIC_ATTRIBUTE_CONNECTION = 'RtEntityAttributeDtoConnection';
5
+ /** Schema type of a typed SECRET field (AB#5528). */
6
+ const SECRET_STATE_TYPE = 'OctoSecretState';
7
+ const NON_TEXT_SCALARS = new Set(['Boolean', 'Int', 'Float', 'Long', 'Decimal', 'DateTime', 'Date', 'TimeSpan']);
8
+ const INLINE_GQL = /gql`([\s\S]*?)`/g;
9
+ const OPERATION_START = /^\s*(#[^\n]*\n\s*)*(query|mutation|subscription|fragment|\{)/;
10
+ /**
11
+ * The GraphQL documents of a source file: the whole text of a `.graphql` file, or the inline
12
+ * `gql` template literals (interpolations removed) of a `.ts` file.
13
+ */
14
+ function extractGraphQlDocuments(path, source) {
15
+ if (path.endsWith('.graphql'))
16
+ return [source];
17
+ return [...source.matchAll(INLINE_GQL)]
18
+ .map((m) => m[1].replace(/\$\{[^}]*\}/g, ''))
19
+ .filter((text) => OPERATION_START.test(text));
20
+ }
21
+ /** Violations of the SECRET rule in one parsed document, validated against `schema`. */
22
+ function findSecretUnsafeSelections(schema, doc, file) {
23
+ const violations = [];
24
+ const variableTypes = new Map();
25
+ for (const def of doc.definitions) {
26
+ if (def.kind === 'OperationDefinition') {
27
+ for (const v of def.variableDefinitions ?? [])
28
+ variableTypes.set(v.variable.name.value, print(v.type));
29
+ }
30
+ }
31
+ const typeInfo = new TypeInfo(schema);
32
+ const path = [];
33
+ visit(doc, visitWithTypeInfo(typeInfo, {
34
+ Field: {
35
+ enter(node) {
36
+ path.push(node.alias?.value ?? node.name.value);
37
+ const fieldPath = path.join('.');
38
+ const named = getNamedType(typeInfo.getType() ?? undefined);
39
+ const selectsValue = node.selectionSet?.selections.some((s) => s.kind === 'Field' && s.name.value === 'items'
40
+ && s.selectionSet?.selections.some((i) => i.kind === 'Field' && i.name.value === 'value'));
41
+ const isGeneric = node.name.value === 'attributes'
42
+ && (named?.name === GENERIC_ATTRIBUTE_CONNECTION || (!named && !!selectsValue));
43
+ if (named?.name === SECRET_STATE_TYPE) {
44
+ const selectsIsSet = node.selectionSet?.selections.some((s) => s.kind === 'Field' && s.name.value === 'isSet');
45
+ if (!selectsIsSet) {
46
+ violations.push({
47
+ key: `${file}#${fieldPath}`,
48
+ message: `SECRET field "${node.name.value}" must be selected as { isSet … }`,
49
+ });
50
+ }
51
+ }
52
+ else if (isGeneric) {
53
+ const arg = node.arguments?.find((a) => a.name.value === 'attributeNames');
54
+ const key = `${file}#${fieldPath}`;
55
+ if (!arg) {
56
+ violations.push({ key, message: 'generic `attributes` without `attributeNames` (returns ALL attributes incl. secrets)' });
57
+ }
58
+ else if (arg.value.kind === 'Variable') {
59
+ const type = variableTypes.get(arg.value.name.value);
60
+ if (!type?.endsWith('!')) {
61
+ violations.push({ key, message: `\`attributeNames\` bound to nullable variable $${arg.value.name.value}: ${type ?? '?'}` });
62
+ }
63
+ }
64
+ else if (arg.value.kind === 'ListValue') {
65
+ for (const item of arg.value.values) {
66
+ if (item.kind === 'StringValue' && isCredentialLikeAttributeName(item.value)) {
67
+ violations.push({ key, message: `\`attributeNames\` lists credential-like "${item.value}"` });
68
+ }
69
+ }
70
+ }
71
+ else if (arg.value.kind === 'StringValue') {
72
+ // A single string is coerced to a one-element list.
73
+ if (isCredentialLikeAttributeName(arg.value.value)) {
74
+ violations.push({ key, message: `\`attributeNames\` lists credential-like "${arg.value.value}"` });
75
+ }
76
+ }
77
+ else {
78
+ violations.push({ key, message: '`attributeNames` must be a non-null list' });
79
+ }
80
+ }
81
+ else if (!node.selectionSet && isCredentialLikeAttributeName(node.name.value)) {
82
+ const scalar = named?.name;
83
+ if (!scalar || !NON_TEXT_SCALARS.has(scalar)) {
84
+ violations.push({
85
+ key: `${file}#${fieldPath}`,
86
+ message: `typed selection of credential-like field "${node.name.value}" (${scalar ?? 'unknown type'})`,
87
+ });
88
+ }
89
+ }
90
+ },
91
+ leave() {
92
+ path.pop();
93
+ },
94
+ },
95
+ }));
96
+ return violations;
97
+ }
98
+ const schemaCache = new Map();
99
+ /**
100
+ * Same rule as {@link findSecretUnsafeSelections}, but from source text: the schema SDL and the
101
+ * document are parsed with THIS module's `graphql` instance. Hosts that consume the library as a
102
+ * published package must use this variant — passing a schema or document built with the host's
103
+ * own `graphql` copy fails with "Cannot use GraphQLObjectType from another module or realm"
104
+ * whenever the bundler resolves `graphql` twice (ESM/CJS or nested copies).
105
+ */
106
+ function findSecretUnsafeSelectionsInSource(schemaSdl, documentText, file) {
107
+ let schema = schemaCache.get(schemaSdl);
108
+ if (!schema) {
109
+ schema = buildSchema(schemaSdl);
110
+ schemaCache.set(schemaSdl, schema);
111
+ }
112
+ return findSecretUnsafeSelections(schema, parse(documentText), file);
113
+ }
114
+
115
+ /*
116
+ * Public API Surface of @meshmakers/octo-services/testing (AB#5542)
117
+ *
118
+ * Test-only helpers. Not part of the runtime entry point, so apps never bundle them; the
119
+ * GraphQL SECRET guard specs of the libraries and the Refinery Studio import them from here.
120
+ */
121
+
122
+ /**
123
+ * Generated bundle index. Do not edit.
124
+ */
125
+
126
+ export { SECRET_STATE_TYPE, extractGraphQlDocuments, findSecretUnsafeSelections, findSecretUnsafeSelectionsInSource };
127
+ //# sourceMappingURL=meshmakers-octo-services-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meshmakers-octo-services-testing.mjs","sources":["../../../../projects/meshmakers/octo-services/testing/src/graphql-secret-guard.ts","../../../../projects/meshmakers/octo-services/testing/src/public-api.ts","../../../../projects/meshmakers/octo-services/testing/src/meshmakers-octo-services-testing.ts"],"sourcesContent":["import { buildSchema, DocumentNode, getNamedType, GraphQLSchema, parse, print, TypeInfo, visit, visitWithTypeInfo } from 'graphql';\nimport { isCredentialLikeAttributeName } from '@meshmakers/octo-services';\n\n/**\n * SECRET-safe GraphQL document rule (AB#5542), shared by the guard specs of the libraries\n * (`octo-services/src/lib/graphql-secret-guard.spec.ts`) and the Refinery Studio\n * (`src/app/graphql-secret-guard.spec.ts`). Pure functions — the specs do the file scanning.\n *\n * A document violates the rule when\n * 1. a generic runtime `attributes` selection (`RtEntityAttributeDtoConnection`) has no\n * `attributeNames` argument, binds it to a NULLABLE variable, or lists a credential-like name\n * (list or single string) — omitting the filter returns every attribute incl. secrets;\n * 2. a typed selection contains a credential-like String field (`password`, `clientSecret`,\n * `apiKey`, `botToken`, …; Boolean/number fields such as `isSecret` or `maxTokens` are fine) —\n * the fallback for models whose credentials are not SECRET yet;\n * 3. a SECRET-typed field (schema type `OctoSecretState`, AB#5528) is selected without `isSet`\n * (the server refuses a scalar selection anyway; the state must be read as `{ isSet … }`).\n *\n * A non-null variable with a default (`$attributeNames: [String!]! = []`) is accepted.\n */\n\n/** One violation: `key` = `<file>#<field path>` (allow-list key), `message` = human readable. */\nexport interface SecretGuardViolation {\n readonly key: string;\n readonly message: string;\n}\n\nconst GENERIC_ATTRIBUTE_CONNECTION = 'RtEntityAttributeDtoConnection';\n/** Schema type of a typed SECRET field (AB#5528). */\nexport const SECRET_STATE_TYPE = 'OctoSecretState';\nconst NON_TEXT_SCALARS = new Set(['Boolean', 'Int', 'Float', 'Long', 'Decimal', 'DateTime', 'Date', 'TimeSpan']);\nconst INLINE_GQL = /gql`([\\s\\S]*?)`/g;\nconst OPERATION_START = /^\\s*(#[^\\n]*\\n\\s*)*(query|mutation|subscription|fragment|\\{)/;\n\n/**\n * The GraphQL documents of a source file: the whole text of a `.graphql` file, or the inline\n * `gql` template literals (interpolations removed) of a `.ts` file.\n */\nexport function extractGraphQlDocuments(path: string, source: string): string[] {\n if (path.endsWith('.graphql')) return [source];\n return [...source.matchAll(INLINE_GQL)]\n .map((m) => m[1].replace(/\\$\\{[^}]*\\}/g, ''))\n .filter((text) => OPERATION_START.test(text));\n}\n\n/** Violations of the SECRET rule in one parsed document, validated against `schema`. */\nexport function findSecretUnsafeSelections(schema: GraphQLSchema, doc: DocumentNode, file: string): SecretGuardViolation[] {\n const violations: SecretGuardViolation[] = [];\n const variableTypes = new Map<string, string>();\n for (const def of doc.definitions) {\n if (def.kind === 'OperationDefinition') {\n for (const v of def.variableDefinitions ?? []) variableTypes.set(v.variable.name.value, print(v.type));\n }\n }\n\n const typeInfo = new TypeInfo(schema);\n const path: string[] = [];\n visit(doc, visitWithTypeInfo(typeInfo, {\n Field: {\n enter(node) {\n path.push(node.alias?.value ?? node.name.value);\n const fieldPath = path.join('.');\n const named = getNamedType(typeInfo.getType() ?? undefined);\n const selectsValue = node.selectionSet?.selections.some(\n (s) => s.kind === 'Field' && s.name.value === 'items'\n && s.selectionSet?.selections.some((i) => i.kind === 'Field' && i.name.value === 'value'),\n );\n const isGeneric = node.name.value === 'attributes'\n && (named?.name === GENERIC_ATTRIBUTE_CONNECTION || (!named && !!selectsValue));\n\n if (named?.name === SECRET_STATE_TYPE) {\n const selectsIsSet = node.selectionSet?.selections.some((s) => s.kind === 'Field' && s.name.value === 'isSet');\n if (!selectsIsSet) {\n violations.push({\n key: `${file}#${fieldPath}`,\n message: `SECRET field \"${node.name.value}\" must be selected as { isSet … }`,\n });\n }\n } else if (isGeneric) {\n const arg = node.arguments?.find((a) => a.name.value === 'attributeNames');\n const key = `${file}#${fieldPath}`;\n if (!arg) {\n violations.push({ key, message: 'generic `attributes` without `attributeNames` (returns ALL attributes incl. secrets)' });\n } else if (arg.value.kind === 'Variable') {\n const type = variableTypes.get(arg.value.name.value);\n if (!type?.endsWith('!')) {\n violations.push({ key, message: `\\`attributeNames\\` bound to nullable variable $${arg.value.name.value}: ${type ?? '?'}` });\n }\n } else if (arg.value.kind === 'ListValue') {\n for (const item of arg.value.values) {\n if (item.kind === 'StringValue' && isCredentialLikeAttributeName(item.value)) {\n violations.push({ key, message: `\\`attributeNames\\` lists credential-like \"${item.value}\"` });\n }\n }\n } else if (arg.value.kind === 'StringValue') {\n // A single string is coerced to a one-element list.\n if (isCredentialLikeAttributeName(arg.value.value)) {\n violations.push({ key, message: `\\`attributeNames\\` lists credential-like \"${arg.value.value}\"` });\n }\n } else {\n violations.push({ key, message: '`attributeNames` must be a non-null list' });\n }\n } else if (!node.selectionSet && isCredentialLikeAttributeName(node.name.value)) {\n const scalar = named?.name;\n if (!scalar || !NON_TEXT_SCALARS.has(scalar)) {\n violations.push({\n key: `${file}#${fieldPath}`,\n message: `typed selection of credential-like field \"${node.name.value}\" (${scalar ?? 'unknown type'})`,\n });\n }\n }\n },\n leave() {\n path.pop();\n },\n },\n }));\n return violations;\n}\n\nconst schemaCache = new Map<string, GraphQLSchema>();\n\n/**\n * Same rule as {@link findSecretUnsafeSelections}, but from source text: the schema SDL and the\n * document are parsed with THIS module's `graphql` instance. Hosts that consume the library as a\n * published package must use this variant — passing a schema or document built with the host's\n * own `graphql` copy fails with \"Cannot use GraphQLObjectType from another module or realm\"\n * whenever the bundler resolves `graphql` twice (ESM/CJS or nested copies).\n */\nexport function findSecretUnsafeSelectionsInSource(schemaSdl: string, documentText: string, file: string): SecretGuardViolation[] {\n let schema = schemaCache.get(schemaSdl);\n if (!schema) {\n schema = buildSchema(schemaSdl);\n schemaCache.set(schemaSdl, schema);\n }\n return findSecretUnsafeSelections(schema, parse(documentText), file);\n}\n","/*\n * Public API Surface of @meshmakers/octo-services/testing (AB#5542)\n *\n * Test-only helpers. Not part of the runtime entry point, so apps never bundle them; the\n * GraphQL SECRET guard specs of the libraries and the Refinery Studio import them from here.\n */\nexport * from './graphql-secret-guard';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AA2BA,MAAM,4BAA4B,GAAG,gCAAgC;AACrE;AACO,MAAM,iBAAiB,GAAG;AACjC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAChH,MAAM,UAAU,GAAG,kBAAkB;AACrC,MAAM,eAAe,GAAG,8DAA8D;AAEtF;;;AAGG;AACG,SAAU,uBAAuB,CAAC,IAAY,EAAE,MAAc,EAAA;AAClE,IAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC;IAC9C,OAAO,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;AACnC,SAAA,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;AAC3C,SAAA,MAAM,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjD;AAEA;SACgB,0BAA0B,CAAC,MAAqB,EAAE,GAAiB,EAAE,IAAY,EAAA;IAC/F,MAAM,UAAU,GAA2B,EAAE;AAC7C,IAAA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB;AAC/C,IAAA,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE;AACjC,QAAA,IAAI,GAAG,CAAC,IAAI,KAAK,qBAAqB,EAAE;AACtC,YAAA,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,mBAAmB,IAAI,EAAE;AAAE,gBAAA,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxG;IACF;AAEA,IAAA,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC;IACrC,MAAM,IAAI,GAAa,EAAE;AACzB,IAAA,KAAK,CAAC,GAAG,EAAE,iBAAiB,CAAC,QAAQ,EAAE;AACrC,QAAA,KAAK,EAAE;AACL,YAAA,KAAK,CAAC,IAAI,EAAA;AACR,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBAChC,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,SAAS,CAAC;gBAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CACrD,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK;uBACzC,CAAC,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,CAC5F;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK;AACjC,wBAAC,KAAK,EAAE,IAAI,KAAK,4BAA4B,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC;AAEjF,gBAAA,IAAI,KAAK,EAAE,IAAI,KAAK,iBAAiB,EAAE;AACrC,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC;oBAC9G,IAAI,CAAC,YAAY,EAAE;wBACjB,UAAU,CAAC,IAAI,CAAC;AACd,4BAAA,GAAG,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE;AAC3B,4BAAA,OAAO,EAAE,CAAA,cAAA,EAAiB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA,iCAAA,CAAmC;AAC7E,yBAAA,CAAC;oBACJ;gBACF;qBAAO,IAAI,SAAS,EAAE;oBACpB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,gBAAgB,CAAC;AAC1E,oBAAA,MAAM,GAAG,GAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,EAAE;oBAClC,IAAI,CAAC,GAAG,EAAE;wBACR,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,sFAAsF,EAAE,CAAC;oBAC3H;yBAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE;AACxC,wBAAA,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;wBACpD,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;4BACxB,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA,+CAAA,EAAkD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAA,EAAA,EAAK,IAAI,IAAI,GAAG,CAAA,CAAE,EAAE,CAAC;wBAC7H;oBACF;yBAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE;wBACzC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE;AACnC,4BAAA,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC5E,gCAAA,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA,0CAAA,EAA6C,IAAI,CAAC,KAAK,CAAA,CAAA,CAAG,EAAE,CAAC;4BAC/F;wBACF;oBACF;yBAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE;;wBAE3C,IAAI,6BAA6B,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;AAClD,4BAAA,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA,0CAAA,EAA6C,GAAG,CAAC,KAAK,CAAC,KAAK,CAAA,CAAA,CAAG,EAAE,CAAC;wBACpG;oBACF;yBAAO;wBACL,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC;oBAC/E;gBACF;AAAO,qBAAA,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/E,oBAAA,MAAM,MAAM,GAAG,KAAK,EAAE,IAAI;oBAC1B,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;wBAC5C,UAAU,CAAC,IAAI,CAAC;AACd,4BAAA,GAAG,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE;4BAC3B,OAAO,EAAE,CAAA,0CAAA,EAA6C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA,GAAA,EAAM,MAAM,IAAI,cAAc,CAAA,CAAA,CAAG;AACvG,yBAAA,CAAC;oBACJ;gBACF;YACF,CAAC;YACD,KAAK,GAAA;gBACH,IAAI,CAAC,GAAG,EAAE;YACZ,CAAC;AACF,SAAA;AACF,KAAA,CAAC,CAAC;AACH,IAAA,OAAO,UAAU;AACnB;AAEA,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyB;AAEpD;;;;;;AAMG;SACa,kCAAkC,CAAC,SAAiB,EAAE,YAAoB,EAAE,IAAY,EAAA;IACtG,IAAI,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC;AAC/B,QAAA,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC;IACpC;IACA,OAAO,0BAA0B,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;AACtE;;ACxIA;;;;;AAKG;;ACLH;;AAEG;;"}