diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-reserved-word-state.ts b/packages/teleport-component-generator-react/__tests__/integration/component-reserved-word-state.ts new file mode 100644 index 000000000..b5529eb8d --- /dev/null +++ b/packages/teleport-component-generator-react/__tests__/integration/component-reserved-word-state.ts @@ -0,0 +1,105 @@ +/** + * A UIDL state name is DATA — it mirrors a database column, and a WoW character + * sheet has a column called `class`. The generator turned that straight into a + * JS binding: + * + * const [class, setClass] = useState("") + * + * which is a SyntaxError, so the prettier post-processor threw and `packProject` + * aborted — every page of the project failed to generate, not just this one. + * + * These tests exercise the reserved name in every position a state can appear + * (declaration, text binding, attribute binding, conditional, event setter). + * `createReactComponentGenerator()` runs the prettier post-processor, so a + * generation that RESOLVES is itself proof that the emitted module parses — + * a missed emission site would reject here. + */ + +import { createReactComponentGenerator } from '../../src' +import { GeneratedFile } from '@teleporthq/teleport-types' +import { + component, + definition, + staticNode, + dynamicNode, + elementNode, + conditionalNode, +} from '@teleporthq/teleport-uidl-builders' + +const generator = createReactComponentGenerator() + +const JS_FILE = 'js' +const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) => + files.find((file) => file.fileType === type) + +const reservedStateUidl = component( + 'Character Sheet', + elementNode('container', {}, [ + // Text binding. + elementNode('text', {}, [dynamicNode('state', 'class')]), + // Attribute binding. + elementNode('input', { value: dynamicNode('state', 'class') }, []), + // Conditional. + conditionalNode( + dynamicNode('state', 'class'), + elementNode('text', {}, [staticNode('Class chosen')]), + true + ), + // Event setter. + elementNode('button', {}, [staticNode('Reset')], null, null, { + click: [{ type: 'stateChange', modifies: 'class', newState: '' }], + }), + // A neighbouring ordinary state must be untouched by the fix. + elementNode('text', {}, [dynamicNode('state', 'realm')]), + ]), + {}, + { + class: definition('string', ''), + realm: definition('string', ''), + } +) + +describe('Component with a RESERVED-WORD state name', () => { + it('generates a module that parses (prettier would reject `const [class, …]`)', async () => { + const result = await generator.generateComponent(reservedStateUidl) + expect(findFileByType(result.files, JS_FILE)).toBeDefined() + }) + + it('declares the state under a bindable identifier', async () => { + const { content } = findFileByType( + (await generator.generateComponent(reservedStateUidl)).files, + JS_FILE + ) + expect(content).toContain('const [class_, setClass] = useState') + expect(content).not.toContain('const [class,') + }) + + it('reads the state through the SAME identifier it declared', async () => { + const { content } = findFileByType( + (await generator.generateComponent(reservedStateUidl)).files, + JS_FILE + ) + // Text + attribute + conditional all bind the sanitised name. + // (`value` is emitted as React's `defaultValue` by the attribute mapper.) + expect(content).toContain('{class_}') + expect(content).toContain('defaultValue={class_}') + expect(content).toContain('{class_ && ') + }) + + it('calls the setter for the state-change event', async () => { + const { content } = findFileByType( + (await generator.generateComponent(reservedStateUidl)).files, + JS_FILE + ) + expect(content).toContain('setClass(') + }) + + it('leaves an ordinary neighbouring state byte-identical', async () => { + const { content } = findFileByType( + (await generator.generateComponent(reservedStateUidl)).files, + JS_FILE + ) + expect(content).toContain('const [realm, setRealm] = useState') + expect(content).toContain('{realm}') + }) +}) diff --git a/packages/teleport-plugin-common/__tests__/utils/parse-string-with-template-expressions.ts b/packages/teleport-plugin-common/__tests__/utils/parse-string-with-template-expressions.ts new file mode 100644 index 000000000..706f1ebdf --- /dev/null +++ b/packages/teleport-plugin-common/__tests__/utils/parse-string-with-template-expressions.ts @@ -0,0 +1,82 @@ +import * as types from '@babel/types' +import generate from '@babel/generator' +import { parseStringWithTemplateExpressions } from '../../src/utils/ast-utils' + +/** The generated source for a template literal, e.g. "`translateX(${x}px)`". */ +const render = (input: string): string => + generate(parseStringWithTemplateExpressions(input) as types.Node).code + +describe('parseStringWithTemplateExpressions', () => { + it('converts a well-formed binding and strips the state prefix', () => { + expect(render(`translate({{ enemy.x || '0' }}px)`)).toBe(`\`translate(\${enemy.x || '0'}px)\``) + expect(render(`translateX({{ -(state.cameraX || 0) }}px)`)).toBe( + `\`translateX(\${-(cameraX || 0)}px)\`` + ) + }) + + it('handles several bindings in one value', () => { + expect(render(`translate({{ ctx.x }}px, {{ ctx.y }}px)`)).toBe( + `\`translate(\${ctx.x}px, \${ctx.y}px)\`` + ) + }) + + it('re-closes a CSS function the binding genuinely swallowed', () => { + // The unit is inferred from the one already present. + expect(render(`translate({{ x }}px, {{ y`)).toBe(`\`translate(\${x}px, \${y}px)\``) + }) + + it('infers deg for rotate and no unit for scale', () => { + expect(render(`rotate({{ a`)).toBe(`\`rotate(\${a}deg)\``) + expect(render(`scale({{ s`)).toBe(`\`scale(\${s})\``) + }) +}) + +/** + * Run 021fa45a — an upstream "repair" turned `{{ -(state.cameraX || 0) }}` into + * `{{ -(state.cameraX || '' }}`, dropping the closing paren. This function then + * counted parentheses across the WHOLE string, mistook the imbalance inside the + * interpolation for an unclosed CSS function, appended `px)` to the end, and + * handed Babel `` `translateX(${-(cameraX || ''}px) }px)` ``. The SyntaxError + * escaped through the inline-style caller (which has no try/catch) and killed + * the entire project build. + */ +describe('parseStringWithTemplateExpressions — a malformed binding must not break the build', () => { + const BROKEN = `translateX({{ -(state.cameraX || '' }}px) }` + + it('does not throw on the exact UIDL value that killed the build', () => { + expect(() => parseStringWithTemplateExpressions(BROKEN)).not.toThrow() + }) + + it('repairs it INSIDE the interpolation, where the paren was missing', () => { + expect(render(BROKEN)).toBe(`\`translateX(\${-(cameraX || '')}px) }\``) + }) + + it('no longer appends a fabricated unit and paren to the end', () => { + expect(render(BROKEN)).not.toContain('px)`') + }) + + it('closes an unterminated quote inside a binding', () => { + expect(render(`{{ label || 'Guest }}`)).toBe(`\`\${label || 'Guest'}\``) + }) + + it('degrades to the declared literal fallback when nothing can be parsed', () => { + // A stray closer cannot be balanced without guessing, so the binding is + // dropped and its literal fallback kept — one value degrades, nothing throws. + const result = render(`{{ name) || 'Guest' }}`) + expect(result).toBe('`Guest`') + }) + + it('degrades to empty text when a broken binding declared no fallback', () => { + expect(render(`{{ a) }}`)).toBe('``') + }) + + it('always returns a TemplateLiteral, even on the degraded path', () => { + expect(types.isTemplateLiteral(parseStringWithTemplateExpressions(`{{ a) }}`))).toBe(true) + }) + + it('is idempotent on an already-repaired value', () => { + const once = render(BROKEN) + // Feeding the generated form back in (minus the backticks) is stable. + expect(render(once.slice(1, -1))).toBe(once) + }) +}) diff --git a/packages/teleport-plugin-common/__tests__/utils/route-utils.ts b/packages/teleport-plugin-common/__tests__/utils/route-utils.ts new file mode 100644 index 000000000..60c0fd30d --- /dev/null +++ b/packages/teleport-plugin-common/__tests__/utils/route-utils.ts @@ -0,0 +1,118 @@ +import { + parseDynamicPathSegments, + pathHasDynamicSegment, + isDynamicRoute, +} from '../../src/utils/route-utils' + +describe('parseDynamicPathSegments', () => { + it('splits a Next.js bracket segment into static text plus a param name', () => { + // The shape every details page's `navLink` actually carries. Before this + // was understood, the literal text "[id]" shipped inside canonical URLs, + // og:url and sitemap entries. + expect(parseDynamicPathSegments('/event-details/[id]')).toEqual({ + staticParts: ['/event-details/', ''], + paramNames: ['id'], + }) + }) + + it('still splits the template-literal form', () => { + expect(parseDynamicPathSegments('/news/' + '$' + '{' + 'slug}')).toEqual({ + staticParts: ['/news/', ''], + paramNames: ['slug'], + }) + }) + + it('handles a full absolute URL, keeping the origin in the static text', () => { + expect(parseDynamicPathSegments('https://example.com/rsvp-event/[id]')).toEqual({ + staticParts: ['https://example.com/rsvp-event/', ''], + paramNames: ['id'], + }) + }) + + it('splits several parameters and keeps the text between them', () => { + expect(parseDynamicPathSegments('/g/[guildId]/e/[eventId]/rsvp')).toEqual({ + staticParts: ['/g/', '/e/', '/rsvp'], + paramNames: ['guildId', 'eventId'], + }) + }) + + it('mixes both spellings in one path', () => { + expect(parseDynamicPathSegments('/a/[id]/b/' + '$' + '{' + 'slug}')).toEqual({ + staticParts: ['/a/', '/b/', ''], + paramNames: ['id', 'slug'], + }) + }) + + it('reports no parameters for a plain static path', () => { + expect(parseDynamicPathSegments('https://example.com/add-guild')).toEqual({ + staticParts: ['https://example.com/add-guild'], + paramNames: [], + }) + }) + + it('always returns exactly one more static part than parameters', () => { + for (const path of ['/a', '/a/[id]', '/a/[id]/b/[other]', '/' + '$' + '{' + 'x}']) { + const { staticParts, paramNames } = parseDynamicPathSegments(path) + expect(staticParts.length).toBe(paramNames.length + 1) + } + }) + + it('rebuilding staticParts + parameters reproduces the original path', () => { + const path = '/g/[guildId]/e/[eventId]/rsvp' + const { staticParts, paramNames } = parseDynamicPathSegments(path) + const rebuilt = staticParts.reduce( + (acc, part, i) => acc + part + (i < paramNames.length ? `[${paramNames[i]}]` : ''), + '' + ) + expect(rebuilt).toBe(path) + }) + + it('ignores a bracket that is not a whole path segment', () => { + // A literal bracket inside a segment or a query string is content, not a + // route parameter — turning it into router.query would corrupt the URL. + expect(parseDynamicPathSegments('/report[2024]/summary').paramNames).toEqual([]) + expect(parseDynamicPathSegments('/search?tags[]=a').paramNames).toEqual([]) + expect(parseDynamicPathSegments('/a/[id]x/b').paramNames).toEqual([]) + }) + + it('ignores Next catch-all segments, whose value is an array', () => { + // `router.query.slug` is a string[] for a catch-all; interpolating it into + // a URL would emit a comma-joined path. Leaving it alone is the honest + // outcome until a caller needs a real join. + expect(parseDynamicPathSegments('/docs/[...slug]').paramNames).toEqual([]) + expect(parseDynamicPathSegments('/docs/[[...slug]]').paramNames).toEqual([]) + }) + + it('ends a segment at anything that cannot be part of a path', () => { + // The same template appears inside a serialized JSON-LD document, where the + // URL ends at the closing quote rather than at a slash. + const embedded = '{"item":"https://example.com/event-details/[id]"}' + const { paramNames } = parseDynamicPathSegments(embedded) + expect(paramNames).toEqual(['id']) + }) + + it('is total for empty input', () => { + expect(parseDynamicPathSegments('')).toEqual({ staticParts: [''], paramNames: [] }) + }) +}) + +describe('pathHasDynamicSegment', () => { + it('is true only for a whole-segment bracket parameter', () => { + expect(pathHasDynamicSegment('/add-character/[id]')).toBe(true) + expect(pathHasDynamicSegment('https://example.com/profile/[id]')).toBe(true) + expect(pathHasDynamicSegment('/add-guild')).toBe(false) + expect(pathHasDynamicSegment('/report[2024]')).toBe(false) + expect(pathHasDynamicSegment('')).toBe(false) + expect(pathHasDynamicSegment(undefined as unknown as string)).toBe(false) + }) +}) + +describe('isDynamicRoute', () => { + it('reads the component output options, not a URL', () => { + expect( + isDynamicRoute({ outputOptions: { folderPath: ['event-details'], fileName: '[id]' } }) + ).toBe(true) + expect(isDynamicRoute({ outputOptions: { folderPath: [], fileName: 'add-guild' } })).toBe(false) + expect(isDynamicRoute({})).toBe(false) + }) +}) diff --git a/packages/teleport-plugin-common/__tests__/utils/template-expression-balance.ts b/packages/teleport-plugin-common/__tests__/utils/template-expression-balance.ts new file mode 100644 index 000000000..7eca9a391 --- /dev/null +++ b/packages/teleport-plugin-common/__tests__/utils/template-expression-balance.ts @@ -0,0 +1,83 @@ +import { + balanceExpression, + countUnclosedStaticParens, + isBalancedExpression, + scanExpression, +} from '../../src/utils/template-expression-balance' + +describe('scanExpression', () => { + it('reports a clean expression as fully closed', () => { + const scan = scanExpression('-(cameraX || 0)') + expect(scan.unclosed).toEqual([]) + expect(scan.strayCloserCount).toBe(0) + expect(scan.unterminatedQuote).toBeNull() + }) + + it('never lets a bracket inside a string affect nesting', () => { + expect(isBalancedExpression(`name || '(unclosed'`)).toBe(true) + expect(isBalancedExpression(`name || ')'`)).toBe(true) + }) + + it('honours escapes inside a string', () => { + expect(isBalancedExpression(`name || 'it\\'s fine'`)).toBe(true) + }) + + it('reports an unterminated quote', () => { + expect(scanExpression(`name || 'oops`).unterminatedQuote).toBe("'") + }) + + it('counts a closer that never had an opener as stray', () => { + expect(scanExpression('0)').strayCloserCount).toBe(1) + }) + + it('treats a mismatched closer as stray rather than guessing', () => { + expect(scanExpression('fn(a]').strayCloserCount).toBe(1) + }) +}) + +describe('balanceExpression', () => { + it('closes the paren the upstream repair dropped', () => { + expect(balanceExpression(`-(cameraX || ''`)).toBe(`-(cameraX || '')`) + }) + + it('closes an unterminated quote BEFORE the brackets around it', () => { + expect(balanceExpression(`fn(x, 'label`)).toBe(`fn(x, 'label')`) + }) + + it('closes nested brackets outermost-last', () => { + expect(balanceExpression('fn(items[0')).toBe('fn(items[0])') + }) + + it('leaves a balanced expression byte-for-byte alone', () => { + for (const expr of [`-(cameraX || 0)`, `a.b`, `items[0].name`, `fn(a, 'b')`]) { + expect(balanceExpression(expr)).toBe(expr) + } + }) + + it('refuses to guess where a missing opener belonged', () => { + expect(balanceExpression('cameraX)')).toBe('cameraX)') + }) +}) + +describe('countUnclosedStaticParens', () => { + it('ignores parentheses inside an interpolation', () => { + // The whole point: the `(` in the expression is not a CSS function call. + expect(countUnclosedStaticParens(`translateX(\${-(cameraX || 0)}px)`)).toBe(0) + }) + + it('counts a genuinely unclosed CSS function', () => { + expect(countUnclosedStaticParens(`translate(\${x}px, \${y}px`)).toBe(1) + }) + + it('does not go negative on extra closers', () => { + expect(countUnclosedStaticParens(`\${x}px))`)).toBe(0) + }) + + it('skips a brace inside a string inside an interpolation', () => { + expect(countUnclosedStaticParens(`translateX(${'${'}fn('}')${'}'}px)`)).toBe(0) + }) + + it('tolerates an unterminated interpolation', () => { + expect(countUnclosedStaticParens(`translateX(\${-(cameraX`)).toBe(1) + }) +}) diff --git a/packages/teleport-plugin-common/src/node-handlers/node-to-jsx/utils.ts b/packages/teleport-plugin-common/src/node-handlers/node-to-jsx/utils.ts index 25da0b4a7..d3d03c4ce 100644 --- a/packages/teleport-plugin-common/src/node-handlers/node-to-jsx/utils.ts +++ b/packages/teleport-plugin-common/src/node-handlers/node-to-jsx/utils.ts @@ -6,7 +6,7 @@ import { convertValueToLiteral, getExpressionFromUIDLExpressionNode, } from '../../utils/ast-utils' -import { StringUtils, UIDLUtils } from '@teleporthq/teleport-shared' +import { JSIdentifiers, StringUtils, UIDLUtils } from '@teleporthq/teleport-shared' import { UIDLPropDefinition, UIDLAttributeValue, @@ -261,10 +261,14 @@ const createPropCallStatement = ( const prefix = options.dynamicReferencePrefixMap.prop ? options.dynamicReferencePrefixMap.prop + '.' : '' + // Un-prefixed the prop name is called as a bare binding, so it must be + // identifier-safe; prefixed it is `props.`, where the UIDL spelling is + // both legal and load-bearing. + const calleeName = prefix + ? prefix + propFunctionKey + : JSIdentifiers.createSafeJSIdentifier(propFunctionKey) return t.expressionStatement( - t.callExpression(t.identifier(prefix + propFunctionKey), [ - ...args.map((arg) => convertValueToLiteral(arg)), - ]) + t.callExpression(t.identifier(calleeName), [...args.map((arg) => convertValueToLiteral(arg))]) ) } @@ -310,6 +314,12 @@ export const createStateChangeStatement = ( const statePrefix = options.dynamicReferencePrefixMap.state ? options.dynamicReferencePrefixMap.state + '.' : '' + // Reading/writing the state through a prefix (`this.class`) is a member + // access and keeps the UIDL spelling; without one the name IS the binding + // and has to match what `createStateHookAST` declared. + const stateReadName = statePrefix + ? statePrefix + stateKey + : JSIdentifiers.createSafeJSIdentifier(stateKey) const declaredType = stateDefinition.type const newState = eventHandlerStatement.newState @@ -326,7 +336,7 @@ export const createStateChangeStatement = ( ) return null } - newStateValue = t.unaryExpression('!', t.identifier(statePrefix + stateKey)) + newStateValue = t.unaryExpression('!', t.identifier(stateReadName)) } else if (typeof newState === 'object' && newState !== null) { const obj = newState as | UIDLDynamicReference @@ -473,7 +483,7 @@ export const createStateChangeStatement = ( return null } return t.expressionStatement( - t.assignmentExpression('=', t.identifier(statePrefix + stateKey), newStateValue) + t.assignmentExpression('=', t.identifier(stateReadName), newStateValue) ) } } @@ -540,7 +550,12 @@ export const resolveAndRegisterGlobalStateSource = ( for (const def of Object.values(definitions)) { if (def.id === id) { params.globalStateReferences.push({ id: def.id, name: def.name }) - return original.replace(LEGACY_GLOBAL_STATE_RE, def.name) + // The rewritten source is embedded as code, so the placeholder becomes + // the LOCAL binding — the sanitised name the destructuring declares. + return original.replace( + LEGACY_GLOBAL_STATE_RE, + JSIdentifiers.createSafeJSIdentifier(def.name) + ) } } // Legacy prefix found but no matching definition (orphaned reference). @@ -568,7 +583,11 @@ export const createGlobalStateExpression = ( definitions?: Record, t = types ): types.Identifier | types.OptionalMemberExpression => { - const name = resolveGlobalStateName(ref.content.id, definitions) + // The global-state name is destructured out of `useGlobalState()` as a local + // binding, so it goes through the same sanitiser the destructuring site uses. + const name = JSIdentifiers.createSafeJSIdentifier( + resolveGlobalStateName(ref.content.id, definitions) + ) const refPath = ref.content.refPath || [] if (refPath.length === 0) { @@ -765,8 +784,12 @@ const createDynamicValueExpressionRaw = ( const prefix = options.dynamicReferencePrefixMap[referenceType as 'prop' | 'state' | 'local'] || '' + // With no prefix the id IS the binding (React hooks: `class`), so it has to + // be sanitised exactly the way the declaration was. With a prefix it is a + // MEMBER (`props.class`, `this.class`), where a reserved word is perfectly + // legal and renaming it would point at a property that does not exist. return prefix === '' - ? t.identifier(idWithPath) + ? t.identifier(JSIdentifiers.createSafeJSIdentifierPath(idWithPath)) : t.memberExpression(t.identifier(prefix), t.identifier(idWithPath)) } @@ -1038,12 +1061,15 @@ export const createBinaryExpression = ( t = types ) => { const { operand, operation, containsField } = condition + // Same rule as `createDynamicValueExpression`: an un-prefixed key is the + // binding itself and must be identifier-safe; a prefixed one is a member + // access that has to keep the UIDL's original spelling. const identifier = conditionalIdentifier.prefix ? t.memberExpression( t.identifier(conditionalIdentifier.prefix), t.identifier(conditionalIdentifier.key) ) - : t.identifier(conditionalIdentifier.key) + : t.identifier(JSIdentifiers.createSafeJSIdentifierPath(conditionalIdentifier.key)) // Array/Object operators if (operation === 'isEmpty') { diff --git a/packages/teleport-plugin-common/src/utils/ast-utils.ts b/packages/teleport-plugin-common/src/utils/ast-utils.ts index 9ac6a0737..7b22a6058 100644 --- a/packages/teleport-plugin-common/src/utils/ast-utils.ts +++ b/packages/teleport-plugin-common/src/utils/ast-utils.ts @@ -1,7 +1,7 @@ import * as types from '@babel/types' import { parse } from '@babel/core' import ParsedASTNode from './parsed-ast' -import { StringUtils, UIDLUtils } from '@teleporthq/teleport-shared' +import { JSIdentifiers, StringUtils, UIDLUtils } from '@teleporthq/teleport-shared' import { UIDLStateDefinition, UIDLPropDefinition, @@ -16,6 +16,7 @@ import { } from '@teleporthq/teleport-types' import babelPresetReact from '@babel/preset-react' import { UnaryOperation, BinaryOperator } from './types' +import { balanceExpression, countUnclosedStaticParens } from './template-expression-balance' /** * Converts HTML attribute names to React/JSX camelCase format @@ -140,9 +141,14 @@ export const addDynamicAttributeToJSXTag = ( t = types ) => { const reactName = convertToReactAttributeName(name) + // Same rule as `createDynamicValueExpression`: with no prefix the value IS the + // binding (React hooks state), so it must match the sanitised name + // `createStateHookAST` declared — `value={class}` does not parse. With a + // prefix it is `props.class` / `this.class`, where the UIDL spelling is legal + // AND load-bearing, so it is left alone. const content = prefix === '' - ? t.identifier(value) + ? t.identifier(JSIdentifiers.createSafeJSIdentifierPath(value)) : t.memberExpression(t.identifier(prefix), t.identifier(value)) jsxASTNode.openingElement.attributes.push( @@ -354,9 +360,15 @@ export const parseStringWithTemplateExpressions = (str: string): types.TemplateL const normalized = str.replace(/state\.(\w+)/g, '$1') // Step 2: Convert well-formed {{ expr }} to ${expr} + // + // The expression is BALANCED on the way in. A binding that lost a closing + // paren upstream (`-(cameraX || ''`) produces source Babel cannot parse, and + // no amount of patching the static text around it can help — the repair has + // to happen inside the interpolation, which is the only place the bracket is + // actually missing. let templateStr = normalized.replace( /\{\{\s*(.+?)\s*\}\}/g, - (_, expr: string) => '${' + expr.trim() + '}' + (_, expr: string) => '${' + balanceExpression(expr.trim()) + '}' ) // Step 3: Handle unclosed {{ expr (no closing }}) @@ -364,16 +376,20 @@ export const parseStringWithTemplateExpressions = (str: string): types.TemplateL if (/\{\{/.test(templateStr)) { templateStr = templateStr.replace( /\{\{\s*(.+?)$/gm, - (_, expr: string) => '${' + expr.trim() + '}' + (_, expr: string) => '${' + balanceExpression(expr.trim()) + '}' ) } // Step 4: Detect and fix incomplete CSS function calls // If the original string contained a CSS function like translateX(...) or translate(...) // but the template expression consumed the closing, we need to re-close it. - const openParens = (templateStr.match(/\(/g) || []).length - const closeParens = (templateStr.match(/\)/g) || []).length - if (openParens > closeParens) { + // + // Counted over the STATIC text only. Including the parentheses inside `${…}` + // made an imbalance in the expression look like an unclosed CSS function, so + // this step appended a unit and a `)` to the end of a string whose real fault + // was several characters earlier and inside the interpolation. + const missingStaticCloses = countUnclosedStaticParens(templateStr) + if (missingStaticCloses > 0) { // Determine the CSS unit by: // 1. Looking for existing units already in the string (e.g. "translate(${x}px, ${y" → px) // 2. Inferring from the CSS function name @@ -393,22 +409,53 @@ export const parseStringWithTemplateExpressions = (str: string): types.TemplateL } } - const missingCloses = openParens - closeParens - templateStr += unit + ')'.repeat(missingCloses) + templateStr += unit + ')'.repeat(missingStaticCloses) } - const ast = parse('const x = `' + templateStr + '`', { - sourceType: 'module', - }) + // Step 5: Parse — and NEVER let a single malformed binding abort the build. + // + // The inline-style caller has no error handling of its own, so an + // unparseable template used to escape as a raw Babel SyntaxError and take the + // whole project generation down with it. A UIDL can always carry a binding + // this module cannot rescue (hand-edited, produced by an older pipeline, or + // broken in a way `balanceExpression` refuses to guess at), and the right + // answer is to degrade that ONE value: emit the original text as a plain + // string so the property still renders and the other 99 pages still build. + try { + const ast = parse('const x = `' + templateStr + '`', { + sourceType: 'module', + }) - if (!ast || !('program' in ast)) { - throw new Error(`Failed to parse template expression: ${str}`) + if (ast && 'program' in ast) { + const decl = ast.program.body[0] as types.VariableDeclaration + return decl.declarations[0].init as types.TemplateLiteral + } + } catch { + // Fall through to the static fallback below. } - const decl = ast.program.body[0] as types.VariableDeclaration - return decl.declarations[0].init as types.TemplateLiteral + return staticTemplateLiteral(stripTemplateExpressions(str)) } +/** + * Drop every `{{ … }}` binding from a string, keeping any `'literal'` fallback + * it declared. `translateX({{ -(x || 0) }}px)` → `translateX(px)` is useless as + * a style value, but `{{ name || 'Guest' }}` → `Guest` keeps the text the + * author intended. Used only when the expression could not be parsed at all. + */ +const stripTemplateExpressions = (value: string): string => + value.replace(/\{\{\s*([\s\S]*?)\s*\}\}/g, (_, expr: string) => { + const literalFallback = /\|\|\s*(['"])([\s\S]*?)\1\s*$/.exec(expr) + return literalFallback ? literalFallback[2] : '' + }) + +/** A TemplateLiteral with no interpolations, holding `value` verbatim. */ +const staticTemplateLiteral = (value: string): types.TemplateLiteral => + types.templateLiteral( + [types.templateElement({ raw: value.replace(/[\\`]/g, '\\$&'), cooked: value }, true)], + [] + ) + const REACT_BOOLEAN_DOM_PROPS = new Set([ 'disabled', 'required', @@ -931,7 +978,11 @@ export const createStateHookAST = ( return t.variableDeclaration('const', [ t.variableDeclarator( t.arrayPattern([ - t.identifier(stateKey), + // The state NAME comes from the UIDL and may be a reserved word (a + // character sheet has a column called `class`), which is fatal in + // binding position. Reads go through the same sanitiser, so the + // declaration and every reference stay in sync. + t.identifier(JSIdentifiers.createSafeJSIdentifier(stateKey)), t.identifier(StringUtils.createStateStoringFunction(stateKey)), ]), t.callExpression(t.identifier('useState'), [useStateArgument]) diff --git a/packages/teleport-plugin-common/src/utils/route-utils.ts b/packages/teleport-plugin-common/src/utils/route-utils.ts index 5b2be7929..7eb8e88c2 100644 --- a/packages/teleport-plugin-common/src/utils/route-utils.ts +++ b/packages/teleport-plugin-common/src/utils/route-utils.ts @@ -1,4 +1,5 @@ import { UIDLWorkflows } from '@teleporthq/teleport-types' +import { RoutePaths } from '@teleporthq/teleport-shared' /** * True when this UIDL component's output route contains a Next.js dynamic @@ -13,6 +14,14 @@ export const isDynamicRoute = (uidl: { ) } +/** + * Reading a route TEMPLATE (`/event-details/[id]`) rather than a URL. Defined in + * teleport-shared because the navlink resolver needs the same two functions and + * lives in a package that does not depend on this one; re-exported here so + * `RouteUtils` stays the single import for route questions in the plugins. + */ +export const { pathHasDynamicSegment, parseDynamicPathSegments } = RoutePaths + const MUTATION_NODE_TYPES = new Set(['data-create-item', 'data-update-item']) /** diff --git a/packages/teleport-plugin-common/src/utils/template-expression-balance.ts b/packages/teleport-plugin-common/src/utils/template-expression-balance.ts new file mode 100644 index 000000000..0bd1f8470 --- /dev/null +++ b/packages/teleport-plugin-common/src/utils/template-expression-balance.ts @@ -0,0 +1,196 @@ +/** + * Delimiter balancing for `{{ … }}` binding expressions. + * + * THE DEFECT THIS EXISTS FOR. `parseStringWithTemplateExpressions` converted a + * UIDL string into a template literal and then handed the result straight to + * Babel. When the binding inside was unbalanced the produced source did not + * parse, `parse()` threw, and — because the inline-style caller has no + * try/catch — the SyntaxError escaped all the way out and killed the ENTIRE + * project build: + * + * const x = `translateX(${-(cameraX || ''}px) }px)` + * ^ Unexpected token, expected "," + * + * Two separate faults produced that line. The interpolated expression + * `-(cameraX || ''` was missing its closing paren, and the "re-close the CSS + * function" step counted parentheses across the WHOLE string — including the + * ones inside `${…}` — decided one was missing, and appended `px)` to the end, + * which could never help because the imbalance was inside the interpolation. + * + * One bad binding in one style property must never cost a project its build. + * These helpers make the imbalance repairable where it actually is, and let the + * caller degrade a single value instead of aborting. + */ + +/** Closing delimiter for each opener that nests inside an expression. */ +const CLOSER_FOR_OPENER: Record = { + '(': ')', + '[': ']', + '{': '}', +} + +const CLOSERS = new Set(Object.values(CLOSER_FOR_OPENER)) +const QUOTES = new Set(["'", '"', '`']) + +export interface ExpressionScan { + /** Openers still waiting for their closer, outermost first. */ + unclosed: string[] + /** Closers that never had a matching opener. */ + strayCloserCount: number + /** The quote character still open at the end of the scan, if any. */ + unterminatedQuote: string | null +} + +/** + * Single left-to-right pass over an expression, quote and escape aware. + * Characters inside a string literal never affect nesting. + */ +export const scanExpression = (expression: string): ExpressionScan => { + const unclosed: string[] = [] + let strayCloserCount = 0 + let quote: string | null = null + + for (let index = 0; index < expression.length; index++) { + const char = expression[index] + + if (char === '\\') { + index++ + continue + } + + if (quote !== null) { + if (char === quote) { + quote = null + } + continue + } + + if (QUOTES.has(char)) { + quote = char + continue + } + + if (CLOSER_FOR_OPENER[char]) { + unclosed.push(char) + continue + } + + if (CLOSERS.has(char)) { + const expected = unclosed.length > 0 ? CLOSER_FOR_OPENER[unclosed[unclosed.length - 1]] : null + if (expected === char) { + unclosed.pop() + } else { + strayCloserCount++ + } + } + } + + return { unclosed, strayCloserCount, unterminatedQuote: quote } +} + +/** True when every quote and bracket closes and no closer is stray. */ +export const isBalancedExpression = (expression: string): boolean => { + const scan = scanExpression(expression) + return ( + scan.unclosed.length === 0 && scan.strayCloserCount === 0 && scan.unterminatedQuote === null + ) +} + +/** + * Close an expression that ends mid-quote or mid-bracket: + * `-(cameraX || ''` → `-(cameraX || '')`. + * + * Returns the expression unchanged when it is already balanced, and when the + * imbalance is a STRAY CLOSER — appending cannot fix a missing opener, and + * inventing one would be a guess. + */ +export const balanceExpression = (expression: string): string => { + const scan = scanExpression(expression) + if (scan.strayCloserCount > 0) { + return expression + } + if (scan.unclosed.length === 0 && scan.unterminatedQuote === null) { + return expression + } + + const suffix = [scan.unterminatedQuote || '', ...unclosedInReverse(scan.unclosed)].join('') + + return expression + suffix +} + +const unclosedInReverse = (unclosed: string[]): string[] => + unclosed + .slice() + .reverse() + .map((opener) => CLOSER_FOR_OPENER[opener]) + +/** + * Parenthesis balance of the STATIC parts of a template string — everything + * outside `${…}`. + * + * This is the number the "re-close the CSS function" step needs. Counting over + * the whole string mixes in the expressions' own parentheses, so an imbalance + * INSIDE an interpolation reads as a missing close on the CSS function and the + * step appends a unit and a `)` that belong nowhere. + */ +export const countUnclosedStaticParens = (templateStr: string): number => { + let depth = 0 + let index = 0 + + while (index < templateStr.length) { + if (templateStr[index] === '$' && templateStr[index + 1] === '{') { + index = skipInterpolation(templateStr, index + 2) + continue + } + if (templateStr[index] === '(') { + depth++ + } else if (templateStr[index] === ')') { + depth-- + } + index++ + } + + return depth > 0 ? depth : 0 +} + +/** + * Index just past the `}` that closes an interpolation opened at `start`. + * Tracks nested braces and string literals so `${ {a:'}'} }` is skipped whole. + * An unterminated interpolation consumes the rest of the string. + */ +const skipInterpolation = (templateStr: string, start: number): number => { + let depth = 1 + let quote: string | null = null + + for (let index = start; index < templateStr.length; index++) { + const char = templateStr[index] + + if (char === '\\') { + index++ + continue + } + + if (quote !== null) { + if (char === quote) { + quote = null + } + continue + } + + if (QUOTES.has(char)) { + quote = char + continue + } + + if (char === '{') { + depth++ + } else if (char === '}') { + depth-- + if (depth === 0) { + return index + 1 + } + } + } + + return templateStr.length +} diff --git a/packages/teleport-plugin-jsx-head-config/__tests__/index.ts b/packages/teleport-plugin-jsx-head-config/__tests__/index.ts index 179cd1bbd..df9564583 100644 --- a/packages/teleport-plugin-jsx-head-config/__tests__/index.ts +++ b/packages/teleport-plugin-jsx-head-config/__tests__/index.ts @@ -350,6 +350,56 @@ describe('plugin-jsx-head-config', () => { expect(structure.dependencies.useRouter).toBeUndefined() }) + it('Should interpolate a Next.js [id] segment in the canonical and og:url', async () => { + // A details page's canonical path is the ROUTE TEMPLATE (`/rsvp-event/[id]`). + // Emitted verbatim it publishes a URL that 404s for every crawler and every + // shared link, so it has to become `${router.query.id}`. + const uidlSample = component('SimpleComponent', elementNode('container')) + uidlSample.node.content.key = 'container' + uidlSample.seo = { + assets: [ + { + type: 'canonical', + path: 'https://example.com/rsvp-event/[id]', + }, + ], + } + + const freshChunk = createFreshJsxChunk() + const structure: ComponentStructure = { + uidl: uidlSample, + options: {}, + chunks: [freshChunk], + dependencies: {}, + } + + await plugin(structure) + + const astNode = freshChunk.meta.nodesLookup.container as types.JSXElement + const helmetNode = astNode.children[0] as types.JSXElement + expect(helmetNode.children.length).toBe(2) + + const canonicalNode = helmetNode.children[0] as types.JSXElement + const canonicalHref = canonicalNode.openingElement.attributes[1] as types.JSXAttribute + expect(canonicalHref.value.type).toBe('JSXExpressionContainer') + const canonicalCode = generator( + (canonicalHref.value as types.JSXExpressionContainer).expression as types.Expression + ).code + expect(canonicalCode).toContain('router.query.id') + expect(canonicalCode).not.toContain('[id]') + + const ogUrlMeta = helmetNode.children[1] as types.JSXElement + const ogContent = ogUrlMeta.openingElement.attributes[1] as types.JSXAttribute + expect(ogContent.value.type).toBe('JSXExpressionContainer') + const ogCode = generator( + (ogContent.value as types.JSXExpressionContainer).expression as types.Expression + ).code + expect(ogCode).toContain('router.query.id') + expect(ogCode).not.toContain('[id]') + + expect(structure.dependencies.useRouter).toBeDefined() + }) + it('Should keep static canonical when i18n has only one language', async () => { const uidlSample = component('SimpleComponent', elementNode('container')) uidlSample.node.content.key = 'container' @@ -414,6 +464,38 @@ describe('plugin-jsx-head-config', () => { const codeOf = (node: types.Node) => generator(node).code + it('Should interpolate a route parameter inside a pre-serialized JSON-LD document', async () => { + // A BreadcrumbList's last `item` is the page's own URL. For a details page + // that URL is the ROUTE TEMPLATE, so shipping the document verbatim + // published `https://example.com/event-details/[id]` — a URL no crawler can + // follow — inside structured data search engines actually parse. + const uidlSample = component('SimpleComponent', elementNode('container')) + uidlSample.node.content.key = 'container' + uidlSample.seo = { + structuredData: [ + '{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":2,"item":"https://example.com/event-details/[id]"}]}', + ], + } + + const freshChunk = createFreshJsxChunk() + const structure: ComponentStructure = { + uidl: uidlSample, + options: {}, + chunks: [freshChunk], + dependencies: {}, + } + + await plugin(structure) + + const astNode = freshChunk.meta.nodesLookup.container as types.JSXElement + const helmetNode = astNode.children[0] as types.JSXElement + const code = generator(helmetNode).code + + expect(code).toContain('router.query.id') + expect(code).not.toContain('[id]') + expect(structure.dependencies.useRouter).toBeDefined() + }) + it('Should emit a static JSON-LD script verbatim', async () => { const uidlSample = component('SimpleComponent', elementNode('container')) uidlSample.node.content.key = 'container' diff --git a/packages/teleport-plugin-jsx-head-config/src/index.ts b/packages/teleport-plugin-jsx-head-config/src/index.ts index 553f606e1..cb453f297 100644 --- a/packages/teleport-plugin-jsx-head-config/src/index.ts +++ b/packages/teleport-plugin-jsx-head-config/src/index.ts @@ -5,7 +5,7 @@ import { UIDLStaticValue, UIDLExternalDependency, } from '@teleporthq/teleport-types' -import { ASTBuilders, ASTUtils } from '@teleporthq/teleport-plugin-common' +import { ASTBuilders, ASTUtils, RouteUtils } from '@teleporthq/teleport-plugin-common' import * as types from '@babel/types' import { buildStructuredDataScript } from './structured-data-ast' @@ -56,6 +56,9 @@ export const createJSXHeadConfigPlugin: ComponentPluginFactory 1 - let routerAdded = false uidl.seo.assets.forEach((asset) => { if (asset.type === 'canonical') { @@ -253,12 +255,26 @@ export const createJSXHeadConfigPlugin: ComponentPluginFactory 0) { uidl.seo.structuredData.forEach((entry) => { - const { scriptTag, usesTranslations } = buildStructuredDataScript(entry) + const { scriptTag, usesTranslations, usesRouter } = buildStructuredDataScript(entry) if (usesTranslations && !translationsAdded) { structure.dependencies.useTranslations = USE_TRANSLATIONS_HOOK reactHooks.push(getTranslationsAST()) translationsAdded = true } + // The script interpolated a route parameter (a details page's own URL in + // a BreadcrumbList), so it needs the same `useRouter` hook the dynamic + // canonical uses. `routerAdded` is shared with the canonical branch + // above so the hook is declared exactly once. + if (usesRouter && !routerAdded) { + structure.dependencies.useRouter = { + type: 'library', + path: 'next/router', + version: '^12.1.10', + meta: { namedImport: true }, + } + reactHooks.push(getRouterAST()) + routerAdded = true + } headASTTags.push(scriptTag) }) } @@ -355,26 +371,12 @@ export const createJSXHeadConfigPlugin: ComponentPluginFactory { staticParts: ["/news/", ""], paramNames: ["slug"] } + * Splits a string into the literal text around its route parameters. + * Understands both `${slug}` and the Next.js `/[id]` form a details page's + * canonical URL actually carries — see `RouteUtils.parseDynamicPathSegments`. + * e.g. "/news/[slug]" => { staticParts: ["/news/", ""], paramNames: ["slug"] } */ - const parseDynamicSegments = (str: string): { staticParts: string[]; paramNames: string[] } => { - const regex = /\$\{([^}]+)\}/g - const staticParts: string[] = [] - const paramNames: string[] = [] - let lastIndex = 0 - let match: RegExpExecArray | null = regex.exec(str) - - while (match !== null) { - staticParts.push(str.slice(lastIndex, match.index)) - paramNames.push(match[1]) - lastIndex = regex.lastIndex - match = regex.exec(str) - } - staticParts.push(str.slice(lastIndex)) - - return { staticParts, paramNames } - } + const parseDynamicSegments = RouteUtils.parseDynamicPathSegments const buildRouterQueryParam = (paramName: string): types.MemberExpression => { return types.memberExpression( diff --git a/packages/teleport-plugin-jsx-head-config/src/structured-data-ast.ts b/packages/teleport-plugin-jsx-head-config/src/structured-data-ast.ts index 7cb7c6867..df442b815 100644 --- a/packages/teleport-plugin-jsx-head-config/src/structured-data-ast.ts +++ b/packages/teleport-plugin-jsx-head-config/src/structured-data-ast.ts @@ -1,5 +1,6 @@ import * as types from '@babel/types' import { ASTBuilders, ASTUtils } from '@teleporthq/teleport-plugin-common' +import { RoutePaths } from '@teleporthq/teleport-shared' import { UIDLStructuredDataEntry, UIDLStructuredDataNode, @@ -22,6 +23,11 @@ export interface StructuredDataScript { scriptTag: types.JSXElement /** True when any leaf resolved to a `translate.raw(...)` (locale) reference. */ usesTranslations: boolean + /** + * True when a route parameter was interpolated, so the caller must add the + * `useRouter` hook this script now depends on. + */ + usesRouter: boolean } /** @@ -184,9 +190,31 @@ const buildObject = ( export const buildStructuredDataScript = (entry: UIDLStructuredDataEntry): StructuredDataScript => { let htmlExpression: types.Expression let usesTranslations = false + let usesRouter = false if (typeof entry === 'string') { - htmlExpression = types.stringLiteral(entry) + // A pre-serialized document can still embed the page's own ROUTE TEMPLATE: + // the BreadcrumbList's last `item` is the current page's URL, which for a + // details page is `https://host/event-details/[id]`. Shipped verbatim that + // is a URL no crawler can follow, so the literal `[id]` becomes + // `${router.query.id}` exactly as the canonical link does. + const { staticParts, paramNames } = RoutePaths.parseDynamicPathSegments(entry) + if (paramNames.length === 0) { + htmlExpression = types.stringLiteral(entry) + } else { + usesRouter = true + htmlExpression = types.templateLiteral( + staticParts.map((part, index) => + types.templateElement({ raw: part, cooked: part }, index === staticParts.length - 1) + ), + paramNames.map((name) => + types.memberExpression( + types.memberExpression(types.identifier('router'), types.identifier('query')), + types.identifier(name) + ) + ) + ) + } } else { const built = buildObject(entry) usesTranslations = built.usesTranslations @@ -211,5 +239,5 @@ export const buildStructuredDataScript = (entry: UIDLStructuredDataEntry): Struc ) ) - return { scriptTag, usesTranslations } + return { scriptTag, usesTranslations, usesRouter } } diff --git a/packages/teleport-plugin-next-data-source/__tests__/refetch-loading-state.test.ts b/packages/teleport-plugin-next-data-source/__tests__/refetch-loading-state.test.ts new file mode 100644 index 000000000..4e6b90d9c --- /dev/null +++ b/packages/teleport-plugin-next-data-source/__tests__/refetch-loading-state.test.ts @@ -0,0 +1,264 @@ +import * as types from '@babel/types' +import generator from '@babel/generator' +import { + ChunkType, + FileType, + ComponentStructure, + ChunkDefinition, +} from '@teleporthq/teleport-types' +import { createNextArrayMapperPaginationPlugin } from '../src/pagination-plugin' + +// A `` shaped like the one `generateDataSourceNode` emits for an +// array mapper: a `renderSuccess` holding a `Repeater` (that is what marks it as +// an array-mapper provider) and, when the mapper has a loading state designed, +// a `renderLoading` slot. +const makeDataProviderJSX = (options: { withLoadingSlot: boolean }): types.JSXElement => { + const repeater = types.jsxElement( + types.jsxOpeningElement( + types.jsxIdentifier('Repeater'), + [ + types.jsxAttribute( + types.jsxIdentifier('renderItem'), + types.jsxExpressionContainer( + types.arrowFunctionExpression( + [types.identifier('product'), types.identifier('index')], + types.jsxElement( + types.jsxOpeningElement(types.jsxIdentifier('div'), [], true), + null, + [], + true + ) + ) + ) + ), + ], + true + ), + null, + [], + true + ) + + const attributes: types.JSXAttribute[] = [ + types.jsxAttribute( + types.jsxIdentifier('name'), + types.jsxExpressionContainer(types.stringLiteral('items')) + ), + types.jsxAttribute( + types.jsxIdentifier('renderSuccess'), + types.jsxExpressionContainer( + types.arrowFunctionExpression([types.identifier('items')], repeater) + ) + ), + ] + + if (options.withLoadingSlot) { + attributes.push( + types.jsxAttribute( + types.jsxIdentifier('renderLoading'), + types.jsxExpressionContainer( + types.arrowFunctionExpression( + [], + types.jsxElement( + types.jsxOpeningElement(types.jsxIdentifier('p'), [], true), + null, + [], + true + ) + ) + ) + ) + ) + } + + return types.jsxElement( + types.jsxOpeningElement(types.jsxIdentifier('DataProvider'), attributes, true), + null, + [], + true + ) +} + +const makeComponentChunk = (dataProvider: types.JSXElement): ChunkDefinition => { + const body = types.blockStatement([types.returnStatement(dataProvider)]) + const arrow = types.arrowFunctionExpression([types.identifier('props')], body) + const declaration = types.variableDeclaration('const', [ + types.variableDeclarator(types.identifier('ProductsList'), arrow), + ]) + return { + name: 'jsx-component', + type: ChunkType.AST, + fileType: FileType.JS, + linkAfter: [], + content: declaration, + meta: {}, + } +} + +// A `data-source-list > cms-list-repeater` UIDL. `category` decides which +// DataProvider updater runs, so every one of them is covered below. +const makeUidlNode = ( + category: 'paginated+search' | 'paginated-only' | 'search-only' | 'plain' + // tslint:disable-next-line:no-any +): any => ({ + type: 'data-source-list', + content: { + renderPropIdentifier: 'items', + resourceDefinition: { + dataSourceId: 'ds1', + tableName: 'products', + dataSourceType: 'postgresql', + }, + resource: { params: { queryColumns: { content: ['name'] } } }, + nodes: { + success: { + type: 'cms-list-repeater', + content: { + renderPropIdentifier: 'product', + paginated: category === 'paginated+search' || category === 'paginated-only', + perPage: 20, + searchEnabled: category === 'paginated+search' || category === 'search-only', + searchDebounce: 300, + nodes: { list: { type: 'element', content: { elementType: 'div' } } }, + }, + }, + }, + }, +}) + +const runPlugin = async (options: { + category?: 'paginated+search' | 'paginated-only' | 'search-only' | 'plain' + withLoadingSlot?: boolean +}): Promise => { + const dataProvider = makeDataProviderJSX({ withLoadingSlot: options.withLoadingSlot !== false }) + const chunk = makeComponentChunk(dataProvider) + const structure: ComponentStructure = { + uidl: { name: 'ProductsList', node: makeUidlNode(options.category || 'paginated+search') }, + chunks: [chunk], + dependencies: {}, + options: { dataSources: {}, extractedResources: {} }, + } as never + const plugin = createNextArrayMapperPaginationPlugin() + await plugin(structure) + return generator(chunk.content as types.Node).code +} + +describe('pagination plugin — refetch loading state', () => { + it('declares the in-flight tracking hooks and drives persistDataDuringLoading from them', async () => { + const code = await runPlugin({}) + + // The state definition that displays the loading state, plus the counter + // that keeps it honest across overlapping requests. + expect(code).toContain('const ds_0_fetchesInFlight = useRef(0)') + expect(code).toContain('const [ds_0_isFetching, setDs_0_isFetching] = useState(false)') + + // While a fetch is in flight the provider stops persisting the previous rows + // and falls through to its renderLoading slot. + expect(code).toContain('persistDataDuringLoading={!ds_0_isFetching}') + expect(code).not.toContain('persistDataDuringLoading={true}') + }) + + it('raises the flag when the request starts and lowers it once it settles', async () => { + const code = await runPlugin({}) + + // Raised synchronously, before the request is issued, so the flip is batched + // with the provider's own switch to its loading status (no intermediate paint). + expect(code).toMatch( + /ds_0_fetchesInFlight\.current \+= 1;?\s*setDs_0_isFetching\(true\);?\s*return fetch\(/ + ) + + // Lowered in `finally`, so a rejected request cannot leave it stuck on. + expect(code).toContain('.finally(() => {') + expect(code).toContain('ds_0_fetchesInFlight.current -= 1') + expect(code).toContain('setDs_0_isFetching(false)') + + // Only the LAST outstanding request lowers the flag, and the counter is + // clamped so a late settle from a remounted provider cannot drive it negative. + expect(code).toContain('if (ds_0_fetchesInFlight.current <= 0)') + expect(code).toContain('ds_0_fetchesInFlight.current = 0') + }) + + it('keeps fetchData referentially stable so the provider does not refetch in a loop', async () => { + const code = await runPlugin({}) + + // The wrapped callback only closes over a ref object and a setState setter, + // both stable across renders — the empty dependency array stays correct. + expect(code).toMatch(/fetchData=\{useCallback\(params => \{[\s\S]*?\}, \[\]\)\}/) + }) + + it.each([ + ['paginated+search' as const], + ['paginated-only' as const], + ['search-only' as const], + ['plain' as const], + ])('wires the loading state for the %s data source category', async (category) => { + const code = await runPlugin({ category }) + + expect(code).toContain('const [ds_0_isFetching, setDs_0_isFetching] = useState(false)') + expect(code).toContain('persistDataDuringLoading={!ds_0_isFetching}') + expect(code).toContain('setDs_0_isFetching(true)') + }) + + it('is idempotent — a second pass does not double-wrap fetchData', async () => { + const dataProvider = makeDataProviderJSX({ withLoadingSlot: true }) + const chunk = makeComponentChunk(dataProvider) + const structure: ComponentStructure = { + uidl: { name: 'ProductsList', node: makeUidlNode('paginated+search') }, + chunks: [chunk], + dependencies: {}, + options: { dataSources: {}, extractedResources: {} }, + } as never + const plugin = createNextArrayMapperPaginationPlugin() + + await plugin(structure) + await plugin(structure) + + const code = generator(chunk.content as types.Node).code + expect((code.match(/setDs_0_isFetching\(true\)/g) || []).length).toBe(1) + expect((code.match(/ds_0_fetchesInFlight\.current \+= 1/g) || []).length).toBe(1) + }) + + it('leaves an unmemoized fetchData alone rather than building a refetch loop', async () => { + // A `fetchData` that is re-created on every render already refetches on + // every render (DataProvider keys its effect on the fetcher identity); + // adding a setState to it would make that loop self-sustaining. Such a + // provider is skipped entirely. + const dataProvider = makeDataProviderJSX({ withLoadingSlot: true }) + dataProvider.openingElement.attributes.push( + types.jsxAttribute( + types.jsxIdentifier('fetchData'), + types.jsxExpressionContainer( + types.arrowFunctionExpression( + [types.identifier('params')], + types.callExpression(types.identifier('fetch'), [types.stringLiteral('/api/items')]) + ) + ) + ) + ) + const chunk = makeComponentChunk(dataProvider) + const structure: ComponentStructure = { + // `plain` is the only category whose updater keeps an existing fetchData + // instead of replacing it with the memoized one. + uidl: { name: 'ProductsList', node: makeUidlNode('plain') }, + chunks: [chunk], + dependencies: {}, + options: { dataSources: {}, extractedResources: {} }, + } as never + await createNextArrayMapperPaginationPlugin()(structure) + + const code = generator(chunk.content as types.Node).code + expect(code).not.toContain('ds_0_isFetching') + expect(code).not.toContain('ds_0_fetchesInFlight') + }) + + it('leaves a provider without a designed loading state untouched', async () => { + // With no renderLoading slot, dropping persistDataDuringLoading would blank + // the list out mid-refetch instead of showing something — keeping the + // previous rows is the better of the two, so nothing is wired. + const code = await runPlugin({ withLoadingSlot: false }) + + expect(code).not.toContain('ds_0_isFetching') + expect(code).not.toContain('ds_0_fetchesInFlight') + expect(code).toContain('persistDataDuringLoading={true}') + }) +}) diff --git a/packages/teleport-plugin-next-data-source/src/loading-state.ts b/packages/teleport-plugin-next-data-source/src/loading-state.ts new file mode 100644 index 000000000..a477c2d71 --- /dev/null +++ b/packages/teleport-plugin-next-data-source/src/loading-state.ts @@ -0,0 +1,297 @@ +import * as types from '@babel/types' + +/** + * ------------------------------------------------------------------ + * Refetch loading state for array-mapper `DataProvider`s + * ------------------------------------------------------------------ + * + * `DataProvider` (from `@teleporthq/react-components`) renders its LOADING + * slot only when it has no data to show: + * + * case "idle": + * case "loading": + * return props.persistDataDuringLoading && data + * ? renderSuccess(data, true) + * : renderLoading() + * + * Every generated array-mapper list ships `persistDataDuringLoading={true}`, + * and that flag is load-bearing on the FIRST paint: when the page prefetches + * rows in `getStaticProps` and hands them over as `initialData`, the provider + * deliberately skips its first client fetch and therefore never leaves the + * `idle` status. Without the flag that page would render the loading slot + * forever instead of the prefetched rows. + * + * The side effect is that once the provider owns data, EVERY later refetch is + * invisible: changing the category filter, the sort order or the search term + * re-runs the query while the stale rows stay on screen, so the buyer gets no + * feedback until the new rows pop in. (Page changes and search changes also + * remount the provider through its `key`, which resets `data` — but a filter + * or sort change keeps the same key, so nothing at all happens visually.) + * + * The provider does pass an `isLoading` flag as the second argument of + * `renderSuccess`, but it is `true` for the `idle` status as well — i.e. + * permanently true on any page that skipped its first fetch because it had + * `initialData` — so it cannot be used to decide what to paint. + * + * Fix: track the in-flight fetches of each data source in the PAGE component + * and hand `persistDataDuringLoading` the negated flag. `fetchData` is the one + * function the generator owns and the provider calls exactly once per fetch, so + * it is where the flag is raised (`true` when the request starts) and lowered + * (`false` once it settles, success or failure). While a refetch is in flight + * `persistDataDuringLoading` is `false`, so the provider falls through to + * `renderLoading()` and the array mapper's designed loading state shows; when + * the request settles the flag drops back to `true` and the rows return. + * + * Why not branch inside `renderSuccess` instead: the loading JSX would have to + * be duplicated into the success render prop, and `styled-jsx` only scopes JSX + * that lives inside the component's returned tree — every workaround that + * hoists the loading markup into a shared local helper silently loses its + * `jsx-` class and therefore all of its styles. + * + * Nothing changes for a provider that is idle or mounting: `isFetching` starts + * at `false`, so the server render and the first client render are identical + * (no hydration mismatch) and the `initialData` fast path is untouched. + */ + +export interface LoadingStateVars { + /** Boolean state: `true` while at least one fetch for this data source is in flight. */ + isFetchingVar: string + /** Setter for `isFetchingVar`. */ + setIsFetchingVar: string + /** + * Ref holding the number of fetches currently in flight. A boolean alone is + * not enough: two controls changed in quick succession (e.g. category then + * sort) start two overlapping requests, and the first one to settle would + * otherwise lower the flag while the second is still running — flashing the + * stale rows back for the rest of the second request. + */ + inFlightRefVar: string +} + +export function getLoadingStateVars(index: number): LoadingStateVars { + return { + isFetchingVar: `ds_${index}_isFetching`, + setIsFetchingVar: `setDs_${index}_isFetching`, + inFlightRefVar: `ds_${index}_fetchesInFlight`, + } +} + +/** + * `const ds_N_fetchesInFlight = useRef(0)` + * `const [ds_N_isFetching, setDs_N_isFetching] = useState(false)` + * + * Both are stable across renders (a ref object and a `useState` setter), which + * is what lets the wrapped `fetchData` keep its empty `useCallback` dependency + * array — a changing `fetchData` identity would retrigger the provider's fetch + * effect on every render. + */ +export function buildLoadingStateDeclarations(vars: LoadingStateVars): types.Statement[] { + return [ + types.variableDeclaration('const', [ + types.variableDeclarator( + types.identifier(vars.inFlightRefVar), + types.callExpression(types.identifier('useRef'), [types.numericLiteral(0)]) + ), + ]), + types.variableDeclaration('const', [ + types.variableDeclarator( + types.arrayPattern([ + types.identifier(vars.isFetchingVar), + types.identifier(vars.setIsFetchingVar), + ]), + types.callExpression(types.identifier('useState'), [types.booleanLiteral(false)]) + ), + ]), + ] +} + +/** + * Wires the refetch loading state into a single `DataProvider` JSX element. + * + * No-ops (returning `false`, so the caller emits no state declarations) when + * the provider cannot benefit from it: + * - no `renderLoading` slot — the array mapper has no loading state designed, + * so falling through to it would blank the list out instead of showing + * something; keeping the stale rows is the better of the two. + * - `fetchData` missing, not memoized, or not an expression-bodied promise + * chain — see `findMemoizedFetchDataArrow`. + * - already wired — keeps a second pass over the same AST idempotent. + */ +export function applyLoadingStateToDataProvider( + // tslint:disable-next-line:no-any + dataProvider: any, + vars: LoadingStateVars +): boolean { + const attributes = dataProvider?.openingElement?.attributes + if (!Array.isArray(attributes)) { + return false + } + + if (!findAttribute(attributes, 'renderLoading')) { + return false + } + + const fetchDataAttr = findAttribute(attributes, 'fetchData') + if (!fetchDataAttr) { + return false + } + + const fetchArrow = findMemoizedFetchDataArrow(fetchDataAttr) + if (!fetchArrow || fetchArrow.body.type !== 'CallExpression') { + return false + } + + fetchArrow.body = buildTrackedFetchBody(fetchArrow.body, vars) + + setPersistDataDuringLoading(attributes, vars) + + return true +} + +// tslint:disable-next-line:no-any +function findAttribute(attributes: any[], name: string): types.JSXAttribute | undefined { + return attributes.find( + // tslint:disable-next-line:no-any + (attr: any) => attr?.type === 'JSXAttribute' && attr.name?.name === name + ) +} + +/** + * The `useCallback(fn, [])`-wrapped arrow behind a `fetchData` attribute, or + * `undefined` when the value has any other shape. + * + * Requiring the memoized form is a safety condition, not a convenience. + * `DataProvider` refetches whenever the `fetchData` identity changes + * (`useEffect(..., [params, fetchData])`), so wrapping a fetcher that is + * re-created on every render with something that sets state would build a + * self-sustaining loop: fetch → setState → render → new fetcher identity → + * fetch. The array-mapper providers this plugin owns are always memoized; the + * few unmemoized `fetchData` values other plugins emit are left exactly as they + * are today. + */ +function findMemoizedFetchDataArrow( + attribute: types.JSXAttribute +): types.ArrowFunctionExpression | undefined { + const value = attribute.value + if (!value || value.type !== 'JSXExpressionContainer') { + return undefined + } + + const expression = value.expression + if ( + expression.type !== 'CallExpression' || + expression.callee.type !== 'Identifier' || + expression.callee.name !== 'useCallback' || + expression.arguments[0]?.type !== 'ArrowFunctionExpression' + ) { + return undefined + } + + return expression.arguments[0] as types.ArrowFunctionExpression +} + +/** + * Turns `(params) => fetch(...).then(...)` into + * + * (params) => { + * ds_N_fetchesInFlight.current += 1 + * setDs_N_isFetching(true) + * return fetch(...).then(...).finally(() => { + * ds_N_fetchesInFlight.current -= 1 + * if (ds_N_fetchesInFlight.current <= 0) { + * ds_N_fetchesInFlight.current = 0 + * setDs_N_isFetching(false) + * } + * }) + * } + * + * `finally` (rather than a `then` pair) keeps the flag honest when the request + * rejects: the provider switches to its error status and the loading state must + * not stay on screen. The counter is clamped at 0 so a late settle from a + * provider instance that was remounted through its `key` can never drive it + * negative and wedge the flag on. + * + * `fetchExpression` is the `fetch(...).then(...).then(...)` chain the generator + * emitted, so `.finally` is always available on it — the caller only reaches + * here for a call-expression body. + */ +function buildTrackedFetchBody( + fetchExpression: types.Expression, + vars: LoadingStateVars +): types.BlockStatement { + const inFlightCount = types.memberExpression( + types.identifier(vars.inFlightRefVar), + types.identifier('current') + ) + + const settleHandler = types.arrowFunctionExpression( + [], + types.blockStatement([ + types.expressionStatement( + types.assignmentExpression( + '-=', + types.cloneNode(inFlightCount, true), + types.numericLiteral(1) + ) + ), + types.ifStatement( + types.binaryExpression('<=', types.cloneNode(inFlightCount, true), types.numericLiteral(0)), + types.blockStatement([ + types.expressionStatement( + types.assignmentExpression( + '=', + types.cloneNode(inFlightCount, true), + types.numericLiteral(0) + ) + ), + types.expressionStatement( + types.callExpression(types.identifier(vars.setIsFetchingVar), [ + types.booleanLiteral(false), + ]) + ), + ]) + ), + ]) + ) + + return types.blockStatement([ + types.expressionStatement( + types.assignmentExpression( + '+=', + types.cloneNode(inFlightCount, true), + types.numericLiteral(1) + ) + ), + types.expressionStatement( + types.callExpression(types.identifier(vars.setIsFetchingVar), [types.booleanLiteral(true)]) + ), + types.returnStatement( + types.callExpression(types.memberExpression(fetchExpression, types.identifier('finally')), [ + settleHandler, + ]) + ), + ]) +} + +/** `persistDataDuringLoading={!ds_N_isFetching}`, replacing any existing value. */ +// tslint:disable-next-line:no-any +function setPersistDataDuringLoading(attributes: any[], vars: LoadingStateVars): void { + const attribute = types.jsxAttribute( + types.jsxIdentifier('persistDataDuringLoading'), + types.jsxExpressionContainer( + types.unaryExpression('!', types.identifier(vars.isFetchingVar), true) + ) + ) + + const existingIndex = attributes.findIndex( + // tslint:disable-next-line:no-any + (attr: any) => attr?.type === 'JSXAttribute' && attr.name?.name === 'persistDataDuringLoading' + ) + + if (existingIndex === -1) { + attributes.push(attribute) + return + } + + attributes[existingIndex] = attribute +} diff --git a/packages/teleport-plugin-next-data-source/src/pagination-plugin.ts b/packages/teleport-plugin-next-data-source/src/pagination-plugin.ts index c6e832631..ddb1cf861 100644 --- a/packages/teleport-plugin-next-data-source/src/pagination-plugin.ts +++ b/packages/teleport-plugin-next-data-source/src/pagination-plugin.ts @@ -13,6 +13,11 @@ import { generateSafeFileName } from './utils' import { generateDataSourceFetcherWithCore } from './data-source-fetchers' import { appendSortsParam, DynamicSortAST, extractDynamicSort } from './sort-utils' import { appendFiltersParam, pushStateIdsAsDeps, pushPropIdsAsDeps } from './filter-utils' +import { + applyLoadingStateToDataProvider, + buildLoadingStateDeclarations, + getLoadingStateVars, +} from './loading-state' // ----- searchDefaultValue support ----- // @@ -1498,6 +1503,12 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> = // We use pure order-based matching - the order of DataProviders in JSX should match UIDL order const usageIndexByDataSourceId = new Map() + // `useRef` / `useState` pairs backing the refetch loading state of every + // DataProvider that ended up wired below. Collected here because whether a + // provider can use one depends on its JSX (it needs a `renderLoading` slot), + // which is only known once the category updaters above have run. + const loadingStateDeclarations: types.Statement[] = [] + dataProvidersWithRepeaters.forEach((dp) => { const nameAttr = dp.openingElement.attributes.find( (attr: any) => attr.type === 'JSXAttribute' && attr.name.name === 'name' @@ -1537,6 +1548,15 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> = updateDataProviderForPlain(dp, fileName, usage) } + // Show the array mapper's loading state while a category/sort/search + // change refetches, instead of leaving the previous rows on screen with + // no feedback. Runs last so it sees the `fetchData` and + // `persistDataDuringLoading` attributes the updaters above just wrote. + const loadingVars = getLoadingStateVars(usage.index) + if (applyLoadingStateToDataProvider(dp, loadingVars)) { + loadingStateDeclarations.push(...buildLoadingStateDeclarations(loadingVars)) + } + // Create API route for all categories (including 'plain' for components) ensureAPIRouteExists( options.extractedResources, @@ -1546,6 +1566,11 @@ export const createNextArrayMapperPaginationPlugin: ComponentPluginFactory<{}> = ) }) + // Declare the loading-state hooks alongside the other data-source state, at + // the top of the component body. Unconditional and in a fixed order, so the + // hook order stays stable across renders. + loadingStateDeclarations.reverse().forEach((s) => blockStatement.body.unshift(s)) + // STEP 3.5: Handle DataProviders WITHOUT repeaters (data-source-item type) // These access single items like data[0].name and should not re-render on state changes // We wrap their params in useMemo to prevent reference changes from triggering re-renders diff --git a/packages/teleport-plugin-next-workflows/__tests__/auth-env-secret-preservation.test.ts b/packages/teleport-plugin-next-workflows/__tests__/auth-env-secret-preservation.test.ts index a164ef28f..a50687184 100644 --- a/packages/teleport-plugin-next-workflows/__tests__/auth-env-secret-preservation.test.ts +++ b/packages/teleport-plugin-next-workflows/__tests__/auth-env-secret-preservation.test.ts @@ -118,4 +118,39 @@ describe('resolveAuthEnvValue', () => { expect(resolveAuthEnvValue('TELEPORT_DB_SSL', 'true', oauthKeys)).toBe('true') expect(resolveAuthEnvValue('AUTH_CREDENTIALS_ENABLED', 'true', oauthKeys)).toBe('true') }) + + // Regression: next-auth v4 `react/index.js` runs `parseUrl(process.env.NEXTAUTH_URL)` + // at module load, and `new URL('')` throws "Invalid URL" — crashing SSR for + // every page that mounts SessionProvider. `createEnvFiles` writes every key, + // so a BLANK NEXTAUTH_URL serializes as the crashing `NEXTAUTH_URL=`. The + // blank case is self-perpetuating (the standalone harness re-injects the + // on-disk empty value), so the resolver must heal it, not pass it through. + describe('blank auth-critical keys heal to their local default', () => { + it.each(['', ' ', undefined as unknown as string])( + 'NEXTAUTH_URL=%p becomes the localhost default rather than an empty assignment', + (blank) => { + expect(resolveAuthEnvValue('NEXTAUTH_URL', blank, oauthKeys)).toBe('http://localhost:3000') + } + ) + + it('a blank NEXTAUTH_SECRET heals to the placeholder default', () => { + expect(resolveAuthEnvValue('NEXTAUTH_SECRET', '', oauthKeys)).toBe( + 'CHANGE_ME_TO_A_RANDOM_SECRET' + ) + }) + + it('a real configured NEXTAUTH_URL / NEXTAUTH_SECRET is left untouched', () => { + expect(resolveAuthEnvValue('NEXTAUTH_URL', 'https://shop.example.com', oauthKeys)).toBe( + 'https://shop.example.com' + ) + expect( + resolveAuthEnvValue('NEXTAUTH_SECRET', 'a-real-32-char-secret-value-xxxxx', oauthKeys) + ).toBe('a-real-32-char-secret-value-xxxxx') + }) + + it('a blank NON-auth key still serializes blank — no behavior change outside the two auth keys', () => { + expect(resolveAuthEnvValue('TELEPORT_DB_SSL', '', oauthKeys)).toBe('') + expect(resolveAuthEnvValue('SOME_OTHER_KEY', '', oauthKeys)).toBe('') + }) + }) }) diff --git a/packages/teleport-plugin-next-workflows/__tests__/auth-nextauth-url.test.ts b/packages/teleport-plugin-next-workflows/__tests__/auth-nextauth-url.test.ts index be73e7d8e..fd30330fd 100644 --- a/packages/teleport-plugin-next-workflows/__tests__/auth-nextauth-url.test.ts +++ b/packages/teleport-plugin-next-workflows/__tests__/auth-nextauth-url.test.ts @@ -56,4 +56,32 @@ describe('generated NextAuth route — dynamic NEXTAUTH_URL', () => { handler({ headers: { host: 'localhost:3000' } }, {}) expect(process.env.NEXTAUTH_URL).toBe('http://localhost:3000') }) + + // Project a62338f9 published with `NEXTAUTH_URL=teleporthq.secrets.NEXTAUTH_URL`. + // The old check saw a non-empty, non-localhost string and treated it as + // explicitly configured, so NextAuth normalised it to + // `https://teleporthq.secrets.nextauth_url`, advertised that as the sign-in + // origin and issued `__Host-`/`__Secure-` cookies against it. Sign-in failed + // with a bare `credentialsSignin`. An unresolved placeholder is now treated + // as unset, so an already-published site self-heals on its next request. + it('overrides an unresolved secret placeholder on a published domain', () => { + process.env.NEXTAUTH_URL = 'teleporthq.secrets.NEXTAUTH_URL' + handler( + { headers: { host: 'rare-last-dunlin.teleporthq.dev', 'x-forwarded-proto': 'https' } }, + {} + ) + expect(process.env.NEXTAUTH_URL).toBe('https://rare-last-dunlin.teleporthq.dev') + }) + + it('falls back to an http origin locally, so cookies are not Secure-prefixed', () => { + process.env.NEXTAUTH_URL = 'teleporthq.secrets.NEXTAUTH_URL' + handler({ headers: { host: 'localhost:3001' } }, {}) + expect(process.env.NEXTAUTH_URL).toBe('http://localhost:3001') + }) + + it('overrides any value that is not an absolute http(s) origin', () => { + process.env.NEXTAUTH_URL = 'my-app.teleporthq.dev' + handler({ headers: { host: 'my-app.teleporthq.dev', 'x-forwarded-proto': 'https' } }, {}) + expect(process.env.NEXTAUTH_URL).toBe('https://my-app.teleporthq.dev') + }) }) diff --git a/packages/teleport-plugin-next-workflows/__tests__/auth-session-cost.test.ts b/packages/teleport-plugin-next-workflows/__tests__/auth-session-cost.test.ts new file mode 100644 index 000000000..fad0711a0 --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/auth-session-cost.test.ts @@ -0,0 +1,614 @@ +/* tslint:disable:no-eval */ +import { + generateAuthOptionsFile, + generateSessionProviderWrapper, + generateNextAuthUrlGuardModule, + buildSessionUserFields, + SENSITIVE_USER_FIELDS, + USER_REFRESH_INTERVAL_MS, +} from '../src/auth-generator' +import { accountGetCurrent } from '../src/nodes/account/account-get-current' +import { UIDLAuthentication, UIDLAuthTableColumn } from '@teleporthq/teleport-types' + +// /api/auth/session measured ~925ms on a published deployment against ~210ms +// for the same route with no session cookie. The whole delta was the `jwt` +// callback re-reading the `users` row through a fresh unpooled pg connection on +// EVERY request — while `strategy: 'jwt'` exists precisely so a session costs no +// database round trip. On top of that, `account-get-current` fetched that +// endpoint again on every click that resolves the current user, serially ahead +// of the workflow's own request, for a session `_app`'s SessionProvider already +// held in memory. And the payload carried every column `SELECT *` returned, +// including the OAuth single-table adapter's provider tokens. + +// The canonical `users` columns the GUI emits (authentication/flows/utils.ts), +// which the UIDL mapper then appends one column per custom account property to. +const CANONICAL_USERS_COLUMNS: UIDLAuthTableColumn[] = [ + { name: 'id', type: 'UUID', nullable: false, isPrimaryKey: true }, + { name: 'name', type: 'VARCHAR(255)', nullable: true }, + { name: 'email', type: 'VARCHAR(255)', nullable: true }, + { name: 'phone', type: 'VARCHAR(255)', nullable: true }, + { name: 'details', type: 'TEXT', nullable: true }, + { name: 'email_verified', type: 'TIMESTAMPTZ', nullable: true }, + { name: 'password', type: 'TEXT', nullable: true }, + { name: 'provider', type: 'VARCHAR(255)', nullable: true }, + { name: 'provider_account_id', type: 'VARCHAR(255)', nullable: true }, + { name: 'provider_type', type: 'VARCHAR(255)', nullable: true }, + { name: 'access_token', type: 'TEXT', nullable: true }, + { name: 'refresh_token', type: 'TEXT', nullable: true }, + { name: 'expires_at', type: 'BIGINT', nullable: true }, + { name: 'id_token', type: 'TEXT', nullable: true }, + { name: 'scope', type: 'TEXT', nullable: true }, + { name: 'session_state', type: 'TEXT', nullable: true }, + { name: 'token_type', type: 'TEXT', nullable: true }, + { name: 'email_unsubscribed', type: 'BOOLEAN', nullable: false }, + { name: 'sms_unsubscribed', type: 'BOOLEAN', nullable: false }, + { name: 'image', type: 'TEXT', nullable: true }, + { name: 'role', type: 'VARCHAR(255)', nullable: false }, + { name: 'created_at', type: 'TIMESTAMPTZ', nullable: false }, + { name: 'updated_at', type: 'TIMESTAMPTZ', nullable: false }, +] + +const CUSTOM_PROPS = [ + { + key: 'company', + label: 'Company', + columnType: 'VARCHAR(255)', + attributeType: 'string' as const, + }, + { + key: 'loyalty_points', + label: 'Loyalty Points', + columnType: 'INTEGER', + attributeType: 'number' as const, + }, +] + +const buildAuth = (overrides: Partial = {}): UIDLAuthentication => + ({ + enabled: true, + dataSourceId: 'ds-1', + dataSourceType: 'postgresql', + passwordAuthEnabled: true, + providers: [], + roles: ['user', 'admin'], + tables: { + users: [ + ...CANONICAL_USERS_COLUMNS, + { name: 'company', type: 'VARCHAR(255)', nullable: true }, + { name: 'loyalty_points', type: 'INTEGER', nullable: true }, + ], + }, + pageProtection: {}, + folderProtection: {}, + authPages: {}, + callbackBaseUrl: '/api/auth/callback', + envKeys: {}, + customUserProperties: CUSTOM_PROPS, + ...overrides, + } as UIDLAuthentication) + +/** + * Boots the generated auth-options file with `pg` stubbed, and reports how many + * `SELECT ... FROM users` queries the callbacks actually issue. + */ +const bootAuthOptions = (auth: UIDLAuthentication) => { + const code = generateAuthOptionsFile(auth, null) + const queries: string[] = [] + + class FakeClient { + public async connect(): Promise { + return undefined + } + public async query(text: string): Promise<{ rows: Array> }> { + queries.push(text) + return { rows: [{ id: 'u-1', email: 'ada@example.com', name: 'Ada', role: 'admin' }] } + } + public async end(): Promise { + return undefined + } + } + + const fakeRequire = (name: string): any => { + if (name === 'pg') { + return { Client: FakeClient } + } + const provider = (config: unknown) => config + ;(provider as any).default = provider + return provider + } + + const moduleObject: { exports: any } = { exports: {} } + // tslint:disable-next-line:function-constructor + new Function('require', 'module', 'exports', 'process', code)( + fakeRequire, + moduleObject, + moduleObject.exports, + { env: { TELEPORT_DB_CONNECTION_STRING: 'postgres://stub' } } + ) + + return { authOptions: moduleObject.exports, queries, code } +} + +describe('sanitizeUser allow-list', () => { + it('keeps every custom account property the project declared', () => { + const fields = buildSessionUserFields(buildAuth().tables, CUSTOM_PROPS) + expect(fields).toContain('company') + expect(fields).toContain('loyalty_points') + }) + + it('keeps custom properties even when the UIDL carries no users table', () => { + const fields = buildSessionUserFields(undefined, CUSTOM_PROPS) + expect(fields).toContain('company') + expect(fields).toContain('loyalty_points') + expect(fields).toEqual(expect.arrayContaining(['id', 'name', 'email', 'image', 'role'])) + }) + + it('keeps the non-credential profile columns pages bind to', () => { + const fields = buildSessionUserFields(buildAuth().tables, CUSTOM_PROPS) + for (const field of [ + 'id', + 'name', + 'email', + 'image', + 'role', + 'phone', + 'details', + 'email_verified', + 'email_unsubscribed', + 'sms_unsubscribed', + 'created_at', + 'updated_at', + // Just the provider's name ("google") — account-social-login declares it. + 'provider', + ]) { + expect(fields).toContain(field) + } + }) + + it('keeps the alternate role spellings the generated middleware falls back to', () => { + const fields = buildSessionUserFields(buildAuth().tables, CUSTOM_PROPS) + expect(fields).toContain('roleName') + expect(fields).toContain('roles') + }) + + it('drops the password hash and every OAuth provider credential', () => { + const fields = buildSessionUserFields(buildAuth().tables, CUSTOM_PROPS) + for (const secret of SENSITIVE_USER_FIELDS) { + expect(fields).not.toContain(secret) + } + expect(fields).not.toContain('access_token') + expect(fields).not.toContain('refresh_token') + expect(fields).not.toContain('id_token') + }) + + it('folds _id into id rather than emitting both', () => { + const fields = buildSessionUserFields( + { users: [{ name: '_id', type: 'TEXT', nullable: false }] }, + [] + ) + expect(fields).not.toContain('_id') + expect(fields).toContain('id') + }) + + it('cannot be re-opened by a custom property named after a credential', () => { + const fields = buildSessionUserFields(buildAuth().tables, [ + { + key: 'access_token', + label: 'Access Token', + columnType: 'TEXT', + attributeType: 'string' as const, + }, + ]) + expect(fields).not.toContain('access_token') + }) + + it('strips credentials from a real row at runtime', () => { + const { authOptions } = bootAuthOptions(buildAuth()) + const safe = (authOptions as any).sanitizeUser({ + id: 'u-1', + email: 'ada@example.com', + name: 'Ada', + role: 'admin', + company: 'Teleport', + loyalty_points: 42, + password: '$2b$10$hash', + access_token: 'ya29.secret', + refresh_token: '1//refresh-secret', + id_token: 'eyJhbGciOi.secret', + session_state: 'state-secret', + scope: 'openid email', + token_type: 'Bearer', + provider_account_id: '11223344', + }) + + expect(safe).toEqual({ + id: 'u-1', + email: 'ada@example.com', + name: 'Ada', + role: 'admin', + company: 'Teleport', + loyalty_points: 42, + }) + expect(JSON.stringify(safe)).not.toContain('secret') + }) +}) + +describe('jwt callback does not re-read the database on every session request', () => { + it('reads the user once, then serves the token from the JWT for the interval', async () => { + const { authOptions, queries } = bootAuthOptions(buildAuth()) + const token: Record = { email: 'ada@example.com' } + + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + + await authOptions.callbacks.jwt({ token }) + await authOptions.callbacks.jwt({ token }) + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + }) + + it('refreshes immediately on trigger "update" — a profile save is never stale', async () => { + const { authOptions, queries } = bootAuthOptions(buildAuth()) + const token: Record = { email: 'ada@example.com' } + + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + + await authOptions.callbacks.jwt({ token, trigger: 'update' }) + expect(queries.length).toBe(2) + }) + + it('re-reads once the interval has elapsed', async () => { + const { authOptions, queries } = bootAuthOptions(buildAuth()) + const token: Record = { email: 'ada@example.com' } + + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + + // Backdate the stamp past the interval instead of waiting on a real clock. + token.__userRefreshedAt = Date.now() - USER_REFRESH_INTERVAL_MS - 1 + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(2) + }) + + it('treats a backwards clock jump as stale rather than trusting the stamp', async () => { + const { authOptions, queries } = bootAuthOptions(buildAuth()) + const token: Record = { email: 'ada@example.com' } + + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + + token.__userRefreshedAt = Date.now() + 60 * 60 * 1000 + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(2) + }) + + it('does NOT stamp on the login branch, so an OAuth user still gets their role', async () => { + const { authOptions, queries } = bootAuthOptions(buildAuth()) + // An OAuth `user` is the provider profile: no `role`, which lives only on + // the users row. Stamping here would leave the visitor role-less for a whole + // interval and silently fail role-protected routes. + const token: Record = {} + await authOptions.callbacks.jwt({ + token, + user: { id: 'u-1', email: 'ada@example.com', name: 'Ada', image: null }, + }) + expect(queries.length).toBe(0) + expect(token.__userRefreshedAt).toBeUndefined() + + await authOptions.callbacks.jwt({ token }) + expect(queries.length).toBe(1) + expect(token.role).toBe('admin') + }) + + it('costs one attempt per interval — not one per request — when the database is down', async () => { + const auth = buildAuth() + const code = generateAuthOptionsFile(auth, null) + let attempts = 0 + + class BrokenClient { + public async connect(): Promise { + attempts += 1 + throw new Error('ECONNREFUSED') + } + public async query(): Promise<{ rows: Array> }> { + return { rows: [] } + } + public async end(): Promise { + return undefined + } + } + + const fakeRequire = (name: string): any => { + if (name === 'pg') { + return { Client: BrokenClient } + } + const provider = (config: unknown) => config + ;(provider as any).default = provider + return provider + } + const moduleObject: { exports: any } = { exports: {} } + // tslint:disable-next-line:function-constructor + new Function('require', 'module', 'exports', 'process', code)( + fakeRequire, + moduleObject, + moduleObject.exports, + { env: { TELEPORT_DB_CONNECTION_STRING: 'postgres://stub' } } + ) + + const token: Record = { email: 'ada@example.com' } + await moduleObject.exports.callbacks.jwt({ token }) + await moduleObject.exports.callbacks.jwt({ token }) + await moduleObject.exports.callbacks.jwt({ token }) + + expect(attempts).toBe(1) + // Never signs the user out on a DB hiccup. + expect(token.email).toBe('ada@example.com') + }) + + it('never copies the refresh bookkeeping onto session.user', async () => { + const { authOptions } = bootAuthOptions(buildAuth()) + const token: Record = { email: 'ada@example.com' } + await authOptions.callbacks.jwt({ token }) + expect(token.__userRefreshedAt).toEqual(expect.any(Number)) + + const session = await authOptions.callbacks.session({ session: { user: {} }, token }) + expect(session.user.__userRefreshedAt).toBeUndefined() + expect(session.user.iat).toBeUndefined() + expect(session.user.exp).toBeUndefined() + expect(session.user.email).toBe('ada@example.com') + }) +}) + +describe('nextauth-url guard prevents the empty-NEXTAUTH_URL SSR crash', () => { + // next-auth v4 `react/index.js` calls `parseUrl(process.env.NEXTAUTH_URL)` at + // MODULE LOAD; `new URL('')` throws "Invalid URL", crashing SSR for every page + // that mounts SessionProvider. The guard runs first and normalizes the value. + const guard = generateNextAuthUrlGuardModule() + + // Execute the guard body against a stubbed process, the way it runs at import. + const runGuard = ( + env: Record + ): Record => { + const body = guard.replace(/export\s*\{\s*\}\s*;?\s*$/, '') + const stubProcess = { env } + // tslint:disable-next-line:function-constructor + new Function('process', body)(stubProcess) + return env + } + + it('deletes an empty NEXTAUTH_URL so next-auth falls back to its default', () => { + const env: Record = { NEXTAUTH_URL: '' } + runGuard(env) + expect('NEXTAUTH_URL' in env).toBe(false) + }) + + it('deletes a whitespace-only NEXTAUTH_URL', () => { + const env: Record = { NEXTAUTH_URL: ' ' } + runGuard(env) + expect('NEXTAUTH_URL' in env).toBe(false) + }) + + it('also normalizes empty NEXTAUTH_URL_INTERNAL and VERCEL_URL', () => { + const env: Record = { + NEXTAUTH_URL_INTERNAL: '', + VERCEL_URL: ' ', + } + runGuard(env) + expect('NEXTAUTH_URL_INTERNAL' in env).toBe(false) + expect('VERCEL_URL' in env).toBe(false) + }) + + it('leaves a real configured NEXTAUTH_URL untouched', () => { + const env: Record = { NEXTAUTH_URL: 'https://shop.example.com' } + runGuard(env) + expect(env.NEXTAUTH_URL).toBe('https://shop.example.com') + }) + + it('leaves an UNSET NEXTAUTH_URL unset (never introduces a bogus value)', () => { + const env: Record = {} + runGuard(env) + expect('NEXTAUTH_URL' in env).toBe(false) + }) + + it('a stubbed next-auth/react module-load pattern no longer throws after the guard runs', () => { + // Mirror of next-auth/react's module-scope `parseUrl(process.env.NEXTAUTH_URL)` + // (parse-url.js: `new URL(url ?? default)` — empty string is NOT nullish, so + // it reaches new URL and throws). + const nextAuthModuleLoad = (processEnv: Record) => { + const url = processEnv.NEXTAUTH_URL + // eslint-disable-next-line no-new + new URL(url != null ? url : 'http://localhost:3000/api/auth') + } + const env: Record = { NEXTAUTH_URL: '' } + expect(() => nextAuthModuleLoad(env)).toThrow() // reproduces the crash + runGuard(env) + expect(() => nextAuthModuleLoad(env)).not.toThrow() // fixed by the guard + }) +}) + +describe('session provider republishes the in-memory session', () => { + const code = generateSessionProviderWrapper() + + it('imports the nextauth-url guard FIRST, before next-auth/react', () => { + const guardIdx = code.indexOf("import './nextauth-url-guard'") + const nextAuthIdx = code.indexOf("from 'next-auth/react'") + expect(guardIdx).toBeGreaterThanOrEqual(0) + expect(nextAuthIdx).toBeGreaterThan(guardIdx) + // It must be the very first non-empty line so nothing imports next-auth/react + // before it in the module graph. + expect(code.trimStart().startsWith("import './nextauth-url-guard'")).toBe(true) + }) + + it('subscribes to the session context from inside SessionProvider', () => { + expect(code).toContain( + "import { SessionProvider, signIn, signOut, useSession } from 'next-auth/react'" + ) + expect(code).toContain('function SessionSnapshotBridge()') + expect(code).toContain('React.createElement(SessionSnapshotBridge') + }) + + it('exposes getSession and refreshSession on the existing window bridge', () => { + expect(code).toContain('window.__teleportNextAuth = teleportNextAuth') + expect(code).toContain('getSession: function ()') + expect(code).toContain('refreshSession: function ()') + // The bridge object is assigned to window ONCE and mutated in place, so a + // handler that captured it earlier still observes the current session. + expect(code).toContain('teleportNextAuth.status = status') + expect(code).toContain('teleportNextAuth.session = data || null') + }) + + it('stops refetching the session on every window focus', () => { + expect(code).toContain('refetchOnWindowFocus: false') + }) + + it('mirrors in an effect, never during render', () => { + expect(code).toContain('React.useEffect(') + const renderBody = code.slice(code.indexOf('function SessionSnapshotBridge()')) + expect(renderBody.indexOf('React.useEffect(')).toBeLessThan(renderBody.indexOf('return null')) + }) +}) + +describe('account-get-current reads the in-memory session before the network', () => { + const evalHandler = (): any => eval('(' + accountGetCurrent.generateHandler() + ')') + + const withWindow = async ( + bridge: unknown, + fetchImpl: () => Promise, + run: (handler: any) => Promise + ) => { + const store: Record = {} + ;(global as any).window = { + __teleportNextAuth: bridge, + localStorage: { + getItem: (key: string) => (key in store ? store[key] : null), + setItem: (key: string, value: string) => { + store[key] = value + }, + removeItem: (key: string) => { + delete store[key] + }, + }, + } + ;(global as any).fetch = fetchImpl + try { + await run(evalHandler()) + } finally { + delete (global as any).window + delete (global as any).fetch + } + } + + const authenticatedBridge = (user: unknown) => ({ + getSession: () => ({ status: 'authenticated', session: { user } }), + }) + + it('returns the signed-in user without touching /api/auth/session', async () => { + const user = { id: 'u-1', email: 'ada@example.com', name: 'Ada', role: 'admin' } + let fetched = 0 + await withWindow( + authenticatedBridge(user), + async () => { + fetched += 1 + return { ok: true, json: async () => ({ user }) } + }, + async (handler) => { + const out = await handler({}, {}) + expect(fetched).toBe(0) + // Same contract as the network path: flat fields AND `.user`. + expect(out.id).toBe('u-1') + expect(out.email).toBe('ada@example.com') + expect(out.user).toEqual(user) + } + ) + }) + + it('still fetches while the provider is loading', async () => { + const user = { id: 'u-2', email: 'grace@example.com' } + let fetched = 0 + await withWindow( + { getSession: () => ({ status: 'loading', session: null as unknown }) }, + async () => { + fetched += 1 + return { ok: true, json: async () => ({ user }) } + }, + async (handler) => { + const out = await handler({}, {}) + expect(fetched).toBe(1) + expect(out.id).toBe('u-2') + } + ) + }) + + it('still fetches when the provider reports unauthenticated', async () => { + // next-auth also reports 'unauthenticated' when its own fetch FAILED, so + // trusting it would send a signed-in visitor down the guest branch. + const user = { id: 'u-3', email: 'alan@example.com' } + let fetched = 0 + await withWindow( + { getSession: () => ({ status: 'unauthenticated', session: null as unknown }) }, + async () => { + fetched += 1 + return { ok: true, json: async () => ({ user }) } + }, + async (handler) => { + const out = await handler({}, {}) + expect(fetched).toBe(1) + expect(out.id).toBe('u-3') + } + ) + }) + + it('falls back to the network when no bridge is published at all', async () => { + const user = { id: 'u-4', email: 'edsger@example.com' } + let fetched = 0 + await withWindow( + undefined, + async () => { + fetched += 1 + return { ok: true, json: async () => ({ user }) } + }, + async (handler) => { + const out = await handler({}, {}) + expect(fetched).toBe(1) + expect(out.id).toBe('u-4') + } + ) + }) + + it('mirrors the in-memory user into localStorage for the offline fallback', async () => { + const user = { id: 'u-5', email: 'barbara@example.com' } + await withWindow( + authenticatedBridge(user), + async () => { + throw new Error('network is down') + }, + async (handler) => { + await handler({}, {}) + const cached = (global as any).window.localStorage.getItem('teleport_auth_user') + expect(JSON.parse(cached)).toEqual(user) + } + ) + }) + + it('ignores a malformed bridge rather than throwing', async () => { + const user = { id: 'u-6', email: 'ken@example.com' } + let fetched = 0 + await withWindow( + { + getSession: () => { + throw new Error('bridge exploded') + }, + }, + async () => { + fetched += 1 + return { ok: true, json: async () => ({ user }) } + }, + async (handler) => { + const out = await handler({}, {}) + expect(fetched).toBe(1) + expect(out.id).toBe('u-6') + } + ) + }) +}) diff --git a/packages/teleport-plugin-next-workflows/__tests__/custom-js-params-env-invariance.test.ts b/packages/teleport-plugin-next-workflows/__tests__/custom-js-params-env-invariance.test.ts new file mode 100644 index 000000000..57895fedc --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/custom-js-params-env-invariance.test.ts @@ -0,0 +1,134 @@ +import { loadHandler, HandlerFn } from './_helpers/load-handler' + +// Moving a top-level `general-custom-js` between `context: 'server'` and +// `context: 'client'` MUST NOT shift its positional `params[N]` indices. +// +// This is what makes the e-commerce placement sweep safe: checkout's +// "Assemble Order Data" reads params[2]/[5]/[6]/[7]/[9]/[10] and +// "Build Order Number" reads params[14] — hard-coded positions into the live +// context. If the environment switch renumbered them the workflow would write +// the wrong columns on a real order. +// +// Two mechanisms could renumber them, and both are pinned here: +// 1. The SERVER executor injects `__nodeId` into the resolved config, which +// makes the handler EXCLUDE the executing node from `params`; the client +// executor does not. That only matters if the executing node ALREADY has a +// context entry — never true at top level, only inside a loop body (which +// is filtered out of `params` anyway). +// 2. Context key ORDER. Keys are inserted as nodes complete, i.e. in graph +// order — the same order regardless of which side each node ran on. + +describe('general-custom-js — params are identical on client and server', () => { + const handler: HandlerFn = loadHandler('general-custom-js') + + // Echoes back whatever positional slots the caller asks about. + const PROBE = [ + 'function customHandler(params) {', + ' return { seen: params.map(function (p) { return p && p.tag ? p.tag : null; }) };', + '}', + ].join('\n') + + const context = () => ({ + trigger: { tag: 'trigger' }, + formNode: { tag: 'form' }, + cartTotal: { tag: 'cart' }, + createOrder: { tag: 'order' }, + // Reserved scaffolding — must never occupy a positional slot. + __stateValues: { x: 1 }, + __baseUrl: 'https://example.com', + __skippedNodes: {}, + triggerElement: { nodeType: 1 }, + }) + + it('injecting __nodeId (the server marker) does not change the params array', async () => { + const asClient = (await handler({ code: PROBE }, context())) as { seen: string[] } + const asServer = (await handler({ code: PROBE, __nodeId: 'thisNode' }, context())) as { + seen: string[] + } + + expect(asClient.seen).toEqual(['trigger', 'form', 'cart', 'order']) + expect(asServer.seen).toEqual(asClient.seen) + }) + + it('reserved __ keys and triggerElement never consume a positional slot', async () => { + const result = (await handler({ code: PROBE }, context())) as { seen: string[] } + expect(result.seen).toHaveLength(4) + }) + + it('a hard-coded index resolves to the same node either way', async () => { + const READ_INDEX_3 = [ + 'function customHandler(params) {', + ' return { picked: params[3] && params[3].tag };', + '}', + ].join('\n') + + const asClient = await handler({ code: READ_INDEX_3 }, context()) + const asServer = await handler({ code: READ_INDEX_3, __nodeId: 'thisNode' }, context()) + expect(asClient).toEqual({ picked: 'order' }) + expect(asServer).toEqual({ picked: 'order' }) + }) +}) + +describe('context key ORDER survives a client→server→client round trip', () => { + // The runtime inserts a key when a node completes, so the order tracks the + // GRAPH, not the execution environment. A server segment rebuilds its context + // from the serialized client context and appends its own nodes; merging the + // response back preserves existing positions. This simulates that round trip + // with the real merge helper and asserts the ordering is env-independent. + // `mergeServerResults` lives in the client runtime, which needs a DOM to load. + // Its rule for plain values is a straight assign in the response's key order — + // reproduced here so the ordering claim can be tested in isolation. + const mergeServerResults = ( + context: Record, + results: Record + ) => { + for (const key of Object.keys(results)) { + context[key] = results[key] + } + } + + const runSplit = (envOf: (id: string) => 'client' | 'server') => { + const graphOrder = ['a', 'b', 'c', 'd', 'e'] + let context: Record = {} + let i = 0 + while (i < graphOrder.length) { + const env = envOf(graphOrder[i]) + const run: string[] = [] + while (i < graphOrder.length && envOf(graphOrder[i]) === env) { + run.push(graphOrder[i]) + i++ + } + if (env === 'client') { + for (const id of run) { + context[id] = { tag: id } + } + } else { + // Server segment: the pruned client context crosses the wire, the route + // appends its own nodes, and the whole context comes back. + const serverContext: Record = JSON.parse(JSON.stringify(context)) + for (const id of run) { + serverContext[id] = { tag: id } + } + mergeServerResults(context, serverContext) + } + } + context = { ...context } + return Object.keys(context) + } + + it('is the same whether c runs on the client or the server', () => { + const cOnServer = runSplit((id) => (id === 'b' || id === 'c' ? 'server' : 'client')) + const cOnClient = runSplit((id) => (id === 'b' ? 'server' : 'client')) + expect(cOnServer).toEqual(['a', 'b', 'c', 'd', 'e']) + expect(cOnClient).toEqual(cOnServer) + }) + + it('is the same when a whole run moves to the client', () => { + const allServerMiddle = runSplit((id) => + id === 'b' || id === 'c' || id === 'd' ? 'server' : 'client' + ) + const allClient = runSplit(() => 'client') + expect(allServerMiddle).toEqual(['a', 'b', 'c', 'd', 'e']) + expect(allClient).toEqual(allServerMiddle) + }) +}) diff --git a/packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts b/packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts new file mode 100644 index 000000000..f7236555c --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts @@ -0,0 +1,644 @@ +import { + generateSharedRuntimeUtilsCode, + generateClientRuntimeCode, + generateServerSegmentAPIRoute, + splitIntoSegments, +} from '../src' +import { redactServerNodeConfig } from '../src/segment-splitter' +import { NextWorkflowProjectPlugin } from '../src/workflow-project-plugin' +import { isFireAndForgetNode, isFireAndForgetSegment } from '../src/await-result' +import type { WorkflowSegment } from '../src/types' + +// A data node always talks to the database over the network. The workflow +// editor lets the author opt OUT of awaiting one (`config.awaitResult: false`), +// which is what makes "add to favourites" feel instant: the insert still runs, +// but the click handler no longer blocks on a full round trip. +// +// The contract this file pins down: +// 1. the workflow does not wait for the query; +// 2. the node's context entry is `null` — never a partial or stale value; +// 3. a failure cannot abort the workflow (it is logged, not thrown); +// 4. the server route STILL settles the query before it responds, because a +// serverless function may be frozen the instant it replies; +// 5. the client dispatches an all-fire-and-forget SEGMENT without awaiting the +// round trip, which is where the latency the visitor feels actually goes. + +interface SharedUtils { + executeNodes: ( + nodes: unknown[], + edges: unknown[], + context: Record, + handlers: Record, + workflowConfig: unknown, + callServerSegment: unknown, + executionId: string + ) => Promise + isFireAndForgetNode: (node: unknown) => boolean + registerPendingNodePromise: (context: Record, p: Promise) => unknown + settlePendingNodePromises: (context: Record) => Promise +} + +function loadSharedRuntime(): SharedUtils { + const src = generateSharedRuntimeUtilsCode() + const wrapper: { exports: Record } = { exports: {} } + // eslint-disable-next-line @typescript-eslint/no-implied-eval + new Function('module', 'exports', src)(wrapper, wrapper.exports) + return wrapper.exports as unknown as SharedUtils +} + +const deferred = () => { + let resolve: (value?: unknown) => void = () => undefined + let reject: (reason?: unknown) => void = () => undefined + const promise = new Promise((res, rej) => { + resolve = res as (value?: unknown) => void + reject = rej + }) + return { promise, resolve, reject } +} + +const dataNode = (id: string, awaitResult?: boolean) => ({ + id, + type: 'data-create-item', + label: 'Save Row', + stepNumber: 1, + config: { + dataSourceId: 'ds-1', + tableName: 'teleport_favourites', + ...(awaitResult === undefined ? {} : { awaitResult }), + }, +}) + +describe('isFireAndForgetNode — classification', () => { + it('only opts out on an explicit false', () => { + expect(isFireAndForgetNode(dataNode('n1', false) as never)).toBe(true) + expect(isFireAndForgetNode(dataNode('n1', true) as never)).toBe(false) + expect(isFireAndForgetNode(dataNode('n1') as never)).toBe(false) + }) + + it('ignores the flag on non-data node types', () => { + // Node replacement copies config across types; a stray flag must not turn + // an unrelated node fire-and-forget. + const stray = { + id: 'x', + type: 'general-custom-js', + label: 'Script', + stepNumber: 1, + config: { code: 'return {}', awaitResult: false }, + } + expect(isFireAndForgetNode(stray as never)).toBe(false) + }) + + it('covers every data node type', () => { + for (const type of [ + 'data-select', + 'data-count', + 'data-raw-query', + 'data-create-item', + 'data-update-item', + 'data-delete-item', + ]) { + const node = { id: 'n', type, label: type, stepNumber: 1, config: { awaitResult: false } } + expect(isFireAndForgetNode(node as never)).toBe(true) + } + }) + + it('is mirrored inside the generated runtime', () => { + const utils = loadSharedRuntime() + expect(utils.isFireAndForgetNode(dataNode('n1', false))).toBe(true) + expect(utils.isFireAndForgetNode(dataNode('n1'))).toBe(false) + }) +}) + +describe('executeNodes — a non-awaited data node does not block the chain', () => { + it('continues to the next node while the query is still in flight', async () => { + const utils = loadSharedRuntime() + const gate = deferred() + const order: string[] = [] + + const nodes = [ + dataNode('write', false), + { id: 'after', type: 'toast-show', label: 'Toast', stepNumber: 2, config: {} }, + ] + const edges = [{ id: 'e1', source: 'write', target: 'after' }] + + const handlers = { + 'data-create-item': async () => { + order.push('write:start') + await gate.promise + order.push('write:finish') + return { id: 'row-1' } + }, + 'toast-show': async () => { + order.push('toast') + return { shown: true } + }, + } + + const context: Record = { __pendingNodePromises: [] } + await utils.executeNodes(nodes, edges, context, handlers, {}, null, 'exec-1') + + // The toast ran BEFORE the insert finished — that is the whole point. + expect(order).toEqual(['write:start', 'toast']) + // And the node published null, not a half-finished result. + expect(context.write).toBeNull() + expect(context.after).toEqual({ shown: true }) + + gate.resolve() + await utils.settlePendingNodePromises(context) + expect(order).toEqual(['write:start', 'toast', 'write:finish']) + }) + + it('still awaits the same node when the flag is absent', async () => { + const utils = loadSharedRuntime() + const order: string[] = [] + const nodes = [ + dataNode('write'), + { id: 'after', type: 'toast-show', label: 'Toast', stepNumber: 2, config: {} }, + ] + const edges = [{ id: 'e1', source: 'write', target: 'after' }] + const handlers = { + 'data-create-item': async () => { + await Promise.resolve() + order.push('write:finish') + return { id: 'row-1' } + }, + 'toast-show': async () => { + order.push('toast') + return { shown: true } + }, + } + + const context: Record = { __pendingNodePromises: [] } + await utils.executeNodes(nodes, edges, context, handlers, {}, null, 'exec-2') + + expect(order).toEqual(['write:finish', 'toast']) + expect(context.write).toEqual({ id: 'row-1' }) + }) + + it('a downstream binding to the non-awaited node resolves to null', async () => { + const utils = loadSharedRuntime() + let seen: unknown = 'untouched' + + const nodes = [ + dataNode('write', false), + { + id: 'reader', + type: 'toast-show', + label: 'Toast', + stepNumber: 2, + config: { + message: { type: 'workflowContext', nodeId: 'write', path: ['write', 'id'] }, + }, + }, + ] + const edges = [{ id: 'e1', source: 'write', target: 'reader' }] + const handlers = { + 'data-create-item': async () => ({ id: 'row-1' }), + 'toast-show': async (config: { message?: unknown }) => { + seen = config.message + return { shown: true } + }, + } + + const context: Record = { __pendingNodePromises: [] } + await utils.executeNodes(nodes, edges, context, handlers, {}, null, 'exec-3') + // `undefined` (not the written id) — the reference had nothing to drill. + expect(seen).toBeUndefined() + }) +}) + +describe('executeNodes — a non-awaited failure cannot abort the workflow', () => { + const silenceConsole = () => { + // tslint:disable-next-line:no-console + const original = console.error + // tslint:disable-next-line:no-console + console.error = () => undefined + return () => { + // tslint:disable-next-line:no-console + console.error = original + } + } + + it('swallows a rejected handler and keeps going', async () => { + const utils = loadSharedRuntime() + const restore = silenceConsole() + try { + const nodes = [ + dataNode('write', false), + { id: 'after', type: 'toast-show', label: 'Toast', stepNumber: 2, config: {} }, + ] + const edges = [{ id: 'e1', source: 'write', target: 'after' }] + const handlers = { + 'data-create-item': async () => { + throw new Error('connection refused') + }, + 'toast-show': async () => ({ shown: true }), + } + + const context: Record = { __pendingNodePromises: [] } + await expect( + utils.executeNodes(nodes, edges, context, handlers, {}, null, 'exec-4') + ).resolves.toBeUndefined() + expect(context.write).toBeNull() + expect(context.after).toEqual({ shown: true }) + // Draining must not reject either — the promise absorbed the failure. + await expect(utils.settlePendingNodePromises(context)).resolves.toBeUndefined() + } finally { + restore() + } + }) + + it('swallows an { error } result instead of throwing it as fatal', async () => { + const utils = loadSharedRuntime() + const restore = silenceConsole() + try { + const nodes = [dataNode('write', false)] + const handlers = { + 'data-create-item': async () => ({ error: 'insert failed' }), + } + const context: Record = { __pendingNodePromises: [] } + await expect( + utils.executeNodes(nodes, [], context, handlers, {}, null, 'exec-5') + ).resolves.toBeUndefined() + expect(context.write).toBeNull() + await utils.settlePendingNodePromises(context) + } finally { + restore() + } + }) +}) + +describe('settlePendingNodePromises', () => { + it('is a no-op with nothing in flight', async () => { + const utils = loadSharedRuntime() + await expect(utils.settlePendingNodePromises({})).resolves.toBeUndefined() + await expect( + utils.settlePendingNodePromises({ __pendingNodePromises: [] }) + ).resolves.toBeUndefined() + }) + + it('drains work queued while an earlier promise was settling', async () => { + const utils = loadSharedRuntime() + const context: Record = { __pendingNodePromises: [] } + const done: string[] = [] + + const second = () => + utils.registerPendingNodePromise( + context, + Promise.resolve().then(() => { + done.push('second') + }) + ) + + utils.registerPendingNodePromise( + context, + Promise.resolve().then(() => { + done.push('first') + second() + }) + ) + + await utils.settlePendingNodePromises(context) + expect(done).toEqual(['first', 'second']) + expect(context.__pendingNodePromises).toEqual([]) + }) +}) + +// ─── Segment classification ────────────────────────────────────────────────── + +const buildWorkflow = (writeAwaitResult?: boolean) => + ({ + id: 'wf-1', + name: 'Toggle Favourite', + trigger: { + type: 'event-element-clicked', + nodeId: 'trigger', + scope: 'element', + config: { nodeId: 'heart-btn' }, + }, + nodes: [ + { + id: 'state', + type: 'state-update-global-state', + label: 'Optimistic update', + config: { property: 'favs', value: [] }, + executionEnv: 'client', + stepNumber: 1, + }, + { + id: 'write', + type: 'data-create-item', + label: 'Add To Favourites Table', + config: { + dataSourceId: 'ds-1', + tableName: 'teleport_favourites', + columnMappings: [{ column: 'entity_id', value: 'x' }], + ...(writeAwaitResult === undefined ? {} : { awaitResult: writeAwaitResult }), + }, + executionEnv: 'server', + stepNumber: 2, + }, + ], + edges: [{ id: 'e1', source: 'state', target: 'write' }], + } as never) + +describe('segment classification', () => { + it('marks a segment whose every node is fire-and-forget', () => { + const segments = splitIntoSegments(buildWorkflow(false)) + const server = segments.filter((s) => s.env === 'server') + expect(server.length).toBe(1) + expect(isFireAndForgetSegment(server[0])).toBe(true) + }) + + it('does not mark the same segment when the write is awaited', () => { + const segments = splitIntoSegments(buildWorkflow()) + const server = segments.filter((s) => s.env === 'server') + expect(server.length).toBe(1) + expect(isFireAndForgetSegment(server[0])).toBe(false) + }) + + it('does not mark a MIXED segment — one awaited node keeps the whole trip blocking', () => { + const mixed: WorkflowSegment = { + id: 'server-1', + env: 'server', + nodeIds: ['a', 'b'], + nodes: [ + { + id: 'a', + type: 'data-select', + label: 'Read', + config: { awaitResult: false }, + executionEnv: 'server', + stepNumber: 1, + }, + { + id: 'b', + type: 'data-select', + label: 'Read 2', + config: {}, + executionEnv: 'server', + stepNumber: 2, + }, + ], + edges: [], + } + expect(isFireAndForgetSegment(mixed)).toBe(false) + }) + + it('never marks a client segment', () => { + const clientSeg: WorkflowSegment = { + id: 'client-1', + env: 'client', + nodeIds: [], + nodes: [], + edges: [], + } + expect(isFireAndForgetSegment(clientSeg)).toBe(false) + }) +}) + +describe('client config redaction', () => { + it('keeps awaitResult but drops the query/table/mappings', () => { + const config = { + dataSourceId: 'ds-1', + tableName: 'teleport_favourites', + query: 'SELECT secret FROM t', + columnMappings: [{ column: 'entity_id', value: 'x' }], + awaitResult: false, + } + const redacted = redactServerNodeConfig(config, 'server') + expect(redacted).toEqual({ awaitResult: false }) + }) + + it('leaves a client-side node config untouched', () => { + const config = { property: 'favs', awaitResult: false } + expect(redactServerNodeConfig(config, 'client')).toBe(config) + }) +}) + +// ─── Generated routes ──────────────────────────────────────────────────────── + +const buildServerSegment = (awaitResult?: boolean): WorkflowSegment => ({ + id: 'server-1', + env: 'server', + nodeIds: ['write'], + nodes: [ + { + id: 'write', + type: 'data-create-item', + label: 'Add To Favourites Table', + config: { + dataSourceId: 'ds-1', + tableName: 'teleport_favourites', + ...(awaitResult === undefined ? {} : { awaitResult }), + }, + executionEnv: 'server', + stepNumber: 1, + }, + ], + edges: [], +}) + +describe('generated server segment route', () => { + const route = generateServerSegmentAPIRoute(buildServerSegment(false), 'Toggle Favourite') + + it('dispatches a fire-and-forget node instead of awaiting it', () => { + expect(route).toContain('utils.isFireAndForgetNode(node)') + expect(route).toContain('utils.startFireAndForgetNode(node, handler, resolved, context)') + expect(route).toContain('context[node.id] = null;') + }) + + it('settles in-flight queries BEFORE responding (the platform can freeze us)', () => { + expect(route).toContain('await utils.settlePendingNodePromises(context);') + const settleAt = route.indexOf('await utils.settlePendingNodePromises(context);') + const respondAt = route.indexOf('res.status(200).json({ success: true, results: context });') + expect(settleAt).toBeGreaterThan(-1) + expect(respondAt).toBeGreaterThan(settleAt) + }) + + it('never ships the in-flight promise list back to the client', () => { + expect(route).toContain('delete context.__pendingNodePromises;') + }) + + it('drains even when the segment throws', () => { + expect(route).toContain( + 'if (__wfContext) { await utils.settlePendingNodePromises(__wfContext); }' + ) + }) + + it('applies the same treatment inside loop bodies and parallel branches', () => { + expect(route).toContain('utils.isFireAndForgetNode(bNode)') + expect(route).toContain('utils.isFireAndForgetNode(pNode)') + }) +}) + +describe('generated client runtime', () => { + const client = generateClientRuntimeCode() + + it('dispatches an all-fire-and-forget segment without awaiting the round trip', () => { + expect(client).toContain('if (seg.fireAndForget) {') + expect(client).toContain('callServerSegment(ffUrl, context).catch(') + // The nodes still get their null entries so downstream reads are defined. + expect(client).toContain('context[seg.nodes[ffi].id] = null;') + }) + + it('keeps awaiting a normal server segment', () => { + expect(client).toContain('const serverResults = await callServerSegment(url, context);') + }) + + it('never serializes the in-flight promise list to the server', () => { + expect(client).toContain("if (key === '__pendingNodePromises') continue;") + }) +}) + +// ─── Generated custom node, end to end ─────────────────────────────────────── + +describe('generated custom node — the "Remove From Favourites Logic" shape', () => { + // Mirrors what teleport-gui's favourites builder emits: + // Extract Params (client-js) → Delete From Favourites Table (data, NOT + // awaited) → Get Favourites State → Filter → Update Favourites State + // The delete is the only server node, so it becomes its own fire-and-forget + // segment and the click never waits for the database. + const customNodes = { + 'cn-remove': { + id: 'cn-remove', + name: 'Remove From Favourites Logic', + parameters: [], + nodes: [ + { + id: 'extract', + type: 'general-custom-js', + label: 'Extract Remove Params', + config: { + code: 'function customHandler(p, q) { return { entityId: "e1" } }', + context: 'client', + }, + executionEnv: 'client', + stepNumber: 1, + }, + { + id: 'delete', + type: 'data-delete-item', + label: 'Delete From Favourites Table', + config: { dataSourceId: 'ds-1', tableName: 'teleport_favourites', awaitResult: false }, + executionEnv: 'server', + stepNumber: 2, + }, + { + id: 'update', + type: 'state-update-global-state', + label: 'Update Favourites Global State', + config: { property: 'teleportProductFavourites', value: [] }, + executionEnv: 'client', + stepNumber: 3, + }, + ], + edges: [ + { id: 'e1', source: 'extract', target: 'delete' }, + { id: 'e2', source: 'delete', target: 'update' }, + ], + }, + } + + interface BootedCustomNode { + run: ( + outerContext: Record, + parameters: Record, + handlers: Record + ) => Promise + segmentCalls: string[] + resolveSegment: () => void + } + + const bootCustomNode = (): BootedCustomNode => { + const plugin = new NextWorkflowProjectPlugin() as unknown as { + generateCustomNodesFile: ( + nodes: Record, + urls: Record> + ) => string + } + const source = plugin.generateCustomNodesFile(customNodes, { + 'cn-remove': { 'server-1': '/api/workflows/remove-seg-1' }, + }) + + // runtime-utils REPLACES module.exports wholesale, so read it back off the + // module object rather than the `exports` alias. + const utilsModule: { exports: Record } = { exports: {} } + // eslint-disable-next-line @typescript-eslint/no-implied-eval + new Function('module', 'exports', generateSharedRuntimeUtilsCode())( + utilsModule, + utilsModule.exports + ) + const utilsExports = utilsModule.exports + + const segmentCalls: string[] = [] + let releaseSegment: () => void = () => undefined + const segmentGate = new Promise((resolve) => { + releaseSegment = resolve + }) + const runtimeStub = { + findStreamingAINodes: () => ({}), + mergeServerResults: () => undefined, + callStreamingServerSegment: async () => ({}), + callServerSegment: async (url: string) => { + segmentCalls.push(url) + await segmentGate + return {} + }, + } + + const requireStub = (id: string) => + id === './runtime-utils' ? utilsExports : id === './runtime' ? runtimeStub : {} + + const moduleStub: { exports: Record } = { exports: {} } + // eslint-disable-next-line @typescript-eslint/no-implied-eval + new Function('module', 'exports', 'require', source)( + moduleStub, + moduleStub.exports, + requireStub + ) + + const registry = moduleStub.exports as Record + return { run: registry['cn-remove'], segmentCalls, resolveSegment: releaseSegment } + } + + it('returns before the delete round trip completes, and returns the LAST awaited node', async () => { + const booted = bootCustomNode() + const handlers = { + 'general-custom-js': async () => ({ entityId: 'e1' }), + 'state-update-global-state': async () => ({ + success: true, + property: 'teleportProductFavourites', + }), + } + + // Never released — if the custom node awaited the segment this would hang. + const result = (await booted.run({}, {}, handlers)) as Record + + expect(booted.segmentCalls).toEqual(['/api/workflows/remove-seg-1']) + // NOT the fire-and-forget node's null: the state update is the last node + // whose result the custom node may hand back to its caller. + expect(result).toEqual({ success: true, property: 'teleportProductFavourites' }) + + booted.resolveSegment() + }) + + it('publishes null under the non-awaited node so downstream reads are defined', async () => { + const booted = bootCustomNode() + const seen: Record = {} + const handlers = { + 'general-custom-js': async () => ({ entityId: 'e1' }), + 'state-update-global-state': async (_config: unknown, context: Record) => { + seen.delete = context.delete + seen.hasKey = Object.prototype.hasOwnProperty.call(context, 'delete') + return { success: true } + }, + } + + await booted.run({}, {}, handlers) + expect(seen.hasKey).toBe(true) + expect(seen.delete).toBeNull() + + booted.resolveSegment() + }) +}) diff --git a/packages/teleport-plugin-next-workflows/__tests__/element-visible-trigger-scoping.test.ts b/packages/teleport-plugin-next-workflows/__tests__/element-visible-trigger-scoping.test.ts new file mode 100644 index 000000000..486667c24 --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/element-visible-trigger-scoping.test.ts @@ -0,0 +1,296 @@ +// `event-element-visible` is a LIFECYCLE trigger (IntersectionObserver, no React +// event prop) that is nonetheless bound to ONE element. Two defects followed +// from that, both shipped in run a15472af's cookie-consent banner: +// +// 1. The observer looked the element up by `config.nodeId` — the +// project-document id (`TQ_…`) — instead of `config.elementHtmlId`, the DOM +// id the generator actually emits. `getElementById` returned null on every +// page, so the observer was never constructed and the banner (whose only +// writer is that workflow) could never appear. 408 dead lookups across 24 +// files. +// +// 2. Having no React prop, it fell into `lifecycleWorkflows`, which were +// activated unconditionally — bypassing the JSX-presence prune that is the +// only thing scoping element workflows to a page. One workflow shipped into +// EVERY generated file, 17 per page, including 404.js and logo.js. + +import { createNextWorkflowPlugin } from '../src/workflow-component-plugin' + +const HTML_ID = 'thq_container_pu-S' +const NODE_ID = 'TQ__X8oOlJm82' + +const elementVisibleWorkflow = (config: Record) => ({ + id: 'wf-cookie-visible', + name: 'Cookie Consent Check on Load', + trigger: { + type: 'event-element-visible', + nodeId: 'trigger-element-visible', + scope: 'element', + config, + }, + nodes: [ + { + id: 'update-1', + type: 'state-update-local-state', + config: { property: 'cookieConsentVisible', value: true }, + stepNumber: 1, + label: 'Show banner', + }, + ], + edges: [{ id: 'e1', source: 'trigger-element-visible', target: 'update-1' }], +}) + +/** A JSX tree whose root element carries `id={HTML_ID}` — i.e. the page that owns it. */ +const jsxWithElementId = (elementId: string | null) => ({ + type: 'chunk-type-ast', + name: 'jsx-component', + content: { + type: 'VariableDeclaration', + declarations: [ + { + type: 'VariableDeclarator', + init: { + type: 'ArrowFunctionExpression', + body: { + type: 'BlockStatement', + body: [ + { + type: 'ReturnStatement', + argument: elementId + ? { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { type: 'JSXIdentifier', name: 'div' }, + attributes: [ + { + type: 'JSXAttribute', + name: { type: 'JSXIdentifier', name: 'id' }, + value: { type: 'StringLiteral', value: elementId }, + }, + ], + }, + children: [], + } + : { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { type: 'JSXIdentifier', name: 'div' }, + attributes: [], + }, + children: [], + }, + }, + ], + }, + }, + }, + ], + }, +}) + +const getWorkflowModule = async ( + workflow: any, + renderedElementId: string | null +): Promise => { + const plugin = createNextWorkflowPlugin({ isPage: true }) + const structure: any = { + uidl: { + name: 'Dashboard', + node: { type: 'element', content: { elementType: 'container', name: 'Container' } }, + stateDefinitions: { cookieConsentVisible: { type: 'boolean', defaultValue: false } }, + }, + chunks: [jsxWithElementId(renderedElementId)], + options: { workflows: { workflows: { [workflow.id]: workflow }, customNodes: {} } }, + dependencies: {}, + } + await plugin(structure) + const moduleChunk = (structure.chunks as any[]).find((c: any) => c.name === 'workflow-module') + return moduleChunk ? String(moduleChunk.content) : null +} + +describe('event-element-visible — element lookup', () => { + it('observes the DOM id, not the project-document node id', async () => { + const code = await getWorkflowModule( + elementVisibleWorkflow({ nodeId: NODE_ID, elementHtmlId: HTML_ID, once: true }), + HTML_ID + ) + expect(code).not.toBeNull() + expect(code).toContain(`document.getElementById('${HTML_ID}')`) + expect(code).not.toContain(NODE_ID) + }) + + it('reports the DOM id in the trigger context too', async () => { + const code = await getWorkflowModule( + elementVisibleWorkflow({ nodeId: NODE_ID, elementHtmlId: HTML_ID, once: true }), + HTML_ID + ) + expect(code).toContain(`elementId: '${HTML_ID}'`) + }) + + it('still falls back to nodeId when no html id was mapped', async () => { + const code = await getWorkflowModule( + elementVisibleWorkflow({ nodeId: NODE_ID, once: true }), + NODE_ID + ) + expect(code).toContain(`document.getElementById('${NODE_ID}')`) + }) +}) + +describe('event-element-visible — per-page scoping', () => { + it('is generated into the page that renders its element', async () => { + const code = await getWorkflowModule( + elementVisibleWorkflow({ nodeId: NODE_ID, elementHtmlId: HTML_ID, once: true }), + HTML_ID + ) + expect(code).not.toBeNull() + expect(code).toContain('Element visible') + }) + + it('is NOT generated into a page that does not render its element', async () => { + // The 404 / logo case: 17 dead observers per file for a banner it never has. + const code = await getWorkflowModule( + elementVisibleWorkflow({ nodeId: NODE_ID, elementHtmlId: HTML_ID, once: true }), + 'thq_container_somewhere_else' + ) + expect(code === null || !code.includes('Element visible')).toBe(true) + }) + + it('stays active when the trigger names no element at all (nothing to prune against)', async () => { + const code = await getWorkflowModule( + elementVisibleWorkflow({ once: true }), + 'thq_container_somewhere_else' + ) + expect(code).not.toBeNull() + expect(code).toContain('Element visible') + }) + + it('leaves element-less lifecycle workflows (page-loaded) unconditionally active', async () => { + const pageLoaded = { + id: 'wf-page-loaded', + name: 'Init Page', + // `allPages` because an UNSCOPED page-loaded is deliberately skipped by + // pre-existing relevance filtering (workflow-component-plugin.ts:2653-2660) + // — unrelated to element scoping, but it would mask what this asserts. + trigger: { + type: 'event-page-loaded', + nodeId: 't1', + scope: 'page', + config: { allPages: true }, + }, + nodes: [ + { + id: 'update-1', + type: 'state-update-local-state', + config: { property: 'cookieConsentVisible', value: true }, + stepNumber: 1, + label: 'x', + }, + ], + edges: [{ id: 'e1', source: 't1', target: 'update-1' }], + } + const code = await getWorkflowModule(pageLoaded, 'unrelated-element') + expect(code).not.toBeNull() + }) +}) + +// Regression for the product-card `ReferenceError: __wfConfig_… is not defined` +// crash. The per-page prune removed the unmatched element-visible workflow from +// the CONFIG emission (`activeWorkflows`) but NOT from the lifecycle HANDLER +// emission — so the module still contained an IntersectionObserver that resolves +// its target with a DOCUMENT-WIDE `getElementById`, matches the shared cookie +// banner another component rendered, and calls `__execWf(__wfConfig_)` for a +// config that was never declared. The single-workflow "not generated" test above +// can't catch it: with only the unmatched workflow the whole module is empty. The +// bug needs a SECOND, active workflow keeping the module alive — exactly the +// product card, which has real click handlers plus ~23 riding cookie observers. +describe('event-element-visible — config/handler integrity when the module is kept alive', () => { + // Unconditionally-active (no element target) — stands in for the card's real + // click workflows: it keeps the workflow module non-empty. + const keepAliveWorkflow = { + id: 'wf-keep-alive', + name: 'Init Card', + trigger: { + type: 'event-page-loaded', + nodeId: 't-alive', + scope: 'page', + config: { allPages: true }, + }, + nodes: [ + { + id: 'a1', + type: 'state-update-local-state', + config: { property: 'cookieConsentVisible', value: true }, + stepNumber: 1, + label: 'x', + }, + ], + edges: [{ id: 'ea', source: 't-alive', target: 'a1' }], + } + + const getModuleForWorkflows = async ( + wfs: any[], + renderedElementId: string | null + ): Promise => { + const plugin = createNextWorkflowPlugin({ isPage: true }) + const workflowsMap: Record = {} + for (const wf of wfs) { + workflowsMap[wf.id] = wf + } + const structure: any = { + uidl: { + name: 'ProductCard', + node: { type: 'element', content: { elementType: 'container', name: 'Container' } }, + stateDefinitions: { cookieConsentVisible: { type: 'boolean', defaultValue: false } }, + }, + chunks: [jsxWithElementId(renderedElementId)], + options: { workflows: { workflows: workflowsMap, customNodes: {} } }, + dependencies: {}, + } + await plugin(structure) + const moduleChunk = (structure.chunks as any[]).find((c: any) => c.name === 'workflow-module') + return moduleChunk ? String(moduleChunk.content) : null + } + + it('prunes an unmatched element-visible handler even when another workflow keeps the module alive', async () => { + const cookie = elementVisibleWorkflow({ + nodeId: NODE_ID, + elementHtmlId: 'thq_not_on_this_card', + once: true, + }) + const code = await getModuleForWorkflows([keepAliveWorkflow, cookie], HTML_ID) + expect(code).not.toBeNull() + // The keep-alive workflow is present, so the module really is non-empty. + expect(code).toContain('const __wfConfig_wf_keep_alive =') + // The unmatched cookie observer must be fully gone: no config, no handler, + // no reference to its element. + expect(code).not.toContain('__wfConfig_wf_cookie_visible') + expect(code).not.toContain('thq_not_on_this_card') + }) + + it('leaves no dangling __wfConfig_ reference (every used config is declared)', async () => { + const cookie = elementVisibleWorkflow({ + nodeId: NODE_ID, + elementHtmlId: 'thq_not_on_this_card', + once: true, + }) + const code = (await getModuleForWorkflows([keepAliveWorkflow, cookie], HTML_ID)) || '' + const declared = new Set( + Array.from(code.matchAll(/const (__wfConfig_[A-Za-z0-9_]+)\s*=/g)).map((m) => m[1]) + ) + const used = new Set( + Array.from(code.matchAll(/__execWf\(\s*(__wfConfig_[A-Za-z0-9_]+)/g)).map((m) => m[1]) + ) + const dangling = Array.from(used).filter((id) => !declared.has(id)) + expect(dangling).toEqual([]) + }) + + it('still emits the element-visible workflow on the card that DOES render its element', async () => { + const cookie = elementVisibleWorkflow({ nodeId: NODE_ID, elementHtmlId: HTML_ID, once: true }) + const code = await getModuleForWorkflows([keepAliveWorkflow, cookie], HTML_ID) + expect(code).not.toBeNull() + expect(code).toContain('Element visible') + expect(code).toContain('const __wfConfig_wf_cookie_visible =') + }) +}) diff --git a/packages/teleport-plugin-next-workflows/__tests__/reserved-word-state-binding.test.ts b/packages/teleport-plugin-next-workflows/__tests__/reserved-word-state-binding.test.ts new file mode 100644 index 000000000..6e03c268a --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/reserved-word-state-binding.test.ts @@ -0,0 +1,112 @@ +/** + * The page-level `__createWorkflowHandlers(stateSetters, stateTypes, stateValuesRef)` + * maps are keyed BY THE UIDL STATE NAME — that is what the runtime looks up when + * a node config says `{"property": "class"}` or a `state-batch-update` carries + * `{"key": "class"}`. Both shapes appear verbatim in the run that broke. + * + * So the fix for the reserved-word crash has to be asymmetric: + * KEY → the UIDL name, ALWAYS (renaming it silently breaks every workflow + * binding written against it — `__stateNameMap` has no camel→original + * entry, so the runtime would just warn "no setter for class" and skip) + * VALUE → the sanitised React binding, because `const [class, …]` is a + * SyntaxError and the whole project build dies on it. + */ + +import generate from '@babel/generator' +import * as types from '@babel/types' +import { createNextWorkflowPlugin } from '../src/workflow-component-plugin' + +/** `const Page = (props) => { return null }` — the shape the plugin injects into. */ +const buildComponentChunkContent = (): types.VariableDeclaration => + types.variableDeclaration('const', [ + types.variableDeclarator( + types.identifier('AddCharacter'), + types.arrowFunctionExpression( + [types.identifier('props')], + types.blockStatement([types.returnStatement(types.nullLiteral())]) + ) + ), + ]) + +const buildStructure = (stateNames: string[]): any => { + const triggerNodeId = 'trigger-1' + const workflow = { + id: 'wf-1', + name: 'Batch update from the form', + trigger: { + type: 'event-page-loaded', + nodeId: triggerNodeId, + scope: 'page', + config: { pageId: 'page-1' }, + }, + nodes: [ + { + id: 'batch-1', + type: 'state-batch-update', + config: { + scope: 'local', + updates: stateNames.map((name) => ({ key: name, value: '' })), + }, + stepNumber: 1, + label: 'Batch State Update', + }, + ], + edges: [{ id: 'e', source: triggerNodeId, target: 'batch-1' }], + } + return { + uidl: { + name: 'AddCharacter', + outputOptions: { pageId: 'page-1', fileName: 'add-character' }, + node: { type: 'element', content: { elementType: 'container', name: 'Container' } }, + stateDefinitions: Object.fromEntries( + stateNames.map((name) => [name, { type: 'string', defaultValue: '' }]) + ), + }, + chunks: [ + { + type: 'chunk-type-ast', + name: 'jsx-component', + content: buildComponentChunkContent(), + }, + ], + options: { workflows: { workflows: { 'wf-1': workflow }, customNodes: {} } }, + dependencies: {}, + } +} + +const generateComponentCode = async (stateNames: string[]): Promise => { + const plugin = createNextWorkflowPlugin({ isPage: true }) + const structure = buildStructure(stateNames) + await plugin(structure as any) + const componentChunk = (structure.chunks as any[]).find((c: any) => c.name === 'jsx-component') + // The maps are injected into the component BODY, not the module chunk. + return generate(componentChunk.content).code +} + +describe('reserved-word state in the workflow runtime maps', () => { + it('keys every map by the UIDL name so `config.property` still resolves', async () => { + const code = await generateComponentCode(['class', 'characterName']) + // `{ class: … }` is a legal object key even though `class` is reserved. + expect(code).toMatch(/class:\s*setClass/) + expect(code).toMatch(/class:\s*["']string["']/) + }) + + it('binds the VALUE to the sanitised identifier the state hook declared', async () => { + const code = await generateComponentCode(['class', 'characterName']) + // __wfStateRef.current = { class: class_ } — never `class: class`. + expect(code).toMatch(/class:\s*class_/) + expect(code).not.toMatch(/class:\s*class\b(?!_)/) + }) + + it('leaves ordinary state names byte-identical', async () => { + const code = await generateComponentCode(['class', 'characterName']) + expect(code).toMatch(/characterName:\s*characterName/) + expect(code).toMatch(/characterName:\s*setCharacterName/) + }) + + it('quotes a key that is not identifier syntax instead of emitting it bare', async () => { + const code = await generateComponentCode(['my key']) + expect(code).toContain('"my key"') + expect(code).not.toMatch(/[^"']my key:/) + }) +}) diff --git a/packages/teleport-plugin-next-workflows/__tests__/workflow-auth-guard.test.ts b/packages/teleport-plugin-next-workflows/__tests__/workflow-auth-guard.test.ts new file mode 100644 index 000000000..2e858d9ec --- /dev/null +++ b/packages/teleport-plugin-next-workflows/__tests__/workflow-auth-guard.test.ts @@ -0,0 +1,277 @@ +import { + generateWorkflowAuthHelperFile, + buildWorkflowAuthInjection, +} from '../src/workflow-auth-generator' +import { + generateServerSegmentAPIRoute, + generateStreamingServerSegmentAPIRoute, +} from '../src/api-route-generator' +import { UIDLWorkflowProtection } from '@teleporthq/teleport-types' +import { WorkflowSegment } from '../src/types' + +// The generated workflow-auth.js guard is the single stateless enforcement +// point. Booting it with a mocked next-auth/jwt proves the runtime behaviour; +// the route generators prove the guard is wired in BEFORE any node runs. + +type Guard = ( + req: any, + context: any, + policy: any +) => Promise<{ status: number; message: string } | null> + +/** Boots the emitted guard file with getToken stubbed to read `req.__token`. */ +function bootGuard(secret: string | undefined): Guard { + const code = generateWorkflowAuthHelperFile() + const moduleObj: { exports: any } = { exports: {} } + const fakeRequire = (name: string): any => { + if (name === 'next-auth/jwt') { + return { getToken: async ({ req }: any) => (req && req.__token) || null } + } + // eslint-disable-next-line @typescript-eslint/no-var-requires + return require(name) + } + // tslint:disable-next-line:function-constructor + new Function('require', 'module', 'exports', 'process', code)( + fakeRequire, + moduleObj, + moduleObj.exports, + { env: { NEXTAUTH_SECRET: secret } } + ) + return moduleObj.exports.guardWorkflowRequest as Guard +} + +const reqWith = (extra: Record = {}): any => ({ headers: {}, ...extra }) + +describe('guardWorkflowRequest (runtime enforcement)', () => { + const guard = bootGuard('server-secret') + + it('is a no-op when there is no policy', async () => { + const context = { n: { userId: 'victim' } } + expect(await guard(reqWith(), context, null)).toBeNull() + expect(context.n.userId).toBe('victim') + }) + + it('rejects with 401 when auth is required and there is no session', async () => { + const res = await guard(reqWith(), {}, { requiresAuth: true, allowedRoles: [] }) + expect(res).toEqual({ status: 401, message: 'Unauthenticated' }) + }) + + it('allows any authenticated user when allowedRoles is empty', async () => { + const res = await guard( + reqWith({ __token: { id: 'u1', role: 'user' } }), + {}, + { + requiresAuth: true, + allowedRoles: [], + } + ) + expect(res).toBeNull() + }) + + it('rejects with 403 when the session role is not allowed', async () => { + const res = await guard( + reqWith({ __token: { id: 'u1', role: 'user' } }), + {}, + { + requiresAuth: true, + allowedRoles: ['admin'], + } + ) + expect(res).toEqual({ status: 403, message: 'Forbidden' }) + }) + + it('allows a matching role (incl. roleName / roles[] spellings)', async () => { + for (const token of [ + { id: 'u1', role: 'admin' }, + { id: 'u1', roleName: 'admin' }, + { id: 'u1', roles: ['admin'] }, + ]) { + expect( + await guard( + reqWith({ __token: token }), + {}, + { requiresAuth: true, allowedRoles: ['admin'] } + ) + ).toBeNull() + } + }) + + it('OVERWRITES a forged user id with the session id (the IDOR fix)', async () => { + const context = { resolver: { userId: 'victim-id', email: 'x' } } + const res = await guard(reqWith({ __token: { id: 'attacker-real-id' } }), context, { + requiresAuth: true, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'resolver', path: ['userId'] }] }, + }) + expect(res).toBeNull() + expect(context.resolver.userId).toBe('attacker-real-id') // forced to the caller + expect(context.resolver.email).toBe('x') // other fields untouched + }) + + it('binds a nested path and creates missing context nodes', async () => { + const context: any = {} + await guard(reqWith({ __token: { id: 'sess-1' } }), context, { + requiresAuth: false, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'n', path: ['user', 'id'] }] }, + }) + expect(context.n.user.id).toBe('sess-1') + }) + + it('falls back to token.sub when token.id is absent', async () => { + const context = { n: { userId: 'victim' } } + await guard(reqWith({ __token: { sub: 'sub-id' } }), context, { + requiresAuth: false, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'n', path: ['userId'] }] }, + }) + expect(context.n.userId).toBe('sub-id') + }) + + it('leaves the client value for a GUEST (no session) on a non-required userScoped write', async () => { + // Guest checkout: no token, requiresAuth false → the anonymous client id is + // kept (there is no server session to bind), and the request proceeds. + const context = { n: { userId: 'guest-anon-uuid' } } + const res = await guard(reqWith(), context, { + requiresAuth: false, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'n', path: ['userId'] }] }, + }) + expect(res).toBeNull() + expect(context.n.userId).toBe('guest-anon-uuid') + }) + + it('honours the internal server-to-server secret bypass', async () => { + const res = await guard( + reqWith({ headers: { 'x-internal-data-secret': 'server-secret' } }), + {}, + { requiresAuth: true, allowedRoles: ['admin'] } + ) + expect(res).toBeNull() + }) + + it('does not treat a wrong internal secret as a bypass', async () => { + const res = await guard( + reqWith({ headers: { 'x-internal-data-secret': 'wrong' } }), + {}, + { requiresAuth: true, allowedRoles: [] } + ) + expect(res).toEqual({ status: 401, message: 'Unauthenticated' }) + }) +}) + +describe('guardWorkflowRequest with next-auth absent / no secret', () => { + it('treats a missing NEXTAUTH_SECRET as no session (401 when required)', async () => { + const guard = bootGuard(undefined) + const res = await guard( + reqWith({ __token: { id: 'u1' } }), + {}, + { requiresAuth: true, allowedRoles: [] } + ) + expect(res).toEqual({ status: 401, message: 'Unauthenticated' }) + }) +}) + +// --------------------------------------------------------------------------- +// Route wiring +// --------------------------------------------------------------------------- + +const dataSegment = (): WorkflowSegment => + ({ + id: 'server-1', + env: 'server', + nodes: [ + { + id: 'w1', + type: 'data-create-item', + label: 'Write', + config: { tableName: 'teleport_favourites' }, + stepNumber: 1, + }, + ], + edges: [], + } as unknown as WorkflowSegment) + +const protection: UIDLWorkflowProtection = { + requiresAuth: true, + allowedRoles: ['admin'], + derivedFrom: 'page', +} + +describe('route generators wire the guard in', () => { + it('injects the guard into a protected non-streaming route BEFORE the node loop', () => { + const code = generateServerSegmentAPIRoute(dataSegment(), 'Admin CRUD', protection) + expect(code).toContain("require('../../../utils/workflows/workflow-auth')") + expect(code).toContain('const __WF_AUTH = {') + expect(code).toContain('__wfAuth.guardWorkflowRequest(req, context, __WF_AUTH)') + // The guard (and its early 401/403 return) must precede the node loop. + expect(code.indexOf('guardWorkflowRequest')).toBeLessThan( + code.indexOf('SEGMENT_CONFIG.nodes.slice()') + ) + // The baked policy carries the runtime fields, not the build-only derivedFrom. + expect(code).toContain('"requiresAuth":true') + expect(code).toContain('"allowedRoles":["admin"]') + expect(code).not.toContain('derivedFrom') + }) + + it('injects the guard into a protected streaming route BEFORE the stream starts', () => { + const code = generateStreamingServerSegmentAPIRoute(dataSegment(), 'Streaming', { + requiresAuth: true, + allowedRoles: [], + derivedFrom: 'graph', + }) + expect(code).toContain('__wfAuth.guardWorkflowRequest(req, context, __WF_AUTH)') + // The guard runs before the node loop. `ensureStream()` (which calls + // res.writeHead for the event-stream) is only invoked DURING node execution, + // so a 401/403 is sent as an HTTP status before the stream ever starts. + expect(code.indexOf('guardWorkflowRequest')).toBeLessThan( + code.indexOf('SEGMENT_CONFIG.nodes.slice()') + ) + // The only ensureStream CALL (not its definition) is inside the node loop. + expect(code.indexOf('guardWorkflowRequest')).toBeLessThan(code.lastIndexOf('ensureStream()')) + }) + + it('emits NOTHING guard-related for an unprotected route (byte-compatible)', () => { + const code = generateServerSegmentAPIRoute(dataSegment(), 'Public') + expect(code).not.toContain('workflow-auth') + expect(code).not.toContain('__WF_AUTH') + expect(code).not.toContain('guardWorkflowRequest') + }) + + it('bakes the userScoped bindings into the policy', () => { + const code = generateServerSegmentAPIRoute(dataSegment(), 'Favourites', { + requiresAuth: true, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'resolve', path: ['userId'] }] }, + derivedFrom: 'graph', + }) + expect(code).toContain('"userScoped"') + expect(code).toContain('"nodeId":"resolve"') + expect(code).toContain('"path":["userId"]') + }) +}) + +describe('buildWorkflowAuthInjection', () => { + it('returns empty pieces when there is no meaningful policy', () => { + expect(buildWorkflowAuthInjection(undefined)).toEqual({ + requireLine: '', + policyConst: '', + guardCall: '', + }) + expect( + buildWorkflowAuthInjection({ requiresAuth: false, allowedRoles: [], derivedFrom: 'default' }) + ).toEqual({ requireLine: '', policyConst: '', guardCall: '' }) + }) + + it('emits pieces for a userScoped-only (guest-capable) policy', () => { + const injection = buildWorkflowAuthInjection({ + requiresAuth: false, + allowedRoles: [], + userScoped: { ownerColumn: 'user_id', bindings: [{ nodeId: 'n', path: ['userId'] }] }, + derivedFrom: 'graph', + }) + expect(injection.requireLine).toContain('workflow-auth') + expect(injection.policyConst).toContain('"userScoped"') + expect(injection.guardCall).toContain('guardWorkflowRequest') + }) +}) diff --git a/packages/teleport-plugin-next-workflows/src/api-route-generator.ts b/packages/teleport-plugin-next-workflows/src/api-route-generator.ts index ffa3b59d8..487770c9c 100644 --- a/packages/teleport-plugin-next-workflows/src/api-route-generator.ts +++ b/packages/teleport-plugin-next-workflows/src/api-route-generator.ts @@ -4,6 +4,7 @@ import { UIDLWorkflowEdge, UIDLWebhookConfig, UIDLCustomWorkflowNode, + UIDLWorkflowProtection, } from '@teleporthq/teleport-types' import { WorkflowSegment } from './types' import { nodeRegistry } from './nodes' @@ -13,6 +14,7 @@ import { generateGetRawBodyCode, generateAllSignatureVerificationCode, } from './webhook-signature-verification' +import { buildWorkflowAuthInjection } from './workflow-auth-generator' // Workflow/segment names, cron schedules, and webhook paths are free-form // UIDL data — never guaranteed not to contain `*/`. Every generated route @@ -27,11 +29,13 @@ const sanitizeForBlockComment = (value: string): string => value.replace(/\*\//g export const generateServerSegmentAPIRoute = ( segment: WorkflowSegment, - workflowName?: string + workflowName?: string, + protection?: UIDLWorkflowProtection ): string => { const usedNodeTypes = new Set(segment.nodes.map((n) => n.type)) const nodeHandlersEntries = generateNodeHandlersForSegment(usedNodeTypes, true) const hasRateLimiter = usedNodeTypes.has('general-rate-limiter') + const auth = buildWorkflowAuthInjection(protection) const segmentConfig = JSON.stringify( { @@ -74,10 +78,10 @@ export const generateServerSegmentAPIRoute = ( return `${header} const utils = require('../../../utils/workflows/server-runtime'); -const resolveConfig = utils.resolveConfig; +${auth.requireLine}const resolveConfig = utils.resolveConfig; const SEGMENT_CONFIG = ${segmentConfig}; - +${auth.policyConst} const nodeHandlers = { ${nodeHandlersEntries} }; @@ -87,18 +91,32 @@ module.exports = async function handler(req, res) { res.status(405).json({ error: 'Method not allowed' }); return; } + // Kept outside the try so the catch below can still drain any fire-and-forget + // query this segment started before it failed. + var __wfContext = null; try { const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; const incomingContext = body.context || {}; - const context = Object.assign({}, incomingContext);${requestInjection} + const context = Object.assign({}, incomingContext); + __wfContext = context; + // Created eagerly so a custom node invoked from here shares the SAME + // fire-and-forget queue (it shallow-copies this context) and its queries + // are drained by the settle below rather than being lost when we reply. + context.__pendingNodePromises = [];${requestInjection} var __proto = req.headers['x-forwarded-proto'] || (req.headers.host && (req.headers.host.startsWith('localhost') || req.headers.host.startsWith('127.0.0.1')) ? 'http' : 'https'); - context.__baseUrl = __proto + '://' + req.headers.host; + context.__baseUrl = __proto + '://' + req.headers.host;${auth.guardCall} const sortedNodes = SEGMENT_CONFIG.nodes.slice().sort(function(a, b) { return a.stepNumber - b.stepNumber; }); for (let i = 0; i < sortedNodes.length; i++) { const node = sortedNodes[i]; const resolved = resolveConfig(node.config, context); + // Every data node lives in a SERVER segment, so this guard — which turns an + // unresolved {{…}} into a validation error instead of letting the literal + // token reach SQL — was doing nothing at all: it ran only in the CLIENT + // executor. Run 02783f65 shipped 55 route files, none of which called it. + const __configError = utils.finalizeResolvedConfig(node.type, resolved); + if (__configError) { throw new Error(__configError); } resolved.__nodeId = node.id; // If-statement nodes must be evaluated using the runtime's evaluateCondition @@ -199,6 +217,11 @@ module.exports = async function handler(req, res) { } var bHandler = nodeHandlers[bNode.type]; if (!bHandler) continue; + if (utils.isFireAndForgetNode(bNode)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(bNode, bHandler, bResolved, context)); + context[bNode.id] = null; + continue; + } var bResult = await bHandler(bResolved, context); if (bResult && (bResult.success === false || (typeof bResult.error === 'string' && bResult.error))) { throw new Error(bResult.error || 'Loop body node execution failed'); @@ -284,6 +307,13 @@ module.exports = async function handler(req, res) { pRes.__nodeId = pNode.id; var pHandler = nodeHandlers[pNode.type]; if (!pHandler) continue; + if (utils.isFireAndForgetNode(pNode)) { + // Registered on the ROUTE context (not the branch copy) so the + // response still waits for the query to land. + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(pNode, pHandler, pRes, branchCtx)); + branchCtx[pNode.id] = null; + continue; + } var pResult = await pHandler(pRes, branchCtx); branchCtx[pNode.id] = pResult; } @@ -331,6 +361,11 @@ module.exports = async function handler(req, res) { console.warn('No handler for node type: ' + node.type); continue; } + if (utils.isFireAndForgetNode(node)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(node, handler, resolved, context)); + context[node.id] = null; + continue; + } const result = await handler(resolved, context); if (result && result.__earlyResponse) { var earlyRes = result.__earlyResponse; @@ -338,6 +373,7 @@ module.exports = async function handler(req, res) { for (var h = 0; h < hKeys.length; h++) { res.setHeader(hKeys[h], earlyRes.headers[hKeys[h]]); } + await utils.settlePendingNodePromises(context); res.status(earlyRes.status || 500).json(earlyRes.body || {}); return; } @@ -348,10 +384,17 @@ module.exports = async function handler(req, res) { if (result && result.__terminal) break; } + // Land every fire-and-forget query BEFORE replying: the platform may freeze + // this function the moment the response is sent, which would drop the write. + // The visitor does not pay for this — the client dispatched this segment + // without awaiting it (see seg.fireAndForget in the client runtime). + await utils.settlePendingNodePromises(context); delete context.__request; + delete context.__pendingNodePromises; res.status(200).json({ success: true, results: context }); } catch (error) { console.error('Workflow segment error:', error); + if (__wfContext) { await utils.settlePendingNodePromises(__wfContext); } res.status(500).json({ success: false, error: error.message || 'Internal server error' }); } }; @@ -364,11 +407,13 @@ export const hasStreamingAINode = (segment: WorkflowSegment): boolean => { export const generateStreamingServerSegmentAPIRoute = ( segment: WorkflowSegment, - workflowName?: string + workflowName?: string, + protection?: UIDLWorkflowProtection ): string => { const usedNodeTypes = new Set(segment.nodes.map((n) => n.type)) const nodeHandlersEntries = generateNodeHandlersForSegment(usedNodeTypes, true) const hasRateLimiter = usedNodeTypes.has('general-rate-limiter') + const auth = buildWorkflowAuthInjection(protection) const segmentConfig = JSON.stringify( { @@ -408,10 +453,10 @@ export const generateStreamingServerSegmentAPIRoute = ( return `${header} const utils = require('../../../utils/workflows/server-runtime'); -const resolveConfig = utils.resolveConfig; +${auth.requireLine}const resolveConfig = utils.resolveConfig; const SEGMENT_CONFIG = ${segmentConfig}; - +${auth.policyConst} const nodeHandlers = { ${nodeHandlersEntries} }; @@ -457,11 +502,17 @@ module.exports = async function handler(req, res) { } } + // Kept outside the try so the catch below can still drain any fire-and-forget + // query this segment started before it failed. + var __wfContext = null; try { const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; - const context = Object.assign({}, body.context || {});${requestInjection} + const context = Object.assign({}, body.context || {}); + __wfContext = context; + // See the non-streaming segment route — shared queue for nested custom nodes. + context.__pendingNodePromises = [];${requestInjection} var __proto = req.headers['x-forwarded-proto'] || (req.headers.host && (req.headers.host.startsWith('localhost') || req.headers.host.startsWith('127.0.0.1')) ? 'http' : 'https'); - context.__baseUrl = __proto + '://' + req.headers.host; + context.__baseUrl = __proto + '://' + req.headers.host;${auth.guardCall} const sortedNodes = SEGMENT_CONFIG.nodes.slice().sort(function(a, b) { return a.stepNumber - b.stepNumber; }); const executed = {}; @@ -469,6 +520,10 @@ module.exports = async function handler(req, res) { const node = sortedNodes[i]; if (executed[node.id]) continue; const resolved = resolveConfig(node.config, context); + // See the non-streaming segment above — without this the unresolved-token + // guard never runs on the server, which is where every data node executes. + const __configError = utils.finalizeResolvedConfig(node.type, resolved); + if (__configError) { throw new Error(__configError); } resolved.__nodeId = node.id; // If-statement nodes must be evaluated using the runtime's evaluateCondition @@ -527,6 +582,11 @@ module.exports = async function handler(req, res) { } var ssbHandler = nodeHandlers[ssbNode.type]; if (!ssbHandler) continue; + if (utils.isFireAndForgetNode(ssbNode)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(ssbNode, ssbHandler, ssbRes, context)); + context[ssbNode.id] = null; + continue; + } var ssbResult = await ssbHandler(ssbRes, context); context[ssbNode.id] = ssbResult; } @@ -610,6 +670,13 @@ module.exports = async function handler(req, res) { sspRes.__nodeId = sspNode.id; var sspHandler = nodeHandlers[sspNode.type]; if (!sspHandler) continue; + if (utils.isFireAndForgetNode(sspNode)) { + // Registered on the ROUTE context (not the branch copy) so the + // response still waits for the query to land. + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(sspNode, sspHandler, sspRes, ssPBranchCtx)); + ssPBranchCtx[sspNode.id] = null; + continue; + } var sspResult = await sspHandler(sspRes, ssPBranchCtx); ssPBranchCtx[sspNode.id] = sspResult; } @@ -683,6 +750,11 @@ module.exports = async function handler(req, res) { const snHandler = nodeHandlers[sn.type]; if (!snHandler) continue; const snResolved = resolveConfig(sn.config, context); + if (utils.isFireAndForgetNode(sn)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(sn, snHandler, snResolved, context)); + context[sn.id] = null; + continue; + } const snResult = await snHandler(snResolved, context); context[sn.id] = snResult; res.write('data: ' + JSON.stringify({ type: 'node-result', nodeId: sn.id, result: snResult }) + '\\n\\n'); @@ -702,6 +774,12 @@ module.exports = async function handler(req, res) { const enHandler = nodeHandlers[en.type]; if (!enHandler) continue; const enResolved = resolveConfig(en.config, context); + if (utils.isFireAndForgetNode(en)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(en, enHandler, enResolved, context)); + context[en.id] = null; + executed[en.id] = true; + continue; + } const enResult = await enHandler(enResolved, context); context[en.id] = enResult; res.write('data: ' + JSON.stringify({ type: 'node-result', nodeId: en.id, result: enResult }) + '\\n\\n'); @@ -711,8 +789,14 @@ module.exports = async function handler(req, res) { executed[onStreamNodes[si2].id] = true; } } else { + if (utils.isFireAndForgetNode(node)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(node, nodeHandler, resolved, context)); + context[node.id] = null; + continue; + } const result = await nodeHandler(resolved, context); if (result && result.__earlyResponse) { + await utils.settlePendingNodePromises(context); if (streamStarted) { res.write('data: ' + JSON.stringify({ type: 'error', error: (result.__earlyResponse.body && result.__earlyResponse.body.message) || 'Request rejected' }) + '\\n\\n'); res.end(); @@ -737,7 +821,12 @@ module.exports = async function handler(req, res) { } } + // See the non-streaming segment route: land every fire-and-forget query + // before the response completes, or the platform may freeze this function + // with the write still in flight. + await utils.settlePendingNodePromises(context); delete context.__request; + delete context.__pendingNodePromises; if (streamStarted) { res.write('data: ' + JSON.stringify({ type: 'done', success: true, results: context }) + '\\n\\n'); res.end(); @@ -746,6 +835,7 @@ module.exports = async function handler(req, res) { } } catch (error) { console.error('Streaming workflow segment error:', error); + if (__wfContext) { await utils.settlePendingNodePromises(__wfContext); } if (streamStarted) { try { res.write('data: ' + JSON.stringify({ type: 'error', error: error.message || 'Internal server error' }) + '\\n\\n'); @@ -955,6 +1045,9 @@ module.exports = async function handler(req, res) { (workflow.trigger.config.schedule as string) || '' }' }; const context = {}; + // Shared fire-and-forget queue (see the segment routes) — drained by the + // execution loop before this route responds. + context.__pendingNodePromises = []; context[WORKFLOW_CONFIG.triggerNodeId] = triggerContext;${requestInjection} ${executionLoop} @@ -1037,6 +1130,10 @@ const generateNodeExecutionLoop = ( for (var i = 0; i < sortedNodes.length; i++) { var node = sortedNodes[i]; var resolved = resolveConfig(node.config, context); + // See the other segment executors — the unresolved-token guard must run + // wherever data nodes execute, and they all execute on the server. + var __configError = utils.finalizeResolvedConfig(node.type, resolved); + if (__configError) { throw new Error(__configError); } resolved.__nodeId = node.id; if (resolved && Array.isArray(resolved.templateParams)) { if (typeof resolved.body === 'string') { resolved.body = utils.applyTemplateParams(resolved.body, resolved.templateParams); } @@ -1122,6 +1219,11 @@ const generateNodeExecutionLoop = ( } var bHandler = nodeHandlers[bNode.type]; if (!bHandler) continue; + if (utils.isFireAndForgetNode(bNode)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(bNode, bHandler, bResolved, context)); + context[bNode.id] = null; + continue; + } var bResult = await bHandler(bResolved, context); if (bResult && (bResult.success === false || (typeof bResult.error === 'string' && bResult.error))) { throw new Error(bResult.error || 'Loop body node execution failed'); @@ -1203,6 +1305,13 @@ const generateNodeExecutionLoop = ( wlpRes.__nodeId = wlpNode.id; var wlpHandler = nodeHandlers[wlpNode.type]; if (!wlpHandler) continue; + if (utils.isFireAndForgetNode(wlpNode)) { + // Registered on the ROUTE context (not the branch copy) so the + // response still waits for the query to land. + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(wlpNode, wlpHandler, wlpRes, wlBranchCtx)); + wlBranchCtx[wlpNode.id] = null; + continue; + } var wlpResult = await wlpHandler(wlpRes, wlBranchCtx); wlBranchCtx[wlpNode.id] = wlpResult; } @@ -1250,6 +1359,11 @@ const generateNodeExecutionLoop = ( console.warn('No handler for node type: ' + node.type); continue; } + if (utils.isFireAndForgetNode(node)) { + utils.registerPendingNodePromise(context, utils.startFireAndForgetNode(node, handler, resolved, context)); + context[node.id] = null; + continue; + } var result = await handler(resolved, context); if (result && result.__earlyResponse) { var earlyRes = result.__earlyResponse; @@ -1257,6 +1371,7 @@ const generateNodeExecutionLoop = ( for (var h = 0; h < hKeys.length; h++) { res.setHeader(hKeys[h], earlyRes.headers[hKeys[h]]); } + await utils.settlePendingNodePromises(context); res.status(earlyRes.status || 500).json(earlyRes.body || {}); return; }${customNodeBlock} @@ -1265,7 +1380,11 @@ const generateNodeExecutionLoop = ( } context[node.id] = result; if (result && result.__terminal) break; - }` + } + + // Land every fire-and-forget query before this route responds — a + // serverless function can be frozen the instant it replies. + await utils.settlePendingNodePromises(context);` } export const generateWebhookWorkflowAPIRoute = ( @@ -1422,6 +1541,9 @@ ${generateSignatureVerificationBlock(webhookConfig)} }; var context = {}; + // Shared fire-and-forget queue (see the segment routes) — drained by the + // execution loop before this route responds. + context.__pendingNodePromises = []; context[WORKFLOW_CONFIG.triggerNodeId] = triggerContext; var __proto = req.headers['x-forwarded-proto'] || (req.headers.host && (req.headers.host.startsWith('localhost') || req.headers.host.startsWith('127.0.0.1')) ? 'http' : 'https'); context.__baseUrl = __proto + '://' + req.headers.host;${requestInjection} @@ -1446,10 +1568,16 @@ ${executionLoop} eResolved.__nodeId = eNode.id; var eHandler = nodeHandlers[eNode.type]; if (eHandler) { + if (utils.isFireAndForgetNode(eNode)) { + utils.registerPendingNodePromise(errCtx, utils.startFireAndForgetNode(eNode, eHandler, eResolved, errCtx)); + errCtx[eNode.id] = null; + continue; + } var eResult = await eHandler(eResolved, errCtx); errCtx[eNode.id] = eResult; } } + await utils.settlePendingNodePromises(errCtx); } catch (innerErr) { console.error('Webhook error handler failed:', innerErr); } diff --git a/packages/teleport-plugin-next-workflows/src/auth-generator.ts b/packages/teleport-plugin-next-workflows/src/auth-generator.ts index 0266f1d1c..bdf1d47e3 100644 --- a/packages/teleport-plugin-next-workflows/src/auth-generator.ts +++ b/packages/teleport-plugin-next-workflows/src/auth-generator.ts @@ -1,5 +1,6 @@ import { UIDLAuthentication, + UIDLAuthTableColumn, UIDLCustomUserProperty, DataSourceType, } from '@teleporthq/teleport-types' @@ -184,19 +185,123 @@ const airtableBase = new Airtable({ } } -const generateSanitizeUserFunction = (): string => { +/** + * How long (ms) a JWT may serve the profile fields it already carries before + * the next session request re-reads the `users` row. See the generated + * comment in `generateAuthOptionsFile` for the measurements behind it. + */ +export const USER_REFRESH_INTERVAL_MS = 60000 + +/** + * Profile fields the session may always carry, even for a UIDL that ships no + * `users` schema at all. + * + * `id`/`name`/`email`/`image`/`role` are the fields the `account-get-current` + * output contract declares (workflow-schema's node-context-schemas), i.e. the + * ones every workflow and binding addresses. `roleName`/`roles` are the two + * alternate spellings `getUserRoleFromToken` in the generated middleware falls + * back to, so dropping them would silently disable role-based route protection + * for projects that use them. + */ +export const SESSION_SAFE_USER_FIELDS: readonly string[] = [ + 'id', + 'name', + 'email', + 'image', + 'role', + 'roleName', + 'roles', +] + +/** + * Credentials that must never leave the server, whatever the `users` table + * happens to declare: the OAuth single-table adapter's provider tokens plus the + * password hash. `findUserByEmail` does `SELECT *`, so without this list they + * ride the JWT into `session.user` and become readable by any script on the + * page through /api/auth/session. + * + * Denied unconditionally, so a custom user property whose key collides with one + * of these names cannot re-open the hole. `provider` itself is NOT here — it is + * just the provider's name ("google"), and `account-social-login` declares it + * as part of its output contract. + */ +export const SENSITIVE_USER_FIELDS: readonly string[] = [ + 'password', + 'password_hash', + 'passwordHash', + 'access_token', + 'refresh_token', + 'id_token', + 'expires_at', + 'session_state', + 'scope', + 'token_type', + 'provider_account_id', + 'provider_type', +] + +/** + * Mongo's primary key. NOT a secret — it is excluded because `sanitizeUser` + * already folds it into `id` (`rawId = user.id != null ? user.id : user._id`), + * so passing it through as well would put the same value on the session twice + * under two different names. A shape concern, not a security one, which is why + * it is kept out of `SENSITIVE_USER_FIELDS`. + */ +const ID_ALIAS_FIELD = '_id' + +/** + * The exact set of `users` columns this project allows into the session. + * + * Derived from the DECLARED schema (`auth.tables.users`), which the GUI + * composes as the canonical auth columns PLUS one column per custom account + * property — so every property the user configured is included by + * construction, while a column that exists in the database but not in the UIDL + * never is. `customUserProperties` is unioned in directly rather than relied on + * transitively, so the list stays complete for a UIDL that carries the + * properties without a matching `tables` entry. + */ +export const buildSessionUserFields = ( + tables: Record | undefined, + customProps: UIDLCustomUserProperty[] +): string[] => { + const declared = (tables?.users || []).map((column) => column.name) + const custom = customProps.map((prop) => prop.key) + const denied = new Set(SENSITIVE_USER_FIELDS) + + return Array.from(new Set([...SESSION_SAFE_USER_FIELDS, ...declared, ...custom])).filter( + (field) => Boolean(field) && field !== ID_ALIAS_FIELD && !denied.has(field) + ) +} + +const generateSanitizeUserFunction = ( + tables: Record | undefined, + customProps: UIDLCustomUserProperty[] +): string => { + // ALLOW-list, not a deny-list. `sanitizeUser` feeds the JWT, and the session + // callback copies the whole token onto `session.user`, so every column the + // `SELECT *` returned used to be readable by any script on the page. A + // two-entry deny-list (`password`, `_id`) could never keep up with a table + // whose shape the project controls; enumerating what the project actually + // DECLARED is the version that stays correct as columns are added. + // // Preserve the native type of the id (integer vs UUID-string) — NextAuth // will JSON-serialize the session payload either way. Coercing with // \`String(rawId)\` would silently turn an integer PK into "1" and make // runtime comparisons against a DB-fetched \`user.id\` (still a number // on pages that read the row via \`getStaticProps\`) always false. - return `function sanitizeUser(user) { + return `// The only \`users\` columns that may reach the browser: this project's declared +// user schema — canonical profile columns plus every custom account property — +// minus the credentials (password hash, OAuth access/refresh/id tokens), which +// stay server-side. Anything else the row carries never reaches the session. +const SESSION_USER_FIELDS = ${JSON.stringify(buildSessionUserFields(tables, customProps))}; + +function sanitizeUser(user) { if (!user) return null; const safe = {}; - const keys = Object.keys(user); - for (let i = 0; i < keys.length; i++) { - if (keys[i] !== 'password' && keys[i] !== '_id') { - safe[keys[i]] = user[keys[i]]; + for (let i = 0; i < SESSION_USER_FIELDS.length; i++) { + const key = SESSION_USER_FIELDS[i]; + if (user[key] !== undefined) { + safe[key] = user[key]; } } const rawId = user.id != null ? user.id : user._id; @@ -528,19 +633,46 @@ const generateProvidersSetup = (auth: UIDLAuthentication): string => { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' } }, + // Every failure used to \`return null\`, which NextAuth reports as the single + // opaque code \`CredentialsSignin\` — the same answer for a wrong password, an + // unknown email, and a database the app cannot reach. Project a62338f9 shipped + // with a DB credential Postgres rejected, and the only thing the user (or the + // sign-in form) ever saw was "credentialsSignin". + // + // NextAuth v4 surfaces a THROWN error's message as the \`error\` value, so each + // cause now gets its own code. \`describeAuthError\` in + // utils/auth/auth-error-messages turns them into copy; the raw cause is logged + // server-side only. + // + // Unknown email and wrong password deliberately share one code: telling them + // apart is a user-enumeration oracle. async authorize(credentials) { if (!credentials || !credentials.email || !credentials.password) { - return null; + throw new Error('MissingCredentials'); } + const { verifyPassword } = require('./hash-password'); + const { classifyAuthInfrastructureError } = require('./db-health'); + let user; try { - const { verifyPassword } = require('./hash-password'); - const user = await findUserByEmail(String(credentials.email)); - if (!user) return null; - if (!verifyPassword(String(credentials.password), user.password)) return null; + user = await findUserByEmail(String(credentials.email)); + } catch (err) { + const kind = classifyAuthInfrastructureError(err); + console.error('[auth] Could not reach the user store (' + kind + '):', err && err.message ? err.message : err); + throw new Error('ServiceUnavailable'); + } + try { + if (!user) throw new Error('InvalidCredentials'); + if (!verifyPassword(String(credentials.password), user.password)) { + throw new Error('InvalidCredentials'); + } return sanitizeUser(user); } catch (err) { - console.error('Authorize error:', err); - return null; + if (err && err.message === 'InvalidCredentials') throw err; + // A hashing/serialisation fault is an infrastructure problem, not a + // wrong password — saying "check your details" would send the user + // round in circles. + console.error('[auth] Credential check failed:', err && err.message ? err.message : err); + throw new Error('ServiceUnavailable'); } } }));`) @@ -590,7 +722,7 @@ export const generateAuthOptionsFile = ( const findUserCode = auth.passwordAuthEnabled ? generateFindUserFunction(auth.dataSourceType, customProps) : '' - const sanitizeUserCode = generateSanitizeUserFunction() + const sanitizeUserCode = generateSanitizeUserFunction(auth.tables, customProps) const signInRoute = auth.authPages.signIn?.route || '/auth/sign-in' return `${providerImports} @@ -601,6 +733,23 @@ ${findUserCode} ${providersSetup} +// How long a JWT may serve profile fields before the next /api/auth/session +// request re-reads the \`users\` row. \`strategy: 'jwt'\` exists precisely so a +// session costs no database round trip; refreshing on EVERY request threw that +// away — each one opened a fresh unpooled pg connection (TCP + TLS handshake) +// for a single indexed SELECT, which measured ~715ms of the ~925ms that +// /api/auth/session took on a published Vercel deployment, against ~210ms for +// the same route when the token carried no email. Profile edits still land +// immediately whenever the app calls \`useSession().update()\` (NextAuth passes +// \`trigger === 'update'\`, which bypasses the interval); the interval is the +// backstop for changes made outside this browser, e.g. an admin editing a role. +const USER_REFRESH_INTERVAL_MS = ${USER_REFRESH_INTERVAL_MS}; + +// Bookkeeping the refresh policy writes onto the token. It must never be copied +// onto \`session.user\` — it is not a profile field, and leaking it would put an +// internal timestamp on every binding that enumerates the user object. +const TOKEN_REFRESH_STAMP = '__userRefreshedAt'; + const authOptions = { providers: providers, pages: { @@ -616,6 +765,13 @@ const authOptions = { for (let i = 0; i < keys.length; i++) { token[keys[i]] = user[keys[i]]; } + // Deliberately NOT stamped. An OAuth \`user\` is the PROVIDER's profile + // (id/name/email/image) — it carries no \`role\`, which only exists on + // the \`users\` row. Stamping here would make the first session request + // after an OAuth sign-in skip the database and leave the visitor + // role-less for a whole interval, silently failing role-protected + // routes. Leaving it unstamped means the next session request refreshes + // exactly as it does today, and the interval applies from there on. return token; } // Subsequent calls (every /api/auth/session): re-read the user from the @@ -623,6 +779,22 @@ const authOptions = { // session. The JWT is otherwise a snapshot captured at login, which is why // the navbar avatar/name reverted to the old value after a refresh: the // navbar reads /api/auth/session, which is derived from this token. + // + // Rate-limited to USER_REFRESH_INTERVAL_MS, because that read is by far + // the most expensive thing a session request does. \`trigger === 'update'\` + // (fired by \`useSession().update()\`, which the auth bridge re-publishes + // as \`window.__teleportNextAuth.refreshSession\`) always refreshes, so a + // profile save is reflected at once rather than up to an interval later. + const now = Date.now(); + const lastRefresh = token && typeof token[TOKEN_REFRESH_STAMP] === 'number' + ? token[TOKEN_REFRESH_STAMP] + : 0; + // \`now - lastRefresh < 0\` covers a clock that moved backwards: treat the + // stamp as stale rather than trusting it until the clock catches up. + const isFresh = now - lastRefresh >= 0 && now - lastRefresh < USER_REFRESH_INTERVAL_MS; + if (params.trigger !== 'update' && isFresh) { + return token; + } try { if (token && token.email && typeof findUserByEmail === 'function') { const fresh = await findUserByEmail(String(token.email)); @@ -637,6 +809,11 @@ const authOptions = { } catch (e) { // Keep the existing token on any DB hiccup — never sign the user out. } + // Stamped even when the read threw, so an unreachable database costs one + // attempt per interval instead of one per request. + if (token) { + token[TOKEN_REFRESH_STAMP] = now; + } return token; }, async session(params) { @@ -644,6 +821,7 @@ const authOptions = { const token = params.token; if (token && session.user) { const skip = { iat: 1, exp: 1, jti: 1, sub: 1 }; + skip[TOKEN_REFRESH_STAMP] = 1; const keys = Object.keys(token); for (let i = 0; i < keys.length; i++) { if (!skip[keys[i]]) { @@ -670,6 +848,125 @@ ${ ` } +/** + * Why a sign-in failed, in words, plus the one-line codes `authorize` throws. + * + * Project a62338f9 could not sign in on the published site OR in the exported + * project, and the only signal anywhere was NextAuth's generic + * `CredentialsSignin`. The real cause was that Postgres rejected the DB + * credential baked into `TELEPORT_DB_CONNECTION_STRING` — a configuration + * failure the form reported as if the user had mistyped their password. + * + * Every code NextAuth can produce is mapped, not just the new ones, so the form + * never shows a machine token again. + */ +export const generateAuthErrorMessagesFile = (): string => { + return `// Codes thrown by the credentials provider's authorize(). +const AUTH_ERROR_MESSAGES = { + // Ours. + MissingCredentials: 'Please enter both your email and your password.', + InvalidCredentials: 'That email and password do not match an account.', + ServiceUnavailable: + 'We could not reach the account service. Please try again in a moment — if it keeps happening, the site owner needs to check its database configuration.', + + // NextAuth's own. + CredentialsSignin: 'That email and password do not match an account.', + SessionRequired: 'Please sign in to continue.', + AccessDenied: 'This account is not allowed to sign in.', + Verification: 'That sign-in link is no longer valid. Please request a new one.', + Configuration: + 'Sign-in is not configured correctly for this site. The site owner needs to check its authentication settings.', + OAuthSignin: 'We could not start sign-in with that provider. Please try again.', + OAuthCallback: 'That provider could not complete sign-in. Please try again.', + OAuthCreateAccount: 'We could not create an account from that provider.', + OAuthAccountNotLinked: + 'An account with this email already exists. Sign in the way you did originally, then link this provider from your profile.', + EmailCreateAccount: 'We could not create an account with that email address.', + EmailSignin: 'We could not send the sign-in email. Please try again.', + Callback: 'Sign-in could not be completed. Please try again.', + Default: 'Something went wrong while signing in. Please try again.', +}; + +/** + * Human copy for a NextAuth error code. Anything unrecognised — including a + * message a future provider invents — falls back to the generic line rather + * than being shown raw. + */ +function describeAuthError(code) { + if (!code) { return ''; } + var key = String(code); + if (Object.prototype.hasOwnProperty.call(AUTH_ERROR_MESSAGES, key)) { + return AUTH_ERROR_MESSAGES[key]; + } + return AUTH_ERROR_MESSAGES.Default; +} + +module.exports = describeAuthError; +module.exports.describeAuthError = describeAuthError; +module.exports.AUTH_ERROR_MESSAGES = AUTH_ERROR_MESSAGES; +` +} + +/** + * Tells a database that is UNREACHABLE from one that REFUSED the credential. + * + * Both surface to the user as "we could not reach the account service", but the + * server log has to name which one: run a62338f9's published site and its + * exported project both failed with `password authentication failed for user + * "p__usr"`, and nothing in the app ever said so. + */ +export const generateAuthDbHealthFile = (): string => { + return `var AUTH_DB_ERROR_KINDS = { + AUTH_FAILED: 'db-auth-failed', + UNREACHABLE: 'db-unreachable', + MISCONFIGURED: 'db-misconfigured', + UNKNOWN: 'db-unknown', +}; + +/** Postgres SQLSTATEs for "the server said no to these credentials". */ +var AUTH_REJECTION_CODES = ['28P01', '28000', '3D000']; + +function classifyAuthInfrastructureError(err) { + if (!err) { return AUTH_DB_ERROR_KINDS.UNKNOWN; } + var code = err.code ? String(err.code) : ''; + var message = err.message ? String(err.message).toLowerCase() : ''; + if (AUTH_REJECTION_CODES.indexOf(code) !== -1 || message.indexOf('password authentication failed') !== -1) { + return AUTH_DB_ERROR_KINDS.AUTH_FAILED; + } + if (code === 'ENOTFOUND' || code === 'ECONNREFUSED' || code === 'ETIMEDOUT' || code === 'EAI_AGAIN') { + return AUTH_DB_ERROR_KINDS.UNREACHABLE; + } + if (message.indexOf('connection string') !== -1 || message.indexOf('client password must be a string') !== -1) { + return AUTH_DB_ERROR_KINDS.MISCONFIGURED; + } + return AUTH_DB_ERROR_KINDS.UNKNOWN; +} + +/** + * True when a value is still the build-time placeholder the deploy step was + * supposed to replace. A placeholder is WORSE than an empty value: code that + * treats "set" as "configured" then trusts a string that means nothing. + */ +function isUnresolvedSecretPlaceholder(value) { + return typeof value === 'string' && value.indexOf('teleporthq.secrets.') === 0; +} + +/** \`NEXTAUTH_URL\` is only usable when it is an absolute http(s) origin. */ +function isUsableNextAuthUrl(value) { + if (typeof value !== 'string' || !value) { return false; } + if (isUnresolvedSecretPlaceholder(value)) { return false; } + return /^https?:\\/\\//i.test(value); +} + +module.exports = { + AUTH_DB_ERROR_KINDS: AUTH_DB_ERROR_KINDS, + classifyAuthInfrastructureError: classifyAuthInfrastructureError, + isUnresolvedSecretPlaceholder: isUnresolvedSecretPlaceholder, + isUsableNextAuthUrl: isUsableNextAuthUrl, +}; +` +} + export const generateHashPasswordFile = (): string => { return `const bcrypt = require('bcryptjs'); const crypto = require('crypto'); @@ -707,24 +1004,54 @@ const authOptions = require('../../../utils/auth/auth-options'); const authHandler = NextAuth(authOptions); +// Inlined rather than required from utils/auth/db-health: this route is the +// entry point for ALL authentication, so it must not depend on a sibling module +// resolving. Three lines, and the shared copy still backs authorize(). +function isUsableNextAuthUrl(value) { + if (typeof value !== 'string' || !value) { return false; } + if (value.indexOf('teleporthq.secrets.') === 0) { return false; } + return /^https?:\\/\\//i.test(value); +} + // NextAuth builds OAuth callback / redirect URLs from process.env.NEXTAUTH_URL. // At build time the real deployment domain is unknown, so the generated .env // ships a localhost default. Derive the correct origin from the incoming // request here so OAuth works on whatever domain the project is published to — // WITHOUT hardcoding it. An explicitly-configured (non-local) NEXTAUTH_URL is // always respected; local dev (host = localhost) is left untouched. +// +// "Explicitly configured" means a REAL absolute http(s) origin. Project +// a62338f9 shipped \`NEXTAUTH_URL=teleporthq.secrets.NEXTAUTH_URL\` — an +// unresolved placeholder — and the old check saw a non-empty, non-localhost +// string and refused to override it. NextAuth then normalised it to +// \`https://teleporthq.secrets.nextauth_url\`, advertised that as the sign-in +// origin and issued \`__Host-\`/\`__Secure-\` cookies against it. Treating anything +// that is not a usable URL as unset lets an already-published site self-heal on +// its next request. module.exports = function nextAuthRoute(req, res) { try { const fwdHost = req.headers['x-forwarded-host'] || req.headers.host || ''; const host = Array.isArray(fwdHost) ? fwdHost[0] : fwdHost; const hostIsLocal = host.indexOf('localhost') === 0 || host.indexOf('127.0.0.1') === 0; const current = process.env.NEXTAUTH_URL || ''; + if (current && !isUsableNextAuthUrl(current)) { + console.error( + '[auth] NEXTAUTH_URL is not a usable origin (' + current + ') — deriving it from the request instead.' + ); + } const currentIsLocalOrEmpty = - !current || current.indexOf('localhost') !== -1 || current.indexOf('127.0.0.1') !== -1; + !isUsableNextAuthUrl(current) || + current.indexOf('localhost') !== -1 || + current.indexOf('127.0.0.1') !== -1; if (host && !hostIsLocal && currentIsLocalOrEmpty) { const fwdProto = req.headers['x-forwarded-proto']; const proto = (Array.isArray(fwdProto) ? fwdProto[0] : fwdProto) || 'https'; process.env.NEXTAUTH_URL = proto + '://' + host; + } else if (hostIsLocal && !isUsableNextAuthUrl(current)) { + // Local dev with an unusable value would otherwise leave NextAuth + // deriving \`https://…\` from the placeholder, so its cookies get the + // \`Secure\` prefix and the browser drops them over plain http. + process.env.NEXTAUTH_URL = 'http://' + (host || 'localhost:3000'); } } catch (e) { /* fall back to the configured NEXTAUTH_URL */ @@ -1273,6 +1600,55 @@ export const config = { ` } +// A side-effect-only module that MUST evaluate before `next-auth/react` is +// imported. It is emitted at utils/auth/nextauth-url-guard.js and imported as the +// FIRST import of session-provider.js (the only module that imports +// next-auth/react). ES module imports evaluate in source order, so this runs +// first. +// +// Why it exists: next-auth v4's `next-auth/react` builds its `__NEXTAUTH` config +// at MODULE LOAD by calling `parseUrl(process.env.NEXTAUTH_URL)` (and the +// NEXTAUTH_URL_INTERNAL / VERCEL_URL variants). `parseUrl('')` runs `new URL('')`, +// which throws "Invalid URL" — so an EMPTY-STRING env value crashes the import +// and, with it, server-side rendering for every page that mounts SessionProvider +// (the terminal shows `TypeError: Invalid URL … input: '' … page: '/products'`). +// An UNSET var is safe: next-auth defaults it to http://localhost:3000. But a +// generated `.env` can ship `NEXTAUTH_URL=` (empty), which Next.js loads into +// process.env as "" rather than undefined — the crashing case. Deleting an +// empty/whitespace value restores the safe "unset" state; a real configured +// value is left untouched. On the browser these are already undefined, so this +// is a no-op there. +export const generateNextAuthUrlGuardModule = (): string => { + return `// GENERATED — see generateNextAuthUrlGuardModule in +// @teleporthq/teleport-plugin-next-workflows/src/auth-generator.ts. +// +// next-auth v4's \`next-auth/react\` reads \`parseUrl(process.env.NEXTAUTH_URL)\` at +// MODULE LOAD. \`new URL('')\` throws "Invalid URL", so an EMPTY-STRING value +// crashes the import — and server-side rendering for every page that mounts +// SessionProvider. An UNSET var is fine (next-auth defaults it to +// http://localhost:3000); only an empty string is fatal. A generated \`.env\` may +// ship \`NEXTAUTH_URL=\` (empty), which Next.js loads as "", not undefined. +// +// This is the FIRST import of session-provider.js — the only module that imports +// next-auth/react — and ES module imports evaluate in source order, so this runs +// before next-auth reads the value. It removes an empty / whitespace value from +// the server's process.env so next-auth falls back to its default. On the client +// these are already undefined, so it is a no-op. +if (typeof process !== 'undefined' && process && process.env) { + var __TQ_NEXTAUTH_URL_KEYS = ['NEXTAUTH_URL', 'NEXTAUTH_URL_INTERNAL', 'VERCEL_URL'] + for (var __i = 0; __i < __TQ_NEXTAUTH_URL_KEYS.length; __i++) { + var __k = __TQ_NEXTAUTH_URL_KEYS[__i] + var __v = process.env[__k] + if (typeof __v === 'string' && __v.trim() === '') { + delete process.env[__k] + } + } +} + +export {} +` +} + export const generateSessionProviderWrapper = (): string => { // Authored as pure ESM. _app.js imports this with an ESM default import // (`import AuthSessionProvider from '.../session-provider'`). When the file @@ -1284,8 +1660,15 @@ export const generateSessionProviderWrapper = (): string => { // it worked locally). Keeping a single, consistent module system removes the // fragile boundary. `SessionProvider` is imported by name (the SWC-safe form // even though next-auth/react ships CommonJS). - return `import React from 'react' -import { SessionProvider, signIn, signOut } from 'next-auth/react' + // + // The `nextauth-url-guard` import MUST stay first: it normalizes an empty + // NEXTAUTH_URL out of process.env before `next-auth/react` evaluates and calls + // `parseUrl('')`, which would otherwise throw "Invalid URL" at module load and + // crash SSR. ES imports run in source order, so first = before next-auth/react. + return `import './nextauth-url-guard' +import React from 'react' +import { SessionProvider, signIn, signOut, useSession } from 'next-auth/react' +import describeAuthError from './auth-error-messages' // Bridge for the workflow account handlers (account-login / -logout / -signup / // -social-login). Those handlers are emitted via fn.toString() and re-bundled @@ -1298,14 +1681,83 @@ import { SessionProvider, signIn, signOut } from 'next-auth/react' // next-auth/react that is reliably bundled into the app shell) guarantees the // handlers can read them off \`window\` without any fragile require/import of // their own. The assignment runs at module-eval time, before any click. +// \`describeAuthError\` rides the same bridge for the same reason. The sign-in +// handler used to surface NextAuth's raw code — project a62338f9's users were +// shown the literal string "credentialsSignin" — and it cannot require the +// message table itself without reintroducing exactly the fragile require this +// bridge exists to avoid. Published from here, where a normal module import is +// safe, so there is ONE table rather than a copy inlined per handler. +// A stable object, assigned to \`window\` exactly once at module-eval time. +// \`SessionSnapshotBridge\` below mutates it in place, so a handler that grabbed +// \`window.__teleportNextAuth\` earlier always observes the current session. +const teleportNextAuth = { + signIn: signIn, + signOut: signOut, + describeAuthError: describeAuthError, + // The session SessionProvider is ALREADY holding in memory, republished so + // that workflow handlers can read it synchronously instead of paying an HTTP + // round trip to /api/auth/session for something the page has had since it + // mounted. On a published deployment that request measured ~925ms — the + // \`account-get-current\` node fired one on every click that resolves the + // current user (favourites, cart, reviews, ...), strictly serial with the + // workflow's own request. \`status\` is next-auth's: 'loading' until the + // provider's first fetch settles, then 'authenticated' / 'unauthenticated'. + session: null, + status: 'loading', + getSession: function () { + return { status: teleportNextAuth.status, session: teleportNextAuth.session } + }, + // \`useSession().update()\`. Calling it re-reads the user server-side (NextAuth + // passes \`trigger: 'update'\` to the jwt callback, which bypasses the refresh + // interval) and updates the in-memory session. This is how a profile save + // makes its change visible immediately rather than at the next interval. + refreshSession: function () { + return Promise.resolve(null) + }, +} + if (typeof window !== 'undefined') { - window.__teleportNextAuth = { signIn: signIn, signOut: signOut } + window.__teleportNextAuth = teleportNextAuth +} + +// Renders nothing; it exists only to subscribe to the session context and mirror +// it onto the bridge. It must live INSIDE SessionProvider for useSession() to +// resolve. Mirroring happens in an effect (never during render, which React may +// discard or replay) — effects flush on the commit that follows the provider's +// fetch, long before any user click. +function SessionSnapshotBridge() { + const sessionContext = useSession() + const status = sessionContext ? sessionContext.status : 'loading' + const data = sessionContext ? sessionContext.data : null + const update = sessionContext ? sessionContext.update : null + + React.useEffect( + function () { + teleportNextAuth.status = status + teleportNextAuth.session = data || null + if (typeof update === 'function') { + teleportNextAuth.refreshSession = update + } + }, + [status, data, update] + ) + + return null } export default function AuthSessionProvider(props) { return React.createElement( SessionProvider, - { session: props.pageProps && props.pageProps.session ? props.pageProps.session : undefined }, + { + session: props.pageProps && props.pageProps.session ? props.pageProps.session : undefined, + // Every regained window focus re-fetched /api/auth/session, and each of + // those is a server round trip for a session the page already has. Tabbing + // away and back was enough to trigger one. Cross-tab sign-in/sign-out + // still propagates: next-auth broadcasts those over its storage channel, + // which is independent of this flag. + refetchOnWindowFocus: false, + }, + React.createElement(SessionSnapshotBridge, { key: 'teleport-session-bridge' }), props.children ) } diff --git a/packages/teleport-plugin-next-workflows/src/await-result.ts b/packages/teleport-plugin-next-workflows/src/await-result.ts new file mode 100644 index 000000000..cf283320f --- /dev/null +++ b/packages/teleport-plugin-next-workflows/src/await-result.ts @@ -0,0 +1,52 @@ +import { UIDLWorkflowNode } from '@teleporthq/teleport-types' +import { WorkflowSegment } from './types' + +/** + * Every node in the `data` category. Mirrors `DATA_NODE_TYPES` in + * teleport-gui's `@teleport/workflow-schema` (`constants/data-node-await.ts`) — + * the two repos cannot import each other, so this list is a PAIRED EDIT. + */ +export const DATA_NODE_TYPES: ReadonlyArray = [ + 'data-select', + 'data-count', + 'data-raw-query', + 'data-create-item', + 'data-update-item', + 'data-delete-item', +] + +/** + * Config key carrying the author's await choice. Only `false` opts out — + * `undefined` (never configured) and `true` both mean "await", so every + * project generated before this option existed keeps its old behaviour. + */ +export const AWAIT_RESULT_CONFIG_KEY = 'awaitResult' + +const DATA_NODE_TYPE_SET = new Set(DATA_NODE_TYPES) + +/** + * True when this node runs fire-and-forget: the runtime starts the query, + * publishes `null` under the node's id and moves straight on to the next node. + */ +export const isFireAndForgetNode = (node: UIDLWorkflowNode | undefined | null): boolean => { + if (!node || !DATA_NODE_TYPE_SET.has(node.type)) { + return false + } + const config = node.config as Record | undefined + return !!config && config[AWAIT_RESULT_CONFIG_KEY] === false +} + +/** + * True when a whole SERVER segment can be dispatched without awaiting the + * response — i.e. every node it holds is fire-and-forget, so nothing + * downstream can read anything the segment produces. + * + * The API route itself still awaits each query before replying (a serverless + * function may be frozen the moment it responds, which would drop an in-flight + * write); what this flag removes is the CLIENT's wait on that round trip, which + * is where the latency the visitor feels actually comes from. + */ +export const isFireAndForgetSegment = (segment: WorkflowSegment): boolean => + segment.env === 'server' && + segment.nodes.length > 0 && + segment.nodes.every((node) => isFireAndForgetNode(node)) diff --git a/packages/teleport-plugin-next-workflows/src/executor-generator.ts b/packages/teleport-plugin-next-workflows/src/executor-generator.ts index f1c9bc1d8..b96dc20cf 100644 --- a/packages/teleport-plugin-next-workflows/src/executor-generator.ts +++ b/packages/teleport-plugin-next-workflows/src/executor-generator.ts @@ -398,6 +398,38 @@ function finalizeResolvedConfig(nodeType, config) { config.filters = keptFilters; } + // BACKSTOP for WRITES: a columnMapping whose resolved value is STILL a whole + // {{…}} token would insert the literal token text into the column. Run + // 02783f65 declared state defaults of '{{url.character_id}}' and + // '{{url.event_id}}' — a token vocabulary that does not exist — and both fed + // event_responses.event_id / .character_id (both uuid) through a state-get, + // so every Accept / Decline / Tentative died on Postgres 22P02. + // + // Deliberately stricter than the filters rule above: only a WHOLE-string + // token counts. An embedded '{{' inside longer prose is text a user may have + // legitimately typed into a form; a value that is nothing but a moustache is + // unambiguously an unresolved token. + // + // Erroring (rather than nulling) matches the write posture above: the column + // may be a NOT NULL foreign key, so dropping it trades 22P02 for a constraint + // violation. The error surfaces through the workflow error handler with the + // column named, instead of a driver-level failure nobody can attribute. + if (isDataNode && config && Array.isArray(config.columnMappings)) { + for (var ci = 0; ci < config.columnMappings.length; ci++) { + var mapping = config.columnMappings[ci]; + if (!mapping || typeof mapping !== 'object') continue; + var mval = mapping.value; + if (typeof mval === 'string' && /^\\s*\\{\\{[\\s\\S]*\\}\\}\\s*$/.test(mval)) { + if (!error) { + error = + 'Column "' + (mapping.column || 'unknown') + + '" would be written the unresolved template ' + mval.trim() + + ' as literal text. That token resolves nowhere at runtime.'; + } + } + } + } + return error; } @@ -564,6 +596,8 @@ function evaluateSingleComparison(config, context) { async function executeWorkflow(workflowConfig, triggerContext, nodeHandlers, options) { options = options || {}; const context = {}; + // See buildContext — one shared fire-and-forget queue for the whole run. + context.__pendingNodePromises = []; const executionId = Date.now() + '_' + Math.random().toString(36).substr(2, 9); context[workflowConfig.triggerNodeId] = triggerContext; if (triggerContext && triggerContext.__stateValues) { @@ -659,6 +693,72 @@ function topoSortNodes(nodes, edges) { return sorted; } +// Data-category node types. Mirrors DATA_NODE_TYPES in await-result.ts (and in +// teleport-gui's workflow-schema) — PAIRED EDIT. +var __DATA_NODE_TYPES = { + 'data-select': true, + 'data-count': true, + 'data-raw-query': true, + 'data-create-item': true, + 'data-update-item': true, + 'data-delete-item': true +}; + +// A data node the author opted out of awaiting. Only an explicit \`false\` opts +// out, so a config written before the option existed keeps awaiting. +function isFireAndForgetNode(node) { + if (!node || !__DATA_NODE_TYPES[node.type]) return false; + return !!node.config && node.config.awaitResult === false; +} + +// Starts a fire-and-forget node and returns a promise that ALWAYS resolves. +// The workflow has already moved on, so a failure here can neither abort it nor +// reach the error handler — it is reported to the console and swallowed, which +// is exactly what "do not await" means. +function startFireAndForgetNode(node, handler, resolvedConfig, context) { + var label = (node && (node.label || node.type)) || 'node'; + var started; + try { + started = Promise.resolve(handler(resolvedConfig, context)); + } catch (syncErr) { + started = Promise.reject(syncErr); + } + return started.then(function(result) { + if (isFatalNodeResult(result)) { + console.error('[workflow] "' + label + '" failed (not awaited): ' + fatalNodeResultMessage(result)); + } + }).catch(function(err) { + console.error('[workflow] "' + label + '" threw (not awaited):', err); + }); +} + +// Keeps every in-flight fire-and-forget promise on the execution context so a +// server route can settle them BEFORE it responds. A serverless function may be +// frozen the moment its response is sent, which would silently drop an +// in-flight write; the visitor still never waits for it, because the client +// dispatches such a segment without awaiting the round trip. +function registerPendingNodePromise(context, promise) { + if (!context || !promise) return promise; + if (!context.__pendingNodePromises) context.__pendingNodePromises = []; + context.__pendingNodePromises.push(promise); + return promise; +} + +async function settlePendingNodePromises(context) { + if (!context) return; + // Bounded drain: a settled promise can only enqueue more work through a + // nested custom node, so a handful of passes is always enough and a runaway + // producer can never hang the response. + for (var pass = 0; pass < 5; pass++) { + var pending = context.__pendingNodePromises; + if (!pending || pending.length === 0) return; + context.__pendingNodePromises = []; + // Every entry swallows its own rejection (see startFireAndForgetNode), so + // this can never reject. + await Promise.all(pending); + } +} + // A node result signals failure either through the legacy string contract // ({ error: '...' } / { success: false }) or through the AI-node contract // ({ error: true, message, code } — provider/auth failures). Both must halt @@ -809,6 +909,20 @@ async function executeNodes(nodes, edges, context, nodeHandlers, workflowConfig, continue; } + if (isFireAndForgetNode(node)) { + registerPendingNodePromise( + context, + startFireAndForgetNode(node, handler, resolvedConfig, context) + ); + // The workflow never waits for this query, so it has no value to + // publish: downstream references resolve to null rather than to a + // half-finished or stale result. + context[node.id] = null; + executed[node.id] = true; + context.__previousNodeResult = null; + continue; + } + let result = await handler(resolvedConfig, context); if (result && result.__customNode && result.customNodeId && workflowConfig.customNodes) { @@ -1116,7 +1230,11 @@ module.exports = { markAllBranchNodes, isStreamingAINode, isFatalNodeResult, - fatalNodeResultMessage + fatalNodeResultMessage, + isFireAndForgetNode, + startFireAndForgetNode, + registerPendingNodePromise, + settlePendingNodePromises }; ` } @@ -1165,6 +1283,10 @@ function pruneContext(context) { const val = context[key]; if (val === undefined || val === null) continue; if (typeof val === 'function') continue; + // In-flight fire-and-forget promises are local to whichever runtime started + // them; serializing them would ship a list of empty objects and let a + // server response overwrite the client's live list. + if (key === '__pendingNodePromises') continue; try { // Replace DOM nodes with serializable snapshots as we stringify, then // re-parse so the request body itself (JSON.stringify(prunedContext) in @@ -1267,6 +1389,9 @@ async function callServerSegment(segmentUrl, context) { function buildContext(workflowConfig, triggerContext) { const context = {}; + // Created eagerly so every nested custom node (which shallow-copies this + // object) pushes into the SAME fire-and-forget queue instead of its own. + context.__pendingNodePromises = []; context[workflowConfig.triggerNodeId] = triggerContext; if (triggerContext) { if (triggerContext.__stateValues) context.__stateValues = triggerContext.__stateValues; @@ -1472,6 +1597,30 @@ async function executeWorkflowWithSegments(workflowConfig, triggerContext, clien var allSkipped = seg.nodes.every(function(n) { return context.__skippedNodes[n.id]; }); if (allSkipped) continue; } + // Every node in this segment is fire-and-forget, so nothing downstream + // can read anything it produces — dispatch it and keep going instead of + // making the visitor wait for the database round trip. The route itself + // still awaits each query before it responds; we simply ignore the + // response. Errors are logged, never routed to the error handler: + // the workflow already moved past this point. + if (seg.fireAndForget) { + const ffUrl = serverSegmentUrls[seg.id]; + if (!ffUrl) throw new Error('No server URL for segment: ' + seg.id); + utils.registerPendingNodePromise( + context, + callServerSegment(ffUrl, context).catch(function(err) { + console.error('[workflow] Segment "' + seg.id + '" failed (not awaited):', err); + }) + ); + for (var ffi = 0; ffi < seg.nodes.length; ffi++) { + // A node on a branch that was not taken must stay absent from the + // context, exactly as it would if the segment had been awaited. + if (context.__skippedNodes && context.__skippedNodes[seg.nodes[ffi].id]) continue; + context[seg.nodes[ffi].id] = null; + } + context.__previousNodeResult = null; + continue; + } const hasStreaming = seg.hasStreamingAI || seg.nodes.some(function(n) { return streamingInfo[n.id]; }); diff --git a/packages/teleport-plugin-next-workflows/src/nodes/account/account-get-current.ts b/packages/teleport-plugin-next-workflows/src/nodes/account/account-get-current.ts index 9562919be..4729acb57 100644 --- a/packages/teleport-plugin-next-workflows/src/nodes/account/account-get-current.ts +++ b/packages/teleport-plugin-next-workflows/src/nodes/account/account-get-current.ts @@ -21,21 +21,56 @@ async function account_get_current(_config: unknown, context: Record { + if (typeof window === 'undefined') { + return + } + try { + if (user) { + window.localStorage.setItem('teleport_auth_user', JSON.stringify(user)) + } else { + window.localStorage.removeItem('teleport_auth_user') + } + } catch (_e) {} + } + + // `_app` renders NextAuth's SessionProvider on every page, so the browser has + // already fetched and is holding the session in memory; session-provider.js + // republishes it on `window.__teleportNextAuth`. Re-fetching it over HTTP cost + // a full round trip (~925ms on a published deployment, because the jwt + // callback re-reads the `users` row) BEFORE the workflow's own request could + // start — for data the page had since it mounted. + // + // Only 'authenticated' short-circuits. 'loading' means the provider's first + // fetch has not settled; 'unauthenticated' is also what next-auth reports when + // that fetch FAILED, and treating a transient error as "signed out" would send + // a signed-in visitor down the guest branch. Both fall through to the fetch — + // which for a guest is the cheap case anyway, since the jwt callback returns + // before touching the database when there is no token. + if (typeof window !== 'undefined') { + try { + const bridge = (window as any).__teleportNextAuth + const snapshot = + bridge && typeof bridge.getSession === 'function' ? bridge.getSession() : null + if (snapshot && snapshot.status === 'authenticated') { + const liveUser = snapshot.session && snapshot.session.user ? snapshot.session.user : null + if (liveUser) { + __cache(liveUser) + return __out(liveUser) + } + } + } catch (_e) {} + } + try { const response = await fetch(baseUrl + '/api/auth/session') if (response.ok) { const session = await response.json() const user = session && session.user ? session.user : null - if (typeof window !== 'undefined') { - try { - if (user) { - window.localStorage.setItem('teleport_auth_user', JSON.stringify(user)) - } else { - window.localStorage.removeItem('teleport_auth_user') - } - } catch (_e) {} - } + __cache(user) return __out(user) } diff --git a/packages/teleport-plugin-next-workflows/src/nodes/account/account-login.ts b/packages/teleport-plugin-next-workflows/src/nodes/account/account-login.ts index c0491dbb9..9360a5354 100644 --- a/packages/teleport-plugin-next-workflows/src/nodes/account/account-login.ts +++ b/packages/teleport-plugin-next-workflows/src/nodes/account/account-login.ts @@ -33,7 +33,18 @@ async function account_login(config: any, context: Record) { }) if (result && result.error) { - throw new Error(result.error) + // NextAuth hands back a CODE (`CredentialsSignin`, `Configuration`, or one + // of the codes the credentials provider throws). It used to be rethrown + // verbatim, so the sign-in form showed users the literal string + // "credentialsSignin" with no idea whether they had mistyped a password or + // the site could not reach its database. `describeAuthError` rides the same + // window bridge as `signIn` — see session-provider — so this handler needs + // no require of its own; the raw code is the fallback if an older bridge is + // on the page. + const describe = nextAuthReact.describeAuthError + throw new Error( + typeof describe === 'function' ? describe(result.error) || result.error : result.error + ) } let user = null diff --git a/packages/teleport-plugin-next-workflows/src/segment-splitter.ts b/packages/teleport-plugin-next-workflows/src/segment-splitter.ts index a3db97d79..c6ffcd7b9 100644 --- a/packages/teleport-plugin-next-workflows/src/segment-splitter.ts +++ b/packages/teleport-plugin-next-workflows/src/segment-splitter.ts @@ -2,6 +2,7 @@ import { UIDLWorkflow, UIDLWorkflowNode, UIDLWorkflowEdge } from '@teleporthq/te import { WorkflowSegment, WorkflowExecutionEnv } from './types' import { getLoopBodyNodes, getNodeById, getTopologicalOrder } from './graph-utils' import { nodeRegistry } from './nodes' +import { AWAIT_RESULT_CONFIG_KEY } from './await-result' const CLIENT_ONLY_NODE_TYPES = new Set([ 'account-login', @@ -289,14 +290,21 @@ const enforceLoopBodyIntegrity = ( export const resolveNodeExecutionEnv = (node: UIDLWorkflowNode): WorkflowExecutionEnv => resolveExecutionEnv(node, null) -// The ONLY field of a server node's config the CLIENT executor ever reads is +// The ONLY fields of a server node's config the CLIENT executor ever reads are // the AI-streaming flag (findStreamingAINodes / callStreamingServerSegment in -// executor-generator). Everything else — the raw SQL query, filters, table -// name, bound params, column mappings, data source id, … — is consumed -// exclusively inside the server API route (see api-route-generator's -// SEGMENT_CONFIG, which keeps the full config server-side). None of it may -// reach the browser bundle. -export const CLIENT_SAFE_SERVER_CONFIG_KEYS: ReadonlyArray = ['streaming'] +// executor-generator) and the data-node await flag (the custom-node runtime +// skips a fire-and-forget node when picking its return value). Everything else +// — the raw SQL query, filters, table name, bound params, column mappings, +// data source id, … — is consumed exclusively inside the server API route (see +// api-route-generator's SEGMENT_CONFIG, which keeps the full config +// server-side). None of it may reach the browser bundle. +// +// `awaitResult` is a plain boolean choice, never a value or an identifier, so +// exposing it leaks nothing about the schema or the query. +export const CLIENT_SAFE_SERVER_CONFIG_KEYS: ReadonlyArray = [ + 'streaming', + AWAIT_RESULT_CONFIG_KEY, +] /** * Strip a server node's config down to the client-safe whitelist before it is diff --git a/packages/teleport-plugin-next-workflows/src/workflow-auth-generator.ts b/packages/teleport-plugin-next-workflows/src/workflow-auth-generator.ts new file mode 100644 index 000000000..f8eceb66a --- /dev/null +++ b/packages/teleport-plugin-next-workflows/src/workflow-auth-generator.ts @@ -0,0 +1,187 @@ +import { UIDLWorkflowProtection } from '@teleporthq/teleport-types' + +/** + * The shared, stateless auth guard for generated workflow API routes, emitted + * once at `utils/workflows/workflow-auth.js`. + * + * The policy is baked into each route at build time (from the workflow's page + * protection + a scan of its graph for user-owned writes), so enforcement is a + * single local JWT decode — `getToken` reads the session cookie the browser + * already sends and verifies it with `NEXTAUTH_SECRET`. No DB, no network, no + * round trip. `next-auth/jwt` is required LAZILY so a project generated without + * authentication (where the package is absent) never fails to load this file — + * such projects also carry no protected workflows, so the guard no-ops. + */ +export const generateWorkflowAuthHelperFile = (): string => { + return `'use strict'; + +// GENERATED — see generateWorkflowAuthHelperFile in +// @teleporthq/teleport-plugin-next-workflows/src/workflow-auth-generator.ts. +// +// Stateless auth guard for workflow API routes. Each route bakes its own policy +// (const __WF_AUTH) computed by the GUI mapper from the protection of the +// page(s) that trigger the workflow plus a graph scan for user-owned writes. + +function getSessionToken(req) { + var secret = process.env.NEXTAUTH_SECRET; + if (!secret) { + return Promise.resolve(null); + } + var getToken; + try { + getToken = require('next-auth/jwt').getToken; + } catch (e) { + return Promise.resolve(null); + } + if (typeof getToken !== 'function') { + return Promise.resolve(null); + } + // Local cookie decode — no DB, no network. + return Promise.resolve() + .then(function () { return getToken({ req: req, secret: secret }); }) + .catch(function () { return null; }); +} + +function sessionUserId(token) { + if (!token || typeof token !== 'object') { + return null; + } + return token.id != null ? token.id : (token.sub != null ? token.sub : null); +} + +function roleOf(token) { + if (!token || typeof token !== 'object') { + return null; + } + if (typeof token.role === 'string') { + return token.role; + } + if (typeof token.roleName === 'string') { + return token.roleName; + } + if (Array.isArray(token.roles) && token.roles.length > 0 && typeof token.roles[0] === 'string') { + return token.roles[0]; + } + return null; +} + +// Overwrites context[nodeId] drilled down \`path\` with the session user id. +function bindPath(root, path, value) { + if (!root || !path || path.length === 0) { + return; + } + var obj = root; + for (var i = 0; i < path.length - 1; i++) { + var key = path[i]; + if (obj[key] == null || typeof obj[key] !== 'object') { + obj[key] = {}; + } + obj = obj[key]; + } + obj[path[path.length - 1]] = value; +} + +// Returns null when the request may proceed, or { status, message } to reject. +// Mutates \`context\` in place to bind user-owned columns to the session user. +async function guardWorkflowRequest(req, context, policy) { + if (!policy) { + return null; + } + + // Trusted internal server-to-server calls (e.g. password reset, server jobs) + // present the app secret in a header; only server code can read + // NEXTAUTH_SECRET, so a browser cannot forge it. These bypass the check. + var internal = req && req.headers && req.headers['x-internal-data-secret']; + if (internal && process.env.NEXTAUTH_SECRET && internal === process.env.NEXTAUTH_SECRET) { + return null; + } + + var token = await getSessionToken(req); + + if (policy.requiresAuth && !token) { + return { status: 401, message: 'Unauthenticated' }; + } + + var roles = policy.allowedRoles || []; + if (policy.requiresAuth && roles.length > 0) { + var role = roleOf(token); + if (!role || roles.indexOf(role) < 0) { + return { status: 403, message: 'Forbidden' }; + } + } + + // Identity binding: force every user-owned column to the AUTHENTICATED session + // id so a caller can never act on another user's rows. Only when a session is + // present — a guest keeps their (anonymous) client identity, which is why a + // guest-capable public write is not blocked here. + if (policy.userScoped && context) { + var sid = sessionUserId(token); + if (sid != null) { + var bindings = (policy.userScoped && policy.userScoped.bindings) || []; + for (var i = 0; i < bindings.length; i++) { + var b = bindings[i]; + if (b && b.nodeId) { + if (context[b.nodeId] == null || typeof context[b.nodeId] !== 'object') { + context[b.nodeId] = {}; + } + bindPath(context[b.nodeId], b.path || [], sid); + } + } + } + } + + return null; +} + +module.exports = { guardWorkflowRequest: guardWorkflowRequest }; +` +} + +/** + * The route-side pieces that wire a workflow's protection policy into a + * generated API-route handler. Empty strings when the workflow has no policy, + * so an unprotected route is byte-identical to before. + */ +export interface WorkflowAuthInjection { + // `require(...)` of the shared helper (placed with the other requires). + requireLine: string + // `const __WF_AUTH = {...};` — the baked policy. + policyConst: string + // The `await` guard call + early 401/403 response, placed after the request + // context is assembled and BEFORE any node runs / any stream starts. + guardCall: string +} + +const EMPTY_INJECTION: WorkflowAuthInjection = { requireLine: '', policyConst: '', guardCall: '' } + +export const buildWorkflowAuthInjection = ( + protection: UIDLWorkflowProtection | undefined +): WorkflowAuthInjection => { + if (!protection || (!protection.requiresAuth && !protection.userScoped)) { + return EMPTY_INJECTION + } + + // Only the fields the runtime guard reads — `derivedFrom` is build-time only. + const policy: { + requiresAuth: boolean + allowedRoles: string[] + userScoped?: UIDLWorkflowProtection['userScoped'] + } = { + requiresAuth: !!protection.requiresAuth, + allowedRoles: protection.allowedRoles || [], + } + if (protection.userScoped) { + policy.userScoped = protection.userScoped + } + + return { + requireLine: `const __wfAuth = require('../../../utils/workflows/workflow-auth');\n`, + policyConst: `const __WF_AUTH = ${JSON.stringify(policy)};\n`, + guardCall: ` + const __authError = await __wfAuth.guardWorkflowRequest(req, context, __WF_AUTH); + if (__authError) { + res.status(__authError.status).json({ error: __authError.message }); + return; + }`, + } +} diff --git a/packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts b/packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts index 970235a15..737f7931b 100644 --- a/packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts +++ b/packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts @@ -12,12 +12,13 @@ import { UIDLCustomWorkflowNode, } from '@teleporthq/teleport-types' import * as types from '@babel/types' -import { StringUtils } from '@teleporthq/teleport-shared' +import { JSIdentifiers, StringUtils } from '@teleporthq/teleport-shared' import { splitIntoSegments, resolveNodeExecutionEnv, redactServerNodeConfig, } from './segment-splitter' +import { isFireAndForgetSegment } from './await-result' import { WorkflowExecutionEnv } from './types' import { getAPIRouteFileName, hasStreamingAINode } from './api-route-generator' import { REALTIME_TRIGGER_TYPES, REALTIME_NODE_TYPES } from './graph-utils' @@ -74,6 +75,25 @@ const DOM_TO_REACT_EVENT: Record = { drag: 'onDrag', } +/** + * Trigger types that run as LIFECYCLE code (no React event prop) but are still + * bound to ONE element, so the workflow only belongs on the page that renders + * it. Returns the DOM id to prune against, or null when the trigger is not + * element-scoped. + * + * Same fallback chain as the element-trigger branch: the HTML id first, the + * project-document node id only as a last resort. + */ +const resolveLifecycleTriggerElementId = ( + triggerType: string, + config: Record +): string | null => { + if (triggerType !== 'event-element-visible') { + return null + } + return ((config.elementHtmlId || config.nodeId) as string) || null +} + const getReactEventProp = (triggerType: string, config: Record): string | null => { switch (triggerType) { case 'event-element-clicked': @@ -219,6 +239,8 @@ export const createNextWorkflowPlugin: ComponentPluginFactory = [] const stateChangeWorkflows: UIDLWorkflow[] = [] const globalStateChangeWorkflows: UIDLWorkflow[] = [] @@ -272,6 +294,17 @@ export const createNextWorkflowPlugin: ComponentPluginFactory 0) { - const targetIds = new Set(elementTriggers.map((t) => t.elementId)) + if ( + returnStatement && + returnStatement.argument && + (elementTriggers.length > 0 || lifecycleElementTargets.length > 0) + ) { + const targetIds = new Set([ + ...elementTriggers.map((t) => t.elementId), + ...lifecycleElementTargets.map((t) => t.elementId), + ]) matchedElements = findJSXElementsById(returnStatement.argument, targetIds) for (const et of elementTriggers) { @@ -315,6 +355,13 @@ export const createNextWorkflowPlugin: ComponentPluginFactory t.workflowId === wf.id) + if (target && !matchedElements.has(target.elementId)) { + continue + } activeWorkflowIds.add(wf.id) } for (const wf of stateChangeWorkflows) { @@ -670,7 +717,15 @@ const defaultValueToLiteral = (val: unknown): types.Expression => { return types.nullLiteral() } -const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1) +/** + * Object key for a state/global-state map that the workflow runtime looks up by + * the name written in the node config (`config.property`). The key therefore + * keeps the UIDL spelling ALWAYS — only the value beside it is a binding and + * gets sanitised. Reserved words are legal unquoted keys (`{ class: ... }`); + * anything that is not identifier syntax at all is quoted. + */ +const stateMapKey = (name: string): types.Identifier | types.StringLiteral => + JSIdentifiers.isValidPropertyKeyName(name) ? types.identifier(name) : types.stringLiteral(name) const resolveStateDefinitionKey = ( rawName: string, @@ -703,39 +758,56 @@ const injectWorkflowCode = ( for (const [key, def] of Object.entries(stateDefinitions)) { const setterName = StringUtils.createStateStoringFunction(key) - stateSetterProperties.push( - types.objectProperty(types.identifier(key), types.identifier(setterName)) - ) + // KEY: the name a workflow node's `config.property` is written against — + // never renamed. VALUE: the React binding declared by `createStateHookAST`, + // which is sanitised because a UIDL state may legally be called `class`. + stateSetterProperties.push(types.objectProperty(stateMapKey(key), types.identifier(setterName))) stateTypeProperties.push( - types.objectProperty(types.identifier(key), types.stringLiteral(def.type || 'string')) + types.objectProperty(stateMapKey(key), types.stringLiteral(def.type || 'string')) + ) + stateValueProperties.push( + types.objectProperty( + stateMapKey(key), + types.identifier(JSIdentifiers.createSafeJSIdentifier(key)) + ) ) - stateValueProperties.push(types.objectProperty(types.identifier(key), types.identifier(key))) } const globalStateStatements: types.Statement[] = [] if (globalStateDefinitions && Object.keys(globalStateDefinitions).length > 0) { const destructuredProps: types.ObjectProperty[] = [] for (const def of Object.values(globalStateDefinitions)) { - const setterName = `set${capitalize(def.name)}` + // `GlobalStateProvider` exposes every entry under its DECLARED name, so + // the context keys stay raw and only the locals we bind are sanitised. + // The pattern then reads `{ class: class_ }` — shorthand only when the + // two coincide, which is the case for every ordinary name. + const setterKey = StringUtils.createGlobalStateSetterName(def.name) + const setterName = JSIdentifiers.createSafeJSIdentifier(setterKey) + const localName = JSIdentifiers.createSafeJSIdentifier(def.name) destructuredProps.push( - types.objectProperty(types.identifier(def.name), types.identifier(def.name), false, true) + types.objectProperty( + stateMapKey(def.name), + types.identifier(localName), + false, + localName === def.name + ) ) destructuredProps.push( types.objectProperty( - types.identifier(setterName), + stateMapKey(setterKey), types.identifier(setterName), false, - true + setterName === setterKey ) ) stateSetterProperties.push( - types.objectProperty(types.identifier(def.name), types.identifier(setterName)) + types.objectProperty(stateMapKey(def.name), types.identifier(setterName)) ) stateTypeProperties.push( - types.objectProperty(types.identifier(def.name), types.stringLiteral(def.type || 'string')) + types.objectProperty(stateMapKey(def.name), types.stringLiteral(def.type || 'string')) ) stateValueProperties.push( - types.objectProperty(types.identifier(def.name), types.identifier(def.name)) + types.objectProperty(stateMapKey(def.name), types.identifier(localName)) ) } @@ -1303,6 +1375,9 @@ function __normalizeAdminFormRow(row, defaults) { id: s.id, env: s.env, hasStreamingAI: hasStreamingAINode(s), + // Every node in this segment runs fire-and-forget, so the browser + // dispatches it and carries on instead of waiting for the round trip. + fireAndForget: isFireAndForgetSegment(s), nodes: s.nodes.map((n) => ({ id: n.id, type: n.type, @@ -1414,8 +1489,26 @@ function __normalizeAdminFormRow(row, defaults) { } } - // Lifecycle triggers + // Lifecycle triggers. + // + // `allWorkflows` here is the already-pruned `activeWorkflows`: a lifecycle + // element-visible trigger whose target element is NOT in this component's own + // JSX was excluded from it (its `__wfConfig_*` was therefore never declared). + // But `generateLifecycleTrigger` emits an IntersectionObserver that resolves + // its target at runtime with `document.getElementById(target)` — a + // DOCUMENT-WIDE lookup that happily matches an element ANOTHER component + // rendered (e.g. the shared "Cookie Consent" banner, which is attached to + // ~23 element-visible workflows and would otherwise ship into every product + // card). When it fires it calls `__execWf(__wfConfig_, …)` for a config + // that was never emitted, throwing `ReferenceError: __wfConfig_… is not + // defined` the moment the element scrolls into view. Pruning the handler in + // lockstep with the config keeps the two in sync: the workflow still runs in + // the component/page that actually renders its target element. + const emittedConfigIds = new Set(allWorkflows.map((wf) => wf.id)) for (const wf of lifecycleWorkflows) { + if (!emittedConfigIds.has(wf.id)) { + continue + } const safeId = wf.id.replace(/[^a-zA-Z0-9]/g, '_') const code = generateLifecycleTrigger(wf, safeId) if (code) { @@ -1999,17 +2092,24 @@ const generateLifecycleTrigger = (wf: UIDLWorkflow, safeId: string): string => { } case 'event-element-visible': { - const nodeId = config.nodeId as string + // `config.nodeId` is the PROJECT-DOCUMENT node id (`TQ_…`); no element in + // the generated app ever carries it. `elementHtmlId` is the real DOM id + // (`thq_container_…`), already stamped by `ensure-element-ids` and mapped + // into the trigger config — the same fallback chain every other element + // trigger uses above. Reading `nodeId` made `getElementById` return null, + // so the observer was never constructed and the cookie-consent banner + // could never appear on any page (run a15472af: 408 dead lookups). + const elementId = (config.elementHtmlId || config.nodeId) as string const threshold = (config.threshold as number) || 0 const once = config.once as boolean return ( ` // Element visible (${wf.name || wf.id})\n` + - ` const __visEl_${safeId} = document.getElementById('${nodeId}');\n` + + ` const __visEl_${safeId} = document.getElementById('${elementId}');\n` + ` if (__visEl_${safeId}) {\n` + ` const __obs_${safeId} = new IntersectionObserver(function(entries) {\n` + ` entries.forEach(function(entry) {\n` + ` if (entry.isIntersecting) {\n` + - ` const triggerContext = { elementId: '${nodeId}', timestamp: Date.now(), intersectionRatio: entry.intersectionRatio };\n` + + ` const triggerContext = { elementId: '${elementId}', timestamp: Date.now(), intersectionRatio: entry.intersectionRatio };\n` + ` ${execCall};\n` + (once ? ` __obs_${safeId}.disconnect();\n` : '') + ` }\n` + diff --git a/packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts b/packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts index 0bf0a6d43..3b75f603f 100644 --- a/packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts +++ b/packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts @@ -11,6 +11,7 @@ import { resolveNodeExecutionEnv, redactServerNodeConfig, } from './segment-splitter' +import { isFireAndForgetSegment } from './await-result' import { generateServerSegmentAPIRoute, generateStreamingServerSegmentAPIRoute, @@ -22,6 +23,7 @@ import { getWebhookRoutePath, hasStreamingAINode, } from './api-route-generator' +import { generateWorkflowAuthHelperFile } from './workflow-auth-generator' import { collectSecrets, collectSecretReferenceEnvNames } from './secret-collector' import { collectUsedNodeTypes, @@ -47,12 +49,15 @@ import { generateRealtimeChannelsMembersRoute, } from './realtime-generator' import { + generateAuthDbHealthFile, + generateAuthErrorMessagesFile, generateAuthOptionsFile, generateHashPasswordFile, generateNextAuthRouteFile, generateSignupRouteFile, generateMiddlewareFile, generateSessionProviderWrapper, + generateNextAuthUrlGuardModule, getDatabaseDriverDependencies, } from './auth-generator' import { generateInvoiceFiles, resolveInvoiceDataSource } from './invoice' @@ -331,6 +336,11 @@ export class NextWorkflowProjectPlugin implements ProjectPlugin { }) } + // Set true the moment we emit ANY route that bakes an auth policy, so the + // shared guard file is emitted iff at least one route actually imports it. + const routeHasPolicy = (p: any): boolean => !!p && (p.requiresAuth || p.userScoped) + let anyGuardedRouteEmitted = false + // Build server segment info for custom nodes so they can call server-side API routes const customNodeServerUrls: Record> = {} if (Object.keys(customNodes).length > 0) { @@ -346,9 +356,12 @@ export class NextWorkflowProjectPlugin implements ProjectPlugin { customNodeServerUrls[cnId] = {} for (const seg of cnServerSegments) { const isStreaming = hasStreamingAINode(seg) + if (routeHasPolicy(cn.protection)) { + anyGuardedRouteEmitted = true + } const apiContent = isStreaming - ? generateStreamingServerSegmentAPIRoute(seg, cn.name || cnId) - : generateServerSegmentAPIRoute(seg, cn.name || cnId) + ? generateStreamingServerSegmentAPIRoute(seg, cn.name || cnId, cn.protection) + : generateServerSegmentAPIRoute(seg, cn.name || cnId, cn.protection) const fileName = getAPIRouteFileName(cnId, seg.id, cn.name || cnId) customNodeServerUrls[cnId][seg.id] = `/api/workflows/${fileName}` files.set(`workflow-api-cn-${cnId}-${seg.id}`, { @@ -473,9 +486,12 @@ export class NextWorkflowProjectPlugin implements ProjectPlugin { for (const serverSeg of serverSegments) { hasServerSegments = true const isStreaming = hasStreamingAINode(serverSeg) + if (routeHasPolicy(workflow.protection)) { + anyGuardedRouteEmitted = true + } const apiContent = isStreaming - ? generateStreamingServerSegmentAPIRoute(serverSeg, workflow.name) - : generateServerSegmentAPIRoute(serverSeg, workflow.name) + ? generateStreamingServerSegmentAPIRoute(serverSeg, workflow.name, workflow.protection) + : generateServerSegmentAPIRoute(serverSeg, workflow.name, workflow.protection) const fileName = getAPIRouteFileName(workflow.id, serverSeg.id, workflow.name) files.set(`workflow-api-${workflow.id}-${serverSeg.id}`, { @@ -503,6 +519,23 @@ export class NextWorkflowProjectPlugin implements ProjectPlugin { ], }) + // Shared stateless auth guard, emitted only when at least one emitted + // route actually bakes a protection policy (so the file is never orphaned). + // Enforcement is baked per-route as `const __WF_AUTH`; this file is the one + // runtime that reads the session cookie via getToken. + if (anyGuardedRouteEmitted) { + files.set('workflow-auth-guard', { + path: ['utils', 'workflows'], + files: [ + { + name: 'workflow-auth', + fileType: FileType.JS, + content: generateWorkflowAuthHelperFile(), + }, + ], + }) + } + const serverHandlerCode = this.generateNodeHandlerFile(usedNodeTypes, 'server') if (serverHandlerCode) { files.set('workflow-server-handlers', { @@ -1213,6 +1246,9 @@ ${entries} id: s.id, env: s.env, hasStreamingAI: hasStreamingAINode(s), + // Every node in this segment runs fire-and-forget — dispatch it and + // carry on instead of waiting for the database round trip. + fireAndForget: isFireAndForgetSegment(s), nodes: s.nodes.map((n) => ({ id: n.id, type: n.type, @@ -1290,6 +1326,27 @@ async function customNode_${safeId}(outerContext, parameters, nodeHandlers) { } var segUrl = serverUrls[seg.id]; if (segUrl) { + if (seg.fireAndForget) { + // Nothing downstream can read this segment's output, so the visitor + // never waits for it. The route still awaits each query before it + // responds; we just ignore the response. A failure is logged and + // cannot reach the custom node's error chain — the workflow has + // already moved past this point. + __utils.registerPendingNodePromise( + context, + __runtime.callServerSegment(segUrl, context).catch(function(__ffErr) { + console.error('[workflow] Segment "' + seg.id + '" failed (not awaited):', __ffErr); + }) + ); + for (var __ffi = 0; __ffi < seg.nodes.length; __ffi++) { + // A node on a branch that was not taken must stay absent from the + // context, exactly as it would if the segment had been awaited. + if (context.__skippedNodes && context.__skippedNodes[seg.nodes[__ffi].id]) continue; + context[seg.nodes[__ffi].id] = null; + } + context.__previousNodeResult = null; + continue; + } if (seg.hasStreamingAI) { var streamHandled = await __runtime.callStreamingServerSegment(segUrl, context, streamingInfo, nodes, edges, nodeHandlers, wfConfig, executionId); Object.assign(handledNodeIds, streamHandled); @@ -1356,10 +1413,16 @@ async function customNode_${safeId}(outerContext, parameters, nodeHandlers) { } } - var sortedNodeIds = nodes.slice().sort(function(a, b) { return a.stepNumber - b.stepNumber; }).map(function(n) { return n.id; }); + // The custom node returns its last executed node's output. A fire-and-forget + // node is excluded: it always stores \`null\`, so if it happens to be last it + // would turn the whole custom node's result into null for every caller. + var __returnableNodes = nodes + .slice() + .sort(function(a, b) { return a.stepNumber - b.stepNumber; }) + .filter(function(n) { return !__utils.isFireAndForgetNode(n); }); var lastNodeId = null; - for (var __ri = sortedNodeIds.length - 1; __ri >= 0; __ri--) { - if (context[sortedNodeIds[__ri]] !== undefined) { lastNodeId = sortedNodeIds[__ri]; break; } + for (var __ri = __returnableNodes.length - 1; __ri >= 0; __ri--) { + if (context[__returnableNodes[__ri].id] !== undefined) { lastNodeId = __returnableNodes[__ri].id; break; } } return lastNodeId ? context[lastNodeId] : {}; }`) @@ -1416,10 +1479,16 @@ async function customNode_${safeId}(outerContext, parameters, nodeHandlers) { } } - var sortedNodeIds = nodes.slice().sort(function(a, b) { return a.stepNumber - b.stepNumber; }).map(function(n) { return n.id; }); + // The custom node returns its last executed node's output. A fire-and-forget + // node is excluded: it always stores \`null\`, so if it happens to be last it + // would turn the whole custom node's result into null for every caller. + var __returnableNodes = nodes + .slice() + .sort(function(a, b) { return a.stepNumber - b.stepNumber; }) + .filter(function(n) { return !__utils.isFireAndForgetNode(n); }); var lastNodeId = null; - for (var __ri = sortedNodeIds.length - 1; __ri >= 0; __ri--) { - if (context[sortedNodeIds[__ri]] !== undefined) { lastNodeId = sortedNodeIds[__ri]; break; } + for (var __ri = __returnableNodes.length - 1; __ri >= 0; __ri--) { + if (context[__returnableNodes[__ri].id] !== undefined) { lastNodeId = __returnableNodes[__ri].id; break; } } return lastNodeId ? context[lastNodeId] : {}; }`) @@ -1463,6 +1532,30 @@ module.exports = __customNodeRegistry; ], }) + // Shared by the NextAuth route (which uses it to reject an unresolved + // NEXTAUTH_URL placeholder) and, when credentials are on, by `authorize`. + // Emitted unconditionally because the route always exists. + files.set('auth-db-health', { + path: ['utils', 'auth'], + files: [ + { + name: 'db-health', + fileType: FileType.JS, + content: generateAuthDbHealthFile(), + }, + ], + }) + files.set('auth-error-messages', { + path: ['utils', 'auth'], + files: [ + { + name: 'auth-error-messages', + fileType: FileType.JS, + content: generateAuthErrorMessagesFile(), + }, + ], + }) + if (auth.passwordAuthEnabled) { const hashPasswordCode = generateHashPasswordFile() files.set('auth-hash-password', { @@ -1546,6 +1639,22 @@ module.exports = __customNodeRegistry; }) } + // Emitted BEFORE session-provider so its file lands next to it. session-provider + // imports it first (`import './nextauth-url-guard'`) to strip an empty + // NEXTAUTH_URL out of process.env before next-auth/react's module-load + // `parseUrl('')` throws "Invalid URL" and crashes SSR. See + // generateNextAuthUrlGuardModule. + files.set('auth-nextauth-url-guard', { + path: ['utils', 'auth'], + files: [ + { + name: 'nextauth-url-guard', + fileType: FileType.JS, + content: generateNextAuthUrlGuardModule(), + }, + ], + }) + const sessionProviderCode = generateSessionProviderWrapper() files.set('auth-session-provider', { path: ['utils', 'auth'], @@ -1895,15 +2004,34 @@ export function resolveAuthEnvValue( value: string, preserveKeys?: Set ): string { - if (value.startsWith('teleporthq.secrets.')) { - // NEXTAUTH_URL / NEXTAUTH_SECRET get a local default (the worker does not - // manage them). OAuth provider credential refs are PRESERVED so the deploy - // worker resolves them from the project secret store — emptying them (the - // old behavior) left the deployed env var blank, so NextAuth could not build - // the provider's authorization URL (error=OAuthSignin / "nothing happens"). - if (Object.prototype.hasOwnProperty.call(AUTH_ENV_DEFAULTS, key)) { - return AUTH_ENV_DEFAULTS[key] - } + const isSecretPlaceholder = typeof value === 'string' && value.startsWith('teleporthq.secrets.') + const isBlank = typeof value !== 'string' || value.trim() === '' + + // NEXTAUTH_URL / NEXTAUTH_SECRET must never reach the generated `.env` as an + // EMPTY assignment. next-auth v4's `react/index.js` runs + // `parseUrl(process.env.NEXTAUTH_URL)` at MODULE LOAD, and `new URL('')` + // throws "Invalid URL" — which crashes server-side rendering for every page + // that mounts SessionProvider through `_app` (an UNSET var is fine, because + // parseUrl defaults it, but `createEnvFiles` writes every key, so a blank + // value serializes as the crashing `NEXTAUTH_URL=`). The blank case is real + // and self-perpetuating: once an older generation left `NEXTAUTH_URL=` on + // disk, the standalone harness's `preserveExistingEnv` re-injects that empty + // string, and this resolver used to pass it straight through. Healing a blank + // (or still-unresolved placeholder) auth key to its local default keeps the + // value a valid origin; the deploy worker and the runtime request-derivation + // (`absolutizeNextAuthUrl`) override it with the real one in production. + if ( + Object.prototype.hasOwnProperty.call(AUTH_ENV_DEFAULTS, key) && + (isSecretPlaceholder || isBlank) + ) { + return AUTH_ENV_DEFAULTS[key] + } + + if (isSecretPlaceholder) { + // OAuth provider credential refs are PRESERVED so the deploy worker resolves + // them from the project secret store — emptying them (the old behavior) left + // the deployed env var blank, so NextAuth could not build the provider's + // authorization URL (error=OAuthSignin / "nothing happens"). if (ALWAYS_PRESERVE_SECRET_ENV_KEYS.has(key)) { return value } diff --git a/packages/teleport-project-generator-next/src/global-state/component-plugin.ts b/packages/teleport-project-generator-next/src/global-state/component-plugin.ts index b49c108d7..a21b2c794 100644 --- a/packages/teleport-project-generator-next/src/global-state/component-plugin.ts +++ b/packages/teleport-project-generator-next/src/global-state/component-plugin.ts @@ -1,5 +1,6 @@ import { ComponentPlugin, ComponentPluginFactory, UIDLDependency } from '@teleporthq/teleport-types' import * as types from '@babel/types' +import { JSIdentifiers, StringUtils } from '@teleporthq/teleport-shared' export const USE_GLOBAL_STATE_HOOK: UIDLDependency = { type: 'local', @@ -9,7 +10,26 @@ export const USE_GLOBAL_STATE_HOOK: UIDLDependency = { }, } -const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1) +/** + * One entry of the `useGlobalState()` destructuring pattern. + * + * The KEY is the context property the provider published — always the declared + * name, never rewritten. The VALUE is a local binding, so it is sanitised: a + * global state may legally be named `class`, which cannot be bound directly. + * Shorthand is kept whenever the two coincide, which is every ordinary name, so + * the emitted output is unchanged for existing projects. + */ +const destructuredEntry = (contextKey: string): types.ObjectProperty => { + const localName = JSIdentifiers.createSafeJSIdentifier(contextKey) + return types.objectProperty( + JSIdentifiers.isValidPropertyKeyName(contextKey) + ? types.identifier(contextKey) + : types.stringLiteral(contextKey), + types.identifier(localName), + false, + localName === contextKey + ) +} export const createNextGlobalStateComponentPlugin: ComponentPluginFactory<{}> = () => { const globalStatePlugin: ComponentPlugin = async (structure) => { @@ -41,18 +61,8 @@ export const createNextGlobalStateComponentPlugin: ComponentPluginFactory<{}> = const destructuredProps: types.ObjectProperty[] = [] for (const [, name] of Array.from(uniqueNames)) { - destructuredProps.push( - types.objectProperty(types.identifier(name), types.identifier(name), false, true) - ) - const setterName = `set${capitalize(name)}` - destructuredProps.push( - types.objectProperty( - types.identifier(setterName), - types.identifier(setterName), - false, - true - ) - ) + destructuredProps.push(destructuredEntry(name)) + destructuredProps.push(destructuredEntry(StringUtils.createGlobalStateSetterName(name))) } const hookCall = types.variableDeclaration('const', [ diff --git a/packages/teleport-project-generator-next/src/global-state/project-plugin.ts b/packages/teleport-project-generator-next/src/global-state/project-plugin.ts index c8db0b107..9c955a0e6 100644 --- a/packages/teleport-project-generator-next/src/global-state/project-plugin.ts +++ b/packages/teleport-project-generator-next/src/global-state/project-plugin.ts @@ -6,6 +6,7 @@ import { UIDLDataSource, } from '@teleporthq/teleport-types' import { generateDataSourceFetcherWithCore } from '@teleporthq/teleport-plugin-next-data-source' +import { JSIdentifiers, StringUtils } from '@teleporthq/teleport-shared' import { collectGlobalStateFetchConfigs, buildRefPathAccessCode, @@ -18,6 +19,32 @@ import { const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1) +/** + * Local binding for a global state inside `GlobalStateProvider`. + * + * The context still publishes the entry under its DECLARED name (see + * `buildContextValueEntry`) — only the `useState` binding is sanitised, because + * a global state may legally be called `class`, which cannot be bound. + */ +const localBindingFor = (name: string): string => JSIdentifiers.createSafeJSIdentifier(name) + +/** `fetchX` helper name for a data-source-bound global state. */ +const fetchFunctionName = (name: string): string => + JSIdentifiers.createSafeJSIdentifier(`fetch${capitalize(name)}`) + +/** + * One `key: value` line of the context object. Emitted as shorthand whenever + * the published key and the local binding are the same string, which keeps the + * output byte-identical for every ordinary name. + */ +const buildContextValueEntry = (contextKey: string): string => { + const local = localBindingFor(contextKey) + if (local === contextKey) { + return ` ${contextKey},` + } + return ` ${JSON.stringify(contextKey)}: ${local},` +} + const serializeDefaultValue = ( value: string | number | boolean | Record | unknown[] ): string => { @@ -91,14 +118,16 @@ const generateGlobalStateContextFileContent = ( for (const def of defs) { const { name, defaultValue, type } = def - const setterName = `set${capitalize(name)}` + const setterKey = StringUtils.createGlobalStateSetterName(name) const normalized = normalizeDefaultValueForType(defaultValue, type) const serialized = serializeDefaultValue(normalized) - stateLines.push(` const [${name}, ${setterName}] = useState(${serialized})`) - valueEntries.push(` ${name},`) - valueEntries.push(` ${setterName},`) - memoDepEntries.push(name) + stateLines.push( + ` const [${localBindingFor(name)}, ${localBindingFor(setterKey)}] = useState(${serialized})` + ) + valueEntries.push(buildContextValueEntry(name)) + valueEntries.push(buildContextValueEntry(setterKey)) + memoDepEntries.push(localBindingFor(name)) } // Build useEffect blocks and fetch functions for data-source-bound states @@ -117,19 +146,22 @@ const generateGlobalStateContextFileContent = ( const userDependentFetches = fetchConfigs.filter((c) => c.needsCurrentUser) if (independentFetches.length > 0) { - const calls = independentFetches.map((c) => ` fetch${capitalize(c.name)}()`).join('\n') + const calls = independentFetches.map((c) => ` ${fetchFunctionName(c.name)}()`).join('\n') effectBlocks.push(` useEffect(() => {\n${calls}\n }, [])`) } if (userDependentFetches.length > 0) { - const calls = userDependentFetches.map((c) => ` fetch${capitalize(c.name)}()`).join('\n') + const calls = userDependentFetches.map((c) => ` ${fetchFunctionName(c.name)}()`).join('\n') effectBlocks.push(` useEffect(() => {\n${calls}\n }, [currentUser])`) } - // Build refreshGlobalState switch + // Build refreshGlobalState switch. The `case` label is the state's DECLARED + // name — that is what `refreshGlobalState('')` is called with. const cases = fetchConfigs .map((c) => { - return ` case '${c.name}':\n fetch${capitalize(c.name)}()\n break` + return ` case ${JSON.stringify(c.name)}:\n ${fetchFunctionName( + c.name + )}()\n break` }) .join('\n') @@ -207,7 +239,7 @@ export const useGlobalState = () => { */ const generateFetchFunctionForState = (config: GlobalStateFetchConfig): string => { const { name, definition } = config - const setterName = `set${capitalize(name)}` + const setterName = localBindingFor(StringUtils.createGlobalStateSetterName(name)) const refPath = definition.dataSourceBinding?.refPath || [] const filterResult = definition.filterConfig ? separateFilters(definition.filterConfig) @@ -215,7 +247,7 @@ const generateFetchFunctionForState = (config: GlobalStateFetchConfig): string = const staticFilters = filterResult.staticFilters const lines: string[] = [] - lines.push(` const fetch${capitalize(name)} = async () => {`) + lines.push(` const ${fetchFunctionName(name)} = async () => {`) lines.push(` try {`) if (config.hasQuery) { diff --git a/packages/teleport-project-generator-next/src/internationalization/project.ts b/packages/teleport-project-generator-next/src/internationalization/project.ts index 6296b6cb3..391572fb7 100644 --- a/packages/teleport-project-generator-next/src/internationalization/project.ts +++ b/packages/teleport-project-generator-next/src/internationalization/project.ts @@ -8,6 +8,7 @@ import { ProjectUIDL, UIDLCustomUserProperty, } from '@teleporthq/teleport-types' +import { RouteUtils } from '@teleporthq/teleport-plugin-common' const findFileInBuild = ( name: string, @@ -208,6 +209,14 @@ const generateSitemapContent = ( if (hasNoIndex) { return false } + // A dynamic route has no single URL to list. Its `navLink` is a TEMPLATE + // (`/event-details/[id]`), and emitting that verbatim publishes a URL that + // 404s for every crawler that follows it. The concrete per-record URLs are + // not knowable here — they come from the rows getStaticPaths resolves — so + // the honest sitemap omits the page rather than advertising a placeholder. + if (RouteUtils.pathHasDynamicSegment(route.pageOptions?.navLink || '')) { + return false + } return true }) diff --git a/packages/teleport-project-generator-next/src/url-search-params-plugin.ts b/packages/teleport-project-generator-next/src/url-search-params-plugin.ts index 912627344..43f0a6534 100644 --- a/packages/teleport-project-generator-next/src/url-search-params-plugin.ts +++ b/packages/teleport-project-generator-next/src/url-search-params-plugin.ts @@ -4,7 +4,7 @@ import type { UIDLDependency, UIDLStateDefinition, } from '@teleporthq/teleport-types' -import { Constants, StringUtils } from '@teleporthq/teleport-shared' +import { Constants, JSIdentifiers, StringUtils } from '@teleporthq/teleport-shared' import { URLSearchParamSync } from '@teleporthq/teleport-plugin-common' import { USE_ROUTER_HOOK } from './internationalization/locale-mapper-component' @@ -270,12 +270,17 @@ export const createNextUrlSearchParamsPlugin = (): ComponentPlugin => { const effectsToInsert: types.Statement[] = [] for (const { stateKey, paramKey, defaultValue } of urlBoundStateKeys) { const setterName = StringUtils.createStateStoringFunction(stateKey) + // The effects READ the state, so they must use the same binding + // `createStateHookAST` declared — sanitised, because a UIDL state may + // legally be named `class`. A no-op for every ordinary name. + const stateBinding = JSIdentifiers.createSafeJSIdentifier(stateKey) // Only a non-empty default changes behavior; an empty default keeps // the effects byte-identical to the pre-default builder. const defaultValueExpr = defaultValue !== '' ? types.stringLiteral(defaultValue) : undefined const hasWriteBack = hasUseEffectMatching( body.body, - (deps, fn) => effectDepsContainStateId(deps, stateKey) && effectBodyHasRouterReplace(fn) + (deps, fn) => + effectDepsContainStateId(deps, stateBinding) && effectBodyHasRouterReplace(fn) ) if (!hasWriteBack) { // State dropdowns read AND depend on the same bare state identifier @@ -284,8 +289,8 @@ export const createNextUrlSearchParamsPlugin = (): ComponentPlugin => { effectsToInsert.push( URLSearchParamSync.buildUrlWriteBackEffect( paramKey, - types.identifier(stateKey), - types.identifier(stateKey), + types.identifier(stateBinding), + types.identifier(stateBinding), defaultValueExpr ) ) diff --git a/packages/teleport-shared/__tests__/utils/js-identifiers.ts b/packages/teleport-shared/__tests__/utils/js-identifiers.ts new file mode 100644 index 000000000..285715d48 --- /dev/null +++ b/packages/teleport-shared/__tests__/utils/js-identifiers.ts @@ -0,0 +1,147 @@ +/** + * A UIDL state named `class` (a WoW character sheet really has that column) + * emitted `const [class, setClass] = useState("")`, prettier threw + * `SyntaxError: Unexpected token, expected "{"`, and `packProject` aborted — + * so the WHOLE project failed to generate, not just that page. + */ + +import { + RESERVED_JS_IDENTIFIERS, + createSafeJSIdentifier, + createSafeJSIdentifierPath, + isReservedJSIdentifier, + isValidJSIdentifierName, + isValidPropertyKeyName, +} from '../../src/utils/js-identifiers' +import { createStateStoringFunction } from '../../src/utils/string-utils' + +describe('isValidJSIdentifierName', () => { + it('accepts ordinary identifiers', () => { + for (const name of ['isSubmitting', 'realm', '_private', '$ref', 'a1', 'setClass']) { + expect(isValidJSIdentifierName(name)).toBe(true) + } + }) + + it('rejects reserved words even though they are valid identifier SYNTAX', () => { + for (const name of ['class', 'if', 'return', 'new', 'this', 'delete', 'in', 'typeof']) { + expect(isValidJSIdentifierName(name)).toBe(false) + expect(isReservedJSIdentifier(name)).toBe(true) + } + }) + + it('rejects strict-mode reserved words (generated code is always a module)', () => { + for (const name of ['let', 'static', 'yield', 'await', 'implements', 'arguments', 'eval']) { + expect(isValidJSIdentifierName(name)).toBe(false) + } + }) + + it('rejects names that are not identifier syntax at all', () => { + for (const name of ['', '2fa', 'my key', 'a-b', 'a.b', 'ünicode']) { + expect(isValidJSIdentifierName(name)).toBe(false) + } + }) + + it('rejects non-strings without throwing', () => { + expect(isValidJSIdentifierName(undefined as unknown as string)).toBe(false) + expect(isValidJSIdentifierName(null as unknown as string)).toBe(false) + }) +}) + +describe('isValidPropertyKeyName', () => { + it('accepts a reserved word — `{ class: x }` and `props.class` are legal', () => { + expect(isValidPropertyKeyName('class')).toBe(true) + expect(isValidPropertyKeyName('default')).toBe(true) + }) + + it('rejects anything that would need quoting', () => { + expect(isValidPropertyKeyName('my key')).toBe(false) + expect(isValidPropertyKeyName('2fa')).toBe(false) + expect(isValidPropertyKeyName('')).toBe(false) + }) +}) + +describe('createSafeJSIdentifier', () => { + it('is a NO-OP for every name that already compiled', () => { + for (const name of ['isSubmitting', 'characterName', 'itemLevel', '_x', '$y']) { + expect(createSafeJSIdentifier(name)).toBe(name) + } + }) + + it('makes a reserved word bindable with a trailing underscore', () => { + expect(createSafeJSIdentifier('class')).toBe('class_') + expect(createSafeJSIdentifier('new')).toBe('new_') + expect(createSafeJSIdentifier('function')).toBe('function_') + }) + + it('cannot collide, because the shared name normaliser erases underscores', () => { + // `dashCaseToCamelCase` replaces /[-_]+(.)?/ so a normalised state/prop name + // never contains `_` — `class_` is therefore unreachable as a sibling name. + expect(createSafeJSIdentifier('class')).not.toBe(createSafeJSIdentifier('classValue')) + }) + + it('repairs names that are not identifier syntax', () => { + expect(createSafeJSIdentifier('my key')).toBe('my_key') + expect(createSafeJSIdentifier('a.b')).toBe('a_b') + expect(createSafeJSIdentifier('2fa')).toBe('_2fa') + }) + + it('falls back for empty / non-string input instead of emitting nothing', () => { + expect(createSafeJSIdentifier('')).toBe('_value') + expect(createSafeJSIdentifier(undefined as unknown as string)).toBe('_value') + expect(createSafeJSIdentifier('', 'fallbackName')).toBe('fallbackName') + }) + + it('re-checks reservedness AFTER the character pass', () => { + // "my class" sanitises to "my_class", which is no longer reserved and must + // NOT pick up a second underscore. + expect(createSafeJSIdentifier('my class')).toBe('my_class') + }) + + it('every reserved word maps to something bindable', () => { + for (const word of RESERVED_JS_IDENTIFIERS) { + const safe = createSafeJSIdentifier(word) + expect(safe).not.toBe(word) + expect(isValidJSIdentifierName(safe)).toBe(true) + } + }) +}) + +describe('createSafeJSIdentifierPath', () => { + it('rewrites only the binding head, never the property path', () => { + expect(createSafeJSIdentifierPath("class?.['spec_role']")).toBe("class_?.['spec_role']") + expect(createSafeJSIdentifierPath('class')).toBe('class_') + }) + + it('leaves an already-legal reference untouched', () => { + expect(createSafeJSIdentifierPath("fields?.['name']")).toBe("fields?.['name']") + expect(createSafeJSIdentifierPath('characterName')).toBe('characterName') + }) + + it('never touches a hand-written EXPRESSION that begins with a keyword', () => { + // `createConditionIdentifier` returns raw expression strings for `expr` + // references; rewriting their first word would corrupt the condition. + expect(createSafeJSIdentifierPath("typeof x === 'string'")).toBe("typeof x === 'string'") + expect(createSafeJSIdentifierPath('new Date()')).toBe('new Date()') + }) + + it('is total for degenerate input', () => { + expect(createSafeJSIdentifierPath('')).toBe('') + expect(createSafeJSIdentifierPath('!isLoading')).toBe('!isLoading') + }) +}) + +describe('createStateStoringFunction', () => { + it('is unchanged for ordinary names', () => { + expect(createStateStoringFunction('isSubmitting')).toBe('setIsSubmitting') + expect(createStateStoringFunction('item-level')).toBe('setItemLevel') + }) + + it('is safe for a reserved state name — `set` + can never be reserved', () => { + expect(createStateStoringFunction('class')).toBe('setClass') + expect(isValidJSIdentifierName(createStateStoringFunction('class'))).toBe(true) + }) + + it('sanitises characters that survive the camel-casing', () => { + expect(isValidJSIdentifierName(createStateStoringFunction('a.b'))).toBe(true) + }) +}) diff --git a/packages/teleport-shared/src/index.ts b/packages/teleport-shared/src/index.ts index dd59719c6..288f29af9 100644 --- a/packages/teleport-shared/src/index.ts +++ b/packages/teleport-shared/src/index.ts @@ -2,5 +2,7 @@ import * as Constants from './constants' import * as StringUtils from './utils/string-utils' import * as UIDLUtils from './utils/uidl-utils' import * as GenericUtils from './utils/generic' +import * as JSIdentifiers from './utils/js-identifiers' +import * as RoutePaths from './utils/route-paths' -export { Constants, StringUtils, UIDLUtils, GenericUtils } +export { Constants, StringUtils, UIDLUtils, GenericUtils, JSIdentifiers, RoutePaths } diff --git a/packages/teleport-shared/src/utils/js-identifiers.ts b/packages/teleport-shared/src/utils/js-identifiers.ts new file mode 100644 index 000000000..bbfa166d2 --- /dev/null +++ b/packages/teleport-shared/src/utils/js-identifiers.ts @@ -0,0 +1,214 @@ +/** + * JavaScript identifier safety for names that originate in the UIDL. + * + * A UIDL state / prop / global-state name is DATA. It is routinely derived from + * a database column or a form field, so it can legally be any string — a WoW + * character sheet really does have a column called `class`. The generators, on + * the other hand, turn those names into JavaScript BINDINGS + * (`const [class, setClass] = useState("")`), and `class` is a reserved word: + * the emitted page does not parse, prettier throws + * `SyntaxError: Unexpected token, expected "{"`, and the whole project build + * dies before a single file is written. + * + * This module is the single place that maps "a name from the UIDL" to "a name + * that is legal in identifier position". + * + * ## What is deliberately NOT renamed + * + * Only IDENTIFIER positions are sanitised. Everywhere a name is a STRING — the + * `stateSetters` / `stateTypes` / `__stateValues` map keys the workflow runtime + * looks up by `config.property`, an object-literal key, a `props.` member + * access — the original name is kept verbatim. Renaming those would silently + * break every workflow binding written against the original name (the runtime + * would log `no setter for "class"` and skip the update), which is a far worse + * failure than the build error this module exists to prevent. + * + * ## Why a trailing underscore is collision-free + * + * Every state / prop name reaches the generators through + * `StringUtils.createStateOrPropStoringValue`, i.e. `dashCaseToCamelCase`, + * whose `/[-_]+(.)?/g` replacement removes EVERY underscore. So a normalised + * name can never itself end in `_`, and `class` -> `class_` cannot collide with + * a sibling name. + */ + +/** + * Words that may never be used as a binding name in the code we emit. + * + * Generated components are ES modules and therefore always strict mode, so the + * strict-mode-only reserved words are as fatal as the unconditional ones. + * + * `undefined` is not a reserved word, but binding it shadows the value the + * generators emit for "no value" (`t.identifier('undefined')`) throughout the + * output, so it is treated as reserved here as well. + */ +export const RESERVED_JS_IDENTIFIERS: ReadonlySet = new Set([ + // Reserved in every context. + 'break', + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'enum', + 'export', + 'extends', + 'false', + 'finally', + 'for', + 'function', + 'if', + 'import', + 'in', + 'instanceof', + 'new', + 'null', + 'return', + 'super', + 'switch', + 'this', + 'throw', + 'true', + 'try', + 'typeof', + 'var', + 'void', + 'while', + 'with', + // Reserved in strict mode / modules — which is all generated output. + 'arguments', + 'await', + 'eval', + 'implements', + 'interface', + 'let', + 'package', + 'private', + 'protected', + 'public', + 'static', + 'yield', + // Not reserved, but binding it breaks the generators' own emissions. + 'undefined', +]) + +/** Matches a complete, syntactically valid ECMAScript identifier (ASCII subset). */ +const VALID_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/ + +/** Matches the leading identifier of an id such as `class?.['spec']` or `fields.name`. */ +const LEADING_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*/ + +/** Every character that is illegal anywhere inside an identifier. */ +const ILLEGAL_IDENTIFIER_CHARS_RE = /[^A-Za-z0-9_$]/g + +/** Used when a name sanitises down to nothing at all (e.g. `"***"`). */ +export const FALLBACK_JS_IDENTIFIER = '_value' + +/** True when `name` is a reserved word that cannot be used as a binding. */ +export const isReservedJSIdentifier = (name: string): boolean => + typeof name === 'string' && RESERVED_JS_IDENTIFIERS.has(name) + +/** + * True when `name` can be emitted verbatim in identifier position — i.e. it is + * a syntactically valid identifier AND not a reserved word. + */ +export const isValidJSIdentifierName = (name: string): boolean => + typeof name === 'string' && VALID_IDENTIFIER_RE.test(name) && !RESERVED_JS_IDENTIFIERS.has(name) + +/** + * True when `name` can be an UNQUOTED object-literal key or a member access + * after a dot. Reserved words qualify — `{ class: x }` and `props.class` are + * both legal — so this is deliberately laxer than + * {@link isValidJSIdentifierName}; only the identifier SYNTAX matters here. + */ +export const isValidPropertyKeyName = (name: string): boolean => + typeof name === 'string' && VALID_IDENTIFIER_RE.test(name) + +/** + * Map any UIDL-supplied name onto a name that is legal in binding position. + * + * Valid, non-reserved names are returned UNCHANGED, so this is a no-op for + * every name the generators have ever produced — the emitted output only + * differs for names that would not have compiled at all. + * + * Not injective in the general case (`a-b` and `a_b` both sanitise to `a_b`), + * which is safe here because state / prop names are normalised through + * `createStateOrPropStoringValue` first and therefore contain neither + * character by the time a generator sees them. + */ +export const createSafeJSIdentifier = ( + name: string, + fallback: string = FALLBACK_JS_IDENTIFIER +): string => { + if (typeof name !== 'string' || name === '') { + return fallback + } + + if (isValidJSIdentifierName(name)) { + return name + } + + let safe = name.replace(ILLEGAL_IDENTIFIER_CHARS_RE, '_') + if (/^[0-9]/.test(safe)) { + safe = `_${safe}` + } + // `"***"` collapses to `"___"`, which is a legal identifier, so the only way + // to reach an empty string here is an empty input — already handled above. + if (safe === '') { + return fallback + } + // Re-check AFTER the character pass: `"class"` survives it untouched, and + // `"my class"` becomes `"my_class"` which is no longer reserved. + return RESERVED_JS_IDENTIFIERS.has(safe) ? `${safe}_` : safe +} + +/** + * A property path is all that may follow the binding: optional chaining, + * dotted access, or a bracket lookup. Anything else (a space, an operator, a + * call) means the string is a hand-written EXPRESSION rather than a reference, + * and rewriting its first word would corrupt it — `typeof x === 'string'` must + * never become `typeof_ x === 'string'`. + */ +const PROPERTY_PATH_TAIL_RE = /^(\?\.|\.|\[)/ + +/** + * Sanitise ONLY the leading identifier of an id that may already carry a + * property path, leaving the path untouched: + * + * `class` -> `class_` + * `class?.['spec']` -> `class_?.['spec']` + * `fields.name` -> `fields.name` (already legal — unchanged) + * `typeof x === 'y'` -> `typeof x === 'y'` (an expression — untouched) + * + * `UIDLUtils.generateIdWithRefPath` produces exactly the first three shapes, + * and the JSX generators hand the whole string to `t.identifier(...)` and rely + * on babel printing it verbatim. Only the head is a binding; the rest is member + * access against real data keys and must keep its original spelling. + */ +export const createSafeJSIdentifierPath = (idWithPath: string): string => { + if (typeof idWithPath !== 'string' || idWithPath === '') { + return idWithPath + } + + const match = LEADING_IDENTIFIER_RE.exec(idWithPath) + if (!match) { + // Does not start with an identifier at all (e.g. a numeric or empty head). + // There is nothing safe to rewrite, so leave it for the caller's own + // validation rather than inventing a binding. + return idWithPath + } + + const head = match[0] + const tail = idWithPath.slice(head.length) + if (tail !== '' && !PROPERTY_PATH_TAIL_RE.test(tail)) { + return idWithPath + } + + const safeHead = createSafeJSIdentifier(head) + return safeHead === head ? idWithPath : `${safeHead}${tail}` +} diff --git a/packages/teleport-shared/src/utils/route-paths.ts b/packages/teleport-shared/src/utils/route-paths.ts new file mode 100644 index 000000000..e5c0b46a2 --- /dev/null +++ b/packages/teleport-shared/src/utils/route-paths.ts @@ -0,0 +1,87 @@ +/** + * Reading Next.js dynamic route templates. + * + * A details page's route is a TEMPLATE, not a URL: `/event-details/[id]`. Two + * different consumers have to understand that, and both got it wrong in + * different ways — the SEO head plugin emitted the template verbatim into + * ``, `og:url` and the sitemap, and the navlink resolver + * handed out the bare prefix (`/event-details`) as if it were a real route. + * Both produce a URL that 404s. + * + * Lives in teleport-shared because the two callers sit in packages that do not + * (and should not) depend on each other. + * + * Pure; never throws. + */ + +/** + * A Next.js dynamic path segment — `/[id]`, `/[slug]` — occupying a WHOLE + * segment. + * + * Anchored on BOTH sides so a stray bracket is never mistaken for a route + * param: on the left it must open a segment (start of string or `/`), and on + * the right it must close one. "Closes a segment" is deliberately wider than + * `/` or end-of-string, because a URL is not always the whole string — the same + * template appears inside a serialized JSON-LD document, where the path ends at + * the closing quote. Anything that cannot itself be part of a path segment ends + * it. + * + * The name must be a plain JS identifier, which excludes Next's catch-all forms + * (`[...slug]`, `[[...slug]]`): their value is an ARRAY and cannot be + * interpolated into a URL by simple substitution. + */ +const DYNAMIC_PATH_SEGMENT_SOURCE = '(^|\\/)\\[([A-Za-z_$][A-Za-z0-9_$]*)\\](?=$|[\\/"\'\\s,)}])' + +/** `${name}` — the template-literal spelling some upstream writers emit. */ +const TEMPLATE_EXPRESSION_SOURCE = '\\$\\{([^}]+)\\}' + +/** + * True when `path` contains at least one Next.js dynamic segment (`/[id]`). + * + * The string form of `isDynamicRoute`, for callers that hold a URL or a + * `navLink` rather than a component's `outputOptions`. + */ +export const pathHasDynamicSegment = (path: string): boolean => + new RegExp(DYNAMIC_PATH_SEGMENT_SOURCE).test(path || '') + +/** + * Split a URL or path into the literal text around its parameters, plus the + * parameter names in order — so a caller can rebuild it as a template literal. + * + * Recognises BOTH spellings a canonical/`navLink` value can arrive in: + * - `${id}` — the template-literal form; + * - `[id]` — the Next.js route form, which is what a details page's + * `navLink` actually carries (`/event-details/[id]`). + * + * Only the `${...}` form was understood before, so every details page shipped + * its canonical URL, `og:url` and sitemap entry containing the literal text + * `[id]` — a URL that 404s for every crawler and every shared link. + * + * `staticParts` always has exactly `paramNames.length + 1` entries, so + * `staticParts[i]` precedes `paramNames[i]`. With no parameters the result is + * `{ staticParts: [str], paramNames: [] }`, which callers use to keep emitting + * a plain string attribute. + */ +export const parseDynamicPathSegments = ( + str: string +): { staticParts: string[]; paramNames: string[] } => { + const regex = new RegExp(`${TEMPLATE_EXPRESSION_SOURCE}|${DYNAMIC_PATH_SEGMENT_SOURCE}`, 'g') + const staticParts: string[] = [] + const paramNames: string[] = [] + let lastIndex = 0 + let match: RegExpExecArray | null = regex.exec(str) + + while (match !== null) { + const isBracketForm = match[3] !== undefined + // For `/[id]` the matched text starts with the separator, which belongs to + // the static text BEFORE the parameter — not to the parameter itself. + const separator = isBracketForm ? match[2] : '' + staticParts.push(str.slice(lastIndex, match.index) + separator) + paramNames.push(isBracketForm ? match[3] : match[1]) + lastIndex = regex.lastIndex + match = regex.exec(str) + } + staticParts.push(str.slice(lastIndex)) + + return { staticParts, paramNames } +} diff --git a/packages/teleport-shared/src/utils/string-utils.ts b/packages/teleport-shared/src/utils/string-utils.ts index 392c7fe95..5e035ac51 100644 --- a/packages/teleport-shared/src/utils/string-utils.ts +++ b/packages/teleport-shared/src/utils/string-utils.ts @@ -1,3 +1,5 @@ +import { createSafeJSIdentifier } from './js-identifiers' + export const camelCaseToDashCase = (str: string): string => str.replace(/([a-z])(?=[A-Z])|([A-Z0-9])(?=[A-Z][a-z])/g, '$1$2-').toLowerCase() export const dashCaseToCamelCase = (str: string): string => @@ -37,8 +39,29 @@ export const slugify = (str: string): string => { } export const createStateOrPropStoringValue = (value: string) => camelize(dashCaseToCamelCase(value)) + +/** + * The single funnel for state SETTER names. `set` + can never be a + * reserved word, but a name carrying characters that survive the camel-casing + * (e.g. a dot) would still produce something that is not an identifier, so the + * result is routed through the shared sanitiser. This is a no-op for every + * name that already produced valid output. + */ export const createStateStoringFunction = (value: string) => - `set${capitalize(dashCaseToUpperCamelCase(value))}` + createSafeJSIdentifier(`set${capitalize(dashCaseToUpperCamelCase(value))}`) + +/** + * The setter name a GLOBAL state is published under on the `useGlobalState()` + * context. Unlike component state this is NOT camel-cased — the provider, the + * consumer destructuring and the workflow setter map must all agree on the + * exact same context key, so the declared name is only capitalised. + * + * Returns the RAW context key. Callers that need a local binding must run it + * through `JSIdentifiers.createSafeJSIdentifier` themselves, so the key and the + * binding stay independently correct. + */ +export const createGlobalStateSetterName = (name: string): string => + `set${(name || '').charAt(0).toUpperCase()}${(name || '').slice(1)}` export const addSpacesToEachLine = (spaces: string, str: string) => { // indent the first line diff --git a/packages/teleport-test/src/standalone.ts b/packages/teleport-test/src/standalone.ts index 59d6d532f..a2448010b 100644 --- a/packages/teleport-test/src/standalone.ts +++ b/packages/teleport-test/src/standalone.ts @@ -305,7 +305,14 @@ const run = async () => { // }), ]) } catch (e) { - console.info(e) + // A generation failure wipes the whole output (the clean above already ran), + // so swallowing it here made `npm run standalone` print a SyntaxError and + // still exit 0 — a silent build break that no CI check could catch. Report + // it and fail the process. `console.info` rather than `console.error` + // because the repo's tslint config bans the latter — the non-zero exit code + // below is what CI actually reads, and chalk keeps it loud for a human. + console.info(chalk.red((e as Error)?.stack ?? String(e))) + process.exitCode = 1 } } diff --git a/packages/teleport-types/src/uidl.ts b/packages/teleport-types/src/uidl.ts index fa98b2e8f..d2b477d05 100755 --- a/packages/teleport-types/src/uidl.ts +++ b/packages/teleport-types/src/uidl.ts @@ -345,6 +345,56 @@ export interface UIDLWorkflow { edges: UIDLWorkflowEdge[] errorHandler?: UIDLWorkflowErrorHandler usedInNodes: Record + // The auth requirement of this workflow's generated API route(s), computed by + // the GUI mapper from the protection of the page(s) that trigger it plus a + // scan of the workflow graph for user-owned writes. The code generators emit + // a stateless (getToken-based) in-handler guard from it. Absent = no guard + // (a purely public workflow, or auth is disabled). See UIDLWorkflowProtection. + protection?: UIDLWorkflowProtection +} + +/** + * The auth policy the generated workflow API route enforces, baked at build + * time so the runtime check is a single stateless JWT decode (no DB, no fetch). + * + * Two orthogonal concerns: + * - `requiresAuth` / `allowedRoles` — coarse "who may call this route", derived + * from the protection of the page(s) that trigger the workflow (most- + * restrictive union across them). `allowedRoles: []` with `requiresAuth` + * means "any authenticated user". + * - `userScoped` — row-level "this call may only act on the caller's own rows". + * Derived from the workflow graph (a resolve-current-user node feeding a + * user-owned column on a data write). The route overrides that column with + * the session user id, which closes the "act as another user" hole WITHOUT + * forcing a login — so a guest-capable public page (favourites/cart) keeps + * working while nobody can forge another user's id. + */ +export interface UIDLWorkflowProtection { + requiresAuth: boolean + allowedRoles: string[] + userScoped?: UIDLWorkflowUserScope + // Provenance, for debuggability and codegen decisions (never a security input): + // - 'page' — exactly one triggering page supplied the requirement + // - 'multiple-pages' — union across several triggering pages + // - 'graph' — no page requirement applied; userScoped came from the graph + // - 'default' — fail-closed default for an unresolved data-mutating workflow + derivedFrom: 'page' | 'multiple-pages' | 'graph' | 'default' +} + +export interface UIDLWorkflowUserScope { + // The user-owned column the write targets (e.g. `user_id`, `follower_id`), + // representative for logging/debug when several are bound. + ownerColumn: string + // Exact context locations the route overwrites with the authenticated session + // user id before executing the write, so a user-owned column can never be + // forged. Each is `context[nodeId]` drilled down `path` (e.g. ['userId'] or + // ['user','id']) — the same reference the write's column mapping/filter reads. + bindings: UIDLWorkflowUserScopeBinding[] +} + +export interface UIDLWorkflowUserScopeBinding { + nodeId: string + path: string[] } export interface UIDLWebhookConfig { @@ -397,6 +447,11 @@ export interface UIDLCustomWorkflowNode { nodes: UIDLWorkflowNode[] edges: UIDLWorkflowEdge[] parameters: Array<{ key: string; defaultValue?: unknown }> + // A custom node's server segment is emitted as its own API route, shared by + // every workflow that invokes it. Its policy is the most-restrictive union of + // the protection of those workflows, plus identity binding from the custom + // node's own graph. Same shape/enforcement as UIDLWorkflow.protection. + protection?: UIDLWorkflowProtection } export interface WorkflowContextValue { diff --git a/packages/teleport-uidl-resolver/__tests__/abilities/utils.ts b/packages/teleport-uidl-resolver/__tests__/abilities/utils.ts index e164c7b90..0606b1d70 100644 --- a/packages/teleport-uidl-resolver/__tests__/abilities/utils.ts +++ b/packages/teleport-uidl-resolver/__tests__/abilities/utils.ts @@ -208,6 +208,114 @@ describe('insertLink', () => { }) }) + it('resolves a navlink whose route value carries a folder prefix', () => { + // A details page's route value is folder-qualified (`add-event/Add-Event`) + // while the navlink still names the page (`Add-Event`). Matching only on + // the whole value missed every one of them and silently fabricated + // `/add-event` — a path with no file behind it. + const node = elementNode('container') + const navlink = navlinkMockedDefinition() + navlink.content.routeName = { type: 'static', content: 'Guild-Details' } + node.content.abilities = { link: navlink } + + const result = insertLinks( + node, + { + projectRouteDefinition: { + type: 'route', + defaultValue: 'home', + values: [{ value: 'guild-details/Guild-Details', pageOptions: { navLink: '/guilds' } }], + }, + }, + false + ) + + expect(result.content.attrs.transitionTo.content).toBe('/guilds') + }) + + it('does not guess when two folders hold a page of the same name', () => { + const node = elementNode('container') + const navlink = navlinkMockedDefinition() + navlink.content.routeName = { type: 'static', content: 'Details' } + node.content.abilities = { link: navlink } + + const result = insertLinks( + node, + { + projectRouteDefinition: { + type: 'route', + defaultValue: 'home', + values: [ + { value: 'events/Details', pageOptions: { navLink: '/events/detail' } }, + { value: 'guilds/Details', pageOptions: { navLink: '/guilds/detail' } }, + ], + }, + }, + false + ) + + // Ambiguous → the pre-existing fallback, not an arbitrary pick. + expect(result.content.attrs.transitionTo.content).toBe('/details') + }) + + it('refuses to link a dynamic route that has no record id to fill it', () => { + // `/rsvp-event/[id]` is a TEMPLATE. Without a differentiator there is no id + // to substitute, so neither the template (a literal `[id]` in the address + // bar) nor the bare prefix (`/rsvp-event`, which matches no file) is + // navigable. Run 798e2775 shipped the bare prefix in the global footer of + // all 17 pages. + const node = elementNode('container') + const navlink = navlinkMockedDefinition() + navlink.content.routeName = { type: 'static', content: 'Add-Event' } + node.content.abilities = { link: navlink } + + const result = insertLinks( + node, + { + projectRouteDefinition: { + type: 'route', + defaultValue: 'home', + values: [{ value: 'add-event/Add-Event', pageOptions: { navLink: '/add-event/[id]' } }], + }, + }, + false + ) + + expect(result.content.attrs.transitionTo.content).toBe('#') + }) + + it('still builds the record URL for a dynamic route WITH a differentiator', () => { + // The row-scoped case must keep working — it is the reason dynamic routes + // exist, and it is what the guard above must not touch. + const node = elementNode('container') + const navlink = navlinkMockedDefinition() + navlink.content.routeName = { type: 'static', content: 'Event-Details' } + navlink.content.differentiatorValue = { + type: 'dynamic', + content: { referenceType: 'global', refPath: ['Current User', 'id'] }, + } as never + node.content.abilities = { link: navlink } + + const result = insertLinks( + node, + { + projectRouteDefinition: { + type: 'route', + defaultValue: 'home', + values: [ + { value: 'event-details/Event-Details', pageOptions: { navLink: '/event-details' } }, + ], + }, + }, + false + ) + + expect(result.content.attrs.transitionTo).toEqual({ + type: 'expr', + content: '`/event-details/' + '$' + '{' + 'currentUser?.id}' + '`', + }) + }) + it('marks the link wrapper display:contents when the flex parent uses a project-referenced style', () => { const child = elementNode('container') child.content.abilities = { link: navlinkMockedDefinition() } diff --git a/packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts b/packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts index bb77a3ad4..57ca13371 100644 --- a/packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts +++ b/packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts @@ -1,4 +1,4 @@ -import { StringUtils } from '@teleporthq/teleport-shared' +import { StringUtils, RoutePaths } from '@teleporthq/teleport-shared' import { GeneratorOptions, UIDLLinkNode, @@ -509,6 +509,18 @@ const createLinkAttributes = ( transitionTo: buildDifferentiatorTransitionTo(baseRoute, differentiatorValue), } } + // No differentiator + a dynamic destination = nothing navigable. See + // UNRESOLVABLE_NAVLINK_HREF. Checked HERE rather than inside + // `resolveNavlink` so the differentiator branch above still receives the + // real `/prefix/[id]` template it needs to substitute the row id into. + if ( + baseRoute.type === 'static' && + RoutePaths.pathHasDynamicSegment(String(baseRoute.content)) + ) { + return { + transitionTo: { type: 'static', content: UNRESOLVABLE_NAVLINK_HREF }, + } + } return { transitionTo: baseRoute, } @@ -538,6 +550,49 @@ const createLinkAttributes = ( } } +/** + * A route whose `value` is folder-qualified (`add-character/Add-Character`) + * still answers to its bare page name in a navlink's `routeName` + * (`Add-Character`) — the folder prefix is part of the ROUTE, not of the page's + * identity. Matching only on the whole value made every such lookup miss and + * fall through to the fabricated `/${friendlyURL}` below. + * + * Resolved only when the last segment identifies the route UNAMBIGUOUSLY; with + * two pages of the same name in different folders there is no way to tell which + * one was meant, so we keep the old miss rather than guess. + */ +const findRouteByName = ( + values: GeneratorOptions['projectRouteDefinition']['values'], + routeName: string +) => { + const exact = values.find((routeItem) => routeItem.value === routeName) + if (exact) { + return exact + } + // `value` is typed `string | number | boolean` — only a string route can carry + // a folder prefix, so anything else can never match by last segment. + const byLastSegment = values.filter( + (routeItem) => + typeof routeItem.value === 'string' && routeItem.value.split('/').pop() === routeName + ) + return byLastSegment.length === 1 ? byLastSegment[0] : undefined +} + +/** + * A DYNAMIC route (`/rsvp-event/[id]`) is not a URL — it is a template that + * needs one record's id. A navlink with no `differentiatorValue` has no id to + * put there, so neither spelling is navigable: the template ships a literal + * `[id]` in the address bar, and the bare prefix (`/rsvp-event`) matches no file + * and 404s. `#` is the platform's existing representation for a link that + * cannot be resolved — the element still renders, it just does not navigate, + * which is strictly better than a link that provably fails. + * + * This is the last line of defence, not the fix: a nav or CTA link pointing at a + * single-record page is a planning defect, and the generator that produced the + * UIDL is where it should be prevented. + */ +const UNRESOLVABLE_NAVLINK_HREF = '#' + const resolveNavlink = ( route: UIDLAttributeValue, options: GeneratorOptions @@ -562,7 +617,7 @@ const resolveNavlink = ( ) const transitionRoute = options.projectRouteDefinition - ? options.projectRouteDefinition.values.find((routeItem) => routeItem.value === routeName) + ? findRouteByName(options.projectRouteDefinition.values, routeName.toString()) : null if (!transitionRoute) { diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo new file mode 100644 index 000000000..25cad6a65 --- /dev/null +++ b/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"program":{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.esnext.intl.d.ts","./examples/test-samples/project-sample.json","./examples/uidl-samples/tests.json","./packages/teleport-types/dist/cjs/helper.d.ts","./packages/teleport-types/dist/cjs/uidl.d.ts","./node_modules/@babel/types/lib/index.d.ts","./packages/teleport-types/dist/cjs/generators.d.ts","./packages/teleport-types/dist/cjs/errors.d.ts","./packages/teleport-types/dist/cjs/vuidl.d.ts","./packages/teleport-types/dist/cjs/index.d.ts","./packages/teleport-shared/dist/cjs/constants/index.d.ts","./packages/teleport-shared/dist/cjs/utils/string-utils.d.ts","./packages/teleport-shared/dist/cjs/utils/uidl-utils.d.ts","./packages/teleport-shared/dist/cjs/utils/generic.d.ts","./packages/teleport-shared/dist/cjs/utils/js-identifiers.d.ts","./packages/teleport-shared/dist/cjs/utils/route-paths.d.ts","./packages/teleport-shared/dist/cjs/index.d.ts","./packages/teleport-project-packer/dist/cjs/index.d.ts","./packages/teleport-project-generator-react/dist/cjs/react-project-mapping.d.ts","./packages/teleport-project-generator-react/dist/cjs/project-template.d.ts","./packages/teleport-project-generator/dist/cjs/index.d.ts","./packages/teleport-project-generator-react/dist/cjs/index.d.ts","./packages/teleport-project-generator-next/dist/cjs/next-project-mapping.d.ts","./packages/teleport-project-generator-next/dist/cjs/project-template.d.ts","./packages/teleport-project-generator-next/dist/cjs/global-state/component-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/global-state/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/ai-chat/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/analytics/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/ecommerce/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/dashboard-layout-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/entity-mutation-ssr-finalize-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/rich-text-editor/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/rich-text-editor/component-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/calendar/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/calendar/calendarkit-css.d.ts","./packages/teleport-project-generator-next/dist/cjs/drag-drop/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/kanban/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/countdown/project-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/widgets/index.d.ts","./packages/teleport-project-generator-next/dist/cjs/drag-drop/component-generator.d.ts","./packages/teleport-project-generator-next/dist/cjs/kanban/component-generator.d.ts","./packages/teleport-project-generator-next/dist/cjs/countdown/component-generator.d.ts","./packages/teleport-project-generator-next/dist/cjs/local-component-path-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/forms/captcha-script-plugin.d.ts","./packages/teleport-project-generator-next/dist/cjs/internationalization/project.d.ts","./packages/teleport-project-generator-next/dist/cjs/data-source-dependencies.d.ts","./packages/teleport-project-generator-next/dist/cjs/data-source-utility-plugin.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/workflow-component-plugin.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/workflow-project-plugin.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/nodes/types.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/nodes/index.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/types.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/segment-splitter.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/secret-collector.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/executor-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/api-route-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/trigger-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/graph-utils.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/realtime-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/invoice/index.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/webhook-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/runtime-storage-generator.d.ts","./packages/teleport-plugin-next-workflows/dist/cjs/index.d.ts","./packages/teleport-project-generator-next/dist/cjs/internationalization/locale-fetcher-component.d.ts","./packages/teleport-project-generator-next/dist/cjs/internationalization/locale-mapper-component.d.ts","./packages/teleport-project-generator-next/dist/cjs/forms/form-submission-handler.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/postgresql.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/mysql.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/mariadb.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/redshift.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/mongodb.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/redis.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/firestore.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/clickhouse.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/airtable.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/supabase.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/turso.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/rest-api.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/javascript.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/csv-file.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/google-sheets.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/teleport.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/raw-query.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/fetchers/index.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/data-source-fetchers.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/utils.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/array-mapper-pagination.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/pagination-plugin.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/count-fetchers.d.ts","./packages/teleport-plugin-next-data-source/dist/cjs/index.d.ts","./packages/teleport-project-generator-next/dist/cjs/partial.d.ts","./packages/teleport-project-generator-next/dist/cjs/split-utils.d.ts","./packages/teleport-project-generator-next/dist/cjs/index.d.ts","./packages/teleport-project-generator-vue/dist/cjs/project-template.d.ts","./packages/teleport-project-generator-vue/dist/cjs/vue-project-mapping.d.ts","./packages/teleport-project-generator-vue/dist/cjs/index.d.ts","./packages/teleport-project-generator-nuxt/dist/cjs/nuxt-project-mapping.d.ts","./packages/teleport-project-generator-nuxt/dist/cjs/project-template.d.ts","./packages/teleport-project-generator-nuxt/dist/cjs/error-page-mapping.d.ts","./packages/teleport-project-generator-nuxt/dist/cjs/index.d.ts","./packages/teleport-project-generator-angular/dist/cjs/angular-project-mapping.d.ts","./packages/teleport-project-generator-angular/dist/cjs/project-template.d.ts","./packages/teleport-project-generator-angular/dist/cjs/index.d.ts","./packages/teleport-project-generator-html/dist/cjs/project-template.d.ts","./packages/teleport-project-generator-html/dist/cjs/plugin-clone-globals.d.ts","./packages/teleport-project-generator-html/dist/cjs/plugin-home-replace.d.ts","./packages/teleport-project-generator-html/dist/cjs/error-page-mapping.d.ts","./packages/teleport-project-generator-html/dist/cjs/index.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/buffer/index.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/file.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/filereader.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/dom-events.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/globals.global.d.ts","./node_modules/@types/node/index.d.ts","./packages/teleport-publisher-zip/dist/cjs/index.d.ts","./packages/teleport-publisher-vercel/dist/cjs/index.d.ts","./packages/teleport-publisher-netlify/dist/cjs/index.d.ts","./packages/teleport-github-gateway/dist/cjs/github-instance.d.ts","./packages/teleport-github-gateway/dist/cjs/types.d.ts","./packages/teleport-github-gateway/dist/cjs/index.d.ts","./packages/teleport-publisher-github/dist/cjs/types.d.ts","./packages/teleport-publisher-github/dist/cjs/index.d.ts","./packages/teleport-publisher-codesandbox/dist/cjs/index.d.ts","./packages/teleport-component-generator-react/dist/cjs/react-mapping.d.ts","./packages/teleport-component-generator-react/dist/cjs/index.d.ts","./packages/teleport-component-generator-vue/dist/cjs/vue-mapping.d.ts","./packages/teleport-component-generator-vue/dist/cjs/index.d.ts","./packages/teleport-component-generator-angular/dist/cjs/angular-mapping.d.ts","./packages/teleport-component-generator-angular/dist/cjs/index.d.ts","./packages/teleport-component-generator-html/dist/cjs/plain-html-mapping.d.ts","./packages/teleport-component-generator-html/dist/cjs/index.d.ts","./packages/teleport-uidl-resolver/dist/cjs/resolver.d.ts","./packages/teleport-uidl-resolver/dist/cjs/html-mapping.d.ts","./packages/teleport-uidl-resolver/dist/cjs/resolvers/style-set-definitions/index.d.ts","./packages/teleport-uidl-resolver/dist/cjs/utils.d.ts","./packages/teleport-uidl-resolver/dist/cjs/index.d.ts","./packages/teleport-project-plugin-i18n-files/dist/cjs/index.d.ts","./packages/teleport-code-generator/src/utils.ts","./packages/teleport-publisher-disk/dist/cjs/index.d.ts","./packages/teleport-code-generator/src/index.ts","./packages/teleport-code-generator/__tests__/index.ts","./packages/teleport-code-generator/__tests__/packproject-widget-deps.test.ts","./packages/teleport-project-plugin-css-modules/dist/cjs/index.d.ts","./packages/teleport-project-plugin-styled-components/dist/cjs/index.d.ts","./examples/test-samples/project-with-import-global-styles.json","./examples/test-samples/project-sample-with-dependency.json","./examples/test-samples/project-with-only-tokens.json","./examples/test-samples/project-invalid-sample.json","./packages/teleport-code-generator/__tests__/end2end/index.ts","./packages/teleport-uidl-validator/dist/cjs/parser/index.d.ts","./node_modules/@mojotech/json-type-validation/dist/types/result.d.ts","./node_modules/@mojotech/json-type-validation/dist/types/decoder.d.ts","./node_modules/@mojotech/json-type-validation/dist/types/combinators.d.ts","./node_modules/@mojotech/json-type-validation/dist/types/index.d.ts","./packages/teleport-uidl-validator/dist/cjs/decoders/utils.d.ts","./packages/teleport-uidl-validator/dist/cjs/validator/index.d.ts","./packages/teleport-uidl-validator/dist/cjs/decoders/component-decoder.d.ts","./packages/teleport-uidl-validator/dist/cjs/decoders/project-decoder.d.ts","./packages/teleport-uidl-validator/dist/cjs/index.d.ts","./packages/teleport-component-generator/src/assembly-line/utils.ts","./packages/teleport-component-generator/src/assembly-line/index.ts","./node_modules/@types/babel__generator/index.d.ts","./packages/teleport-component-generator/src/builder/generators/js-ast-to-code.ts","./packages/teleport-component-generator/src/builder/generators/html-to-string.ts","./packages/teleport-component-generator/src/builder/index.ts","./packages/teleport-component-generator/src/index.ts","./packages/teleport-uidl-builders/dist/cjs/project-builders.d.ts","./packages/teleport-uidl-builders/dist/cjs/component-builders.d.ts","./packages/teleport-uidl-builders/dist/cjs/index.d.ts","./packages/teleport-component-generator/__tests__/index.ts","./packages/teleport-component-generator/dist/cjs/index.d.ts","./packages/teleport-plugin-angular-base-component/dist/cjs/index.d.ts","./packages/teleport-plugin-css/dist/cjs/style-sheet.d.ts","./packages/teleport-plugin-css/dist/cjs/index.d.ts","./packages/teleport-plugin-import-statements/dist/cjs/index.d.ts","./packages/teleport-postprocessor-prettier-ts/dist/cjs/index.d.ts","./packages/teleport-postprocessor-prettier-html/dist/cjs/index.d.ts","./packages/teleport-component-generator-angular/src/angular-mapping.ts","./packages/teleport-component-generator-angular/src/index.ts","./packages/teleport-component-generator-angular/__tests__/end2end/component-referenced-styles.ts","./examples/test-samples/component-sample.json","./examples/test-samples/component-invalid-sample.json","./packages/teleport-component-generator-angular/__tests__/end2end/index.ts","./examples/uidl-samples/component.json","./packages/teleport-component-generator-angular/__tests__/integration/company-with-object-prop.ts","./packages/teleport-component-generator-angular/__tests__/integration/component-conditional.ts","./packages/teleport-component-generator-angular/__tests__/integration/component-with-smilar-element-name-depependencies.json","./packages/teleport-component-generator-angular/__tests__/integration/component-dependency.ts","./packages/teleport-component-generator-angular/__tests__/integration/component-repeat.ts","./packages/teleport-component-generator-angular/__tests__/integration/component-with-nested-styles.json","./packages/teleport-component-generator-angular/__tests__/integration/component-style.ts","./examples/test-samples/component-html.json","./packages/teleport-plugin-html-base-component/dist/cjs/index.d.ts","./packages/teleport-plugin-import-statements-html/dist/cjs/index.d.ts","./packages/teleport-component-generator-html/src/plain-html-mapping.ts","./packages/teleport-component-generator-html/src/index.ts","./packages/teleport-component-generator-html/__tests__/end2end/index.ts","./packages/teleport-component-generator-html/__tests__/integration/index.ts","./packages/teleport-plugin-react-base-component/dist/cjs/index.d.ts","./packages/teleport-plugin-jsx-inline-styles/dist/cjs/index.d.ts","./packages/teleport-plugin-react-jss/dist/cjs/style-sheet.d.ts","./packages/teleport-plugin-react-jss/dist/cjs/index.d.ts","./packages/teleport-plugin-css-modules/dist/cjs/style-sheet.d.ts","./packages/teleport-plugin-css-modules/dist/cjs/index.d.ts","./packages/teleport-plugin-react-styled-components/dist/cjs/style-sheet.d.ts","./packages/teleport-plugin-react-styled-components/dist/cjs/index.d.ts","./packages/teleport-plugin-react-styled-jsx/dist/cjs/index.d.ts","./packages/teleport-plugin-jsx-proptypes/dist/cjs/index.d.ts","./packages/teleport-postprocessor-prettier-jsx/dist/cjs/index.d.ts","./packages/teleport-component-generator-react/src/react-mapping.ts","./packages/teleport-component-generator-react/src/index.ts","./packages/teleport-component-generator-react/__tests__/end2end/index.ts","./packages/teleport-component-generator-react/__tests__/integration/component-with-old-format-attributes.json","./packages/teleport-component-generator-react/__tests__/integration/component-attrs.ts","./packages/teleport-component-generator-react/__tests__/integration/component-conditional.ts","./packages/teleport-component-generator-react/__tests__/integration/component-with-smilar-element-name-depependencies.json","./packages/teleport-component-generator-react/__tests__/integration/component-dependency.ts","./packages/teleport-component-generator-react/__tests__/integration/component-with-import-definitions.json","./packages/teleport-component-generator-react/__tests__/integration/component-import-definitions.ts","./packages/teleport-component-generator-react/__tests__/integration/component-referenced-styles.ts","./packages/teleport-component-generator-react/__tests__/integration/component-repeat.ts","./packages/teleport-component-generator-react/__tests__/integration/component-reserved-word-state.ts","./packages/teleport-component-generator-react/__tests__/integration/component-slot.ts","./packages/teleport-component-generator-react/__tests__/integration/component-with-invalid-state-styles.json","./packages/teleport-component-generator-react/__tests__/integration/component-with-valid-single-prop-style.json","./packages/teleport-component-generator-react/__tests__/integration/component-with-valid-state-reference.json","./packages/teleport-component-generator-react/__tests__/integration/component-style.ts","./packages/teleport-component-generator-react/__tests__/integration/component-with-object-prop.ts","./packages/teleport-component-generator-react/__tests__/integration/dynamic-style-inline.ts","./packages/teleport-component-generator-react/__tests__/performance/big-sample.json","./packages/teleport-component-generator-react/__tests__/performance/index.ts","./packages/teleport-plugin-vue-base-component/dist/cjs/index.d.ts","./packages/teleport-postprocessor-prettier-js/dist/cjs/index.d.ts","./packages/teleport-postprocessor-vue-file/dist/cjs/index.d.ts","./packages/teleport-component-generator-vue/src/vue-mapping.ts","./packages/teleport-component-generator-vue/src/index.ts","./packages/teleport-component-generator-vue/__tests__/end2end/index.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-with-old-format-attributes.json","./packages/teleport-component-generator-vue/__tests__/integration/component-attrs.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-conditional.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-with-smilar-element-name-depependencies.json","./packages/teleport-component-generator-vue/__tests__/integration/component-dependency.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-referenced-styles.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-repeat.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-slot.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-with-valid-style.json","./packages/teleport-component-generator-vue/__tests__/integration/component-with-nested-styles.json","./packages/teleport-component-generator-vue/__tests__/integration/component-style.ts","./packages/teleport-component-generator-vue/__tests__/integration/component-with-object-prop.ts","./packages/teleport-component-generator-vue/__tests__/performance/big-sample.json","./packages/teleport-component-generator-vue/__tests__/performance/index.ts","./node_modules/cross-fetch/index.d.ts","./node_modules/before-after-hook/index.d.ts","./node_modules/@octokit/types/dist-types/requestmethod.d.ts","./node_modules/@octokit/types/dist-types/url.d.ts","./node_modules/@octokit/types/dist-types/fetch.d.ts","./node_modules/@octokit/types/dist-types/signal.d.ts","./node_modules/@octokit/types/dist-types/requestrequestoptions.d.ts","./node_modules/@octokit/types/dist-types/requestheaders.d.ts","./node_modules/@octokit/types/dist-types/requestparameters.d.ts","./node_modules/@octokit/types/dist-types/endpointoptions.d.ts","./node_modules/@octokit/types/dist-types/responseheaders.d.ts","./node_modules/@octokit/types/dist-types/octokitresponse.d.ts","./node_modules/@octokit/types/dist-types/endpointdefaults.d.ts","./node_modules/@octokit/types/dist-types/requestoptions.d.ts","./node_modules/@octokit/types/dist-types/route.d.ts","./node_modules/@octokit/types/node_modules/@octokit/openapi-types/types.d.ts","./node_modules/@octokit/types/dist-types/generated/endpoints.d.ts","./node_modules/@octokit/types/dist-types/endpointinterface.d.ts","./node_modules/@octokit/types/dist-types/requestinterface.d.ts","./node_modules/@octokit/types/dist-types/authinterface.d.ts","./node_modules/@octokit/types/dist-types/requesterror.d.ts","./node_modules/@octokit/types/dist-types/strategyinterface.d.ts","./node_modules/@octokit/types/dist-types/version.d.ts","./node_modules/@octokit/types/dist-types/getresponsetypefromendpointmethod.d.ts","./node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/request/dist-types/index.d.ts","./node_modules/@octokit/graphql/dist-types/types.d.ts","./node_modules/@octokit/graphql/dist-types/error.d.ts","./node_modules/@octokit/graphql/dist-types/index.d.ts","./node_modules/@octokit/request-error/dist-types/types.d.ts","./node_modules/@octokit/request-error/dist-types/index.d.ts","./node_modules/@octokit/core/dist-types/types.d.ts","./node_modules/@octokit/core/dist-types/index.d.ts","./node_modules/@octokit/plugin-paginate-rest/dist-types/generated/paginating-endpoints.d.ts","./node_modules/@octokit/plugin-paginate-rest/dist-types/types.d.ts","./node_modules/@octokit/plugin-paginate-rest/dist-types/compose-paginate.d.ts","./node_modules/@octokit/plugin-paginate-rest/dist-types/paginating-endpoints.d.ts","./node_modules/@octokit/plugin-paginate-rest/dist-types/index.d.ts","./node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types.d.ts","./node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types.d.ts","./node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/types.d.ts","./node_modules/octokit/dist-types/octokit.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-device/node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/oauth-methods/dist-types/version.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/oauth-authorization-url/dist-types/types.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/oauth-authorization-url/dist-types/index.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestmethod.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/url.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/fetch.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/signal.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestrequestoptions.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestheaders.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestparameters.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/endpointoptions.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/responseheaders.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/octokitresponse.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/endpointdefaults.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestoptions.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/route.d.ts","./node_modules/@octokit/openapi-types/types.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/generated/endpoints.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/endpointinterface.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requestinterface.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/authinterface.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/requesterror.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/strategyinterface.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/version.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/getresponsetypefromendpointmethod.d.ts","./node_modules/@octokit/oauth-methods/node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/oauth-methods/dist-types/get-web-flow-authorization-url.d.ts","./node_modules/@octokit/oauth-methods/dist-types/types.d.ts","./node_modules/@octokit/oauth-methods/dist-types/exchange-web-flow-code.d.ts","./node_modules/@octokit/oauth-methods/dist-types/create-device-code.d.ts","./node_modules/@octokit/oauth-methods/dist-types/exchange-device-code.d.ts","./node_modules/@octokit/oauth-methods/dist-types/check-token.d.ts","./node_modules/@octokit/oauth-methods/dist-types/refresh-token.d.ts","./node_modules/@octokit/oauth-methods/dist-types/scope-token.d.ts","./node_modules/@octokit/oauth-methods/dist-types/reset-token.d.ts","./node_modules/@octokit/oauth-methods/dist-types/delete-token.d.ts","./node_modules/@octokit/oauth-methods/dist-types/delete-authorization.d.ts","./node_modules/@octokit/oauth-methods/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-device/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-device/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/version.d.ts","./node_modules/@octokit/oauth-authorization-url/dist-types/types.d.ts","./node_modules/@octokit/oauth-authorization-url/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/get-web-flow-authorization-url.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/exchange-web-flow-code.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/create-device-code.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/exchange-device-code.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/check-token.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/refresh-token.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/scope-token.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/reset-token.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/delete-token.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/delete-authorization.d.ts","./node_modules/@octokit/auth-oauth-user/node_modules/@octokit/oauth-methods/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-user/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-user/dist-types/requires-basic-auth.d.ts","./node_modules/@octokit/auth-oauth-user/dist-types/index.d.ts","./node_modules/@octokit/oauth-app/node_modules/@octokit/core/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/node_modules/@octokit/auth-oauth-device/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/node_modules/@octokit/auth-oauth-device/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/dist-types/requires-basic-auth.d.ts","./node_modules/@octokit/auth-oauth-app/node_modules/@octokit/auth-oauth-user/dist-types/index.d.ts","./node_modules/@octokit/auth-oauth-app/dist-types/types.d.ts","./node_modules/@octokit/auth-oauth-app/dist-types/index.d.ts","./node_modules/@octokit/oauth-app/dist-types/oauth-app-octokit.d.ts","./node_modules/@octokit/oauth-app/dist-types/types.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/get-user-octokit.d.ts","./node_modules/@octokit/oauth-app/node_modules/@octokit/oauth-methods/dist-types/index.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/get-web-flow-authorization-url.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/create-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/check-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/reset-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/refresh-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/scope-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/delete-token.d.ts","./node_modules/@octokit/oauth-app/dist-types/methods/delete-authorization.d.ts","./node_modules/@octokit/oauth-app/dist-types/middleware/types.d.ts","./node_modules/@octokit/oauth-app/dist-types/middleware/node/index.d.ts","./node_modules/@octokit/oauth-app/dist-types/middleware/web-worker/index.d.ts","./node_modules/@types/aws-lambda/common/api-gateway.d.ts","./node_modules/@types/aws-lambda/common/cloudfront.d.ts","./node_modules/@types/aws-lambda/handler.d.ts","./node_modules/@types/aws-lambda/trigger/alb.d.ts","./node_modules/@types/aws-lambda/trigger/api-gateway-proxy.d.ts","./node_modules/@types/aws-lambda/trigger/api-gateway-authorizer.d.ts","./node_modules/@types/aws-lambda/trigger/appsync-resolver.d.ts","./node_modules/@types/aws-lambda/trigger/autoscaling.d.ts","./node_modules/@types/aws-lambda/trigger/cloudformation-custom-resource.d.ts","./node_modules/@types/aws-lambda/trigger/cdk-custom-resource.d.ts","./node_modules/@types/aws-lambda/trigger/cloudfront-request.d.ts","./node_modules/@types/aws-lambda/trigger/cloudfront-response.d.ts","./node_modules/@types/aws-lambda/trigger/cloudwatch-alarm.d.ts","./node_modules/@types/aws-lambda/trigger/eventbridge.d.ts","./node_modules/@types/aws-lambda/trigger/cloudwatch-events.d.ts","./node_modules/@types/aws-lambda/trigger/cloudwatch-logs.d.ts","./node_modules/@types/aws-lambda/trigger/codebuild-cloudwatch-state.d.ts","./node_modules/@types/aws-lambda/trigger/codecommit.d.ts","./node_modules/@types/aws-lambda/trigger/codepipeline.d.ts","./node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-action.d.ts","./node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-pipeline.d.ts","./node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch-stage.d.ts","./node_modules/@types/aws-lambda/trigger/codepipeline-cloudwatch.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/_common.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/create-auth-challenge.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-email-sender.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-message.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/custom-sms-sender.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/define-auth-challenge.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/post-authentication.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/post-confirmation.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-authentication.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-signup.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-token-generation.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/pre-token-generation-v2.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/user-migration.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/verify-auth-challenge-response.d.ts","./node_modules/@types/aws-lambda/trigger/cognito-user-pool-trigger/index.d.ts","./node_modules/@types/aws-lambda/trigger/connect-contact-flow.d.ts","./node_modules/@types/aws-lambda/trigger/dynamodb-stream.d.ts","./node_modules/@types/aws-lambda/trigger/iot.d.ts","./node_modules/@types/aws-lambda/trigger/iot-authorizer.d.ts","./node_modules/@types/aws-lambda/trigger/kinesis-firehose-transformation.d.ts","./node_modules/@types/aws-lambda/trigger/kinesis-stream.d.ts","./node_modules/@types/aws-lambda/trigger/lambda-function-url.d.ts","./node_modules/@types/aws-lambda/trigger/lex.d.ts","./node_modules/@types/aws-lambda/trigger/lex-v2.d.ts","./node_modules/@types/aws-lambda/trigger/amplify-resolver.d.ts","./node_modules/@types/aws-lambda/trigger/msk.d.ts","./node_modules/@types/aws-lambda/trigger/s3.d.ts","./node_modules/@types/aws-lambda/trigger/s3-batch.d.ts","./node_modules/@types/aws-lambda/trigger/s3-event-notification.d.ts","./node_modules/@types/aws-lambda/trigger/secretsmanager.d.ts","./node_modules/@types/aws-lambda/trigger/self-managed-kafka.d.ts","./node_modules/@types/aws-lambda/trigger/ses.d.ts","./node_modules/@types/aws-lambda/trigger/sns.d.ts","./node_modules/@types/aws-lambda/trigger/sqs.d.ts","./node_modules/@types/aws-lambda/trigger/transfer-family-authorizer.d.ts","./node_modules/@types/aws-lambda/index.d.ts","./node_modules/@octokit/oauth-app/dist-types/middleware/aws-lambda/api-gateway-v2.d.ts","./node_modules/@octokit/oauth-app/dist-types/index.d.ts","./node_modules/@octokit/webhooks-types/schema.d.ts","./node_modules/@octokit/webhooks/dist-types/createlogger.d.ts","./node_modules/@octokit/webhooks/dist-types/generated/webhook-names.d.ts","./node_modules/@octokit/webhooks/dist-types/types.d.ts","./node_modules/@octokit/webhooks/dist-types/event-handler/index.d.ts","./node_modules/@octokit/webhooks/dist-types/middleware/node/types.d.ts","./node_modules/@octokit/webhooks/dist-types/middleware/node/index.d.ts","./node_modules/@octokit/webhooks/dist-types/index.d.ts","./node_modules/@octokit/app/dist-types/types.d.ts","./node_modules/@octokit/app/dist-types/middleware/node/index.d.ts","./node_modules/@octokit/app/dist-types/index.d.ts","./node_modules/octokit/dist-types/app.d.ts","./node_modules/octokit/dist-types/index.d.ts","./packages/teleport-github-gateway/src/constants.ts","./packages/teleport-github-gateway/src/types.ts","./packages/teleport-github-gateway/src/github-instance.ts","./packages/teleport-github-gateway/src/utils.ts","./packages/teleport-github-gateway/src/index.ts","./packages/teleport-github-gateway/__tests__/index.ts","./packages/teleport-plugin-common/dist/cjs/builders/ast-builders.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/parsed-ast.d.ts","./packages/teleport-plugin-common/dist/cjs/builders/style-builders.d.ts","./packages/teleport-plugin-common/dist/cjs/builders/hast-builders.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/types.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/ast-utils.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/style-utils.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/hast-utils.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/url-search-param-sync.d.ts","./packages/teleport-plugin-common/dist/cjs/utils/route-utils.d.ts","./packages/teleport-plugin-common/dist/cjs/node-handlers/node-to-jsx/types.d.ts","./packages/teleport-plugin-common/dist/cjs/node-handlers/node-to-jsx/utils.d.ts","./packages/teleport-plugin-common/dist/cjs/node-handlers/node-to-html/types.d.ts","./packages/teleport-plugin-common/dist/cjs/node-handlers/node-to-html/index.d.ts","./packages/teleport-plugin-common/dist/cjs/node-handlers/node-to-jsx/index.d.ts","./packages/teleport-plugin-common/dist/cjs/index.d.ts","./packages/teleport-plugin-angular-base-component/src/utils.ts","./packages/teleport-plugin-angular-base-component/src/constants.ts","./packages/teleport-plugin-angular-base-component/src/index.ts","./packages/teleport-plugin-angular-base-component/__tests__/index.ts","./packages/teleport-plugin-angular-module/src/utils.ts","./packages/teleport-plugin-angular-module/src/constants.ts","./packages/teleport-plugin-angular-module/src/index.ts","./packages/teleport-plugin-angular-module/__tests__/index.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./packages/teleport-plugin-common/src/utils/parsed-ast.ts","./packages/teleport-plugin-common/src/utils/types.ts","./packages/teleport-plugin-common/src/utils/template-expression-balance.ts","./packages/teleport-plugin-common/src/utils/ast-utils.ts","./packages/teleport-plugin-common/src/builders/ast-builders.ts","./packages/teleport-plugin-common/__tests__/builders/ast-builders.ts","./packages/teleport-plugin-common/src/builders/hast-builders.ts","./packages/teleport-plugin-common/__tests__/builders/html-builders.ts","./node_modules/csstype/index.d.ts","./node_modules/jss/src/index.d.ts","./node_modules/jss-plugin-default-unit/src/index.d.ts","./node_modules/jss-plugin-rule-value-observable/src/index.d.ts","./node_modules/jss-preset-default/src/index.d.ts","./packages/teleport-plugin-common/src/utils/style-utils.ts","./packages/teleport-plugin-common/src/utils/hast-utils.ts","./packages/teleport-plugin-common/src/builders/style-builders.ts","./packages/teleport-plugin-common/__tests__/builders/style-builders.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-html/types.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-html/utils.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-html/constants.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-html/index.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-html/index.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-html/utils.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-jsx/types.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-jsx/utils.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-jsx/constants.ts","./packages/teleport-plugin-common/src/utils/url-search-param-sync.ts","./packages/teleport-plugin-common/src/utils/route-utils.ts","./packages/teleport-plugin-common/src/index.ts","./packages/teleport-plugin-common/src/node-handlers/node-to-jsx/index.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/calendar-events-reviver.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/index.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/url-search-params-expression.ts","./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/utils.ts","./packages/teleport-plugin-common/__tests__/utils/ast-utils.ts","./packages/teleport-plugin-common/__tests__/utils/content-property-sanitiser.ts","./packages/teleport-plugin-common/__tests__/utils/parse-string-with-template-expressions.ts","./packages/teleport-plugin-common/__tests__/utils/resource-auth-scheme.ts","./packages/teleport-plugin-common/__tests__/utils/route-utils.ts","./packages/teleport-plugin-common/__tests__/utils/style-utils.ts","./packages/teleport-plugin-common/__tests__/utils/template-expression-balance.ts","./packages/teleport-plugin-common/__tests__/utils/url-search-param-sync.ts","./packages/teleport-plugin-common/src/utils/url-search-params.ts","./packages/teleport-plugin-common/__tests__/utils/url-search-params.ts","./packages/teleport-plugin-common/src/types.d.ts","./packages/teleport-plugin-css/src/utils.ts","./packages/teleport-plugin-css/src/style-sheet.ts","./packages/teleport-plugin-css/src/index.ts","./packages/teleport-plugin-css/__tests__/mocks.ts","./packages/teleport-plugin-css/__tests__/component-scoped.ts","./packages/teleport-plugin-css/__tests__/index.ts","./packages/teleport-plugin-css/__tests__/referenced-styles.ts","./packages/teleport-plugin-css/__tests__/selector-paren-sanitize.ts","./packages/teleport-plugin-css/__tests__/style-sheet.ts","./packages/teleport-plugin-css-modules/src/style-sheet.ts","./packages/teleport-plugin-css-modules/src/utils.ts","./packages/teleport-plugin-css-modules/src/index.ts","./packages/teleport-plugin-css-modules/__tests__/mocks.ts","./packages/teleport-plugin-css-modules/__tests__/component-scoped.ts","./packages/teleport-plugin-css-modules/__tests__/index.ts","./packages/teleport-types/src/helper.ts","./packages/teleport-types/src/uidl.ts","./packages/teleport-types/src/generators.ts","./packages/teleport-types/src/errors.ts","./packages/teleport-types/src/vuidl.ts","./packages/teleport-types/src/index.ts","./packages/teleport-plugin-css-modules/__tests__/style-sheet.ts","./packages/teleport-plugin-html-base-component/src/constants.ts","./packages/teleport-plugin-html-base-component/src/node-handlers.ts","./packages/teleport-plugin-html-base-component/src/index.ts","./packages/teleport-plugin-html-base-component/__tests__/index.ts","./packages/teleport-plugin-import-statements/src/index.ts","./packages/teleport-plugin-import-statements/__tests__/index.ts","./packages/teleport-plugin-import-statements-html/src/index.ts","./packages/teleport-plugin-import-statements-html/__tests__/index.ts","./packages/teleport-plugin-jsx-head-config/src/structured-data-ast.ts","./packages/teleport-plugin-jsx-head-config/src/index.ts","./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","./packages/teleport-plugin-jsx-inline-styles/src/index.ts","./packages/teleport-plugin-jsx-inline-styles/__tests__/index.ts","./packages/teleport-plugin-jsx-next-image/src/index.ts","./packages/teleport-plugin-jsx-next-image/__tests__/index.ts","./packages/teleport-plugin-jsx-proptypes/src/utils.ts","./packages/teleport-plugin-jsx-proptypes/src/index.ts","./packages/teleport-plugin-jsx-proptypes/__tests__/index.ts","./packages/teleport-plugin-next-data-source/src/fetchers/postgresql.ts","./packages/teleport-plugin-next-data-source/src/fetchers/mysql.ts","./packages/teleport-plugin-next-data-source/src/fetchers/mariadb.ts","./packages/teleport-plugin-next-data-source/src/fetchers/redshift.ts","./packages/teleport-plugin-next-data-source/src/fetchers/mongodb.ts","./packages/teleport-plugin-next-data-source/src/fetchers/redis.ts","./packages/teleport-plugin-next-data-source/src/fetchers/firestore.ts","./packages/teleport-plugin-next-data-source/src/fetchers/clickhouse.ts","./packages/teleport-plugin-next-data-source/src/fetchers/airtable.ts","./packages/teleport-plugin-next-data-source/src/fetchers/supabase.ts","./packages/teleport-plugin-next-data-source/src/fetchers/turso.ts","./packages/teleport-plugin-next-data-source/src/fetchers/rest-api.ts","./packages/teleport-plugin-next-data-source/src/fetchers/javascript.ts","./packages/teleport-plugin-next-data-source/src/fetchers/utils/header-detection.ts","./packages/teleport-plugin-next-data-source/src/fetchers/google-sheets.ts","./packages/teleport-plugin-next-data-source/src/transformations/shared-utils.ts","./packages/teleport-plugin-next-data-source/src/transformations/blog-post.ts","./packages/teleport-plugin-next-data-source/src/transformations/ecommerce-product.ts","./packages/teleport-plugin-next-data-source/src/transformations/index.ts","./packages/teleport-plugin-next-data-source/src/fetchers/teleport.ts","./packages/teleport-plugin-next-data-source/src/fetchers/raw-query.ts","./packages/teleport-plugin-next-data-source/src/fetchers/index.ts","./packages/teleport-plugin-next-data-source/src/validation.ts","./packages/teleport-plugin-next-data-source/src/count-fetchers.ts","./packages/teleport-plugin-next-data-source/src/data-source-fetchers.ts","./packages/teleport-plugin-next-data-source/src/utils.ts","./packages/teleport-plugin-next-data-source/src/fetchers/csv-file.ts","./packages/teleport-plugin-next-data-source/__tests__/csv-header-detection.test.ts","./packages/teleport-plugin-next-data-source/__tests__/detect-transformation-type.test.ts","./packages/teleport-plugin-next-data-source/__tests__/ecommerce-product-out-of-stock.test.ts","./packages/teleport-plugin-next-data-source/__tests__/ecommerce-product-variant-swatch.test.ts","./packages/teleport-plugin-next-data-source/__tests__/mocks.ts","./packages/teleport-plugin-next-data-source/__tests__/fetchers.test.ts","./packages/teleport-plugin-next-data-source/src/filter-utils.ts","./packages/teleport-plugin-next-data-source/__tests__/filter-utils.test.ts","./packages/teleport-plugin-next-data-source/__tests__/integration.test.ts","./packages/teleport-plugin-next-data-source/src/array-mapper-pagination.ts","./packages/teleport-plugin-next-data-source/__tests__/pagination.test.ts","./packages/teleport-plugin-next-data-source/src/sort-utils.ts","./packages/teleport-plugin-next-data-source/src/pagination-plugin.ts","./packages/teleport-plugin-next-data-source/src/index.ts","./packages/teleport-plugin-next-data-source/__tests__/plugin.test.ts","./packages/teleport-plugin-next-data-source/__tests__/search-url-sync.test.ts","./packages/teleport-plugin-next-data-source/__tests__/utils.test.ts","./packages/teleport-plugin-next-data-source/__tests__/validation.test.ts","./packages/teleport-plugin-next-data-source/src/array-mapper-registry.ts","./packages/teleport-plugin-next-data-source/src/pagination-with-count.ts","./packages/teleport-plugin-next-inline-fetch/src/utils.ts","./packages/teleport-plugin-next-inline-fetch/src/index.ts","./packages/teleport-plugin-next-static-paths/src/utils.ts","./packages/teleport-plugin-next-static-paths/src/index.ts","./packages/teleport-plugin-next-static-paths/__tests__/same-table-mutation-skip-static-paths.test.ts","./packages/teleport-plugin-next-static-props/src/utils.ts","./packages/teleport-plugin-next-static-props/src/index.ts","./packages/teleport-plugin-next-static-props/__tests__/same-table-mutation-server-side-props.test.ts","./packages/teleport-plugin-next-workflows/src/nodes/types.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-get-current.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-login.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-signup.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-compare-passwords.ts","./packages/teleport-plugin-next-workflows/__tests__/account-node-output-contract.test.ts","./packages/teleport-plugin-next-workflows/src/executor-generator.ts","./packages/teleport-plugin-next-workflows/src/types.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-activecampaign.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-airtable.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amplitude.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-apollo.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-asana.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-generic.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-ashby.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-atlassian.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-bamboohr.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-bannerbear.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-basecamp.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-beeminder.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-bitbucket.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-calendly.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-clickup.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-coda.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-confluence.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-copper.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-discord.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-docusign.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-dropbox-sign.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-dropbox.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-eventbrite.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-excel.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-facebook.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-figma.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gainsight.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-github.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gmail.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gong.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-analytics.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-bigquery.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-calendar.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-docs.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-drive.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-maps.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-sheets.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-greenhouse.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-heap.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-hive.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-hotjar.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-hubspot.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-insightly.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-insomnia.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-intercom.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-jira.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-keap.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-lever.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-linear.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-looker.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-mailchimp.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-miro.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-mixpanel.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-monday.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-netsuite.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-notion.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-oracle.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outlook.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outreach.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pandadoc.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pardot.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pipedrive.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-postman.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-powerbi.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-productboard.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-quickbooks.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-rapidapi.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-salesforce.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-segment.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-sentry.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-serp-api.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-shopify.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-slack.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-smartsheet.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-snowflake.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-stripe.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-tableau.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-tavily.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-trello.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-typeform.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-whatsapp.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-woocommerce.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-workable.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-wrike.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-x.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-xero.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-youtube.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-zendesk.ts","./packages/teleport-plugin-next-workflows/src/nodes/integrations/index.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-delete-current.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-hash-password.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-logout.ts","./packages/teleport-plugin-next-workflows/src/nodes/account/account-social-login.ts","./packages/teleport-plugin-next-workflows/src/nodes/audio/audio-play.ts","./packages/teleport-plugin-next-workflows/src/nodes/audio/audio-stop.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-provider-utils.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-custom-prompt.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-detect-language.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-generate-text-embedding.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-sentiment-analysis.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-summarization.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-text-classifier.ts","./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-text-transform.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-ask-permission.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-fullscreen.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-get-device-info.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-get-location.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-get-media-devices.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-get-network-status.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-pick-files.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-print.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-read-clipboard.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-share.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-show-notification.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-speech-to-text.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-subscribe-to-push.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-text-to-speech.ts","./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-write-clipboard.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-add-item.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-clear.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-get-items.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-get-total.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-remove-item.ts","./packages/teleport-plugin-next-workflows/src/nodes/cart/cart-update-item-quantity.ts","./packages/teleport-plugin-next-workflows/src/nodes/ecommerce/ecommerce-generate-invoice.ts","./packages/teleport-plugin-next-workflows/src/nodes/ecommerce/ecommerce-get-settings.ts","./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-upload.ts","./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-list.ts","./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-get-details.ts","./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-delete.ts","./packages/teleport-plugin-next-workflows/src/nodes/event/event-workflow-error.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-count.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-create-item.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-delete-item.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-raw-query.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-select.ts","./packages/teleport-plugin-next-workflows/src/nodes/data/data-update-item.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-add-class.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-get-attribute.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-get-classes.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-get-input-value.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-hide.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-remove-class.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-scroll-to.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-set-attribute.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-set-text.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-show.ts","./packages/teleport-plugin-next-workflows/src/nodes/element/element-toggle-class.ts","./packages/teleport-plugin-next-workflows/src/nodes/email/email-mailersend.ts","./packages/teleport-plugin-next-workflows/src/nodes/email/email-mailgun.ts","./packages/teleport-plugin-next-workflows/src/nodes/email/email-postmark.ts","./packages/teleport-plugin-next-workflows/src/nodes/email/email-resend.ts","./packages/teleport-plugin-next-workflows/src/nodes/email/email-sendgrid.ts","./packages/teleport-plugin-next-workflows/src/nodes/form/form-blur.ts","./packages/teleport-plugin-next-workflows/src/nodes/form/form-focus.ts","./packages/teleport-plugin-next-workflows/src/nodes/form/form-reset.ts","./packages/teleport-plugin-next-workflows/src/nodes/form/form-set-value.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-custom-js.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-custom-node.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-delay.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-emit-custom-event.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-extract-form-data.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-http-request.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-rate-limiter.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-if-statement.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-loop.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-parallel.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-switch.ts","./packages/teleport-plugin-next-workflows/src/nodes/general/general-trigger-download.ts","./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-go-back.ts","./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-go-to-page.ts","./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-navigate-to-url.ts","./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-refresh-page.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-cancel-plan.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-charge-user.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-create-customer.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-create-product.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-create-subscription.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-customer.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-product.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-customers.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-plans.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-products.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-subscriptions.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-subscribe-to-plan.ts","./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-update-customer.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-join-channel.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-leave-channel.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-list-channel-members.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-list-channels.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-send-channel-event.ts","./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-send-channel-message.ts","./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-infobip.ts","./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-smsapi.ts","./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-textmagic.ts","./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-twilio.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/state-batch-update.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/_state-get.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/state-get-global-state.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/state-get-local-state.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/state-update-global-state.ts","./packages/teleport-plugin-next-workflows/src/nodes/state/state-update-local-state.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/_storage-get.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-local-get.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-local-remove.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-local-set.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-session-get.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-session-remove.ts","./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-session-set.ts","./packages/teleport-plugin-next-workflows/src/nodes/toast/toast-show.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-array.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-calculate.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-convert.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-currency.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-image.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-object.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-string.ts","./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-validate.ts","./packages/teleport-plugin-next-workflows/src/nodes/url/url-get-current-url.ts","./packages/teleport-plugin-next-workflows/src/nodes/url/url-get-query-parameter.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-anonymize-data.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-barcode-generate.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-csv-parse.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-encode-decode.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-format-phone-number.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hash-data.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hybrid-search.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-markdown-to-html.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-ocr-extract-text.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-extract-text.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-generate.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-semantic-search.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-similarity-scoring.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-verify-email.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-verify-phone.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-xml-parse.ts","./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-youtube-transcript.ts","./packages/teleport-plugin-next-workflows/src/nodes/index.ts","./packages/teleport-plugin-next-workflows/src/graph-utils.ts","./packages/teleport-plugin-next-workflows/src/webhook-signature-verification.ts","./packages/teleport-plugin-next-workflows/src/api-route-generator.ts","./packages/teleport-plugin-next-workflows/__tests__/ai-error-contract.test.ts","./packages/teleport-plugin-next-workflows/src/await-result.ts","./packages/teleport-plugin-next-workflows/src/segment-splitter.ts","./packages/teleport-plugin-next-workflows/src/secret-collector.ts","./packages/teleport-plugin-next-workflows/src/realtime-generator.ts","./packages/teleport-plugin-next-workflows/src/invoice/email-sender-code.ts","./packages/teleport-plugin-next-workflows/src/transactional-email-code.ts","./packages/teleport-plugin-next-workflows/src/auth-generator.ts","./packages/teleport-plugin-next-workflows/src/invoice/invoice-html-code.ts","./packages/teleport-plugin-next-workflows/src/invoice/pdf-service-client-code.ts","./packages/teleport-plugin-next-workflows/src/invoice/pdf-generator-code.ts","./packages/teleport-plugin-next-workflows/src/invoice/data-access-code.ts","./packages/teleport-plugin-next-workflows/src/invoice/api-routes-code.ts","./packages/teleport-plugin-next-workflows/src/invoice/index.ts","./packages/teleport-plugin-next-workflows/src/webhook-generator.ts","./packages/teleport-plugin-next-workflows/src/sql-validator.ts","./packages/teleport-plugin-next-workflows/src/data-api-route-generator.ts","./packages/teleport-plugin-next-workflows/src/pg-client-code.ts","./packages/teleport-plugin-next-workflows/src/account-delete-route-generator.ts","./packages/teleport-plugin-next-workflows/src/runtime-storage-generator.ts","./packages/teleport-plugin-next-workflows/src/ecommerce/stock-decrement.ts","./packages/teleport-plugin-next-workflows/src/ecommerce/cart-availability.ts","./packages/teleport-plugin-next-workflows/src/ecommerce/order-number-generator.ts","./packages/teleport-plugin-next-workflows/src/ecommerce/order-ownership.ts","./packages/teleport-plugin-next-workflows/src/ecommerce-customhandler-rewriter.ts","./packages/teleport-plugin-next-workflows/src/security-scanner.ts","./packages/teleport-plugin-next-workflows/src/raw-sql-param-binding.ts","./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","./packages/teleport-plugin-next-workflows/__tests__/auth-env-secret-preservation.test.ts","./packages/teleport-plugin-next-workflows/__tests__/auth-nextauth-url.test.ts","./packages/teleport-plugin-next-workflows/__tests__/auth-oauth-providers.test.ts","./packages/teleport-plugin-next-workflows/__tests__/cart-availability-add-to-cart.test.ts","./packages/teleport-plugin-next-workflows/__tests__/cart-availability-place-order.test.ts","./packages/teleport-plugin-next-workflows/src/is-logged-in-gate.ts","./packages/teleport-plugin-next-workflows/src/trigger-generator.ts","./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","./packages/teleport-plugin-next-workflows/__tests__/client-config-redaction.test.ts","./packages/teleport-plugin-next-workflows/__tests__/component-scope-trigger-routing.test.ts","./packages/teleport-plugin-next-workflows/__tests__/cron-route-loop-templateparams.test.ts","./packages/teleport-plugin-next-workflows/src/index.ts","./packages/teleport-plugin-next-workflows/__tests__/_helpers/load-handler.ts","./packages/teleport-plugin-next-workflows/__tests__/custom-js-loop-scope.test.ts","./packages/teleport-plugin-next-workflows/__tests__/custom-js-params-env-invariance.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-anon-user-id-fallback.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-boolean-checkbox-coercion.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-low-stock-autofire.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-on-conflict-do-nothing.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-safe-query.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-api-uuid-coercion.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-create-item-cart-mark-ordered.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-create-item-order-notification.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts","./packages/teleport-plugin-next-workflows/__tests__/data-update-item-runtime.test.ts","./packages/teleport-plugin-next-workflows/__tests__/ecommerce-customhandler-rewriter.test.ts","./packages/teleport-plugin-next-workflows/__tests__/element-event-trigger-value.test.ts","./packages/teleport-plugin-next-workflows/__tests__/element-visible-trigger-scoping.test.ts","./packages/teleport-plugin-next-workflows/__tests__/email-body-context-resolution.test.ts","./packages/teleport-plugin-next-workflows/__tests__/file-storage-upload-picked-files.test.ts","./packages/teleport-plugin-next-workflows/__tests__/form-submitted-trigger-context.test.ts","./packages/teleport-plugin-next-workflows/__tests__/global-workflows-handler-map-integrity.test.ts","./packages/teleport-plugin-next-workflows/__tests__/graph-utils-topological-order.test.ts","./packages/teleport-plugin-next-workflows/__tests__/handler-output-shapes.test.ts","./packages/teleport-plugin-next-workflows/__tests__/invoice-generate-hydration.test.ts","./packages/teleport-plugin-next-workflows/__tests__/is-logged-in-gate.test.ts","./packages/teleport-plugin-next-workflows/__tests__/loop-collection-unwrap.test.ts","./packages/teleport-plugin-next-workflows/__tests__/_helpers/run-generated-middleware.ts","./packages/teleport-plugin-next-workflows/__tests__/middleware-guest-order-details.test.ts","./packages/teleport-plugin-next-workflows/__tests__/middleware-home-route-protection.test.ts","./packages/teleport-plugin-next-workflows/__tests__/middleware-row-owned-pages.test.ts","./packages/teleport-plugin-next-workflows/__tests__/navigation-go-to-page.test.ts","./packages/teleport-plugin-next-workflows/__tests__/node-audit-fixes.test.ts","./packages/teleport-plugin-next-workflows/__tests__/node-handler-file-inline-map.test.ts","./packages/teleport-plugin-next-workflows/__tests__/order-number-generator.test.ts","./packages/teleport-plugin-next-workflows/__tests__/order-ownership.test.ts","./packages/teleport-plugin-next-workflows/__tests__/page-loaded-scoping-skip.test.ts","./packages/teleport-plugin-next-workflows/__tests__/payment-charge-user-handler-serialization.test.ts","./packages/teleport-plugin-next-workflows/__tests__/payment-redirect-and-order-notification.test.ts","./packages/teleport-plugin-next-workflows/src/sql-query-validator.ts","./packages/teleport-plugin-next-workflows/__tests__/raw-query-param-binding.test.ts","./packages/teleport-plugin-next-workflows/__tests__/raw-sql-param-binding.test.ts","./packages/teleport-plugin-next-workflows/__tests__/reserved-word-state-binding.test.ts","./packages/teleport-plugin-next-workflows/__tests__/resolve-handler-entry-name.test.ts","./packages/teleport-plugin-next-workflows/__tests__/route-changed-trigger.test.ts","./packages/teleport-plugin-next-workflows/__tests__/runtime-absolutize-url.test.ts","./packages/teleport-plugin-next-workflows/__tests__/runtime-operator-aliases.test.ts","./packages/teleport-plugin-next-workflows/__tests__/runtime-template-token-resolution.test.ts","./packages/teleport-plugin-next-workflows/__tests__/runtime-trigger-element-roundtrip.test.ts","./packages/teleport-plugin-next-workflows/__tests__/salesforce-opportunity-id.test.ts","./packages/teleport-plugin-next-workflows/__tests__/security-runtime-shadow.test.ts","./packages/teleport-plugin-next-workflows/__tests__/state-setter-value-key-unwrap.test.ts","./packages/teleport-plugin-next-workflows/__tests__/state-update-array-type-guard.test.ts","./packages/teleport-plugin-next-workflows/__tests__/state-update-default-value.test.ts","./packages/teleport-plugin-next-workflows/__tests__/state-update-missing-setter-warn.test.ts","./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","./packages/teleport-plugin-next-workflows/__tests__/streaming-on-end-env-filter.test.ts","./packages/teleport-plugin-next-workflows/__tests__/transform-generate-output.test.ts","./packages/teleport-plugin-next-workflows/__tests__/utility-nodes.test.ts","./packages/teleport-plugin-next-workflows/__tests__/webpack-safe-handlers.test.ts","./packages/teleport-plugin-next-workflows/src/nodes/webpack-runtime-globals.d.ts","./packages/teleport-plugin-react-app-routing/src/utils.ts","./packages/teleport-plugin-react-app-routing/src/index.ts","./packages/teleport-plugin-react-app-routing/__tests__/index.ts","./packages/teleport-plugin-react-base-component/src/constants.ts","./packages/teleport-plugin-react-base-component/src/index.ts","./packages/teleport-plugin-react-base-component/__tests__/index.ts","./packages/teleport-plugin-react-jss/src/utils.ts","./packages/teleport-plugin-react-jss/src/style-sheet.ts","./packages/teleport-plugin-react-jss/src/index.ts","./packages/teleport-plugin-react-jss/__tests__/mocks.ts","./packages/teleport-plugin-react-jss/__tests__/component-referenced.ts","./packages/teleport-plugin-react-jss/__tests__/index.ts","./packages/teleport-plugin-react-jss/__tests__/referenced-styles.ts","./packages/teleport-plugin-react-jss/__tests__/style-sheet.ts","./packages/teleport-plugin-react-styled-components/src/constants.ts","./packages/teleport-plugin-react-styled-components/src/utils.ts","./packages/teleport-plugin-react-styled-components/src/style-sheet.ts","./packages/teleport-plugin-react-styled-components/src/index.ts","./packages/teleport-plugin-react-styled-components/__tests__/mocks.ts","./packages/teleport-plugin-react-styled-components/__tests__/component-scoped.ts","./packages/teleport-plugin-react-styled-components/__tests__/index.ts","./packages/teleport-plugin-react-styled-components/__tests__/referenced-styles.ts","./packages/teleport-plugin-react-styled-components/__tests__/style-sheet.ts","./packages/teleport-plugin-react-styled-jsx/src/utils.ts","./packages/teleport-plugin-react-styled-jsx/src/index.ts","./packages/teleport-plugin-react-styled-jsx/__tests__/mocks.ts","./packages/teleport-plugin-react-styled-jsx/__tests__/component-scoped.ts","./packages/teleport-plugin-react-styled-jsx/__tests__/index.ts","./packages/teleport-plugin-react-styled-jsx/__tests__/referenced-styles.ts","./packages/teleport-plugin-react-styled-jsx/__tests__/utils.ts","./packages/teleport-plugin-vue-app-routing/src/index.ts","./packages/teleport-plugin-vue-app-routing/__tests__/index.ts","./packages/teleport-plugin-vue-base-component/src/utils.ts","./packages/teleport-plugin-vue-base-component/src/constants.ts","./packages/teleport-plugin-vue-base-component/src/index.ts","./packages/teleport-plugin-vue-base-component/__tests__/mocks.ts","./packages/teleport-plugin-vue-base-component/__tests__/index.ts","./packages/teleport-plugin-vue-head-config/src/index.ts","./packages/teleport-plugin-vue-head-config/__tests__/index.ts","./node_modules/@types/prettier/index.d.ts","./node_modules/@types/prettier/standalone.d.ts","./node_modules/@types/prettier/parser-html.d.ts","./packages/teleport-postprocessor-prettier-html/src/index.ts","./packages/teleport-postprocessor-prettier-html/__tests__/index.ts","./node_modules/@types/prettier/parser-babel.d.ts","./packages/teleport-postprocessor-prettier-js/src/index.ts","./packages/teleport-postprocessor-prettier-js/__tests__/index.ts","./node_modules/@types/prettier/parser-postcss.d.ts","./packages/teleport-postprocessor-prettier-jsx/src/index.ts","./packages/teleport-postprocessor-prettier-jsx/__tests__/index.ts","./node_modules/@types/prettier/parser-typescript.d.ts","./packages/teleport-postprocessor-prettier-ts/src/index.ts","./packages/teleport-postprocessor-prettier-ts/__tests__/index.ts","./packages/teleport-postprocessor-vue-file/src/index.ts","./packages/teleport-postprocessor-vue-file/__tests__/index.ts","./packages/teleport-project-generator/src/assembly-line/index.ts","./packages/teleport-project-generator/src/constants.ts","./packages/teleport-project-generator/__tests__/mocks.ts","./packages/teleport-project-generator/__tests__/assembly-line.ts","./packages/teleport-project-generator/src/utils.ts","./packages/teleport-project-generator/__tests__/details-page-info-propagation.ts","./packages/teleport-project-generator/src/types.ts","./packages/teleport-project-generator/src/file-handlers.ts","./packages/teleport-project-generator/__tests__/file-handlers.ts","./packages/teleport-project-generator/src/resource.ts","./packages/teleport-project-generator/src/index.ts","./packages/teleport-project-generator/__tests__/index.ts","./packages/teleport-project-generator/__tests__/utils.ts","./packages/teleport-plugin-angular-module/dist/cjs/index.d.ts","./packages/teleport-project-generator-angular/src/constants.ts","./packages/teleport-project-generator-angular/src/angular-project-mapping.ts","./packages/teleport-project-generator-angular/src/project-template.ts","./packages/teleport-project-generator-angular/src/index.ts","./packages/teleport-project-generator-angular/__tests__/end2end/template-definition.json","./packages/teleport-project-generator-angular/__tests__/end2end/index.ts","./packages/teleport-project-generator-html/src/project-template.ts","./packages/teleport-project-generator-html/src/error-page-mapping.ts","./node_modules/domelementtype/lib/index.d.ts","./node_modules/domhandler/lib/node.d.ts","./node_modules/domhandler/lib/index.d.ts","./node_modules/htmlparser2/lib/tokenizer.d.ts","./node_modules/htmlparser2/lib/parser.d.ts","./node_modules/dom-serializer/lib/index.d.ts","./node_modules/domutils/lib/stringify.d.ts","./node_modules/domutils/lib/traversal.d.ts","./node_modules/domutils/lib/manipulation.d.ts","./node_modules/domutils/lib/querying.d.ts","./node_modules/domutils/lib/legacy.d.ts","./node_modules/domutils/lib/helpers.d.ts","./node_modules/domutils/lib/feeds.d.ts","./node_modules/domutils/lib/index.d.ts","./node_modules/htmlparser2/lib/index.d.ts","./node_modules/css-what/lib/es/types.d.ts","./node_modules/css-what/lib/es/parse.d.ts","./node_modules/css-what/lib/es/stringify.d.ts","./node_modules/css-what/lib/es/index.d.ts","./node_modules/css-select/lib/types.d.ts","./node_modules/css-select/lib/pseudo-selectors/filters.d.ts","./node_modules/css-select/lib/pseudo-selectors/pseudos.d.ts","./node_modules/css-select/lib/pseudo-selectors/aliases.d.ts","./node_modules/css-select/lib/pseudo-selectors/index.d.ts","./node_modules/css-select/lib/index.d.ts","./node_modules/cheerio-select/lib/index.d.ts","./node_modules/cheerio/lib/options.d.ts","./node_modules/cheerio/lib/types.d.ts","./node_modules/cheerio/lib/api/attributes.d.ts","./node_modules/cheerio/lib/api/traversing.d.ts","./node_modules/cheerio/lib/api/manipulation.d.ts","./node_modules/cheerio/lib/api/css.d.ts","./node_modules/cheerio/lib/api/forms.d.ts","./node_modules/cheerio/lib/cheerio.d.ts","./node_modules/cheerio/lib/static.d.ts","./node_modules/cheerio/lib/load.d.ts","./node_modules/cheerio/lib/index.d.ts","./packages/teleport-project-generator-html/src/plugin-clone-globals.ts","./packages/teleport-project-generator-html/src/plugin-home-replace.ts","./packages/teleport-project-generator-html/src/index.ts","./examples/test-samples/comp-style-overrides.json","./examples/test-samples/html-image-use-cases.json","./packages/teleport-project-generator-html/__tests__/index.ts","./examples/test-samples/project-with-slot.json","./packages/teleport-project-generator-html/__tests__/end2end/index.ts","./packages/teleport-project-generator-html/src/path-browserisify.d.ts","./packages/teleport-project-generator-next/src/analytics/tracker-source.ts","./packages/teleport-project-generator-next/src/analytics/tracker-component.ts","./packages/teleport-project-generator-next/src/app-sibling-injection.ts","./packages/teleport-project-generator-next/src/analytics/project-plugin.ts","./packages/teleport-project-generator-next/__tests__/analytics-project-plugin.test.ts","./packages/teleport-project-generator-next/__tests__/analytics-tracker-double-count.test.ts","./packages/teleport-plugin-jsx-next-image/dist/cjs/index.d.ts","./packages/teleport-plugin-jsx-head-config/dist/cjs/index.d.ts","./packages/teleport-plugin-next-static-props/dist/cjs/index.d.ts","./packages/teleport-plugin-next-static-paths/dist/cjs/index.d.ts","./packages/teleport-plugin-next-inline-fetch/dist/cjs/index.d.ts","./packages/teleport-project-generator-next/src/utils.ts","./packages/teleport-project-generator-next/src/global-state/data-source-utils.ts","./packages/teleport-project-generator-next/src/state-data-source-plugin.ts","./packages/teleport-project-generator-next/src/next-project-mapping.ts","./packages/teleport-project-generator-next/src/project-template.ts","./packages/teleport-project-generator-next/src/internationalization/locale-mapper-component.ts","./packages/teleport-project-generator-next/src/url-search-params-plugin.ts","./packages/teleport-project-generator-next/src/internationalization/locale-fetcher-component.ts","./packages/teleport-project-generator-next/src/forms/form-submission-handler.ts","./packages/teleport-project-generator-next/src/data-source-dependencies.ts","./packages/teleport-project-generator-next/src/data-source-utility-plugin.ts","./packages/teleport-project-generator-next/src/global-state/component-plugin.ts","./packages/teleport-project-generator-next/src/global-state/project-plugin.ts","./packages/teleport-project-generator-next/src/ai-chat/db-generator.ts","./packages/teleport-project-generator-next/src/ai-chat/provider-generator.ts","./packages/teleport-project-generator-next/src/ai-chat/api-route-generator.ts","./packages/teleport-project-generator-next/src/ai-chat/hook-generator.ts","./packages/teleport-project-generator-next/src/ai-chat/widget-generator.ts","./packages/teleport-project-generator-next/src/ai-chat/auth-wrapper-generator.ts","./packages/teleport-project-generator-next/src/npmrc-legacy-peer-deps.ts","./packages/teleport-project-generator-next/src/ai-chat/project-plugin.ts","./packages/teleport-project-generator-next/src/nav-active-link/nav-active-link-component.ts","./packages/teleport-project-generator-next/src/nav-active-link/project-plugin.ts","./packages/teleport-project-generator-next/src/collapsible-text/collapsible-text-overflow-component.ts","./packages/teleport-project-generator-next/src/uidl-element-traversal.ts","./packages/teleport-project-generator-next/src/collapsible-text/decompose.ts","./packages/teleport-project-generator-next/src/collapsible-text/project-plugin.ts","./packages/teleport-project-generator-next/src/ecommerce/ecommerce-context-generator.ts","./packages/teleport-project-generator-next/src/ecommerce/ecommerce-api-routes-generator.ts","./packages/teleport-project-generator-next/src/ecommerce/email-sender-generator.ts","./packages/teleport-project-generator-next/src/ecommerce/cart-api-routes-generator.ts","./packages/teleport-project-generator-next/src/ecommerce/project-plugin.ts","./packages/teleport-project-generator-next/src/dashboard-layout-plugin.ts","./packages/teleport-project-generator-next/src/entity-mutation-ssr-finalize-plugin.ts","./packages/teleport-project-generator-next/src/rich-text-editor/component-generator.ts","./packages/teleport-project-generator-next/src/rich-text-editor/project-plugin.ts","./packages/teleport-project-generator-next/src/rich-text-editor/component-plugin.ts","./packages/teleport-project-generator-next/src/app-import-injection.ts","./packages/teleport-project-generator-next/src/calendar/calendarkit-css.ts","./packages/teleport-project-generator-next/src/calendar/project-plugin.ts","./packages/teleport-project-generator-next/src/drag-drop/component-generator.ts","./packages/teleport-project-generator-next/src/drag-drop/project-plugin.ts","./packages/teleport-project-generator-next/src/kanban/component-generator.ts","./packages/teleport-project-generator-next/src/kanban/project-plugin.ts","./packages/teleport-project-generator-next/src/countdown/component-generator.ts","./packages/teleport-project-generator-next/src/countdown/project-plugin.ts","./packages/teleport-project-generator-next/src/widgets/project-plugin-factory.ts","./packages/teleport-project-generator-next/src/widgets/qrcode-component.ts","./packages/teleport-project-generator-next/src/widgets/barcode-component.ts","./packages/teleport-project-generator-next/src/widgets/signature-component.ts","./packages/teleport-project-generator-next/src/widgets/color-picker-component.ts","./packages/teleport-project-generator-next/src/widgets/emoji-picker-component.ts","./packages/teleport-project-generator-next/src/widgets/motion-component.ts","./packages/teleport-project-generator-next/src/widgets/form-file-input-component.ts","./packages/teleport-project-generator-next/src/widgets/categories-megamenu-component.ts","./packages/teleport-project-generator-next/src/widgets/categories-filter-component.ts","./packages/teleport-project-generator-next/src/widgets/index.ts","./packages/teleport-project-generator-next/src/local-component-path-plugin.ts","./packages/teleport-project-generator-next/src/forms/captcha-script-plugin.ts","./packages/teleport-project-generator-next/src/internationalization/project.ts","./packages/teleport-project-generator-next/src/partial.ts","./packages/teleport-project-generator-next/src/split-utils.ts","./packages/teleport-project-generator-next/src/index.ts","./packages/teleport-project-generator-next/__tests__/calendarkit-end2end.test.ts","./packages/teleport-project-generator-next/__tests__/calendarkit-project-plugin.test.ts","./packages/teleport-project-generator-next/__tests__/cart-mark-ordered-checkout.test.ts","./packages/teleport-project-generator-next/__tests__/cart-persistence-endpoint.test.ts","./packages/teleport-project-generator-next/__tests__/cart-persistence-provider.test.ts","./packages/teleport-project-generator-next/__tests__/collapsible-text-decompose.test.ts","./packages/teleport-project-generator-next/__tests__/collapsible-text-project-plugin.test.ts","./packages/teleport-project-generator-next/__tests__/dashboard-layout-plugin.test.ts","./packages/teleport-project-generator-next/__tests__/dragdrop-kanban-end2end.test.ts","./packages/teleport-project-generator-next/__tests__/dragdrop-kanban-project-plugins.test.ts","./packages/teleport-project-generator-next/__tests__/ecommerce-context-backstop.test.ts","./packages/teleport-project-generator-next/__tests__/email-sender-and-low-stock-alert.test.ts","./packages/teleport-project-generator-next/__tests__/_helpers/rules-of-hooks.ts","./packages/teleport-project-generator-next/__tests__/emitted-components-rules-of-hooks.test.ts","./packages/teleport-project-generator-next/__tests__/entity-mutation-ssr-finalize-plugin.test.ts","./packages/teleport-project-generator-next/__tests__/form-file-input-end2end.test.ts","./packages/teleport-project-generator-next/__tests__/global-state-default-value.test.ts","./packages/teleport-project-generator-next/__tests__/motion-end2end.test.ts","./packages/teleport-project-generator-next/__tests__/motion-stagger-repeater.test.ts","./packages/teleport-project-generator-next/__tests__/order-notification-template-rendering.test.ts","./packages/teleport-project-generator-next/__tests__/partial.ts","./packages/teleport-project-generator-next/__tests__/state-data-source-fetch-grouping.test.ts","./packages/teleport-project-generator-next/__tests__/state-data-source-runtime-user-fetch.test.ts","./packages/teleport-project-generator-next/__tests__/stock-check-endpoint.test.ts","./packages/teleport-project-generator-next/__tests__/url-search-params-plugin.ts","./packages/teleport-project-generator-next/__tests__/widget-project-plugins.test.ts","./packages/teleport-project-generator-next/__tests__/end2end/project-with-import-without-global-styles.json","./packages/teleport-project-generator-next/__tests__/end2end/project-with-same-page-names-in-diff-routes.json","./packages/teleport-project-generator-next/__tests__/end2end/template-definition.json","./packages/teleport-project-generator-next/__tests__/end2end/index.ts","./packages/teleport-project-generator-nuxt/__tests__/end2end/template-definition.json","./packages/teleport-project-generator-nuxt/src/error-page-mapping.ts","./packages/teleport-plugin-vue-head-config/dist/cjs/index.d.ts","./packages/teleport-project-generator-nuxt/src/utils.ts","./packages/teleport-project-generator-nuxt/src/nuxt-project-mapping.ts","./packages/teleport-project-generator-nuxt/src/project-template.ts","./packages/teleport-project-generator-nuxt/src/index.ts","./packages/teleport-project-generator-nuxt/__tests__/end2end/index.ts","./packages/teleport-project-generator-react/__tests__/end2end/template-definition.json","./packages/teleport-plugin-react-app-routing/dist/cjs/index.d.ts","./packages/teleport-project-generator-react/src/react-project-mapping.ts","./packages/teleport-project-generator-react/src/project-template.ts","./packages/teleport-project-generator-react/src/index.ts","./packages/teleport-project-generator-react/__tests__/end2end/index.ts","./packages/teleport-project-generator-vue/__tests__/end2end/template-definition.json","./packages/teleport-plugin-vue-app-routing/dist/cjs/index.d.ts","./packages/teleport-project-generator-vue/src/project-template.ts","./packages/teleport-project-generator-vue/src/vue-project-mapping.ts","./packages/teleport-project-generator-vue/src/index.ts","./packages/teleport-project-generator-vue/__tests__/end2end/index.ts","./packages/teleport-project-packer/__tests__/template-definition.json","./packages/teleport-project-packer/src/utils.ts","./packages/teleport-project-packer/src/constants.ts","./packages/teleport-project-packer/src/index.ts","./packages/teleport-project-packer/__tests__/index.ts","./packages/teleport-project-plugin-css-modules/src/next.ts","./packages/teleport-project-plugin-css-modules/src/index.ts","./packages/teleport-project-plugin-custom-files/src/index.ts","./packages/teleport-project-plugin-custom-files/__tests__/index.ts","./packages/teleport-project-plugin-i18n-files/src/index.ts","./packages/teleport-project-plugin-next-revalidate-api/src/utils.ts","./packages/teleport-project-plugin-next-revalidate-api/src/component-plugin.ts","./packages/teleport-project-plugin-next-revalidate-api/src/index.ts","./packages/teleport-project-plugin-parse-embed/src/utils.ts","./node_modules/@types/unist/index.d.ts","./node_modules/@types/hast/index.d.ts","./node_modules/hast-util-raw/complex-types.d.ts","./node_modules/hast-util-to-html/node_modules/stringify-entities/lib/util/format-smart.d.ts","./node_modules/hast-util-to-html/node_modules/stringify-entities/lib/core.d.ts","./node_modules/hast-util-to-html/node_modules/stringify-entities/lib/index.d.ts","./node_modules/hast-util-to-html/node_modules/stringify-entities/index.d.ts","./node_modules/property-information/lib/util/info.d.ts","./node_modules/property-information/lib/util/schema.d.ts","./node_modules/property-information/lib/find.d.ts","./node_modules/property-information/lib/hast-to-react.d.ts","./node_modules/property-information/lib/normalize.d.ts","./node_modules/property-information/index.d.ts","./node_modules/hast-util-to-html/lib/types.d.ts","./node_modules/hast-util-to-html/lib/index.d.ts","./node_modules/hast-util-to-html/index.d.ts","./node_modules/vfile-message/lib/index.d.ts","./node_modules/vfile-message/index.d.ts","./node_modules/vfile/lib/minurl.shared.d.ts","./node_modules/vfile/lib/index.d.ts","./node_modules/vfile/index.d.ts","./node_modules/parse5/dist/common/html.d.ts","./node_modules/parse5/dist/common/token.d.ts","./node_modules/parse5/dist/common/error-codes.d.ts","./node_modules/parse5/dist/tokenizer/preprocessor.d.ts","./node_modules/parse5/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts","./node_modules/parse5/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts","./node_modules/parse5/node_modules/entities/dist/commonjs/decode-codepoint.d.ts","./node_modules/parse5/node_modules/entities/dist/commonjs/decode.d.ts","./node_modules/parse5/node_modules/entities/decode.d.ts","./node_modules/parse5/dist/tokenizer/index.d.ts","./node_modules/parse5/dist/tree-adapters/interface.d.ts","./node_modules/parse5/dist/parser/open-element-stack.d.ts","./node_modules/parse5/dist/parser/formatting-element-list.d.ts","./node_modules/parse5/dist/parser/index.d.ts","./node_modules/parse5/dist/tree-adapters/default.d.ts","./node_modules/parse5/dist/serializer/index.d.ts","./node_modules/parse5/dist/common/foreign-content.d.ts","./node_modules/parse5/dist/index.d.ts","./node_modules/hast-util-from-parse5/lib/index.d.ts","./node_modules/hast-util-from-parse5/index.d.ts","./node_modules/hast-util-from-html/lib/index.d.ts","./node_modules/hast-util-from-html/index.d.ts","./packages/teleport-project-plugin-parse-embed/src/component-plugin.ts","./packages/teleport-project-plugin-parse-embed/src/hast-util-to-jsx-inline-script.d.ts","./packages/teleport-project-plugin-parse-embed/src/index.ts","./node_modules/magic-string/index.d.ts","./packages/teleport-project-plugin-react-jss/src/next.ts","./packages/teleport-project-plugin-react-jss/src/index.ts","./packages/teleport-project-plugin-styled-components/src/constant.ts","./packages/teleport-project-plugin-styled-components/src/next.ts","./packages/teleport-project-plugin-styled-components/src/react.ts","./packages/teleport-project-plugin-styled-components/src/index.ts","./packages/teleport-project-plugin-tailwind/src/constants.ts","./packages/teleport-project-plugin-tailwind/src/next.ts","./packages/teleport-project-plugin-tailwind/src/default.ts","./packages/teleport-project-plugin-tailwind/src/react.ts","./packages/teleport-project-plugin-tailwind/src/vue.ts","./packages/teleport-project-plugin-tailwind/src/angular.ts","./packages/teleport-project-plugin-tailwind/src/nuxt.ts","./packages/teleport-project-plugin-tailwind/src/index.ts","./packages/teleport-project-plugin-tailwind/__tests__/index.ts","./packages/teleport-publisher-codesandbox/src/constants.ts","./packages/teleport-publisher-codesandbox/src/utils.ts","./packages/teleport-publisher-codesandbox/src/index.ts","./packages/teleport-publisher-codesandbox/__tests__/mocks.ts","./packages/teleport-publisher-codesandbox/__tests__/index.ts","./packages/teleport-publisher-codesandbox/__tests__/utils.ts","./packages/teleport-publisher-disk/src/utils.ts","./packages/teleport-publisher-disk/src/index.ts","./packages/teleport-publisher-disk/__tests__/project-files.json","./packages/teleport-publisher-disk/__tests__/index.ts","./packages/teleport-publisher-disk/src/path-browserisify.d.ts","./packages/teleport-publisher-github/src/types.ts","./packages/teleport-publisher-github/src/utils.ts","./packages/teleport-publisher-github/src/index.ts","./packages/teleport-publisher-github/__tests__/project-files.json","./packages/teleport-publisher-github/__tests__/github-files-content.json","./packages/teleport-publisher-github/__tests__/index.ts","./packages/teleport-publisher-netlify/src/constants.ts","./packages/teleport-publisher-netlify/src/errors.ts","./packages/teleport-publisher-netlify/src/netlifyclient.ts","./packages/teleport-publisher-netlify/src/index.ts","./packages/teleport-publisher-netlify/__tests__/project-files.json","./packages/teleport-publisher-netlify/__tests__/index.ts","./node_modules/form-data/index.d.ts","./node_modules/@types/node-fetch/externals.d.ts","./node_modules/@types/node-fetch/index.d.ts","./node_modules/@types/async-retry/index.d.ts","./node_modules/async-sema/lib/index.d.ts","./packages/teleport-publisher-vercel/src/types.ts","./packages/teleport-publisher-vercel/src/hash.ts","./packages/teleport-publisher-vercel/src/utils.ts","./packages/teleport-publisher-vercel/src/index.ts","./packages/teleport-publisher-vercel/__tests__/mocks.ts","./packages/teleport-publisher-vercel/__tests__/index.ts","./node_modules/jszip/index.d.ts","./packages/teleport-publisher-zip/src/utils.ts","./packages/teleport-publisher-zip/src/index.ts","./packages/teleport-publisher-zip/__tests__/project-files.json","./packages/teleport-publisher-zip/__tests__/index.ts","./packages/teleport-shared/src/utils/js-identifiers.ts","./packages/teleport-shared/src/utils/string-utils.ts","./packages/teleport-shared/__tests__/utils/js-identifiers.ts","./packages/teleport-shared/__tests__/utils/string-utils.ts","./packages/teleport-shared/src/constants/index.ts","./packages/teleport-shared/src/utils/generic.ts","./packages/teleport-shared/src/utils/route-paths.ts","./packages/teleport-shared/src/index.ts","./packages/teleport-shared/src/utils/uidl-utils.ts","./packages/teleport-shared/__tests__/utils/uidl-utils-style.json","./packages/teleport-shared/__tests__/utils/uidl-utils.ts","./packages/teleport-test/src/component.ts","./packages/teleport-test/src/constants.ts","./examples/uidl-samples/project.json","./packages/teleport-test/src/packer.ts","./node_modules/chalk/types/index.d.ts","./packages/teleport-test/src/standalone-partial.ts","./packages/teleport-test/src/standalone-sandbox.ts","./packages/teleport-code-generator/dist/cjs/index.d.ts","./packages/teleport-project-plugin-react-jss/dist/cjs/index.d.ts","./packages/teleport-project-plugin-parse-embed/dist/cjs/utils.d.ts","./packages/teleport-project-plugin-parse-embed/dist/cjs/component-plugin.d.ts","./packages/teleport-project-plugin-parse-embed/dist/cjs/index.d.ts","./examples/uidl-samples/contentful.json","./examples/uidl-samples/strapi.json","./examples/uidl-samples/wordpress.json","./examples/uidl-samples/caisy.json","./examples/uidl-samples/flotiq.json","./packages/teleport-test/src/standalone.ts","./packages/teleport-test/src/test-html-only.ts","./packages/teleport-uidl-builders/src/component-builders.ts","./packages/teleport-uidl-builders/__tests__/component-builders.ts","./packages/teleport-uidl-builders/src/project-builders.ts","./packages/teleport-uidl-builders/__tests__/project-builders.ts","./packages/teleport-uidl-builders/src/index.ts","./node_modules/deepmerge/index.d.ts","./packages/teleport-uidl-resolver/src/utils.ts","./packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts","./packages/teleport-uidl-resolver/src/resolvers/abilities/index.ts","./packages/teleport-uidl-resolver/src/resolvers/style-set-definitions/index.ts","./packages/teleport-uidl-resolver/src/resolvers/referenced-styles/index.ts","./packages/teleport-uidl-resolver/src/resolvers/embed-node/utils.ts","./packages/teleport-uidl-resolver/src/resolvers/embed-node/index.ts","./packages/teleport-uidl-resolver/src/resolvers/unbound-expressions/expression-lexer.ts","./packages/teleport-uidl-resolver/src/resolvers/unbound-expressions/expression-identifiers.ts","./packages/teleport-uidl-resolver/src/resolvers/unbound-expressions/expression-fallback.ts","./packages/teleport-uidl-resolver/src/resolvers/unbound-expressions/ambient-identifiers.ts","./packages/teleport-uidl-resolver/src/resolvers/unbound-expressions/index.ts","./packages/teleport-uidl-resolver/src/resolver.ts","./packages/teleport-uidl-resolver/src/html-mapping.ts","./packages/teleport-uidl-resolver/src/index.ts","./packages/teleport-uidl-resolver/__tests__/index.ts","./packages/teleport-uidl-resolver/__tests__/mapping.json","./packages/teleport-uidl-resolver/__tests__/resolver.ts","./packages/teleport-uidl-resolver/__tests__/utils.ts","./packages/teleport-uidl-resolver/__tests__/abilities/mocks.ts","./packages/teleport-uidl-resolver/__tests__/abilities/utils.ts","./packages/teleport-uidl-resolver/__tests__/embed-lottie-node/index.ts","./packages/teleport-uidl-resolver/__tests__/html-mapping/index.ts","./packages/teleport-uidl-resolver/__tests__/referenced-styles/index.ts","./packages/teleport-uidl-resolver/__tests__/style-set-definitions/index.ts","./packages/teleport-uidl-resolver/__tests__/unbound-expressions/expression-fallback.ts","./packages/teleport-uidl-resolver/__tests__/unbound-expressions/expression-identifiers.ts","./packages/teleport-uidl-resolver/__tests__/unbound-expressions/index.ts","./packages/teleport-uidl-validator/src/decoders/custom-combinators.ts","./packages/teleport-uidl-validator/src/decoders/utils.ts","./packages/teleport-uidl-validator/__tests__/decoder/index.ts","./packages/teleport-uidl-validator/__tests__/parser/component-with-primitive-values.json","./packages/teleport-uidl-validator/__tests__/parser/component-with-proper-values.json","./packages/teleport-uidl-validator/__tests__/parser/component-with-reusalble-styles.json","./packages/teleport-uidl-validator/__tests__/parser/componennt-with-referenced-styles.json","./packages/teleport-uidl-validator/__tests__/parser/compoenent-with-state-reference.json","./packages/teleport-uidl-validator/src/parser/index.ts","./packages/teleport-uidl-validator/__tests__/parser/component-parsing.ts","./packages/teleport-uidl-validator/__tests__/parser/component-referenced.ts","./packages/teleport-uidl-validator/src/decoders/component-decoder.ts","./packages/teleport-uidl-validator/src/decoders/project-decoder.ts","./packages/teleport-uidl-validator/src/decoders/index.ts","./packages/teleport-uidl-validator/src/validator/utils.ts","./packages/teleport-uidl-validator/src/validator/index.ts","./packages/teleport-uidl-validator/src/index.ts","./packages/teleport-uidl-validator/__tests__/validator/component-element-with-empty-name.json","./packages/teleport-uidl-validator/__tests__/validator/component-uidl-with-event-modifier-undefined.json","./packages/teleport-uidl-validator/__tests__/validator/component-invalid-sample.json","./packages/teleport-uidl-validator/__tests__/validator/project-sample.json","./packages/teleport-uidl-validator/__tests__/validator/old-project-invalid-sample.json","./packages/teleport-uidl-validator/__tests__/validator/project-invalid-sample.json","./packages/teleport-uidl-validator/__tests__/validator/project-invalid-sample-no-route.json","./packages/teleport-uidl-validator/__tests__/validator/component-uidl-with-null-undefined.json","./packages/teleport-uidl-validator/__tests__/validator/index.ts","./node_modules/@types/jest/node_modules/jest-diff/build/cleanupsemantic.d.ts","./node_modules/@types/jest/node_modules/jest-diff/build/types.d.ts","./node_modules/@types/jest/node_modules/jest-diff/build/difflines.d.ts","./node_modules/@types/jest/node_modules/jest-diff/build/printdiffs.d.ts","./node_modules/@types/jest/node_modules/jest-diff/build/index.d.ts","./node_modules/@types/jest/node_modules/pretty-format/build/types.d.ts","./node_modules/@types/jest/node_modules/pretty-format/build/index.d.ts","./node_modules/@types/jest/index.d.ts","./node_modules/@types/jest/ts3.2/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"12edcd445cb9e33ea27fcc850d7a2d036f6b56f5cdd2db31de03c433f50b1e40","f15e3bec9caeecb5ce979149735e189892d176bdd1596861ff3cd548d45c4e78","14fc7efae8b184b18019a5906c6f6de752823b44ff1acf7924bbdc8877ded21b","fafadaaef1d249d0d9289b3fa2bdd1c24092e25517aadfb3055ab448b3d534b2","8d27e5f73b75340198b2df36f39326f693743e64006bd7b88a925a5f285df628","343127c4427e6beba0b34b9b691494eb4d38c017c298869da90f51cf82a7311d","71a689048584cde03cb508408ae7c3b04ad8f10af887865e8b65c27ed9d91488","d9118ed71b9968fea213b070209081a1b1c378b55ddcd026fb1ae8a7f52c15b7","6ba1631f84ef4507073189c4ada06d6de8bac89375ea3b49e34e49006cc44a3f","afa9397f3aa80897cec3ddec1dd6f7c8741106ce96090f74df790a474b114ed6","be3df36f1bc7117ec8362ac989fd22c1fc5d87cdc96949aa8a6555a7eff43a29","242e6ce3f14c79123c25c35660899ba483f3fdc14ac8fa4a8eee5d03231c6bc3","403723c612eb5754e02e99e0509f13822535b3b559bba19f01cfc7a543919142","ef444c3abed06ad312847e29b4ba4432f7c195314c4bb82a25ce95f95c778a5b","1b61ce81728e5eefe2336faebf4903301c70b9e2ce8f92d79100937fc5ed643a","0cc98b9ae582df76e39330798a3c702781a7759e4d1a26674027416d112d3506","51f0a177bb1de517e82d8e68769802e9e85a5b1fdcae29f077a7113ff22b3163","c83a049ad27df395e3b360799f1b8116530e11ae456b79621738990a7307529d","8cac701edfbda1539b24f6e6084855e367f2c965913576f52d3d3c951c9fc665","bd45acc99cfbfd26ae4630e190c168a5b7f6d3d2bda2ca0504c9bbb5f8feb703","1e74357ff18cb9c56a76abfbbfd04201e26e1a20ff13375df035f36f322d987d","bc85fafac2ca57d1496a35b330821ad543a74e0c0fc00bbc032827b80bd025b4","8cac701edfbda1539b24f6e6084855e367f2c965913576f52d3d3c951c9fc665","4065a077806db5a259ae65d6b332caab57e7b1cd27a500a657787f476d68f7a4","9d95a39bf4f465e5ba62a307f100be1ee496ccc80b6f7c863e122607cc6e08b7","441911b6e8e7fcf03887c10825994852a72c0b6b9a3a3815549a29e1eec7f543","bab5614e96bbb9c99197882fb7711795168d770aa18d6111d1374ae9abab9c46","6c926aff7645b21f57ca29449933c247c400a1868fb3b67750bb5897715dc6cf","4c2862dc136a53538a61e1502087bcddeb99c717f905d21caaf6af022d1a6926","6764fb9e33b6dab0b68b22d9b0b59c25ae0cb08f0eddca5a20222e17f40436c6","b4e08d8ebc41dd2e05832edac609dcd5c559d3f9aaafef004705cd91e4f64234","9a7a3bf5ee086272859e6585cf460f37de1616b9032e12498f2c88ecaf5f4c62","cacdc631002c6657319044b65d82e94bb26c9b2e986dd6760950a664bb6c9a64","e2d1bf73b628f8fe9c7727f9129d3e84ebedb907cf17ef8a4aaa88032d98e5eb","ddb8b1998b17bd879f746efade5971679c238f1a363bcd856748de43b115ad50","89632acccecf5994dcd44925983fb0a8c72b1ea4dc4eff883f67906a7b493751","73159d7e0d93bb02f3170133dceed3ed39805c23f4e8586f421c49bb6b57c714","9670c6e34191d46cc7d4ceaf5c15c707d10a8cd44fc71b64f533619fb84d30c4","72fee83c3f9ff303215dd277769cf2fb47a41e5bcd3c386fabb0e64504d813af","ea6d076c11fb355fa107cf3328add153619c29b7fe7f88261ff362ba9a0adcb0","7cca02310e75af71c7835790bb242c53da9cfc0aa7adba2d541562125046eef2","66edbe1afd7c8c57e2bd0d49bd61af871e2e0c1016edde39437b02a89a355043","486e34129b5869187ec4018031f1732de3f45407cca0f4cf0ca600605ec3ce70","4851b189d71f5563f10ea07b84b56e8c72f08274a18bdcccf8972bb96c6a1965","93ad73aa1702e92a7e357717b7724c320015645de9920f29c7355f752c71c235","ba1148b1e9478d4a3af494474979400779765bb62e2b158167e744b4c6bf9b4b","5dcc9b80f5dacaf8fd88d25f9790b537b5cadd31e6241b9d50f79a20c2d17368","2639b103a0d38c4c7db78b2cfc1cc0f1029d9effaa651376c8726d1877be0ee8","91f4b1a491248789536ad414886b832194855293c2435a92ad7369950b046218","e8d5c97bd9b1641763a334b7db917dc50822b0dc63c7234dc5659a68afba16c3","6d471dce3506baf1cb382e35944b08d9c8dfac76a215b213e13446927ff0f2ea","d6a5a612060fd48ad7a6b40cdbf1380ef9ea704c9b8dd295a005fb484ab0bd1e","3042ab649d46bad82b012452939b6de21f442435b86646922d2de1a470f3c315","9760f28bc51142d437434ae23dbfdfdaf1f0feddc0a10e63851d04e2acf9ee65","be56990eb6ea9196c6c5049285f53863c86909bcbb983e0e76d5021d56d98c88","0b4e89b3cb88954059f8c81285626259426bb5cbaecc889dde5f4ad89d151457","f4a6f8e1d743786291276e4d2eeac20a938b24d06f4fbd72f2366e4795d33742","7fc1ee96d1751a25ff690b58072dced0ce0620f82092eadea237cff631d5928e","d9390915309501d066812fd25f04736d4d20bd74ab7a3d51ace0c08a5afa45b6","eacd5a5e2757d26395c5385450f58fac3e3ba15e86d3a12f4a502bfc76382e04","87bd0b121e507a0e099c54891734ca14c2b4d6f9a7b83fa1d974e36bca5d9c4f","f91e1fa203e6345832d04f32cfccaac4d7f86b69b2099c0f07bf58fabe59a380","df3e0050f73070375bb35f5153ab50ae3f0f5aa14c3da2f39542bc1649422abe","e53d39a26ac710cb0a8f5b7e5618361688f2295c7e9b72b6274f80cd82280bbe","389c516d38c5a031be86a7075558dbff50fc31c0124b9057cfdef059484859c2","f839a0b5527bbe56a4e14feae6bf63509ddde8519fd55d3a10d99cf2356b90bc","7dc61388f16fddb0b25d487589299a27806165c37319fb2820a40c4dc2aed302","f608712eb65ec731ce1500a1c4b246df38b6137a25ffa2f00cddb0f1f9801ac2","2ec3ce8fb225f64367fe930fde4152e6d44f56f175e32536b9323fae7eaaf77d","9ee7bcffdbae6ff9b17fa0557a19dbd92d96dbf926cfe0e443301574fa1751bf","6075292445e581639de77fe75e5fda0a182beb517b038926efb0e962f18b74e3","f41c0789907bf7e00745616b594a949bdea19d9841879a0eeec712783fdd0385","21bb2c359837f9a03412099d7781d71603b347b4bb01941ee5657732d0ff833b","35750532767bb029f1c4100ccc1ba16d22bbfb4dfe5478277c9727f799aafa74","ba2fb95f9f60feb276f5ad43e9a3ed7beb2402d0dcd3411ec9de2d81da59166b","cca3002eedfafeb1502c5811d3814da4aa2cc8a251f83d033fdfeaa97bb55ae1","1ba6d7914654581a36c931b0c7a609d51f08cc03009fac13246db60c15b0b252","f9202ce5529ca05a3772e3e8c607781c0679b091c767f1cce58e0ed3bb402b04","849c5928b2057ca5132d9c8d22c2cf51e7a9fe8304fbcc51ea97c1298f8eeeb4","50cf1e6ccbdf6538cd14a8ab534e74e98096fb1d778eb2f3a4c175d0a8205885","4b4da3bd3050b2460be3a0fffef0113bc494d62847f5cec9279cbebf28f691de","7901af73fbb2de684666ea12034cc414f02156538b1d419f2c8ad62e4897b8b2","051ae3908e879735dab8e8ca57c8cb7ebc369b6e353fdfaaedc814184d768b3b","e8d156f2455a4e1cd9074acd434a63850997442c811aa037b1392dc8f596adef","f7afb417f9bdd7ec34cfe3ead9d9263687a33b5a6650a3c61a77d068231ba52a","0a9e62c12a764cfbd04581cc481e3c5f1ce123996105b0f01a76e92896fb4e4f","c6e64577e4dd615700bca2b8c960df1fb582da3c290a78d73b51521161567fa0","0e4fe0ec3634f674dc941fc66e500aa2cb3c490b85511079a829905a34df734f","57eacc4a67e3aaf7dbc394d3c02064272a88fcc3bc607351c1df27adde13fe8a","3924d290863aea6da44a52560129cc0a2fd5f3fef5a24c30a92427a41a0e0659","ccf6574498dce8eb8736dd390c42d16503161ba233bef23bfc740d24de4de4f1","14e4da53e35c99112cdc820ccf731cdf218394b4639a382eb90d2c8a93aecc50","8cac701edfbda1539b24f6e6084855e367f2c965913576f52d3d3c951c9fc665","419b76ec8d8b26b42ea1fd9d2e8f2157604e7bd12266b50a262480ab4dc9d1d1","9af7b6e418d92fa06bc9ee3692ea0e58b08ed954c47766d6be4ae6e03de6efa2","042cb5697538e357df0bfebf38bc633f30df60989499a8594ba8d426b0c6f043","6eb538011f6a870acfa2f8ed91a44d34df1190df94021d0f22d08700f0a85912","b482397de3227abe139217c0747649f94e169768c4bc3ee770b8fdc491c68cd1","33a0834d333543aa67476b86b77ce315b90ed3f8845f2bb2391cf4bc0763e79d","00d4ea1b1376ba30ebdfe47148ad2b80ccb3bfc7b9ed789a6425730896994823","c5af9c6978612db4b3b40589613015d1bce55ec7c8102bbcc7cfb867f50b5504","c3dc82220e2a526d73046e3de83ee45359ccc79ddf1f455e6abc3e2378e8c2d6","9a2915e9f9d430d7dc6c048b1401878c8c5e8f3bbb68e57d750a644dcb91c6c0","80feb6b0aea538048efe39d31af0dcb308a888bebb42f66834f91d1f7967a364","cd8186fb500652002f543acf02f8068ed784744233bd68a90ba2c35fc606a63a","afe09269f34d822261a547d97f425bb02fd221f4f92cb61a23534fff2b931d87","cd74525e7dc2db3cfdb6f2bfb4f2118afa7bf16c7ffc6e6c156405bd095f5658","0b4bc32128fda7bb0752cf284730dd3a817aae04a3d7f92e3b2d54bd61362fe1","7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","7180c03fd3cb6e22f911ce9ba0f8a7008b1a6ddbe88ccf16a9c8140ef9ac1686","25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","54cb85a47d760da1c13c00add10d26b5118280d44d58e6908d8e89abbd9d7725","3e4825171442666d31c845aeb47fcd34b62e14041bb353ae2b874285d78482aa","c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","a967bfe3ad4e62243eb604bf956101e4c740f5921277c60debaf325c1320bf88","e9775e97ac4877aebf963a0289c81abe76d1ec9a2a7778dbe637e5151f25c5f3","471e1da5a78350bc55ef8cef24eb3aca6174143c281b8b214ca2beda51f5e04a","cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","db3435f3525cd785bf21ec6769bf8da7e8a776be1a99e2e7efb5f244a2ef5fee","c3b170c45fc031db31f782e612adf7314b167e60439d304b49e704010e7bafe5","40383ebef22b943d503c6ce2cb2e060282936b952a01bea5f9f493d5fb487cc7","4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","3a84b7cb891141824bd00ef8a50b6a44596aded4075da937f180c90e362fe5f6","13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","33203609eba548914dc83ddf6cadbc0bcb6e8ef89f6d648ca0908ae887f9fcc5","0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","e53a3c2a9f624d90f24bf4588aacd223e7bec1b9d0d479b68d2f4a9e6011147f","339dc5265ee5ed92e536a93a04c4ebbc2128f45eeec6ed29f379e0085283542c","9f0a92164925aa37d4a5d9dd3e0134cff8177208dba55fd2310cd74beea40ee2","8bfdb79bf1a9d435ec48d9372dc93291161f152c0865b81fc0b2694aedb4578d","2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","d32275be3546f252e3ad33976caf8c5e842c09cb87d468cb40d5f4cf092d1acc","4a0c3504813a3289f7fb1115db13967c8e004aa8e4f8a9021b95285502221bd1",{"version":"5f290ea7efbe9d8431e10df12c0d5672b67988e7c171c2d356749fac70347a55","affectsGlobalScope":true},"39b1a50d543770780b0409a4caacb87f3ff1d510aedfeb7dc06ed44188256f89",{"version":"49c89f8fa09d21c161e6a367448639e032f42d77cc2ec8ab54ecb8fa9a3ad59f","affectsGlobalScope":true},"e4b50850c2a62c7750428e452ee24b167180104d514d5e5c0ca691753365f610","304504c854c47a55ab4a89111a27a2daf8a3614740bd787cc1f2c51e5574239c",{"version":"95f9129a37dcace36e17b061a8484952586ecfe928c9c8ce526de1a2f4aaefa7","affectsGlobalScope":true},"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","0f9061846236850a872cb44097d071631e93c8749a8b16c191fe3c2a48faede4","e46fa644658c2d6e5c85e954ea76b92c97d63f0851d3ccdab8c2a80d5962aaa9","1c611ff373ce1958aafc40b328048ac2540ba5c7f373cf2897e0d9aeaabe90a0","a307d22a0130ac94c1a17fffa6d57ac272deb5838cb966a9420911d259cdf1be","d2e415abf6cb81ac9e2700b4db5ea7be76b997e812285b8e5e1e414eb2750b6e","09d6cebdced6aa1181ac1523c8f22a133f5ed80589678b64051f0602f0518374",{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true},{"version":"7c35691dc3972ff1507d8dd279d833f540973d0917bde22e191cf7a8feaac29f","affectsGlobalScope":true},"62662d7a886e5cfa870685720fd27b763743ca4d2cf29326f75d76606a64eadd","b8c670688bd228d3cc9c169690b09b687188c50ff263a94df63b207701105ad9","d8e16905907111390d5a943816306ae997dfe56476f14142166f8b13ee322eea","8068c911a1c40bc6c5ffc58c625b21d807778f6aa6d63a73e6f04f88bcac5b79","a1dbce56ad5f3a37caafb9033c9d190a199217d673f5fa099c8968d471a2fdaa","c6f77efcc19f51c8759779b6b6ee0d88046c15c15dadac8ffed729a6620daf39",{"version":"089867511b37a534ae71f3d9bc97acc0b925b7f5dbec113f98c4b49224c694eb","affectsGlobalScope":true},"269d0ea3202820c29a32c1f2a357837a4f1918426844f7e7c90af15ec40d1dc1","66432f885e30cf471573de22a5af5eca9ab46b37b122aec98beadf77e9b7df24","323506ce173f7f865f42f493885ee3dacd18db6359ea1141d57676d3781ce10c",{"version":"034e635df3c014df1d6b1110b724ca0c4d2d324b45a84974c7d6931f9cf95ea7","affectsGlobalScope":true},{"version":"87f9456115554cb0f78f098ddbd585096871c19d2d05274c1b1b4ade3151da78","affectsGlobalScope":true},"ea3ab3727cd6c222d94003ecafa30e8550c61eadcdabbf59514aee76e86211a5","d3cdd41693c5ed6bec4f1a1c399d9501372b14bd341bc46eedacf2854c5df5a7","2de7a21c92226fb8abbeed7a0a9bd8aa6d37e4c68a8c7ff7938c644267e9fcc1","6d6070c5c81ba0bfe58988c69e3ba3149fc86421fd383f253aeb071cbf29cd41","da618f0ea09d95c3b51514de43bf97dab008c85bede58aa57cf95e4984c7c957","48a35b181ecf47dbbc0a7ab4b5ba778d91eaa838ba42bf4aaaead42be77ef39a","269929a24b2816343a178008ac9ae9248304d92a8ba8e233055e0ed6dbe6ef71","93452d394fdd1dc551ec62f5042366f011a00d342d36d50793b3529bfc9bd633","5195aeb0de306d1c5ca8033457fbcab5987657112fa6d4971cfeb7644493a369","c5dbf0003bc9f0f643e54cd00a3868d1afe85497fecb56be6f2373dc85102924",{"version":"ce73eb199c4bf96c015f069aac161488ed73ebeaea3d87b6d5aa9a968a7b38d4","affectsGlobalScope":true},{"version":"300f8e9de0b0c3482be3e749462b6ebc3dab8a316801f1da0def94aed0cd2018","affectsGlobalScope":true},"4e228e78c1e9b0a75c70588d59288f63a6258e8b1fe4a67b0c53fe03461421d9","962f105729d5b888c8b70e193f6020ee92c6c8144c827de40f80d65dd188ad7f","ac74e2b754fba690036f8221d978f6debb867462b87af254f24e924b677395d0","80858f6de9af22e53aff221fe3590215ea544c2aeb2cc60cf8e08a9c785c8fef",{"version":"068b8ee5c2cd90d7a50f2efadbbe353cb10196a41189a48bf4b2a867363012b4","affectsGlobalScope":true},{"version":"340659b96782f5813aad6c1f89ea1b83b2f3fa993115c7b30366375d9bae5a4e","affectsGlobalScope":true},"6f44a190351ab5e1811abebe007cf60518044772ccc08244f9f241706afa767f","fecdf44bec4ee9c5188e5f2f58c292c9689c02520900dceaaa6e76594de6da90","cf45d0510b661f1da461479851ff902f188edb111777c37055eff12fa986a23a",{"version":"895ca532c15c77cbb6a871af1870b57bcd0ca4f38a1bd69669dd0e95bb58565a","affectsGlobalScope":true},"f2b9440f98d6f94c8105883a2b65aee2fce0248f71f41beafd0a80636f3a565d",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"b510d0a18e3db42ac9765d26711083ec1e8b4e21caaca6dc4d25ae6e8623f447","1fa9d0e577f30689a1a15eeb5bd9234aaf3a5435a66a7664ebb21584b1ffe9ce","b93eeaa29af602abc563f6dc32a31acd9aeffbd55ff4569b7088919618c626b2","6e87cc8fcbc2ab666e3a1e7453361830317ed24e018701014101ff729f721ef3","f756193a0a88ab13fa156ef16a1da22c75cd6105ab8f8e7d6faf1c431be6bad1","5e05c8ebebb72d6f2c99da500f32ff95818fd7812b3205e76bbcbcd8ffc1762c","e6418eefa8cd23463c552e4f4616c8c408b7342b4cb2dcf8dfd887f88bef9bc3","fc7d109693f846e73c620628c1a84dd3c423f1f4949abfe17275351a62abd6f2","be96ff3d2a80414c9d4dffc48aff76a4e4dd0d7fcb3512787c171fd65f9c1bca","9953349796279be4ac3ac25ddae915254c44ead32db891c7e5460f6c1f933579","b0916259cd69aaac474c7e4dfbbd709dd77495040017ecb3a17f00712c51791a","30707b1ca9645c595199de2e8a14c20730857923e6707b743886de5e634ab2f8","8276eebafa5980dbd05b82c18719859e50123c4eb8226d0e1ac768157bac531b","56f79dcd474eef8028cfc3ce517c3808c76b363e67bfc0e905d90aed092640f8","cf8092295a3074e953cd2c6e692af6f3467f1e40d262ece02854f06d3b4afb31","00f8fc5d5f27e2ead5734e3f58a2548f16c2e9ac5cdb96f71794859674a907f7","e90c2bd182fb1a1a64b690a6f1a0d49058edcd8467a2354960f89aa87774f3c5","867472edc1aa1bfd1b063dbbabb97a29f6abab171330b0122ad1656531954f4b","5c82488594ec942923705b93a1e87bf48064486afd51f8b7697f8bdd87b33e7f","d61ebfdbabb80997daa32b0b8af8e38264f8f4e8a8c1668fc9ade91c607507b1","342bd3b0ed123072c6fd6f5d5fe937e9aa3f553e2b99347334b6c186de0f1757","f85a1027e01d4e35eab2679cbc20c80351a0c8f694ac38114e19653a2473274e","f9fd946925b7c2ac04f573e1250274a60c05aa9296e19609f101d5111ed0ca8f","87b54ad27a6e6f0f0bee50caf18dd15315e67171dd90480feb43ef0b20d5387d","ec54e6b49ba380b7c75a344ade88552acd4ab7d35338ba4cba5b91328d23b065","1ed817ac1f510faa6357b0a1214c736d640fa7fa31ddfd3ed45a517b87b18aa9","d2ae92fc65b6db3a7a77df57dee945503939005bf287c76fa4d2dc99182f3d8b","50e76bdcb42cc03d38676df7fedaa44cd305399871842b8b6a55aecb9acfa734","d8b61d1d409f49fa11c812224805e93a136cc125bdcb152c76f3d05b5f60acd6","2ce67826b99705125d2e6ae727b329f9d52d050707fd5601aa1596665eb179be","fde294a03529960d1be4a5b83b9f907e42c3ce6bd8ecd8c9f1c54b07750a1861","617b1734c1b008b24f241ad81a191e7e3d386357b36f702514c37b58fea5f8d9","ae427e227447b9ca6b5062c76cbf82da9d890bcec70b5da2e146cc60820d99ce","8bee9f3ef553540ec89d6dd3218d8ace5f97907f24b587a54765343c129e30f3","9597b612982fb179cef21127ff29ec8f3563a2116396e22a3222dfd0bc12097a","8609cdc243437ed1d22677a3612a1abc39a94374f149207492c67513daf597db","ad58fab926d11a5308cd4906c9bc1ffa83bbfb6a69581d1b78c20e7ba72982bd","79100ef62a6aefca99e96651119e9bd7620b5eea2bc50b8cb3bd1291317f1e24","c6dcbd5ea7dc92ca6c9670ac5bce4c4a0eb17581ef806d6392e012934df41c5b","974f45848283c166a28ec625ae917491e62421ca46fd369f187b7cae232372bd","5f5bbf3fa89cf2cf093a4c7c0788d9ef3b55c2bd51533c39f693ab81eb3f2b5e","d607f4556c0d2a7e546f2c371040f921cee4406aab43dede2d27420823efa049","075e1c3ed98f70f6b02b1fafa4cd8d40533435a9e0e1d4904e2b9889d90eb92d","c946f5534c68474d6c9fb2098c7aeebf2993c9436bac4b123c51a9039323dc95","2d204244acf17de51926648133ac781843aef6946adeb7dab6fdbb8464def402","bbafd97117733dd4f9c4c08d34e30f2da2cd2e5f96246d0d84fcc4445366a99e","524d685b11aceba6b56456a1af3374bd9b2d0a4a0d20343b3192486fb6731c08","75da46d5bce80cadc89e6add493fa765d2f6ba9370c16fd9b8ed5e578a696074","2c8e55457aaf4902941dfdba4061935922e8ee6e120539c9801cd7b400fae050","82d4261e74ab574ad840a2aa04db368beb3a1cad31cfbd5d11c98b366fe52dc3","c32a384c7d2e8df2195c3b90b085d35ed549e1ebbe0a00e7c0eef45946e1cc57","6f8e0302bbee4f22e5aaadd4e24ab48d582c9825c912e0b54913aa968b50b62b","49dfdf7fdefe5f4feb38c27b1ca2fec6d520c14e564299e9cc1e7031a3a986d7","5354dded2c90d7b89a2563069398ff48f857c5c037b9e10b908145f1e040f6b4","ec08100be7c386d864a0b1cd3c3b635c48a4b9aa1cf42e428c5a92ac03086317","ad6265a20df35a7dc8b2e8bed5bfca55282354ac1a9abe6c33a1d20c83f2039f","1bab3083e7b44a8de9057d7746c0408383d6fd1d2db4429fffb19aedc6ee15de","dbd4e3c1c81a350659f3ba09d931a953c37f6ea39d9e5880decfb22130fbbf70","dda4a11a03a313918d7dc8031e19a4460b0cd7b6eeeb03ded31b53de1ec58a1b","d9073e5cceff020600ceb1d43e1df68fcaee78d21ab2dd79e19746a68c9064c6","df30fdfe418b2ae60735252593e0a4425979c2f5b693dae133769c7d3e377e29","c8d113d442ce7d757244e9ca2616396c5d9bd5076d3f14c66851d1561d34b943","c9c5b2f1f70a643a1b2f569074cd15fb3476c56e77cde1fef7be5b84879123c3","6d37944cc0a56ea0751a75c29f6faed95f59d78a11ca9e03450d2d519d43688d","fd7898202458496fd2303f05a7a344da68e2fc8f1bb28691027ee12e7d641f6b","00ee7035e7b76c92f3fe7538d453a22dfa3ff5a57d3208a6db903df35a6fba54","752882874a250f073779b92a7a9861a094e7bc98a1d98e30ecc05a9281d0dcb1","e5305ad2875c69654fc4cda0243fa499d724e54dbc1c758610eafb4146a297d9","35d80ed0c468d87b01f8bfbbade878f63146e22b92095af924659cb94d42c24a","4d313c8b1d96af71af054f8f2ea2b8001b2d21d02550c3c37404f32159eabc92","12aa184a07801df1fc19510aacc72a60dcc415541e8215c37b2270ccad5fe819","1d2ee030f65c0cccf2a251c9c1bef7704ba0c079401d3026917cce6a2e10e748","816c148b3d58779d62de10a2842916cb15a80575b22deb889890dcba5ad8bdaf","95346b655ee9df7d62be2eceab88b295a46330e8655b4f238756ea9a87a3ee9f","0aba500b66eafb0cb8ace91a292548452f52d0bc647b328aeccfb9a593ec88c2","d7c01a61b7335905b400cf3952e80e5033b6d2021b8caf1b5790cd8230c5536e","d317d086661882128371850bcb1d479b87fd8a76636484c7119590e413a6f283","8dab7b4d302ee0e47549ab400acc425aba35340401a1ded308ee0f0b2f23f764","c28987a51e254e93521a3e77f06efa15dc8bf57de0bebf28aef4c456b50aad60","c6a96806d2c922cdcb3931e42c3ecaebe7822b31f14003c2dd3fe9a4d9c7a9db","ff81189691bfbb7f19ccb5b532526d090eb04648658a9d9d6c40a95da2d9a7e5","d1162caee9b95946113bcf1a44adbe53472fb7360005e54204f29adca53b7dca","cb80ddd32f843f7bb0936dda06fb415d05d8dba9ad4e41cfd4a2342b2a2d0cf3","b98ed367104010149b20ae5fa2428307f3f131195232dec13eea8976c74ccba5","f81f535c51cf622a29e7e63e132a717ebe8d8e9f67e024324c2fd1b635ca8b48","ba1f8bfcf67a46c1839a232ed1dc0c17f636b02dd594dd1f1402059a1d3ba5ae","233f2de1a6341e6de3b9c27825da6098f4e5d27eb89b09bd97399d64f1ec5fef","9bf115ff19832e75f39c112dd4fc74a806883f01e5e6d1e5c14934800685da13","de7c04de8764667ac8981c3067b5a68f37db3d53b450c819f3368fb22be9af7b","0f33288673df76c6aadf0e30f7e8dfd4f90ef598e79ce39292761ab015b74319","fe0fc883e4c63584434e8b04c53cda53c54e2ddab725bb3b25a73d26712f6b51","9bf115ff19832e75f39c112dd4fc74a806883f01e5e6d1e5c14934800685da13","6bdbe574442ad9cc81e2e0d150036e886d3711f48e7734fe7ecb6e7dfe1cf988","de1d812aed36782ae60228c956b43ca81776ef501b5eb8094a9feca27818bd41","d8cac0978bfb1df1f260af8193721d974959aece2b3ae81e8e9aa2da3d4e3e7c","6f990bd8d1f3e359d43624ceb4ff64f19708601caa8bf3f66430e288bdd7219c","1d5886e478b132783298b3468231f244ffa6f824dcdd6a87e544bd77309407ed","b28d52c19c31f6ded9652d1eb2c3dc0afb3142cc2d65eb459b72aa7f234a5bfa","32f3e4afb34dee45f8ddfcf7b85079b68856e6d64269cfdbe10a68a17cfe2ba7","c9a7303254c1ef3342bbbad12cc913f4ea8a7d089f0cc712f73d41dd37a5daf4","99ff39306126f9fc881132b119e9570c29f01237a68476b6ad3abf5a89bcbb6e","db1a3d54d77968ab89ec979dfe00a2703d5d1f495694893ac1b1adc5fb14d60e","95346b655ee9df7d62be2eceab88b295a46330e8655b4f238756ea9a87a3ee9f","f38c2b8b607f48d22150fd3ba9a97099cbffdd954765dfa2da7c4f96a7f5826f","f5168f0ed78b855171907b46f3c84b4c8335a5217c25503f18db2e4ee09fc3d1","9429fcc7407506e17474ac379674d94ce4710813b36d39f2101f5faff0c503fa","7e9df0603f4d0e92a7409c560176a4f0e878d5c0c216dbfd33d862662bf7507d","6700f4aa563bd1a5a810a302d6bb8f0dff6df7a035f9175d6565fad667c9a13e","4d6a6327bcfe8ec2dc33667ba54fc96684e77f050d54db84968a69ac728bf169","2146cc86da465e20905bf6257b4009387209f7899c5d1391a7df30dd385438f9","047a65ebbd8e4fb878346fd430f27a06a4fc4086412789af77bb4e4f03bf324c","10191fec36de17b0f540054c49f35f383cfd15c184105a6bbe55e2e4937f089a","a0d9a635a1e3a841a1f5c2f82b115abc412067ea83251e4f05d9818cea6dcf5e","d252263eaa47969f48265a7aeb5f8dd773d3ed2e56380c25d40cddfcecf2bb87","927d526de973b2b6a2f018df0dfa38a305ddce62984995b89e23b34532fbdd26","c56299490d810eb27502dbdda31c0e133a1d44663d53bc24719d8d7e32c31602","6728d4f7e1ec321d1664c3fc248a64ec4b26d99a0c518465d58db6b2783b8a4d","645887f7061288d5e9f9166fe883d04f9c69bdbf41661ac7dbe758f21ab523e6","888ae1253e01d53023aaf8cedb3dd6bc70993913921548e8a130b6574a650f95","49ecfc82833cce5065bf13363e7049baa284df8c7d4f141759d6910fc00d31cc","60d3a00bbae9a22ff2ac1d9486fe781330e85e521cdeabe12385bb6f2781142e","c5ba3188342bffb6f6ff0bef49e242e1544720d3521c99899f11cc84cb02f371","8541096ac668ba3e84a2f98e71cb1ce9ea1e0cdccd78919128b80679277b8d89","36c0d7a6164b2669a97866c576dbf455c7f56f16220130e5e72c80153fc6fafa","9946ecbcb7bdd1ef04b09e9604b731aa2eabfa702c475884bf5d23c9ef4253c9","2bc18669b4bb27df79b4dc3f2ee3773e84e8bcf87a28dc8cda079bf9793c2968","ed7a56eeadd3289066acabdb27acf93f05f1ca290875a7c2059e552edeb5bd40","9d55eb45ec8f050c9d07fb18979bf9727d64760cd6398bd97337d7003503de5b","e3f7921c4c8544270ea397cee5d090f3a912af18f746aceb6144f28a3437d864","48b0f7ab0460e5abea201abcdf3010e345dec033400f77b8671ce9dae6fb9e7d","97f606d50bfc762530f9273c4113e4b4065798b6c0ddada305cfcea39b43eb43","fcc85bab948ff38aceda0f7201134a38791359b412e4cad3f3794470f0add8ac","b5d5b07d95ed461a2bac70c5e34f7f3b2fd8c0c7094064d959493e730cc1acbb","d317d086661882128371850bcb1d479b87fd8a76636484c7119590e413a6f283","0cdb5f0aa206e074fefeb9241d731d6b7a960f5e68ea7776fc2956258cfca6f4","c1dbe916c7fe99e1832998f438c666f4c513b36409d8915aabb04524c62f4ca4","6728d4f7e1ec321d1664c3fc248a64ec4b26d99a0c518465d58db6b2783b8a4d","4bf3f491adf76daa27f10bafaf4c4ff82ba2243e9eef2e44a549e880af59476c",{"version":"409cf8770fbb9f099124e9ca744282ebfd85df2fd3650ae05c4ee3d03af66714","affectsGlobalScope":true},"0726d18ac9cb69b989c60a9804b7b0f628b5bc95e5e8878a4cc5f5e7dad6ee65","54160aaec4f72e2045e7341301c096344b9e5162a1e48333a531117af5938713","3f0d8705992ebf25221e0d3f72d496bbcebacb47c2b6ee90f4de66d760ee9152","af628c57e9826fbe767ae6afbffa7b197405a8c53ba6197bb32e806d35c1ca8f","76b87f8b5d13712d3fc53a231be1664c4071186120624f2ae1b5bf3db6c7b502","2c7742afcffed27fef8e373c7939f20b64b8783d37e737bba2b3e0d70899ee2c","a9cdd476c9e36aa3bf4212f4337254f2f2676506aabb6f7d8f6db50490d25c33","52c0780e990d8d2ef666d618a303bca67a5e968dbaa4e4eaaad4e415a7217fd1","80a16135e14ed2540f9687f4fb5daee3a4249126272a5a922a5a21ee3b7048c3","7f7aa3e938180da966143e16c4686c7eb2ab8d0f762f038648e1cc6577e1d52e","6e9413bf8a3ce70c3b7db79a29de97281576b731de079d0853f1de499304fbb3","f6aef032da1a16fa155757a6ee8a79c749e579a378d9ba54256d1cefc753d475","5f9c212f98b4df7d638dd9a8125c5e828acbf9710586cd8027e41e4e55819a37","2c574466b0d7ded0bfedaea3660d8f008cefa06db748d79274b4aaea46564763","caa881dd5d50ad64aab709ecf06219874cbc23045e46630bdcdc7c4c32892965","ae07438e2c832c3fb33b98bf3894e460fe71a590b65e6dc55d5a5e1a32062066","7e122724e79d97fc601b9517da07dacf9e8162f5d78ad5740b349e2065ded611","3c9c80b328558dde371257f1dec7ee2f26004c3497b3e302b94fc415b01c0190","3455a4c5f5feefa1f7062e4d8b00837e1edf7922b10cb50769b4ed3c5e37437f","74fd4b09963df6d2a1c94b653199c48d5a578164517a7ae27ff86771662f6764","6a6752f432019855ae0c882f1dd5b6ca11d4da35f2279e7efaa98caec41588af","569c4482357560c490a62d200409d3bedf92efa43bd2e2d728be1daa6d4140ab","7a50f76e773ead4a34b5308879130da83192040ef6dafc5f18570ff6ad2bda61","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","758e92a92871b11a9aede1787106be4764ae6a32f6c76bb29f072bfa28d9f69a","5c291d7429bff327ce5502221f1d2fea64277760793324e7419892e3af29dd63","126eb12a1d90e542ab5c67389bf04063eb0a6102450903a4e9a660fb1b1d2abe","a513bf738f28c66621a4c2c577d72f37b74175df5c645dc6df6befdd6b090044","6d575187149a38a8d06d986e6d8111aad796785dd57847672f01ba07987c8e3d","24a1a5007809de3b55b5f86ae8dac8a71f262d508595a04d8de76f692cd127b0","8e7ed96554279194f78c20d966ed1517aaa27dcfb60d23e5d36a51e07daeb823","63db3f21f835af9dfa90829a54ba11a5f34c9fb9f73a235d603d5705c126f7bb","5a0e97850ab7f500be1fae2c73135e8722011dbe325352405da40e5694c2105a","bbb47b581e8e5495c1754b066202d24f762fd7fccfe1fcc443aec07c992cc229","0940279b6cdfb51032bd6bb0b02c3a4ac2b0a73e380d6c48bf8b503d0de08350","06ae8b7ddac3aff63085a4c6384557b36ef61075aa6c5173fdf3834b19a702d6","b5b49a989ba1e33c2d84afe92eb47029b57df7c14a226468ca0b34c65f995a91","95eb6d75484e2d939a90fde29d6f8d44f7b60e95383b0b2fbe509312b96a5927","7acba69bb1e26caff186d177f681eab25b4b10284c2d19d6368d48f999f1857f","c523378d3aa12273db8ccda1879bc645b76161b32bde7060c7381af113879312","28f5badd8f49040bbb6c8baacd36d8657b0548081f3e25a24aa304a85cbe547a","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","b0e7c0714d8e1b39338bb765751adcec183011cd42f9010a502d3588d831c39e","1e07ee1e221ac235ec40d279772b1bf8a0f6bb3b35d4a48120a7145a8dd1a3ba","97d5e2c55b36bc75322408bef63ccd7d212600cdd211e1cfb064dd2d2a0a745e","1257ee54981d320653568ebc2bd84cf1ef6ccd42c6fb301a76b1faf87a54dbd5","9ab0a0c34faa1a3dd97f2f3350be4ecf195d0e8a41b92e534f6d9c910557a2e6","45d8db9ee4ddbc94861cf9192b30305ba7d72aea6a593961b17e7152c5916bd0","f96f8df3e47e27cab8159e91a4f35cab83ba8acc751731c64c23437f60a2bc83","3e14fb4377f6095e39743fb478c748cd6b75db63d348a0d6a07a9d7bf6fef7c9","5da94e87e7ddce31c028d6b1211c5c4e9b5b82e5a4b5caeb6cf7c5d071d6e0f3","10b4561a2288e844755c8808a59bef1430e89de94408b7f58af5d1132ed0cb14","63424f371877f8fe8e13c3f10f37a46604ec6a14293c6ca7ca8ff6d2f1caf60b","d51c97c7be9951d58cb068411a1bdc101b5e2c78639a2143c729d3dfdfd104b0","ba4185925d04d42d9ac02da482306a01ba410888a761cbeb0aabbb56ad96cf3d","63dad9d61ac39957c4c51ddab5cc2d2366ec92345ee9d6dbd3c279f2559d65d1","a886d9f1dcfb10a97ef7aaa076028a2579428d16f06f874a2a6ab4508d529c72","5180a1a33602d0eb1ff18a8370eab0bc98f81060f4c64dcbbfab9d8db0075379","ab50c67f84ddee799c4bae585f75380a6dade4051e3df567378d5209d55d9dd4","c88d922a5f4dbed0c9f9327c8975d94dff11e499654ca071fda0b48d5c0963a1","7e122724e79d97fc601b9517da07dacf9e8162f5d78ad5740b349e2065ded611","3c9c80b328558dde371257f1dec7ee2f26004c3497b3e302b94fc415b01c0190","3455a4c5f5feefa1f7062e4d8b00837e1edf7922b10cb50769b4ed3c5e37437f","b6f2a56a96124f9d919e98532b4d0299d1c0798881bc30da196845d4f0d9a374","6a6752f432019855ae0c882f1dd5b6ca11d4da35f2279e7efaa98caec41588af","f09cda5ae8a71b35dc49d2495ecd42d7fa30f73fa6d9ac4a22b05c8d96b30d4a","a4c07340daf98bb36410874a47a9c6f8de19fa54b015505f173bffb802fd110a","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","4458568824d3b6282ba265e09a831812bfa152b8924d7856367eb6e3d41187c8","c6a9669d9599e3e5d40c8ef637963c5fa3e3b23620561062c0567da2f3661b5e","6aec4f31e84d0fb676472c7b4927e4d1588b2e12b4b699f4019be4626219ab90","520a60fff6b561bab033dc0a3a9da06d06c00a6c5b745ba2a08df3892210c77b","bd326d6cb825cce0278e2424d777c5bc6af9843858fddf8ca112a6ffd766eb1d","164febfe1b9866698fae4d8d6e988fd5aa4a1378d2d1a51f6d43bcb62288380a","eee88094eb6d6916ee7cb37de791849759d137868a8419cda0eb7385a1e78e19","b936279c5c2ba68e045625a7d7b694fc56d117fa5ebeeac6248f5cedead12935","0ad081bf80e6a824011077cb5fe70fd91da24e805278e30c319b2bda5491c7c5","976f1274b025d67f597a315b294026787a92f33c2b427394c783c7ca3d281d3d","20d5b5c441ed3aa6996064dc968b13c134cb673fbe457e0c106b559ec460b031","fb0f1b9c9f7eb3c159da7f7841fee3fd5fc8e4a48a56e3f6545832d954d050a5","351dd117196181ac288b4f226dd833d89a6bb9bd63b91825270a59b774a26b19","aff85c8f80899d28c97e4fe077a3ce04973d69018d8170df4dc80e90cdde47ac","6698749a22d20fb2b63db22ba345985181e4412a9a252eb0cf615b46b0a63a47","1e07ee1e221ac235ec40d279772b1bf8a0f6bb3b35d4a48120a7145a8dd1a3ba","97d5e2c55b36bc75322408bef63ccd7d212600cdd211e1cfb064dd2d2a0a745e","9a852470e57b447934073e6850c9e1228e439afb21b1d6b7799b50a73c44d185","b349e7d33988cf67db0050e93fed97fa2c54742d0fe242f7f88750cbf8246389","e35e68e401aec5e7d1445a2d55d40e63bba157cda32922c5d74449c632bb0917","d0369282c3799e53bcf842ea8993fd2f093cb1b3977d0529f1fa59f65e1883c5","dee117798c2f605e579147a29bd9e81d02314778eaaf4c13a3368f0cc3d1fd96","d2338b21bd93e2d2457e8665f38dea8ee864ce2898ad7e298ff379c3d4436fd3","e801dfa0d06f0537efbad388d1ac44c1106c836ece7f8cb38bd887a76736e02e","8e8952d786ed5922780c1347de4a8f7092e39fbb9fb6e87b7309af5330ba3015","ee1ea0634307b1b58ed709c0313f46401bbb1dd02216cae02873765e49751f31","a03b5d544ccc8dc74ae25b302b8233ca5e6595733cc25f7fcfaffb18648c897b","729d4c3655e3ec1bf17bec277207c649fad5224d257ef3318ec64dec580b8c2b","e1541484bfa74024daf9459ef86dcaf8059f4a4e4d8cb5f16b76cacde74fc9b3","85c710e65cab03e02ea37bdd1e35a2937467efd0141c9cfcec3f099cc450d192","2d0cef1e8f2d8d9f25cf1813dd3d796877916345449fbc58bbb6038104d49989","d0bd1edeab62499879485f88364c171dfa863177c5f721b794727a038cf7e082","63db3f21f835af9dfa90829a54ba11a5f34c9fb9f73a235d603d5705c126f7bb","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","70f53130d4dcf2f25b58eba7bb7ab4dd80994ad7dab46b37e60cd13a70761fd4","4ea7910220947cbf3b925244bc43719cbd7ff470c814917e77670cc905463cf7","05fe211c121ba4ca76a49c4fa863faf43e69d0fa53b66367915fe021ea4b8ddb","d9816c2c5f3f78a289b2951660f9d79c86079ee37100f1281301505649ad9a5e","2d0cef1e8f2d8d9f25cf1813dd3d796877916345449fbc58bbb6038104d49989","dcfa53654f2ce8e01d500a48e0acbbd42fe748158d54f3fa06ab984a6361e7d1","3b74c8ed5f08d02f603f456f981620450c500041bb60d95cb4febe7332c715ea","2867b1d0288b35971e19bd5781416c84541f94318c62d0e01640f6946b8a2349","fb14e297b3b96cbf91192454ca3d932b3c4948f8a249119477f4c61e5f3937c3","2d638098e696b3ab0eb0ef8380402f28daca39e93ec575265893dde2e3fcc621","f3b421dbb872c1f4b4b1bbb80706b884a9b02c2abf0026f49f4af1f48331a0a1","e1541484bfa74024daf9459ef86dcaf8059f4a4e4d8cb5f16b76cacde74fc9b3","be2e726b92ffbdffa59ad5c49c4667eb27c6df13f743b344d3c5b33f311ec528","56c720402e0f054fff5cb3c6a657bc719a62efd2eebc643a7d44fb4993c2c55b","cdae63498e21c910526ce1566d1c48d697e90ed2c457cf612c0e8256d46d80d8","7b5502da9dd6c6ad29d484d32daf031df751f3e1d484f1ea01fe8e8791a0d99f","b7219b5a0affa34d911db9d396747129838db63d0ef2818cf87e2b0b740221e9","00d4f8e4ae40b13e3c43790cf1071fd060bde73648bcd1fbb9b9c6400a54f94f","d66099c65b88075e369fcb8b91a3cbfea0cac5ad76e0e3c6e927a3f2a2eef25a","b48775572ed3798c38130605cc5ce92bb3df3aba6dcd6a3e2f2d8d789ca07a3f","4b679a192cabfb0e8a815b68ec8cf1109dc52695b571f17a5ecffbcd4ad0a59f","c24f4aa44e5d32f803925e434a030d2a68574fbf304347de0d80c98532aa1a8b","a6ce42a372e5e7f9bebdb5e7470f8093be326a3b892e3afbce82f7f06b16439d","78ef0198c323d0f7b16f993ada3459f0e7e20567e7f56fe0c5ee78f31cb0840c","01dea450d742aa55ce9b8ab8877bbda8eb73bf88609e440cc34f6f59f35080db","5ec614ed82e045de15417a47e2568be5310d43d4764ee43d295ea38caafbfd17","b788ef070e70003842cbd03c3e04f87d46b67a47b71e9e7d8713fd8c58c5f5ec","583d365dc19f813f1e2767771e844c7c4ea9ab1a01e85e0119f2e083488379c2","b82fc3869c625b828dd3feac4b5ebf335ed007d586dc16176602db73bc4e7c65","05e30605274c26f405c411eebed776fa2102418c05beec885e5c9bd0fa716f32","58c7f7820dc027a539b0437be7e1f8bdf663f91fbc9e861d80bb9368a38d4a94","f8e6a8fa14ad7cfab128f9922505b57fb4fbd82828047c46d7137c066c9bff21","57ab70cf1fcc245d66577501f0846fae49a953c92f004e7927e5ea7bb57c6a68","bbc49fd9dc6ee162ba3d270c834398e0c1d44e657ac4edfa55ac837902b7e0da","6993f360de4984b6743764fad3b88246d5dc6cfa45567783fc23833ad4e50c13","f11eb1fb4e569b293a7cae9e7cdae57e13efc12b0e4510e927868c93ec055e82","715682cddbefe50e27e5e7896acf4af0ffc48f9e18f64b0a0c2f8041e3ea869b","6d2f5a67bfe2034aa77b38f10977a57e762fd64e53c14372bcc5f1d3175ca322","4ff4add7b8cf26df217f2c883292778205847aefb0fd2aee64f5a229d0ffd399","33859aa36b264dd91bef77c279a5a0d259c6b63684d0c6ad538e515c69a489ec","33fa69f400b34c83e541dd5f4474f1c6fb2788614a1790c6c7b346b5c7eaa7dd","be213d7cbc3e5982b22df412cf223c2ac9d841c75014eae4c263761cd9d5e4c0","66451f9540fdf68a5fd93898257ccd7428cf7e49029f2e71b8ce70c8d927b87a","8a051690018330af516fd9ea42b460d603f0839f44d3946ebb4b551fe3bc7703","301fb04ef91ae1340bec1ebc3acdd223861c887a4a1127303d8eef7638b2d893","06236dfec90a14b0c3db8249831069ea3f90b004d73d496a559a4466e5a344a4","fc26991e51514bfc82e0f20c25132268b1d41e8928552dbaed7cc6f3d08fc3ac","5d82bb58dec5014c02aaeb3da465d34f4b7d5c724afea07559e3dfca6d8da5bc","44448f58f4d731dc28a02b5987ab6f20b9f77ad407dcf57b68c853fe52195cd7","b2818e8d05d6e6ad0f1899abf90a70309240a15153ea4b8d5e0c151e117b7338","1c708c15bb96473ce8ec2a946bd024ecded341169a0b84846931f979172244ba","ba1b8e276abe5519e0ba134fd0afba6668ba26d8d5a1fb359d88aff6357457c2","dc187f457333356ddc1ab8ec7833cd836f85e0bbcade61290dc55116244867cb","25525e173de74143042e824eaa786fa18c6b19e9dafb64da71a5faacc5bd2a5c","7a3d649f2de01db4b316cf4a0ce5d96832ee83641f1dc84d3e9981accf29c3a1","26e4260ee185d4af23484d8c11ef422807fb8f51d33aa68d83fab72eb568f228","c4d52d78e3fb4f66735d81663e351cf56037270ed7d00a9b787e35c1fc7183ce","864a5505d0e9db2e1837dce8d8aae8b7eeaa5450754d8a1967bf2843124cc262","2d045f00292ac7a14ead30d1f83269f1f0ad3e75d1f8e5a245ab87159523cf98","54bcb32ab0c7c72b61becd622499a0ae1c309af381801a30878667e21cba85bb","20666518864143f162a9a43249db66ca1d142e445e2d363d5650a524a399b992","28439c9ebd31185ae3353dd8524115eaf595375cd94ca157eefcf1280920436a","84344d56f84577d4ac1d0d59749bb2fde14c0fb460d0bfb04e57c023748c48a6","66738976a7aa2d5fb2770a1b689f8bc643af958f836b7bc08e412d4092de3ab9","35a0eac48984d20f6da39947cf81cd71e0818feefc03dcb28b4ac7b87a636cfd","f6c226d8222108b3485eb0745e8b0ee48b0b901952660db20e983741e8852654","93c3b758c4dc64ea499c9416b1ed0e69725133644b299b86c5435e375d823c75","4e85f443714cff4858fdaffed31052492fdd03ff7883b22ed938fc0e34b48093","0146912d3cad82e53f779a0b7663f181824bba60e32715adb0e9bd02c560b8c6","b515457bebb2ad795d748d1c30d9d093a1364946379baf1fbb6f83fd17523ed5","220783c7ca903c6ce296b210fae5d7e5c5cc1942c5a469b23d537f0fbd37eb18","0974c67cf3e2d539d0046c84a5e816e235b81c8516b242ece2ed1bdbb5dbd3d6","b4186237e7787a397b6c5ae64e155e70ac2a43fdd13ff24dfb6c1e3d2f930570","2647784fffa95a08af418c179b7b75cf1d20c3d32ed71418f0a13259bf505c54","0480102d1a385b96c05316b10de45c3958512bb9e834dbecbbde9cc9c0b22db3","eea44cfed69c9b38cc6366bd149a5cfa186776ca2a9fb87a3746e33b7e4f5e74","7f375e5ef1deb2c2357cba319b51a8872063d093cab750675ac2eb1cef77bee9","b7f06aec971823244f909996a30ef2bbeae69a31c40b0b208d0dfd86a8c16d4f","0421510c9570dfae34b3911e1691f606811818df00354df7abd028cee454979f","c61d8cc814035424b5d55348b6aede37074151c408de931ac3f63c7b6f761efb","527a65e1d2963e96f600bb776bc788f5c7400947ada8677917066e66548fba44","8cd160eebcc1bfec9b1bb7d6335ec566fe280edda08a3991ae8a94b30ff2e99a","3be775feb34b951705e634e1702f0a886a601135c67c4dcf6e19170a79a6788a","375f9e40fd365284c5db8fb661fc1d8bde9b33fd89fed25db1a263e0a181ffd8","cdeea24d217b06f597246c215af7c8488a8cc963b26aeab3f30fdbc04c3638c7","32684eca94b76799df29ff777e9425062456489d4d80405f4ac5d769ac1dbb7d","b708fc2911456eb3065f831c8e152a24ec42e8b2ec260b1772e6976039616ef0","16739082244f59e0856fae2410fdc9d38eddce8ad6424dc5d4223ca59e4a7ec2","189ba8368e43627d18bb88c99de5982ac347e5911f5d89851a3c43f8b6e14569","4f10472206bfa7bed6ccad0775423dfb19daff28b7ac32ace3b72d3721596eef","7984964df543f9092f501c17ddf6e705a41b3fcfa17708716e0dfdeaf4b15087","092f926dc9f141977dc163cb0a4bd8df28d1def1a3091f30af42ea702db98fc1","045d1a655be163fb6b3ad3f268bc01be46e7ad6082b14d1f4ad4a2e0bbc05886","b62a43b6a6d9e59f44e1aa1e999bda95e1d3eb54e240e430f93d3d9c7570433d","483de91ef8923b2af8373c72008a783cb4f2a7de89a505a6009d54ad1ace9ad2","c73735e04d34008da466e1f9f9dfb45db7bf088dbf9cfa9151b543fe2a0f3bf6","8f75cde2e414a7d71c08c6b38c9763d454cef8a7ace0ad36ac0f3513c549a022","d4989e6cce27cd46614f8aa6dadbefb44a2928501c1c87f324c9ed7f0cdf097f","7d7d02339c1e7525c17e4a8c187d27277720bd4173efcecf76b690119429e8b1","e2ded67844df7a5c97362f9c53886cc8f428cbe250cff9b56b4deae09e4e4a3f","abe4c8a08d87b346f0365eeb644074de18f30ccc9b848d8974fe0ecdf40bc4ab","14333413f837f052b9d02d099640d551003bc0242151a620930297f68c989ad2","6aada0516b747e127dbca7a0a145eef342b8ae4929eb315e00c835c733e4ca94","b7f5a08a542459965e03364a10ce321d28eb5dc96c7cef00a48cb89e455f8532","7d69ac79c9de7620a1bdd926fd4b20b8e968d6467a220eac2a836988ab47c933","d350fc146b46550e424850ab9f7e7d8951156584dbd27bf493e37d7d2300af87","51df45d44f1a2052bd14063736f385bfbdcfee3759fa5597c89f62b3bbdb02e5","10b2bb0a74b12ecbab5003ff91aa8b3da674f81a5d72fdd6f998bfaf664948c8","03a27d1292d90f99bb102194906f19583ca78236337cf9062460062ff8c67b47","3f4fe2fe5f1425cb3e04f5c898d990a1925a7c8a84548a4804f831cfaa2194cb","6ff754e93a1ef94f7a92e7f6f9b67357f3b25836ab36d66202d1d07343186ab7","504f64fcde588e7650963530c4108c700d2bf56e7c381a713e09c106987e9e3c","0f8a91a725deb2bc4f3d64760262135d51a7f5b27e0749424ea90218b719461c","2795b8b6c014ede81ac8f75e75ee7787ea17e9b7abf0f4bf4482265d0caa00eb","8254c731f443493374e1df97d7385ff83abd90ee29a21aa66aa233284d1be2a7","48533e135178c91d9abe0789d1c09802696a42985217396ccfcfd1034a099a0e","dcaef7f7c1f0cb2dba19a1a70cc8d5276faa68e50bc69d6a006d3aaaaa9f7aa7","ffd67adf9464cf9bcddc3954fcd27d59b60e85acb02101fefe8b0eb642a2be2f","a5fb95c2217a6e8d3cb48bfe33a56548dab85c7d84c57b720f03159bc289827b","a2b3e49239225e5d7435059fe79e5f5a10de90d1fdca5639f595ed16107d4e61","78d135d6db7f15d7ae7c7e90e80c1fa84610e5d127e8a7cd282dc270b2167bcc","a6b027be3d2d9dd15959326c0c38c34dbe2da63c0437316fcfe91efcbc42199e","a61fed6df9d3df92232cb133da6b81ad6c1a18d5b48849afb3d68cdad9b64af6","0d3bf00fb0a5c49c90526b68a5d01b93124e0d347e81884138e6a637bf84c80f","c9d5efce7e7cf64d87acbb96fd6cf5f5cec79aad63fd023efff6b5cb88d3c81f","232e039d6acaa06967bacb5d0e50ec12ac2ac035d62e5a1e5c0813d2a1ccdcc2","3b765697ea2c4c11f5b9133642917cc5b225efe0e2f2133122a9986960e7fc13","1c2cd862994b1fbed3cde0d1e8de47835ff112d197a3debfddf7b2ee3b2c52bc","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","9e0cf651e8e2c5b9bebbabdff2f7c6f8cedd91b1d9afcc0a854cdff053a88f1b","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","1e35f7c504c2b27ba96d41cfa8813231cc3b11362d94d9b17467ca205ee4294c","66fa934446c5d88774869247dc23e7982fa531636eb2dd2fda20ab7e427b77b9","f87d2c9480535cb2ec909398d3ed6e753adaea760ea1dac57ec54b896bc7085c","3ac1b05b9e123ce3cc2803532e665e7f996800c12972e3e868b1b39e5abab496","7e08b37b326905f4690f4918d8ab4361e99f0bd0d9ca5bafc4269cec5b860fe8","15c9d339f3dd0a758cae6b286c670fa2e5346b721fb0ad2c57a14628c5378978","057bbfb53f44e1aab459e249ffea641de520e0c826b8a761e2b4af76fe6d2860","c1f43d76f51581a9fc7b53e3e3134c441f421336f1ea11f6729a97fe84f17ca2","8a8eb4ebffd85e589a1cc7c178e291626c359543403d58c9cd22b81fab5b1fb9","db1b85efd41f64be64d5573206e2d97d835e909048c8f9021fa49165f492a346","ca2142ef239baddf4db61fd6a08a8cdf63ebf0dcab50598a1f210c8405769d26","353ce05dc624ae1652048e55af57b6a0c152c4633c29035f2431b2430503a544","4b0d18c9244fc7aa0733c97006a61a83e9322e9bc19baaa9b91d3c26e11a7158","bead43259c78c3672a90a781f85d22b5f3ae16ab9f71a0535c55c6fdbf5aec58","b53583893cb263b420987fd8b07412da4652680e2b4e892532a7e900a73af53d","2fa847d51e674845b241bbcdceaa71a4b8177b958824dc3a5c4543dd7ef0c621","5eb14512218fdc889b03b1d3cfa50989a1a0642862365561b498a849f8f4762e","5e624dcdc395987a866768e2e0c1250f79ce3d0a425f2f58849a8cb3ab2c094a","9a30429285c5d093dc0259585090cb422861e7fe8d9c8c822ad45167bfaee491","13c9ccb787cdded34ab7e98cdad2ed1c10479450562e6933945f7bb7d2a03772","7091464f68a89b2758204c095fc6749667be3ca8fa0d6a048465a48e951c0ad4","16922741203717a045a976dd6e21109980671de2b81c48afac2fe66fd5c6e09c","d2b555aa584efeb0057ca6f8b4571afb1b9bd1cc96835b4a7d2f2189c37537b8","bcd6272f4f285ccb799f3ba0f8f28f0838f9e5ca6a26390100704c50f5d69562","cd9850900433273aa4debeb746f6f9cbb6a0db32432961f05792b496b97becad","6c77062c18afe7d2a037e09a51175cc39c329c40fa923cb6b68c114c2a145fb0","a22e38a00a323516f62f949d8251e2ebdbdb26ca1e89ce9512e6533153aa3d54","ddd0576d01ada329f953515fedeb207b6cca85fecb5947b36ad9fa2ec6aa6c6f","1ee58e2749ba6ee0f4259e5998a25d73348e35e52bf6f6f1d7add9929248fe27","818fad4a1c9846a36767d27c77192709aaf42804e6161d56f159d76f9eb303c7","2836eb10f2347b05e371e47ca582d55c384b99a1f4c77a834c2fd537f465e7e1","6952b9e7cad12bc650ccb1750ecd096b9fa64bb089cd425b943f9644aabd040b","eef56d546678021cfaa6e276fab0d92ccf06f2b807cf009bad5626bb768f7116","ef1880102281adce8ba50ed7d34c40feeeb532f96eca879992f017aef61bfaad","4ddf02f45b9370fa19bfc53490d24c83cef5e021b224b4ab08475b527874f717","19672bef4742438ce88650034fcd378192e3e16e740a3f923534c1e0a370d4d2","ad5e2a9be63725132188d40d1d2a6778cccc4ca00776c2efad3a61a865f0c2ac","a7d5aeb560ad157c1cb00166e23ccfd556913b3f83ee700acd61820178cc2f2c","1c19677ca9e43987ce4df37b81f890c3cc57337625f92e7d7afeaacb684820b7","a7ee2295676f92b92801cb586ba4f662591e159b56ff902713d407e46cfd6f69","ed5a2a52aeacf424f1e908cc75872559d0c1d405b6ef14c894bef442a0557638","c076f15c9cae82c15944d7a2ab869b6691434ebeedf84989906e07de7de43eea","2265d334998fab6923b0a7a66c2b24e6fc95f9311ca3cf1f9f9d96a6c079ab85","b51e04bd3f56f390fbdaa3d882d0d1a5b6596c7128dfdd25b20192e4d8454dc5","804cf5a171475ceca79769cf2326b7dd0757aa41bbbcd969d22c7f67ea0882b0","1aadcc7f7662295d93d7b175a4fcbe1bd595708887b0545084bf581b4758b386","5082a6bacf1889eaede29704901a3d1f190b4e95954faf1948917a610ca0c959","04ef3d78acbcb2855a0f43490c8129d5ae30e3668ad66c4329608e55c52718af","91d0e22a16f440e788728ff108e0f2a08691794b439c47522950542fcb0d9be2","21aa8b796fd38726535d5cb3b26808149e611f968b31fe9d0ef94af627a5749e","9da2d5a641188cf1ed4ce9028dad2c2bc29fa914aa0c9f792ece7bbb40d89ea3","28d3fb4f72bcb64ffa959c844dddb43800acafc7c4aaeb76f8838aae19ce1e69","bd3ec9a1215440201495ba69d7b84a1ba0b446a3ceae645e02a3b6e540a42bfa","04b3aaf2bf458ea2798cac43d63f410ebd0c4970cc00a7f82d3cac0edb1252ba","3226265080b90cc5e4a10db5c546a96d2bb81c818f88835cbbf884c6fbab55c2","18043ddd83c806db9bae5b05e7d7aa4edf5c77524c640c74cdfc3ffa677816a0","b159db384bc4bbe4566d79eb2e1dc06623a9d38d9bc15c724729e71080daec3f","e378192dc26cfcc506f666717f6ab9fd04174e2cc5a8459b66f53aecfeec64b8","b51b5ba0cd764fcfa6353ca2ae15a949101e1982214817d2a7f79e5a63ddcb7f","71411d775b4eb0d8467dfe721c40816dd94389e631b54ce0b68c5c92f490a497","7bfca537672cf8f998467a332f9e70a36932ac2246d8b055d1419edb2fa76868","42d84735f54006668f6c1fadc2962280decb0d3a6f579984c57940d79138f914","6c2f022a8915c40a8f7d518d7de0bb3ec3e61ab510f323ee0ecf9dbe7f298296","a1d2820e537db3a4a35d7be2b49d5a76a770c45e3f213c4135ae76c13742b350","08748edd10b66ba88b3e65c9da0c9c632f94327164dff036a5b4a375a94c4c9a","6753dab69efa45c83ade878bb9310ff0a5637e942218e21cb8a84989f194fb23","698247c4302a21d448eaa10fe5317f0b947d7cbe67f1f279a88a414b88332a51","7d3c6dc50efc544b3875bd0faf50cee781c35811dc46f848cbb2e7ec33e902b6","7d18297b10fd34d68bb8ba96ee8ec82cb930fb18144deee92cf5112f262f1315","8b295abf9d6ca632e47a70760beabc4e9c90194a34f9dce3fd302e53be02574f","1a938cc75f38e9dc2f521e7965effce5abfb038ee81a868f55d397ed0695f915","33ea11a2cc2ebe78fe9ac3e14211cd1e7b5643c26b10764a8143331622d4c4f0","cc426463a9d2baeb85533b7ad8ab0c9f5f489a850a7e5d676da584d4a08ddc1e","0f2ea92474ff8f583650989770898672d0b731ccc2b50fe2bb08eed74db6f465","63f666b451c20cdf27d51decfd508f90ef905fecb7c30c24c823d913705b8f4d","19a62bf1b91a23bc9e6848d904d62f649c785a908eecf93a923ca824f0b55cd1","6a010b63d4f7f6395709bf21e22a64ce7b7e54d4a4f205ab2267dccd25002736","5ea1fcb294dafb836a452f515492504f707ea196f737a2d7c164ba53666d5421","eaf0ab1bf7ccc004bd3946beb3ab770a9dbc06747c3ed000db62afed9fb8dc53","b2f337e7654912e1fb312c03b7e049dd5370251e25e3e2518b4fe18742c0af35","c9d8353683e969c3e9e7af2d5421ef825b738d4414609035b0d0740fdad87e3b","50264940873b15737410c41353a36a9278ab06a14389fe440e38a3413ac13b9f","0c0e401dccaa66646b7d57f8c659355f9b7cb74ceabe5a61263f15c575db54b8","72281165f55d0ebc566195517d01e2b466a93b989c913ba0194c1da454f5f9be","d8ea4b75db1e5e8ab371cee67a9b15afd616ee87fd0d8ee0d38ca638dcbdb723","d4dfa630db8e4a7e9dd8cd44bb78392174e0f5588119591d103409351c81b9ab","9b7f0e521e1b4596b39063a0a979487583842211bfd427293b3b8b7bdfa828f5","5d1a7a46f218bd927028130607a8c552656d4fe8cedaa57efcbf810c6477b09f","2717f6454b3dbb8a7cf5acbbd2f48209ba6d126d736cd858c5b5687ee2652aae","60b08c9a49795ae888a0c2e9c749470619196d38649eccb3b6a72299707814d0","de2ca6e8f7b95566cde68e681726e04b9ba9e5adc979994fb8c013994e90d86c","4b0cfe9110b745df569d1ae33ad25b968107400285f79d198dc5f08bfcebe7ee","478ebcfc229746b9e8921c62821870d299c512028dd3841a94884f89c99e14a0","1af30eb6d6b8cbf8c271e9574e0be812a65207e965e37fbe98c7ccd5109c2fb6","05300da7f9381e3535f5713e8448daca93c16e76522b4ed3cb90d643d1ff6751","3384e38ce8f3eb163e0ff56f6a982a0677f797ba4657eb371214a1a45f32dd14","c5120a61318f05d981353cc67de4488219516d3bc06c7eb59c764cf94a1374c7","3a3882ee0651c8d8ae087c6f34ea75908443ec2cb3457982a162f0cb73dacd64","b4f81c99b4783307322c0dda97fa6b295e53ca5c3749bb46dd46ff65114c7939","a53d3edaf0b513e725872307d4cfa5f6f5b7476f3828320c46a0c131a806edac","f9d75e0d8f655f31a1371e49dc01e7063b037860f62d91ab0b44e5ff754330f1","0fe2fa537e82568a7dd1b7ea104c2a1d2b2cd95a32d0050109e52ebd958acb4f","e200b7a5260d550db834da0d0d8d3d1a2e72e5cfd67d405330f4f484eac8600e","d1ea793b9f74e3abe7c1f6ce190ba3801c1f2d380bf30249500a62ed9e090b1c","5aeb59d3916c7bd5177addb6eb1004dfa714ff8d259a4c0076d9f2dea972dd71","0ec5a2b5c22249e2a811e27a2cc368769e007da4d3bff555ab651bc5b714cb2f","35a1eb1c55a2d086ba888a0a535a0939f44b123933a812a1b8e8bb3843762827","4fb8c0cc9c3c0f02789eb46932de57ff337f279eed83405ab60c7fabbffd2479","b1f8280cf0bdbe930233ae48df96b6a871a7f24fc0d32f04e6e22f7d84daa529","17220b442aa2ba3af423cca0a7214488d4260a2f910d572abf2f52e268f2ad3c","991fce3bbd7f76271e9a010ff7efb0e31bdb0260491b7e80b1c2ac650e82f873","7cd4b54cf3a9402b0ae2fce241da97f59b33c69b5aca0f916630c7e8050e0b89","2f2e91750b06e2ba291a16e9f673fde12d18caea79a730e0f6169ee5befcf606","9845bac298419a124eecab5fd9ef8639d2e94b9000241211c6d23961dee2d3d5","66230000dece92e81f97014f3e8f812bfa1058188b64e25f087ce86dea15fdeb","b1fbb07fa7da197d2339625908ab59c50d8f9be5aac644848f487d97b8d3484f","2c452f20458e86dbfa926410247ff1bfb17a097763b54dada4eed8f026cebaa1","7643d392e56bcbe9ae402026aac456ed09169d80eab9342b2e42709db79feed4","fe3d7c154d26ff780ce2239874b4ef7b94108e57d2050dd796722f79852378f7","191096d1c0dc14b8e87846644110648b1e14367a93dd619288cf135f4d556bd8","af3bdbbe17e70ea7c7acb8a3d67d23909202d97e6de188b83e2aae754a8df149","c0ca43993486eeee95a5e3c1ab0c0362861376025516a83378c208849dad6cd6","712402492f47d73b356ff4f1460120bb85ae343f3069d7b91e812957fa315d1c","516456888ee35d15a2ac3251216d4ca74999771d07c74507a47f22b2c1d7bdfc","901fcbd9bd70633000887a8f350fb13805d2def8e049ba287407ecdf4f47d444","4ab59cf224759db0cffb135f0a88cd11a6501604c77ff49164397e85053b8818","3947a4118c6ea77f88f704f68d1d8b4202814e517059fbb0c8d34d8db1482e2a","c505904ce55eed563a2960e945cee41b46caf60688da9174e000f16098dcaa7c","680353d32db854a45624d9f828ddf6ff338b3f8cf28a46ac6ce03695fe5458c1","dbaff11380a0913d54e37f14e332c8b1b23565ea8e9a5d5773dcfe4220ee1af1","926bc1cfc68d5c76e052b07669cf86d180d0e20848c90e5bec9bda0e0368246b","643868a552706f3347b5c1fe5388344e9f77e0620b2fc950c026d4ce6398539a","2d89d7f42fdfcfeae0b496b8504fd1c15f3397c0359aba77d5fe4307a482a003","aa82481ae23a9b95ff6f33ff8fab20f2dca9ade4a64e36e2469e9aace1d8d562","1d43146b0c22fc478e51efd4033eddc3ca3ebef4eb5317ec4dc6d2c71a881bcd","b5f9cc409e7831abad8c2e613d432dc80b0153264a5998377da1c646e548c1dc","d7a624f7a4f71fb545482378c214acfa86aa3d0255520a448039f68f4fb147c0","9f4bbc32c9be86461cde904beb6ea1f50bbe8424193dabe55b51a83c6c172941","05108c4f04d3673f32b10ec8916ae59d2f516a74be41bad2c1ae008e3966ea5b","e9f1019aa2600c06d56ae671ba4edee0a4703fcfef022abcd9edb48b7d4e16c7","11fe6870d5652c32906cf1f4d6612138542ccb7c27a90e4fe05d007dcedc9cea","b01a3086080d88b7620de4a8f7c38c737c228c8db20cae9b3ebb27ffa09bf2d0","031c8823c65e0815838194e9c1a0e5ed8b478c7b6bd3e985cf3e62e1a885e5c4","254a68f9cddcd9a5ba215af81a5b2286f0fae9ca522c28d1b1bf2f1e464f9253","2e30b9f3762cb8cff3afc1772e1d162a0690f44848e43f0943206fbd5332427a","55695aec4e81cf826a2501028865e6d63e33c65c7c90da4bc72a8488a7f2be88","10912798b8099c066e60cff37d17a8f83dd8e42ff0f9600de7dab962cd4f05e2","5f84c65a4aeda4620e9cb757222e3c020166ec9298a0ec1f9ef35c200669fd51","3c84e9d7c461d5576c751cfb06b5e78b72d736550bd4d13abbe6b46211aaa06e","420aafda455e70d75766dc69c9801a41bca7de90d082a398a552b780e9efbeae","ac0480336023a5c9d75423c1ffe6cd65addf377b0b53944016242cf3c5f265c2","997f871ef54fbffd5c3e0efae5386c89061aa7933acf592f8e505628506eca5c","d9be3f4d1d880c1f76835a4d91a2956c2d6596b1d0916ea13fb6aa7cc83c94d7","7bdb6c48b092e66dcd9893db8414aa404f7792414e7456ec00ee1483dcd43897","7c6f4f75027f425cad875755bb71a4871441a6b8947500f33c86e54b37afb76c","0fcc01333cd9a48af7206cca94fe9b826448a62efd3960b0246feb30048432c0","799bd8b904e2311594fb3af29d46bb610c77fecce3e2941932bc134841cbb446","f1f7ee585922f50ba8b0bb969b6742136bdf8b6860bb21ec64c18b56d6d555ec","184e8051da08b35e9380ae504c93c403106e04dc8c7a2ec98a775ca961c69a01","d642cd385ebba66e398c80909ecd2d87afb776f4cf6846a7ae6df73fa45672ab","c652926be88e53d3917b3422a0bb9376dddc3479a67bdfb16b14e2880292cf66","e635d00661a164d6058c583ef57bd4c108f83619f00c6a8d1df1a675660c8e65","73179d2d34855f8c8e75619bf748cd340cc2a6c959f61fd5095cf96e5e315db8","bd3378a09a913ac538037960836c8a51ba6415fbc33a8063441dd87d49662674","d764d2dc2a2712bf2f97af5fd9489be2a8f08112dccb20adf895d94626f0978d","7a7237108053b88de41e1824fedddb595bef0db7590eed4a359d0986a888c896","dda55874be4e84235dc1738f1621d60008ef6166a07efe809f8a1b08a9ecfedc","160fc594b7f7c2a59c5ccecc97cf5320fb1e1fe8ad76e88421d29a10737179ce","67e288c184dae8084d13391cb552578c5504dcb87d288972ec781fc60524185d","b208fb30a29e7349d61b61d0583d403115d124e5ce3cf01891215ed7baa73286","1f4141e89b735f5c75dee82d27894825c4bd9fea37da9a89aed706437353675c","308acde5528328cb08fb9cc0ea40197ce75b94eef356239a782f84788b2fae02","0f9306e51a7ea76c9381d990d99b128f40196c8b99603470720cdb338b252c2a","e6adf0eb606acd1c181b6dfb2c972e759a4f659ca212c098595109c48833f023","856ff2ae7058de14aba2686d4423c00469b3bccbb091f6692e24523838d3acfa","8ddd3ac30b7a813f6c9143eaa4a0592283d631fc5316d2b40fa7452ec69ca8ce","7e01010dea00e308dd599bce9e79e623e3d5c6fe584228e68a5ef3d0b3d7ed56","e6c00a82d0e94b057ed22bac1d754af7eb8d43ef95b5277f0fc64201191c48fd","3b15c78ca9dcde57ea393b8ce916ee66925a5e9e9d632da59242c139eaa47195","2436074640c83a780830d57c19a69e8e0fb11dd3157b82076cee6b4e81ac7bd0","8566d64c342f16bf3f745cdb03da17cb8aff7b1437098aa995ce01f5aed8d3ea","a81c87a5f333c444f23c08543da83930f449ee503cafd24f81bbdb63440c671a","b3e183c972b336ca89e6ea2156b1bb3bb65dba2af1139e6952296708566d7357","9378e073616bbba323a8ca1065cb6f6c445b1a85575937986dd1a6f9ae41876e","7684d877027731d056907d26cf382438b4b5c1d36ea62e39f341cd9bda9448bd","af5974a01f59df657e66790e678dafd14b1f36b8ffaff60ec308804e7502663a","90d4eb42c0dd92ebdf1d60fda2dcc728b974e618ac54400610d5cf1b7aa9b48f","e4e203d5acc0f4fc7ca7c6515fde3cf835dd4fa61aeeed274f8dc5756c923f9f","7912b087f2568e3828b39343baa96d3b45c433c7c3c6acfb5456dcc461a76ba4","d71f35c256c1946151053e1fec133af871f8c2ca0428e9f4d1adbdee76512b8c","d46aeddd8e6bff27052810ecc7f61ae7bade59a5fbb8d18f9c15a3dada781f78","d6f0831510c7ea5d22674769bc7308d05627ec5655959097f422807fd0344839","045c754c4a269a010546d4e639462bf45de862b7ce69ea1b0df5515dc77ed607","1d767a4483e1914d1fe54732f236d75d3f592a3af398582a56b71124dc99519a","275565de455bfbfa00e080b069479add31b11cba3973bdf784e96a8b7a7047e4","e3da9f579f711da843cbaf4ec6cbabb43d7bb68bb682638977f1cd7f8d29d384","684e2c4a698727f7feb01d7d8231c9b420c683c0914a2cce7be0a0397a2f701a","2acd6c32a8308ecbce9b496ccd390e341847a5a9475bfbadba3c0b40d41cdf24","0e439434c25c6dd1a43ec9567e1eabb376a696dbc4b06fe925791e4229b4dbe6","563bccfba9d8e1acc57b948d395295312df28b9505324977e3d259ebfbf7c1ed","f550e521c4a02d47757bd5935b9bf5948b5723990ef0fc1fd2b86ca0cc8b93e5","98fce8db8acbaa185fdcbc54a82eca82bd0639c7673400e10a0b4ba27c889099","1443f263a3150af4fc206d40178cb4116ebdcc84f7b26b4a1e1755bf1641aaff","26a063364814a393ad8ba6b7e797fdb5a5d290ab4e74e131a494d3bb6f943f97","e99ad076c78f9277b244ae44b91f0cf1e315f823fe5f528098af57fdf9be0a2e","f30e128caaef9caa20d9c0176183df90a73db23f8f9ee708b08e85d33685214d","82b8b4a13c40952722ca39b40ef53ef208deddb0b0891945bed8e66e43ad6943","cfed695bcf959ee09f4c78ccf850da1338898667ef795bd4995a62eefbd4f771","f6805050c012000066b1f3098a047348360a6a2649e5d1edd5590ca04921a37f","9d3697277c517c88e702944aa86b3c26744bb1cba3ce8836a30ae9cd890b415f","3fee7afd5e6e0960fe53ae7401af18f75cc65504d6400ffc41213c5d6dad4414","1ccbe4fb71a0060dab02081258230342251a88b7f55de18ac02abb12dc6c3bd7","19b56c296d6c0644396e8491bb09fab989164db1fd0894e12d7f6772e60611a8","a6dd3d71ec4de3d5232ff6b160f2fc0b2552f54837b9985893cfa1e19520e813","f5f4548d07d0945a1dfbf79c9dfcf88ecb73f8aa15f3ff1656d605b54e732b4d","cbef2e3a4874946dfc676e31ab3d29c663f745677496d5addfc5547838c4efd4","307098107e746f7cea70ef885dcb6175c073f133206e44efb5c8fa06f27ceea0","c0af06ffde321e24331d738facc8da14ffeab85b21279f14f312f7e6f020c0ec","4cbfaccc07167a025470c76a4b042ede8d9a3a9e385116e3f595feff7e742db8","f1c7028fd3fd216dfd8e54efdafdb31bfaf42229e0536039b9e68fa466074d54","faa8c82a6ae27a4611f117699475eec9a11e2cc4d936796da760a46aadef0a3a","b6a548ecc524b7f2a10c721037813bc02db52e7dee74c8461439b3d4be127edc","e7adc27f1120035fedc3e6e465885c4150b70ed8a087dbec02390f57c77199b8","bfa712a6334bc7f84ca666fc08c823d718ccdfd49c55cf8b6b0220fb2d980dc8","6a611dce7f869d14ea4befa1e3353e3a5cc9f592c845e48194823a7f45afe557","a0777584507545cca6560b68b2e765cdb2e3ff8c9d6d108a2a7f8ef5be013887","dbb159fc7d416a649f7aba014ff8c1eecbce90340022fc48c057d0b427cc4050","9e075bb07a1008f9dfd5418ef5bdb94e2cee62c75a59173cca9a226bbcc915ca","33690047e286d60e1a65997e59797c4695d70dc40033c5ad673e157761886cbc","e8ba4bded8bd33002727f3807c612392cd594a0e3db0b1c349bdbd182c6b36df","0dbf820c539052e1a9bbddcbb1776ea0967115871b07b792db7ad1c823afd288","07d6984ee804fb041b8450089dede1925838bc87d05a7606ffb6d1ab97900580","1cecc55c20c16afc98c1c02eafda284919c183e86d1b15fe78f84058433a748e","53d6bdd0afc5b0258a6f774cacfbda94b6123161c18dd6aea5177118f7269bd2","1772f165d59a5b405092a0ba37eb3f097e8560e4302956e1e45c9cad9fc49eff","a740ebd4b7b14e134756493177799a162836bf78dd800e70ab5478a52ef8f82a","b97bc4effdf4a09cb389b62dade587d900de5c05dd52d709089be8461762c95d","0d1d65e1557da66557d922391247304b60e55bd5a3156173fbbeeefec53ce0aa","04a9501e376b1c928a3f9e003faecc77bc90db333ea8d3816c2c42fa5b336845","2eec9abafe071e06bdf4618327d94cbbb6586e96e9b0d91eca499b6ba6ae9afd","01e15a35941e2ebc7d1300738d4b8b324435b3b7b7d8207a719e17e69f3554cf","34778716e4f5e4fe4be3a7011c4836a142e52705dc022361f1d655357e51ad60","56883ce345025ac4bb4574a101b082aabed27715559c6f8d4d5dbf4ba6100835","46d1f93cca4b2ca1d9401bb074b36b19cbb476e80436ff88512321802b8bc871","62f364babc873bb229806749ae14ff5e6cc5a38831f5d2bb95b52e86c1837b9d","b501b15db45774da6023a67e13395aff0bd237fa3a6c3f79036390d0784dff3d","aa4f798bec4f5b280bd39f5ac393bb9765ea8573d46249945d19d85d8932d5ec","c8733fc224591cef23b5ef87e6bda5614cbd8f1a9263d39b75ce2856fc19c34e","f5fe05782bfb066d52d0017a1d5d000a1a18c49ea0e5225cc08b9ddf2b2a5990","1f6d552c4cb0970c5cfe84ec7d44950eae502c1eaeb56eecebb45a49aed7e78b","9264b5f1eb2f230afc94522ef4b91fb2eadea7d1bd635fbf58acf9194bd28454","52a2a692e9ff0a35039d9b3b3afcacdc32ee16f5e76075a2fdd5ff5318a5746c","6bb0fe32fb9ffdc4f455e6b88e10149a08bcddd392aec1bbc76ccbe0c0348c07","326d522d2bf134a9fe113252640dc45cd9277edc99885f2deabd623e92b15922","6c913b28fbc33ebc0b7fae41422668ddabda6ab9aca0efb834de31944017745f","7cf7124a0554b3269204436d027d747d7817a0dfc790c585f966a99eedc3ff76","616dafc5f9cf31f1b49967ce662f62a9a10887779712e07333b90c6be9b2b0db","475a85a2957221625651a85f8ec715e2e3003507b47cd92e976bd5fc149b538c","9a648ae0b489e1d9fdae95e38ac9ce0b9f9b2b9ed56ef055d1057af10ed823c0","94d209a2c483d7394af61e5cbff98c61fb8353c0a599ff0472daf87818685a21","aa9c49cba78cda44a3e35f550ad74e36cca89273b2a4fdfbeea248689af8965c","a9ebc17c12fea67de23589c548f9324161ac8ef00e7e2b200001eb35617148c6","46717fa86949ac6f7fdd128c8baac37857547653a245a879c4deb641d44f7a1d","c2eee45943151f5b0d0f2c3a8658ccd2aed6d529c5b94c542722f847aba651a8","73a13622f4968dc5592490d2e9ab35058fe38dc3a9d850e5202a2a91edf8e2af","d97d2bb0a9e52db1e9a859857bf446ac00af5a0c785796f153d9a7143eb83a31","b600b1876dfe18dc23b1547b55bc4d80779f8f150328c1330f9cddd6901e46cf","a0784fc20b877544ebda0a3402306ddac4d6b10899e5ea59886bc1c1059942f6","b96ef11cb1269af95158cafc7c8b7ceac2fd785cfdc99de15007d1071c2c1c3f","ceb514546b3b0b09e8766bdca11315444e6971c0c8afef7e65689e2153d8592c","c07b484fbceb1bea19f54e9ae829cf33afe01721548b7554679ead608bdd5161","5e63bab247a3ce136b8adca947bf778cd91b3775debaec09ae380e696f656b2b","1e8a576be040badf6ece3b8012ce3148cf88031cf6762470e316f94d2ad8c9b6","522d8dc5ea8d8ed0b2f862cb10895c1ef229c5dcf3cf0712abc2986e87931b88","c9f2a6ec3bdb08a8d87da15697d2b2b403b7cd033a416a27cfd9aae0ebfc1474","7a64f7161d77158d62abf78973b06953d6749ca4277a4b39c4823ebbb3a5aa11","b3d9b3151aa58f5f17696695b0b40f17c8cb3390822dba76756ddb6d5c3f5469","971b1d6e56412b0ea401d8b4eef6d184803e8d08fca97f64b28848923504dc65","dcef54c0c9a6496b4d742650692520db19140eec3d7922a61eb06f50fdb05aaf","defc6ec853ac43b579b542dda93eb0573105c8380cbdef61f3b91760f4a75528","f2817a9df43f8717b32e9fc4103e275fd3a435be22faf1a620dc2c7f4aefb9dd","b6bc606d92ab2afbf01866483515611a019bdf44477217e305541526647b5a98","76954cf82e0ecb8e13fcfbd446e3d8a2c9ca842337966f32185a61d6e25f9699","0f5389929d52cc28abb20c51c0397b5988a9b731014508c474fa6cafa4baa8b3","96db026bab5c373bf378e534205994a7f27b9568c209b1aceec9603ed64db9e0","22989fd9ede3679d4733af6947a871500b5e499849168ac441b7869f6a843244","ce4a0a85a3fda74fae0a66c07f77adb1ac847c2af248fe12c08f1b03e9e5a802","0af58c28347d9ccb04389b3cd0d571d08f3b4610c3da7f379ed892006389e8e3","de6109b1670ff5b763d4556f9a0c864808207fa3bbb91c19c5100b8c204d02e6","2f949aca7cff9bc1d78e6e72a587f435bf6aa905a3fcefc22876065f6b42582b","fd9973615049fbfcc39d7877df124f8ab197045bfd316176ecb07a07a1b18c3c","ec13be8e64d68ec8aeb15d2895d93e42c74a1a790abdee6202adf954d7ea82f9","fdd6c3a675459c92a6171b423c1035526b78ab19852cbda9194a8fc16a6c3793","7dccfaa6ea6009f3b73931a9efae46cea19faf9984e4bd941e384940af54d65d","d894ad640845a310e91b8709edac9a2d30a034acdb3de94610b89d5ce726974f","aec04d8ef2f484df41901a840a01d8bc835b73fe6d107c4037a051b07305e16a","6d815a862869815af888194c062f2be579a5ec1c78be29b2ba58a6054664cbe0","5a12c90590772a07314dfffe2d102d2030332abe85d6549970b55b7b710c21b2","8e17cdf7e2b09ac6af88ecbc00a6f767c42861fa111cfe942b7259e1aa54886f","55b4adaadc33e700ba554a7d7d13696f3ea888beb76a46dded8d5c25bd8490b4","83d53190978587e2531317746df89252f5c9c43799b2b150d5645167050d080c","dfc4907dc3f56449784e0e0b1a33fbf01ef03ac20acdf5dbd121c2d77ac98ea7","9b8b3d044702dc28be2f6661b8ca9ba398c0b2a186531da31b9dbcd2f0e61abc","0524b995030d6d817884468fd96711a8096884a2ab5a9c76694d173f01c75b23","5a01f17678316c584f4802eadaea9940d1b4fd5f5a80b3dc966237e11cedfa6b","fb8cd7e05a169c053cd70f04bbe1a8f217738f728f9b6b4d34ddc7ad0c86b9cc","a9e4b9b40169699f48380b992627511a690162cdc48e8ffedab88eb8a2c66e84","9b0ff305b6cd974910104b6335c60ad5c370a7092abe13e6c50d009d2d56d5e2","675b9cd43c2ff77aea7265ee503aa3e681fbdb4fc7d4394d3dcd98d549e9147a","605bc33695dcf05d308d80a441d3e08de09dfca449b121b293e84fa40ad115e5","c2bcdc6c724da8ba69e1854433ba474b7afb252b72d95f761f2d3caab7f9a42c","acf87dfb7cc3c3a4797bd1a393ab33376d4cf3882cfa45674a8c181f7a0da126","e5f1ee3d851a12ee7845e061f7f00e8bdcf9ad8c70906e32bdefe747475ae8c1","d7d1af34ef3a3927f214f46e2eea22c0c21e80c98aa6421f4a740c04cfc634bb","cd38cf7325fb8560a1d4f1ce22179fa6cb38d5bb388e1ac97ea01986d3e16b30","e6a2f8c037a0dc7658d21c5f4a26c95ab2f2e3ceb3ff316551998da8ca87e562","c6b8447abc45bde175b3b2fb90682107e39fc444f63f35708063c7ba201f852b","bdc6db8aa5abfae159e2e6c94bd58cafd770d81d0a65f2c057b74e02613baadb","d296a9b3631fb0e6e120823eab3974c8084c0708ca9bf1fb1043b3921741286c","151207d9415870b14be6a03ea7255043406d3e4495ffc6a845d52a7cfe8a388b","ae5124ce80fa8a372635d67f3eb466f72339cfddc6190076926e5c71f27356af","b776fcf13f0f01560d1076488978c99c48f5fb662170f3b6526d0f0a2eea2cbb","f1ea5b8ef34b1717050083ac0126dfcead52bc3d28f1ba778c55e95c0083d030","74f584cd960e1c44946fc5391622f6073c924342fb5441c4d7a8336ff51e6a41","413ae596fb8c5f15a989be71ca8e717422d7c57ae2c853f5b6f39d0351ee719b","a2b4f2edfb268826eeb78f4501241fbd2a2fb879b93e6c707f2b06cd4485c53d","b11af8cd8ae9788653456752bca94745d1a262ec2d2d1d34e3a190554961dd3f","0408eadbb6c5cf0b865ea8835e95f32af0ab633e45498186f41b86c040516573","3513af214658428ad79940f5e3d1d11a90d479488922d9a94a460785233f1ce7","1e8464c72cf2321e9a31e518282cde4f218cebbfb95e225a5b71d778739882f8","355d3aae506d6bf04cfc964b2e29f19d67d48bc510f5311e905b55d71d0841dc","69640573851ef9cb22aaa64b1c4cde107d412abfa34760829238493573bd96cf","b81684995bd4c2b20b4f7fa0e7a42fe266324ab8d7b3272feb25fb6f3daa9f93","34e456686dbfb10cf39293d5d8183a0613bf9559b372069b2d13bae5f56aeaa1","aa7d8cd7b4432f8e132a106da7ee7c8901c55443ef5cb4be0ee31715c6222ef9","90aa8fa601356ecedf6cda4d50d9f6dbba4b159b5e9eab3d7cd6cc242b87b575","ad93e57566b8f0bd07f08d031783c6c0e6d0c4d5ad718dcf238c63376337aba9","0002dcae9aa254be5b0c2f4a4b4700ff9244c321b6af7d812e3175548a0dc951","1b052a60ea1c83a1246c1decaeb5bea366528b686b17fd7c2298b2bd63ff3b71","79692adcd3788e4e2bf07ad32cac0e7a56a4b63df7cb94bb88cd38dbe6ea6fd2","d1e2faa9402835428b620af7dc44a1630d1afba4c6d9839c0eee43e6994e8588","aff1199ee4dca82c9adc3e6342f3b5abf5eff1d213fb53e07fbd2467db1f592a","d5c1688b64f46a4ea5cb7d481fcc39194590b003067a714e4adc4079b308c9dd","8855ac24753192d7c536e8e2aad6b384852647e47d11d2a65147ecf32a8a0906","40722c24be88255e7067c302346318146e49a1b2c864ac8a89095af86b643fba","71086a1be6e7c99c09be8decd6d99c53c661fa31a0065ccc31f3e985b3aa34df","8ec157ad9bdd7d68c4ab306ce078a756697e2f8a2a47ec663693aeeac1d93416","45c6ddd9f06ef9f9f52f4520981dd124c64b8f425f53cca3b81bcdd2b0f978f5","a0ff19664a5e7c85fa0584ef606bb1ae2965336af533f53533fc09496544b512","47976c10c3503baffc09d83053fd6aded2b0d616728cc2210fca92734dccea08","78c29a73b637ced80bcdcbc972f718b3f375c44727c91e4f25e8b2894489bc97","3741a084758db51f7f6e9113c0509b089e6b716632d1918b86c2a972d236008a","e09feac96eae37bf5a35a21126def9cc6cfe639f3e3a0f84a406a36e5d452c53","66322c288533dc39135900bfaf88205bd0211a4f21b0f59270ac9ffaa2717409","41493f422c9f294dccb85518ff63a1b007a4356f467301935f4f933756c0f887","983f98dff77d4b7f092e68c0b0f5781f9d0275950c5dd2ba07b1dde7d826200b","c4d91e7213a1edadc91aa92db7e9ab51691886a84e250b7b352994a023e6077b","41e97593ca6b82d485654ca9f8aec313190704fa6653e75e036b2521b3bec34a","6a8bf802bac97b99deccec00bfd4dc73b98e90a55a577af00b9822031d418d00","985ed26acff9389cee411e3d5605ad4dbb0afb24c6dfdf4b4b8d8fe26dd831a0","2d5bc34b07e7898657ec2c5c586284991360ae64d3990de841d9c54f6d6b969b","8c3e0a08cb4c7eb7b831848a55b8585274d03649d2d5b07e1a2d404157d4940c","c7a70ceedcc51209ddb938273a0bee089331feec34edf9299cfbac57a4d3e64c","1da1947e473528f4a1dc13fd6d0086b8bd0f9e00780c5e9a5fc1fee73bb2ff18","dd30cb1c04c41963864b0b15e7a8b926e0fec54a919a49613e1024a6b9d5db75","f05bf459ea70864d0a312806d46b660cfa311650d29748ef35ed83c52bbecf9b","c2ca84e25041f419481262fadce83a29907f8bf6fb27c0ee5b1badcb370a8296","ffd1e919641f0b9c83b294dab4c2659c9924fdec03b9458de5d10d1991dcf2fb","dc1f2748cd806fbb42275d02bbe5c148a72c4e5cc2c90c8300ba97605d3acd9d","553d3d0039bdfb78d92bca4abd991f190b43d279533d0aa155975a7760447898","9c3bf8f14c4adf7dc44f0d0c2893f27cc0c9191947be1c2e2c9c10ffc5b42409","8cc18e8393ad2cf02b4b4da91dcdb5c1f12e754a919a4f19b608531b7451cd59","0a0178b4e57bead10d4980cdc5ab1685e10aac091aaa0e6eb5548ec13d7be8e3","7f13235f59392d2364669691b2eb511dd69e1b30248ff266270138ded814e9ce","a39a8f73553045e837bd4822f6e20fe39d880fe265a5aae7cdd32e5983696544","cf346d1f71b8bb16546d1e326a40c1a0f58bb2703c1def94859bd1f73bf8ff46","33b79dff59e4e668f430784a17a9b177d59305e5c1260f14e94870c587af0741","b7404eeedf95037aee66f9f2e920f15d94c3a8f006bd01905b523408d71ba2c0","2e12cd586480e59da60052dd89813e88d6e61906b23ea05588125e83f441c965","3a6c751b5bd9f39ffffa2a5fd3dbed8cc1826ec6dc6774eba3f13e7574a507f7","ebbb9fdd9a718f3d3959b1753167fbb91ca165d5e02e9a893aab6fd924b6d320","81ff53c0a84be3b605e64d8b6df4c7231ad6d2a76c337ff27190598fc347dc15","df4114748d3192bc7468ecfce7c0ceefec29be8ea3e0985c5d088f3f95a33ef8","148a62ca99715ed5098cd30555ab30e055f54327adc517b2ea5f0a8ad265815b","b6c89c7d71004f4d454e98215e44cfd5e72e182ab82a754346db78501c198d73","665f2f37f8cdf79bcf5cccb654644eacd71f9a9982cc8ded4e9324a7d1571ec7","df1c051b67b9b62f9c5b4881a831293a04a407673a0e31c2eeb641a5d7fc7f4a","475772cd16f877245e0f92f60840dc860ef3db55fea31484562a8d347221ee19","66bb78b3c783119a2b61fffd0948f9a09481d893b09b6a1d35dbf19e6ac68df4","542c607ba7f1b6604b03297115958995bcf2d5fd25889685a21b26968b636101","be8d59689e65bb94bf95cf208d0769e5f8f7d0189e0b5009b188b9040c920abe","55de18192c45ae6178eb4d1617f96a048b832bc57c50306247169e81e7af4e8d","23b9b233c0911e7ee2cf8419b82dd0cc127c5c0ca6d0bd191d10abcbbb139d4a","58d00853c97e049839cef000002ddb77b527c2d17b2aa8f521092d13a442fc3e","b6d0e53e00d0034a0ec1b3b3b92a9841f88cbe297699b3e7f9338ce1b2e63eb6","36bf923e9157ca73a8e3cf2b6c0ccf91affb659c5a35071a6004f5d2647cca7e","1d6d0023b00c624d3c86a446da181d8e26d87439888dbc0b4f8f80c821d3b5d4","45f3add24538e55c215c1d5224b269c1b735e1f008c608f5f3c875f0ca4df68e","f0e8d8dc7e958f2486cceccdc3e11b8c9a73a70a23b2f1444074e2acb9837ffc","1d7fe1f577430bb5eeda74647757d05a169aefdb0e338654e0355af802c46697","2f067424e6bb7ff9229565e5f8c817419153dc759b79d1ca84254e34f261796b","cafaf3ca2db4658a3d00e0032cdd4a576242a732d704436f6145eef5c524d18b","e60a140dabd84c51b4baf5a29e92b9d5f47210e3cebf84d94807403b253e57af","10d206e56b146ae58b5c24227d6262a7bccd31fb53ca41f0d7b095dc8154283a","830ab289eb74f250f40102c64ccec99802ebf7e68d9ce30a1ed59e447c989f5c","d0af485128c572421b4a7689bdd1ab4b5e9fd34bc9dec8ccc2c2a708534222fd","30501dc7b6e664cf612af9cc092e54c4dabddc30a409de7f3ff8ee20a1140c38","82521d9a349e2974145d0ac60bd47643dc6b20f84aa4fcb7f2687b2c6e57b1f9","8e2ee46e92f948b4a2b46a82239e8154580f196debfb52363292a2dbded48761","67c3d3ea09eabf84932fd48071fbee2ddf4b797c269c8e8e4a5db61f4d24fc3a","10452b6512f4d6b2370ce5b8fe352228e2f797269fb813c51f298e4bb995bb87","09df456fd71072ae813616ef644491aa696f9d1e97b16315f9e5d7cc22429310","17c14f4caaf1e8024fa1f725b3842899d2b014da6acb077c22a99ff700deecba","7ecab1231fe0304413e10542b01fa7c44a5bfcce18aef3ab829841015472ac50","7f561a42d3c836c1d2c71b8a8dc317c9308b8ada2bd1b1b9705bfe7338e6c942","ac57e9dfbce0f3cff91cfc86f18f57edf90ab5c34bde7597419f516424c2424f","afb88860826b00dc6ce1accc406522805de8047e52929dbcc576d1e465cc37a7","b5f21db5a25eee48928e85465d1d6edabdf782f8e06738cf4f4ac35796d9070b","e10bea2bbf75a4b6d51be5fb063c9e33f90d7168a2c5f40446a28390239a54b4","ef1d69b9fbdb3a674873068d052ce8c0c6827485eb520234cd847964a7e2ed32","6041a605a9baf175a8c3f9c40ad5845688c6f63e021736eb39b2ae6c7f521c7c","507509880d70c5b923c301a1cd80071e9901c092ad0e61223f8c9a95e5c81d7a","1bd6a0bedf156785d897249827e56ebf4f14ab79268870aaab23097eafbd2958","f3caad9e57e606f1f4bcfec4dadb6e5e9ae1e0721729992519780238504ecd75","f3bfe72ab3df7cf11bdb95aeaca63ed3db50d0866f494ce3aec852c34c42486f","a77076562a4d9a4434bb7697eb8703bfaffd639010179c6697992e5a87227e42","30c6e4d2810c80ece5da39951236ca50d9a9a9e664df841bcb9bcfbff64d84e1","77992b793b116b8f187411b34c8d232808ce7b63f9124f2b6b12fdf64531d46e","dffde4b6613271be6eb48341d2482a2d9dbe4912fac62623a9b86ba665c42965","e6330a8f782abbc49c25aaf2aa686b01c715d04b390ed4f552bf9db2835babe9","81306f4b15ed92ca4c1786d54e71dca459b86ca14fe7660ed4b98bdbf2d6d730","777fa9786b058c9e2dc488b4dc541b9ce202d9011ce413ceb2a7111aa3379307","10df92a30a2c37785bcd2590996624c2a94048b08e7e93e0addc102d3d6e367b","b7caf40205bbc34bdc5f0a980e820e08ca401cd1b6cf41c7b4eafc6da639a7ce","2d5dd25add3747e2bd979b97029e5bd20e4d488c07098c80e109f3309e35d9f5","5003db6523988854299f637eb9d1e5612cb7cdb0d9302c8f8c9366a0e4535ed8","e2d56d1013add7749f88bfe262b9bada14edf95e508c401974fa5dd2c972cb72","97a5ca0ef38cc19e2d205dbb23d6eb5836de27e7222f61033f95aec1cc074eb0","2649a8de45b9ec3f7f9416a8d5b715c0a72d65ba1971be2f31757fee838add2d","81d643e4d4b9d73f17d3c4b2749efa524d889f7013452cfb1b12cdb225901264","cf56e47961181d62a3b914250266eab07ccb1cb9cb57868e65fd9a475fdc4d27","16a02ffa8871f5e174439d6139c5994e3510d6e7105c6462b8c96cde07470ef8","0d034e9fa4ebce2b411ff9a57277c78665c404cc74f05a7519bc4d737b847504","0d39790a51c204ca9853edb657a29bd48724788181b68fe5e2856eb5ffb7f356","2e8aea739b113553f38c6a0434f3e2003e597759a0fad8d72a454f7c37e11561","68f9b375df973e71dfe0ddd37684c503737b708b3bad33cd6bf80cf520ff87b1","b6b29e7506aa4ef134cace5cd8624c007675d415cb2ed0351d0d6e3d6212d885","106a23845d7acd380f821c7b73a8856072bea55c4a09c60e7af546694152bb11","dab895032b46f798ebdf571bb589f6c3a39b86c645f641a51939c89867c8b2db","aa7194f40c0f66ffd199c68e06203053e19818a2e8c69ca61ed02ab1c756be6f","24e6cf796064da63fce893532e877053cad9f7119cd91bf6b8e8409376319cd5","270778aa0f96788335fcdda56c3990150c9c70c4127973087119000af47b9c87","a7ef14566edbad4f498c40ddbf17d6f6d37de4f210979dcfae784ad4dea9cfe3","2bdaa52d976f90feadf1e966d78c07838141d61537f599b55027d4df7008f9a2","a979775112d270761ab6c7f62bcd43d13625662b68b3a42209df33c68f2ffe12","31f227adfee6fdbd19587d8fb6bc809a0dbcc3f4ae6488cdee9fddf2c50601e3","a25a5aa48ed253acb9dd912f68697479f3dd751c1b97fe67f6e19d82e8839494","513f5524faade2a9439189902fdd25ac0b121faa1a80725863d50c409362d0d5","e7186e9d9be94c53b9ab996fa8efea9eda2eae935fbd16f1c6b5ac6fdb5be15e","499fbc559d17a7248b2f538e7755e0380430a3cb12947e75ccd47a07cf15021d",{"version":"e1a890ed53cb4676eab169487264a2c5d24dd8905d1fea4f2cd51db85cb7504a","affectsGlobalScope":true},"26ecd6b3dd7aa7b85e67b6b97093dbb0f029971902bd9849dac0f90f7badb956","d637fba9f347e022248088fa72e10c70b495739dbe306ff649de0680ec2bcde5","a4f449ff257246a34caf2c4f533a813c4ea1c74dfae07b68066db37d0ee39777","06767f4ce6205149e791459c598ef645b41c155b4a6e47440b592203794f83ee","5197eb709948fbbfa6cba210979383746a9a7d8abf68f7312246e0dafa25d281","6cf01a3b71aa8885c4b6c79f7860a3e01b500483395dd17bf6c9d00faaad5c8a","6b2ba2bdd1757f473de7507c75a9253063e93c3d39d2bae881e24960ec1670b7","e7c17785f44b2c3932be6f8a2424423142058918a4aa0c998237c8d54eeaca16","840f24a6de7d567789a5e66ce88a574905198bafd75875d408f6584e35c6b3ee","69d4659cf75f2cc92be4480442dd772c6fc74feff06120f70744f24a14003a32","f5fa95c13b4ccf83713c7d2acf158cdd785d549936cf689efb6f62a80a629f59","8f180e4e70649555d548ffd2933867e3e446bb62170871b6a72c15dfc6c42f02","0bbb480e177089c65466ceaecdfbe54fbecf8df2fbb56970eaf822a687540d0e","b14429371146a84d6c5f93cb4fc52c3b9263ffc68d599b75263d55cc0cc6d04f","38f9da7a986610a0d3d7bf5de41add9fe6b0304a6f1e9e4d3890e470d9947b76","f7bd6e7b87594f75be46280bac6bec0938267299d89ce4eac06c2d64a48e9443","75ea6a1883c7744b52ff08fa9f7720c4e35fde15d032c117275f302c19bd6b38","9c745653a72628ad0fcaf43e487f895d6ec733f8ed8a884b36c87a328455009f","6d08a78d7295037d3840f44327655720d90bb7cf872f5c04387c85b7000bb3a7","cec9de841877cf6fbdb27b693bd8422be608882be29ffb273621b96e78006b31","52e96033a411c9ecfc4c3b1127ac22cb02ad13a5f22c819c282498582343ea96","bec2b61b5b51a350a60fdc9241fb6f25a3d0b088fab84d2c35a1845f1595a7b7","4ed417349fafe5983d41684187f3ad9d4841d6d234d0e440325c780d4d49e1cb","8860d0eecb8bc73fbf2884e0ffde89359c006fbef415224a78b895d0199ced30","f112c952971d0f90846d1cf3070b66295bfdb24bb8375fd5a321452278ae1f9c","c709297a37f5eabf8d08f95011980fc115f503522708f602b108e8c228c5beb2","1cb2fc1fe8a3846c7449d770d66e12eb9a24af9d6141a4fb2dcbf58e54833864","53f8c3f84c5504b2fa617dc8e193361feccda19945eb1ab1d1d6af7aa71c6fe8","be5d7188a94ad4a5dfe7bd72d006da8a5cb358e14edab3e67c532bc112a5353d","c7a90d9fbad8bc602beff396a842c7118f9836a77a0dac6477ea2c716ddbcd1d","974ebd0b134ea73de458918a2cfd2278d4a60d103504c5e11a19758b1a274db6","871056eb98c7d60cea8ae99e399fb8ecd9a4e0c22e0d331b684e32e82a4aca7b","57ace039eec4bda6b838c8b1918fac89c4ab48703bed47c6cd32f61c1c2100e6","a39b547b72376c8c7000d190c1ac75e4160a7d733381b15540c7b8918667e143","0132fb17cea4047cae6c3756e04eb4dc608f02337911e99c17be6d4d01a670f2","7fdf96f03fe2663ea07d44d54861f4ad461fb368b5f6811f95a32cd38e91abac","4d6e7555ae7f69cfada51cbddc1c72b864a9e87a89851d17a010cfdc280b2dc8","cce9e1d3209639b032dd51044a294006105ccd675f2f24f091dcc06a469452c2","1c23c5e017ef3ea1a4e59d81db43263fb1c25fbdb26232ca2301b84cefbc0a4f",{"version":"83d8defa770332ecb37541a62a7c9395f360b1bfc13c3167ceee9081dc9100d8","affectsGlobalScope":true},"1bdde84208b3d9d4f8530317e63dee21df766d75a32257b24e98e6a42d571d58","addc89cfa968f95de21740110a5ef71274a55bfc85e01f858c75d3fcf377893f","1bdb0583e833341821a20835a2a607135c999c136a63a85d42c5747c3303acbc","0e4ef31b6d1602704bfeb03fe9a9f325c7f99b86207a6cffbff9080b448ecd62","ecfe442e0d68bc98c7e5f68395d38e1bc406c8aa82d5507bb0e767cdb68ef16c","f01961e6cdf79ac6f923df280c10ec76acb51f181131c2a2e5f6a2e529bcbb31","20cccae9a087bcf3c61b4572d2b5f469baf003f90c8ac97d7f683dd4da2e9af6","470e64efc91445bf6b1c29051c6ef81d72b754c2f6bcde5a38263df5b1940240","4b830d383168c2b84b43eb69014595a33095bc16112a9708c00c59f89ea4e0bc","9bcb308f56a69975023e3e8ffda2863e6fe1676e9c763bcef31ee9b8edb682c3","701cd09c690a164f8d69c2741bebe2283fa6858bc51655e1027b52bb0a6d5db9","1994e8cf973abf13b67e8019ee3a98b48105a115e37f658e5440d72fc976799d","a1e906c44f2f9b20f2ff3031deb4b742b3566212042880d9becc31dcc6cc294b","2561f9cbaca89d1d5ca223dfd59d3ccb9d9b4a2e2986150d5f34853030dc665b","7fe9bcb6812e04ba1b6680bd44720eefe2a1b6ca566758408f9b6fa04090cf82","ba704cd3cb772ff2c9f82b950cfa035e86a030f3913e128cbd598bc6a21fe100","3308f4e9355594691f687fe146e14fa2735eb1a3cd58bb2af028c695380ded2b","00ee5d422019adc427730c4f2f6a2e6ed6d7e1247d2f6ce6903fa9bfec27bf0f","36b8257975498e19d5e04482c0cc8d26a05620b7e062fa45aeb6bae9328887a9","9e64bed68c83d629098ddbf3b50851ef24090d63962d52a933c9fa8adb423c6c","0eb05f59751b619f8d02607c493a475b3b825a54c535456c204720c1db2fc86f","4fbebe4087f1b5f95112b739fb7d71e9954ff342501aea6fcea1dbfda50d284a","050319521271494235e62dc9d0abd60b6cdab7047203161fa45cd7151d4b6357","54039b4d16b943ac81a3e239d8db01c3f1e6585778aa304fcabafe0714661e46","ce97ecfbc207520af8d2821692527253f7a5ffd56b296ba250e8f13bb432e94e","372fd2bd20270a34659866cb7e03ff444ce81cfde613851bd7efad0b17192223","725d6bc1a7bd14307a517849c2fecd3cbe20868f991403a57e9c1b6accbc8684","494dfe6e0da232ee09766fec26259d08f27662cad2ae0f5e0d9afd00252bced1","1dc031a05cf0ab91eca7db94f1fcd8c8f9078484969c8f8566785e845e5c7aec","3b124ccc11052a20335bd0a0987722e8927a5d8c9868664b5e48843e4f57e677","a3fc9b60f3d1af443b29309946ac8db4eb800dfdc5ea2a1859f64a03354ef0ff","88460b5c22695e58cd34514726c7324bbc1ee148046d1242f282eab07853deab","22bcd477588e11413ba84a01a96c5bb46c21c3c6d5e21e9947d7ad3f1411c456","3a51c6700b8579c6a720caaffa387296f72e1486c7a9a7b5312502c16daed79f","95345fb6d37d2ef254884167d5a02e0cdfb17f3fe55a6b9d5e98a45965c52857","0b27ce17fe62d8a38e6f898b833c14295a5ba5badaadfed653be36af1650f9e6","3747df9172462a0d3c52bbf22993f9bc0f51f99661fe76f8423a91a3655f5a4f","8ee72c0cb7c8fa024646899267ae3a2bbadefa6abfa7e5bf3b7acd51bf97f027","05289fc3e8cbf3f6a30f36ff7d0582dd8a3ebdc1e9230899350bcaf5c241cbe0","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","71d2c9f8a4c9a368d74571330c19ae83cc1cc86245f75b631c56e5f192bb3e70","bbdcf178d57c9842d738638579ee22ab7decd29532c6b68f2a7460e5e4cd5d4c","797fbc0cbb2e56bde2fca0bfb70f9a397fda30b0ee3f71c32cc87d2a8d07af05","001640c817859f0f0cdcfa994bd427797d02213b98a35e9d9974ea9d5d508d6d","8592b3ee11de8e3d3257868571f52dfdcb973ec8af799c23681b41744934e3fd","d0f6a32db4a0e064d29cd1216f529cd895fec3e8c9aa33874c7986a34d4dd6e9","ef4b4d3e39cf827e7f2be88ede3bbaa9d25c8ced500b615831b1bf9fc3f73e1c","fdbb5818502a2bd526238ae07b78c765a52f1577f7e5ee065dd13ecfb204a475","69e85dc8c0cf38e11ee37161ecf55bd3d0a1383ec115ea9ec1863b6e3ee6cb5b","29e3b3d43eabf299958f82ae98dcf3a68b7330305cc6904c07917e8cd46e05e2","2f49e129648fd071896ba9e98b59bd70f6ebad232507b95bbe06bce18ca36fa3","7d3c5e914d1afe56f8a95f8cefca6ad71dbb8b30e2f11bfc5a064f9ed4767897","ea8c840acd0a063c6198e0d6846b48fb14de311fe9b4837f8feaa35fdbfbeef3","f0dd31edb04d5b75a95548f7cfcbdb67783898df388f2241c4127730515eb851","96dbe9ef2c707a259d6111bd24e5cf7cfe034021f0210b3cb0d1aa537e1e0963","e395c23179299a62110629c0e6bfc153b61ff6214eb1bbf8cda75ca41cb2ad3b","9000d7131a28c926fd09dea76712555b38739e6b2a5c47f0c4f084b3599dbb35","0346d1f2732d4fa903c739751949418528e857e859544d8b788361836736e038","2d12e3f292963c13e87a66f23aa2d1169138fcb4c940666010577b13d03116c2","ea94b542cb1dbdf7d609c8caca51446ab95cca020c42e58440aaa8b6bb3d3032","0f2a817bb7b11fda23e4f307e4f98aaa9fae5ad41ce5163c7d3a67f57c4b2006","f6fc928a6ed4c7554cdb4a08b0366c836694be1481b418e535942650ce1e38f4","ba730a1314ded71f3fc272ea353dc41dd01b81c99eb4c1d818d9516de1da4306","b952cf14463a45645794b47edfa8edb3e65a675e39ccba3ea9004cdb9fcc7811","2f8635bc0a2d5cfc16670943bc2df3369a20ec318c1a19a403915981b618cc57","3ec4cacd76555f9bda11c3ffd22e6047cbd199af72ec1d50b400996498d56c7e","3f54b384b17a5d9a74d969e0258cb6f0d57cbaecb295751e9d27bf5d9a15aa5b","47bc5af142b36eb8b5f419781c08ac6dc8901cff8338281c9791493f26f75029","72e353fa58eb757168195680b78d6541ad9733e400fa6e8ebede75259b307014","c5aded6a9d5f4c85d2431b8d9d768883a282157896877f93143b13d82e8b675f","7e5d221c4e67c1c20771348647301b48f1b18e58b0b3407a1f7ce9533cf19f19","74668f1db11402d645297d6a138d103e29a3555f6965c495f4f66ecf925d8c59","c7173b5d819166be8fe820a2d4d3393e0b626d4fdb12ec854c9b280e8a595f23","f7f4f0959596dccb50b0ac1feb25eac2614fcb2df4c7eba68b202eb71f3eafe2","e2fc9a2465d77e3fc430358bdc831ed5ab41594e7fa77a50586cfeeac9c156c7","159bd0fa1a78d6a8ea1813ce437c72f3fbf67264187ec830b0f292fe1dea3288","3f66330e8b4197a482f4c9cc3f50aeebde7505106f23f94ff8f8f812179544d5","cbe4c1c3102db917851a77fe8fce9f00365da63876e4f0822f4bb4bd954f5ef8","622fa89fbaee1b771e58517dbbb3ed8bf60aa4bd501a81b129032c981e825df4","261bd352b27231e30932efafb4e163919c64aad439b7bd19c819c1b2b033885f","a9f87332c75ff064d1113454a108c237cc9f2c792c8175a1ca432cd81fcc6e2b","21f4b283586d94c6df8e71a811d8cadc32e7510ce8027b7901a22524de2b7cca","1c12378cf61ec63760cf5dacea71d7f3372ffce3be36fa06f40b2cd6ce580b76","300089d670fb821ab229218307330be2f71cc6917b550b4f6d915b3f13ee5b45","7d27c68bf0ffa6e7906eb99540ac506dbe25454ea60f705b561b91c9e5449864","648a19f8cd734a9448d9a70c968c793d00cb573d2b4258269db1a4e67d9cf84c","55173f8ae914f540b17307bbd0f96b0ec5debafa94eaa5a185d2b57cec64dff1","88b4ebb3cdd1df4a29fb82a1c7e5ef66a0ee652fc33e7ab619037c73431e0a5c","aecfe4c19ff5bd1d3e3735a007e96dacfe71e22605ce10d782d1e001d11d071a","6132270ffd0016d6c16cdaaf2aeae132982ec2e4d2b655b4cf1bb4107148c6aa","50cf61a7d6c89a070a90bd8a86c19157a7e66ba44362c1b00264e3644498bd87","ddad45d65ef8133e1f0cbd4b541219c70bcfc7c460d3deef668a2b7dc65309c2","6aa06d658c0520bd80e10910e90938464d599b458b3100b904b9371a36672aea","63959ac370486f4540356911537fe6f1f00752b39e808c68c79bd4941f5ebfdd","65898b7aa4d4d0c1b6a86a00127c64d5098207af330bd94d6c6d1772f1dac99e","4b9310761d049db02c1c21994ed2114ac71b28df52224518cf7b9241c8e042fb","3f0f50fe50424eaeb68ff303dda45f0725a267b542070163f1aed99d757779cd","602be747befe4390633c8d470bdad9f464ad0c41f8dedd1a1e528dc2922a593d","757066997ceb2aecb6fb0310759698023e754deeaea4d116c999472bf818c791","10af4b2f1d59591aa93d57c6152326850a8c28f126fffedd726432b152740609","4cf25ed0d118d7e4624825af780e9f69c688040c764b0c426af36ab44c2f92b4","bf75ca5b3ce462ab57a892613154b1e41fbf0add55bea4de14c398071494446e","f05e8fe6cc0dd666353105e181af55d910219765287fd1217d2232aa9f17c5d2","f704f00d5cf1056c4aab14efd50a26fb33cdf52c775c67c82759a588f3e7ff57","2447f4390bcee60c41b754b28e711ca13e8bd28b5bb32b1bfb0ad1ce3b32df88","ae2ac975eda75f6b0a2103f8b84b25fea22d6603fcc052ca51305c2cc7839a3a","f7863b0f771d00b4bd63ae91bc49266b58760170111fff924bf5aaa407051185","158c1df81da4ba785bb31c6512b1c013361a5654366a20557b30ba3f54053931","870654f1e76948231de54e5ec9e0c1f9b9385392454d2e614f6873010036f7dc","183c8bb9f0f399fe2383135c7c02e8447486200e5b7a6bac297fa920e0a8f01f","836a9758bd685bab5a312dfe65368e430a99ed9f26c6943617cd869fee83c22b","5b86de8dd75c48064cac9aa37641c7fef5eedcb63541c8ec8e798898a116d103","9bacb937a771858755bbdd192db5e5f6dc666829d2626e11676e4c0d8bf33a61","de76fe40240a2965fcb79a04c9e72a78cc6688633af79422e74f837f3f40de2c","eca34c408b627f074074aab574d3b6498581240cdce262f207a9ab4974d65e01","a7f06b12b98b7b9f81421ee524d826a7f1e6a5165efc7b06773d656aae2dd835","a968187dfe1768ab481fa7bc13d92d95eebbc63237784e4676288a8d73b62ebf","c006d5c2af6b75af661560e84fe83d1087bf6b75119a7a6e71c2f00788f8061d","621bdfe6bfa087da0aaf2b000bd786e468cd4260af825b7a9f78eb4168cbce5d","0bba401d94c28345a5b47a0c954010c61d8bb08bf1756e222bbf2db2c654ebab","87073aacaf8ee714023e4d1f9bf1d258b38638251bb00744d5160e32b534e490","43e9b8ac8e766d2702c38170e21352d5395797fc0edf1de861b60df74423b8b1","a543a3dc6a07db81e43c3a883194c2e0ef68318fcdf850c0daf6895d5d9d580d","42342cb40ebc2fdb3bdde487d31e1dc14de4b4875af243690a0f75616406c248","6c8101199034c32263da13b914745662298920a42b9e9ba5f855b141a6b1ff54","729ad2834a322b626756f92f8e2aa1a68505ba0e26dd5ed1173bb66d3075acb2","94ffc3cc91950415787624d41dadb850c2ad597c254496f805ef92c28ca93d07","32e59719c12bee81131ff9d6f1b32d7fdb35997e2c963845405ef22f07aa0e99","3266a2ea12e8e2df9d4f20670ac96fbfa1c99806c7b44716695ae4b5d72eebfd","eb3860b4a09312896db637e10d1517d6395e1e17ad2f50bd4fd9ab782a0bd078","62061da20180fadd10a62997a5b6124e727894261bb8f560b26596f3d62ebf9a","bd91c0cec0f3219488efdfb8553afb0669e109d18e0da536c55dc4870f151967","62e4f707d278c09d61ee8c67a969332f7bffd645faa585efb5aedc3bc32dfcf6","9f6e109a517abac1099037eee800c59a271deba1ad0f471bf997df804e35c8c2","997e12f86e1cb896af21b2e278a5e81ad1cdf6118723e9ca3078cd7cade7b650","8a0856f751a988e74c786a64f43a4bc89fff6668ffdd9ca3cc01aa1faffc3e06","3bb5190c755e2f37ce53324f90a796dcc62e098cb65be74c9be5695337793ac1","b9f67e55a3bfbb405124e6aadf34b234ce75a0e159ae3c85788e10088796ffdb","f0db8824c7da30e706ea21f6b4a231e0f63d14e3885dcc1f5166500d2fee44a1","1fe49063f840bab71172cbf6cdd013538483af9dc84bdb6f7eab5d9b90d17a72","ff87b02025981e6a63c31552454cf42c9120d55f6461ab6038752568b0df82cf","0338a3baf082d34a2a3a6adc8b946a7a3ce56f55ca54f6eae89c33d7f4a03e7e","6a5fd6d994c1111259fe0988f5b3e066d5148278d46c236e61e9e8da951e3639","70a388e809e69f422d383d2649bc03d6006d698a066455d7c55653f46c97350d","3bf2cdbb0e56c5f10a74f08b6e42b28afc3fadd4de8f4264033c66c4f20ec0d9","2e3f10f925082d870aff4aad8c67c8436103e4713929e2d24b898b4c3d76f01a","da02124ee07445c14fb5dd0ef35f00cdfa7d66de4257dae29c5554465593d917","882ab64ea9c80431a3784d147c6eb0c93dc15ba55ebf8b9ab77d31f5864cdfc3","9192d71eab5fb3aae3b91c1fddfa321179d7846a11d6a78ec8018fa5142e2647","b421420dd3f400a8c1c06b7f613d200d060a13e84447d981e3240e684fecc1a8","310b2f9bda7e070ca723d0ae4efc861511eac1b1d56c055d25c34e76364e07c4","065adee6073674a2c7da53f575c22aa30561166ba7b56b48f781724c0150453c","089b6f0d68f51d5148a44afde3b6fbc22d44b0794d9718475d7e0a8de0285837","ca4eb3b7e0ee51e1329627cfbd0091b61a5f5ed315047dea4569742a49090e5e","0de7bd986e9bf5f5a45874473aeaac434735c4c88632fbd6e7d89fec67421e22","d5ff31302e4e1b0f336e6d98fb7d0226f051c9d2faa4f936761a43bf2b606e4f","fe8f3b9b4a3bde23e8f05f60b56cb608fc2ba333bee1f9e4132a6724b04d62d1","47e1951768500343059c4e85844eab00e0a83cd4376ab48465142d4d6d9973e4","a35afa2ecb53171941579403dcf9d04cc45522e59c4520f1bba9245cd800fab8","1b57545ecce3a49949e67a63c45303d2ac40c884569cab7e0b13379ce4b7a9e7","c596a0880e41cac78febfc783c725c5b122df65ebe788d6480c249c6bd4f03c6","897559d533e4500cecb323add73af434d74588083141bcbeff1cbc02c7cfbab6","0702c2b2d455661d077fa86854744e7f877167af34e5c18be289b3b5a51e8fdf","066a482be718b091721fc670c9487dccd6704f8595f6472a10ac50b9bf22b582","58abf61b7d8f64e786f1ad4724430038a5cf6b1a49baebe4f9dfa75c45a1515e","bf9968ce3f51845911ec260290615d0355ca34392fdc2e1cc4395258cf256977","89fb01694259e8a622d835e4b627074ef27d34b812247615782853ca2ed7c577","77175ed2398e5879e8dcd878516e55ec5efa880065071a3478a7edb5dbfc755a","053b383e890db107407ef83b75d28da071bd6bc90c5b4960367331f7867d33b8","71484699df2a7b20d0c29ec1a3f75dceb3be077ff59466e76a2d4e0d7a06f372","ff523d10bfedaf121232a56b2f35043784ddeaddeb5aaefb691b6a1560f61f51","09c38e2ee2764f06ac6e8cf5f0ec62cceaef4fd13031ca169797c874c6ec4953","cdc2f9e15e160eeaf1030ae88f7b8aca579437ee55af084cd0882b9be8003ce7","1adae5c108a445540eff06e2d2a8905010d784085e7d31ee2facebf0f6dc1f6c","c4e6f9c57280aa6e76214f24cf7ea57e1bf81b2817f088375b87dc35a12e9336","c5063c77dad57806b76466eff0f13f45218657f9372ed7edde5be2ef34afb9c6","507eab371b1886ca90a9555eb2cfb15424f9c2cc2db1112d4687abaa815f5570","8283e53de5b79da5309633fc05022e95022ab9ffb7e4e6330b05fb8685e68f1f","d9f4d3133638c75445be11ce7da37501a1fb6a43cd5e610c67e8e0af8f342e0f","a8f0f4eee4b84cbdc703c8c794e4cbe041e9567b47dcc3d4149168e2abe252dc","f816d9035ea5406c6f4664f682624d0a5319b08772c988ae960462cf5889faa2","ebed9960c6a080f65fc9306aa93ccb5d08d35ad7ea1c0c85853c03946b837a1a","18b9288e5e727ad5fc2bdc8825ea6835344863e2d78b44b63f5506b183ee3203","abfcd8d01d4cfbc58cc8e44ae9369a5feb083cb55a6d715f3b4c7ff4213c3e23","c0ef90c2345aeb81a8cd28503d875344f748872e19414d9bc27c09956fb516d3","c11fe40f226dca353b77c5d5d45a8b44bb5fd1abc369b5e2f6b0f2f7f6e0acc6","d706493ffa2700d13bc0bc131b1f91190067b85cac1dd4db48a21dbe0a88d40b","cb8b0e6c4a796533aec034297952665f0d62a7551dcc2617408ff07f01ae3902","26ac0adf6571bb5967fe7ec6c7531dac8d2960a3e284ce95274c000874d278d9","9ef637cc115918621c603fc5259e6a5e67e570115678e9608843f7d94c9e5143","fa56779af34b4d68d95f58138d840534b0d0c4643289570c3cee405abdcd29a3","a04161aa5942a2441f34c98b5cc005f732d2d2123441e62cf54d6e150becd77c","a2fab2da85e0d4c3516b8b9095e5af39a599a46d2e80db178ccb63a1b0f69f6a","6e3d4a00b2ea75d66c90c6aa0cfe98e8db19c8bd4e28eb370fb82e948a63193e","70a933f1d50d3c3ba02647e07907511468ca0b586fede2183a5791dcb841bc42","995b25ebf684325d0bcdfd17ecdfdbd11aaff3d27ddbc1661fab0ecaa949c9e4","0a935a621377a10eda3095eb3b59cf470741af224e3e3893e6c5741abc93272b","8d0edb5cbe8c56ef82c29f24be9908b4034fa1b5eb1752a3b984af4e8dea89b8","b4b9f7051ac3ac07d2e2e1cfa5ed95fa6527edf07248d622dcf028040eae0e41","1322537a4c1986d72bf216323d840f61042ee93799eb283bf44c8b461a29da7d","719b97af774406c5ce2ffe33303f37e83823ddee26fd961a3d29b595a24f2a08","8f365f5fa3a43c115371c657b5f71b330ef9a7bc45ba224098fbf7fa6edc3c28","71d3544477ffdc6e1d58b9a3ff9449e51f0faf416a5b5065f45e93bf23eec358","88ac862bff6526f081ef4e9dfab39a22972b01a6fb44a804072f075191b55276","4fdb8c55b176709737b7e87b42b1507ce0ec3a93fdf52341ed56167e07d1669a","b1e54be817521412543831d47b0156342516ccc3e9b6b2bc92c7ad44a5fe8fa3","354476e9485ed3311edb3a343660840896540ee2dfe801fb8da1a610e2057da2","6b0ecb73ac67f71fb5a11242e9dddf9f993ba4f54b108e3ebfb60ac4e4eb4316","645ccf85ce690ab40ce7b41cff57d433af24b7b8ed176e653e0465207afa2d6f","f4fbe3010b70b01a2ea8136db00e871bfec9e999f236c73f40f86dd3d985a4b5","1c1f2f6a8929c8453fb4653dc48aecce8d7886694b98289134a19de21caca868","5b2a7edbe577df1278724490e81b7117c553b2345b1074e194bb4d2cbd4df10b","de0510b5740558cadbcea8727501f2c994c62a885916ae09af0b59b06ff0385b","c892963a9ba4b4cfc7791ca09068077e5076e6435a96ce22d5f1a95f2c62e667","48bcf23187a1b51f47a8276f900015e7dba8f8c695de177c2ed4007b0e0c6fe2","c9c83d8ccb1ff6da1120f06aeca5eb1b062d168808b1012d7b7725770a700afa","322fadbda102d30dcfc06ba8f1d15eb5b16cb74c4edd1d5a1003384504424557","f39c18caa9fba1ff56e8a5daa98c88c6751e67900af5d6df8165b89cf70f52c9","0b94dcb042557d3bd443d90c62232743ee6e13c7948e98e9c6cb818ab2d74193","15661bd4984f67015e1b965bbe8190ed12ed327c078805fb9ef0126eae884354","0c37b5b5f64c69524c02db5e135f25769cff5820bfca2206fcd16c262e49f1e6","6bea1333c2724a27a1f3a90766c3d6681f7ea6718a2313882a127c6b6de5b987","9f15a51a673a9d6012a1f1f2727e73110db20fe57c7379f2d59da0d8d1ba60c8","bdf41796ab319870ccee9f11ed44bc6a0256ee427eafd83ac3ce01fdbe70a8bb","4dced31a38601b707816d536070c05cce583f7091f42f6d324dd19bd501fffba","e51a7a9f9d6e778c9552e579d1e18df71f19276a123ce38a2b9f37e8c2b54a3a","4ca9b306fdf0d2089ccb3dacc9d2f8d49809511bc613c53270dad46eed051dce","de1e8532daaab452b72f4e3b39ec57804d763abdd28508309bf325e91c7e56a8","8df270bf04d75740e1ca90c24f0395f1545a83b785eff5023634c193e62c638e","6487b97069bfeb4b742bb2b56a2f037c345071bac28716ec25199e05f71b4c85","628c4d727e740a85c33533726d5d75f8ec14d992b1f0c734c039b982a8a7081f","2ddcb4551627ca631abcad2e5bd2aa52457e7f4d0e28693eb9fe10e17623b4b6","35321bdb9ba713b4a53cb660c7233b82a8052d3c55e45ae2105f15b82cdfeb67","c6324b7d876e1bf50f1e2d8cf803754f685ece004d0e4a53929725d3f6ce5b04","035a8d815cdcaf07c53d02ffb36e90ba4b62e82c75361c1daa489c23c2709cf1","8267f75fa24c9e41d8b29e7ed6f5f8c6d5af76414028f1c186a03859bc820af9","1442e0a670a230841c361a2955a99b3d31a6359610ac5e486e48d4a297193d0c","1c619398200160c3e10a9143362200bcd459c811af6d52bf39a30527a305e52a","561d7fd3c3fc79b3d29f98b156ed8f30275490b21b46c0c7672273001c1ba99a","a97b2a7ce57423083773c5af089f07f555c0d4c8f248cba027652a0a714df755","367ca303e97e1d8b9fcc915039b1277e5cee9ab312f3d45eaedde6d074ce8e51","510b150f25644e001574475f6cc6044738624f57570d287811e6dc74e86dd7b0","b960cdc130428b43846246846b8de4e5586c0ec370ec711ee64739df99f3d775","2f75313d5109ed40a853d52619cdd57afbb15051d508d9c7d36e6c8d3f3d5a7d","fdd711e572f7578ef306c6dfea458f30a644607c317960debfb222c7420c5ba3","0df1d1e1d7e0297148aa51f9189eea87c009c82da222c8a48f4dde36d7e003d9","c39b05d197c2091b18aed56d3566bccae3f6c30bf4e04e105806310fc9192ffb","e51a7a9f9d6e778c9552e579d1e18df71f19276a123ce38a2b9f37e8c2b54a3a","d3b78a74e856ddc0865d613e40ec4ce16b43c09b03181d89c865e272fef40da8","e754cacc993b899150a9e9ff86d68bec25dcd2f46ac7a606749b40716432f842","a29720c08997c22652d52c3e9b7bd6fb080876dbb9e4252d3c6ba7bfd852a4bd","5289ec752f8088c3cfbc15d654cacf4b514ab0878c1bea0506e163d1e27048c2","0e8cadb118a29dc13f6df5f4e1c840802f885f67688fe2a0c013366f59955ae3","3c9e8ed3afc6c40aa92caf5f4e42c5587a6002c88de41384618859f519b56e05","60af3ff7250c26ec9f0aaf88c5d9041e13dc4462756269ac8ce981dbdd9cc222","431ddd1df3ed10631b7c063f1c58cf76066c2b69ac55d5d68494efc91b470a8e","b57160dcdbedbf00947080320d5c8645bdd09f0ad96d8c428160730d0f6980c0","dde40699416e666aa460d2890eec16bb9f4ac739fb0421a6bb6d3b5cefeee96e","991a1469a744cab4c7430a85229b3a616b24e3b2a0ca3fb1bf4491e8d44d5226","da7e4a134126a008c8f7e79a56d519b61bbafea33527eb9e9e16873a79909132","a076f07b60223f6a8efef81e129d5f7cb6f6be3ea108d1d83de0b3b60ce1fb9d","6d09838b65c3c780513878793fc394ae29b8595d9e4729246d14ce69abc71140","fefa1d4c62ddb09c78d9f46e498a186e72b5e7aeb37093aa6b2c321b9d6ecd14","0e6d87e1af5b3cb046c54714f8afdd0d0fe3c499d96954f29466f92def0f435c","a65735a086ae8b401c1c41b51b41546532670c919fd2cedc1606fd186fcee2d7","fe021dbde66bd0d6195d4116dcb4c257966ebc8cfba0f34441839415e9e913e1","d52a4b1cabee2c94ed18c741c480a45dd9fed32477dd94a9cc8630a8bc263426","d059a52684789e6ef30f8052244cb7c52fb786e4066ac415c50642174cc76d14","f1226c85c75dba57bf83b0df3fcf20af9c8d8a6f1043f33a637425bc41abda85","f2d80ce361931836b85db164e993b2770538c0ca2c13119dcbcdbc8962e2fdaf","a38fbe9176d15bbdfc75bec1e64c8adee2fdc1a3c9c65c1fb15d66ce764cc881","7a819c7133551418f5dcdbf7038879edcf2392baefde8296389f5c3c20cec2e7","a458446a6e4ef3db8be5f214f42490acd6d2bebc9c15c397077b0aae75da6a74","0413281c480cbe10fc6de715e912bf05688c53024884c57d0433981c06e5eb7d","b3afe3e29860550105c6b7c090457ffdf379c9cff3af7f971b4b98506156f413","6b8149d07a97d1cae2528d2a9d9592623fda9df6442dfcd8c64d551eb6e96cd9","d361b28568b863d605dffaa71640cea7c70cd8076f9471cd47ee59f5ce87b250","e0c7d85789b8811c90a8d21e25021349e8a756a256ae42d9e816ecd392f00f71","bb8aba28c9589792407d6ae0c1a6568f3ddc40be20da25bc1939e2c9d76436bb","8fa1868ab5af3818ff4746f383ea84206596e284f7dc5ffd40a0fac08ed093f9","8d4537ea6fcdde620af5bfb4e19f88db40d44073f76f567283aa043b81ef8a3e","0bb848976eff244e33741d63372cbfb4d15153a92c171d0a374a3c0ef327a175","19990350fca066265b2c190c9b6cde1229f35002ea2d4df8c9e397e9942f6c89","8fb8fdda477cd7382477ffda92c2bb7d9f7ef583b1aa531eb6b2dc2f0a206c10","66995b0c991b5c5d42eff1d950733f85482c7419f7296ab8952e03718169e379","9863f888da357e35e013ca3465b794a490a198226bd8232c2f81fb44e16ff323","700e175233fc5158e9d2e02268dcbc2709c8487936a6f292cb97ede32549ab3a","b77b94b224dc00977a2b7cb66e52832d3b2dec7097b2ca10ef3b7e7c751f37a8","e9c96f08c7909362d5ee343d5ea9c0f315b585626545ed7b96ed6dd272e9e847","565902cb0755fa703d1dff0e50714ff40c26f786fc98606c10b8ff0662b261db","9462ab013df86c16a2a69ca0a3b6f31d4fd86dd29a947e14b590eb20806f220b","b4c6184d78303b0816e779a48bef779b15aea4a66028eb819aac0abee8407dea","db085d2171d48938a99e851dafe0e486dce9859e5dfa73c21de5ed3d4d6fb0c5","62a3ad1ddd1f5974b3bf105680b3e09420f2230711d6520a521fab2be1a32838","a77be6fc44c876bc10c897107f84eaba10790913ebdcad40fcda7e47469b2160","06cf55b6da5cef54eaaf51cdc3d4e5ebf16adfdd9ebd20cec7fe719be9ced017","91f5dbcdb25d145a56cffe957ec665256827892d779ef108eb2f3864faff523b","052ba354bab8fb943e0bc05a0769f7b81d7c3b3c6cd0f5cfa53c7b2da2a525c5","927955a3de5857e0a1c575ced5a4245e74e6821d720ed213141347dd1870197f","fec804d54cd97dd77e956232fc37dc13f53e160d4bbeeb5489e86eeaa91f7ebd","d490fd491b1d464673622833af5fcddcecbe16d8e35e4e93b4ffe0be2dbbf24a","3ddd84f13846024c7e50a2d8ac6503c4f5839390007a4a78fe49cdda847d6873","6d1bc2660ecb2702daf6952d4b60c9421cdc7a70ca801f6c02100308f1b93d25","3303b9b6c497d7b4f4ca73431b599a4f1ef95c713d1e25e8d64435ffc435f9d9","ce28074d078a84ebe715d3cca967400568d494028044e15689eda3e78aaa25d1","a51ec59808167919b26d173c7f192d531e8aecf80e6dee221144d664f572e11c","fbef5dcf020425aa28dd1617db8259826f6e66cd160b8de777796f7cddabd10b","dd6a4b050f1016c0318291b42c98ab068e07e208b1ae8e4e27167c2b8007406f","91c7d7e8c73102c8d13f0d111bc8bba74881f657c4161eda5c3fc60ea36bf9d2","1a20380db579a422ffdf31049ac1fbdb99c7b282e4e5d77f7d237cd06022d654","0289b0c5ac5cecbd37b2708dd111315c8f3f3f68e4dbbeaa47809c4e9677d32b","67ba9c0f074b9c465b4ff736ef4e7acf9f2f254826876961bc9453b0304388b7","f212d302bbc77ad61b539cb56cac886e6d8a32ca78de5e5a6d8c2d4b8fcc74eb","4cdd2d5c74c8387a9f107db566403fcc02eaaf6982441ef6df65f3df2f68d5f9","04ef5e7f22b66f75188fb1a9d757c04800b3438d41ad8d85658a143984bb1e77","7b422d96d17c6136b75268b6c087a038f73d7d97f8a2417cbbde344a67e5d983","4152e7e368a6241c0b85fba978053ff2dc3d6ea52145009c12eb06917d82d4b4","e46f472b384885ecee3fa5455074331ecd0991fc6ebb8ecfa8417b9770e0e106","ecb4408fa7e1a169fa225033e3d774714aea9a956de3e53078857e5553d46f1e","85078ab3da27e3b2afc5a0968d00dea22582c78cc4ec624df66a42b10f51ae41","e6e29f77526c35650f63d323862e5cfed6eb5313467547b62dea8135862abeaf","f17cbfc2ec38c6f84e7d66b65a428d1c90f3f1ef9a8c46d69490f3cb22541948","19d6856e801289b528b6db2505d3f32df49c8ab45a66dc0b497df00ff793d80f","f2b2f0193eb96e6fe05e73dbac9696d09a1b94557293038d88a499a1a1b49eeb","76442a5364a6c719313bf5b88508a563f482b44ceea5d14ab94dbe20597c33ff","f9ff64de84283c93f28c3a467f65c1618088488e72d3018f9602c532f89c614d","8eaefabb06b251a9f9314fc0004689872496726e5b78f120ccc4215afaa7a2e0","ad168a9c225efb565037b4d5f3c5e88a4fcde1a34143e05cc5b1af44e6fd70ea","5bf439b1517d577edaaa00e673e1c777fc7eb7444c1c5c78607b825c76ac4a3d","570bd44d915b7262cbfec16729029db8d6154ea37c0f0ddf4265ac6c4cc7ca64","c1e2a3a01e6403393c08ba83ed15dce9579f5ae1758401406b03cbf5d79e8a1e","acf11e3741c7fd3f0e817c449db26e38e9880ed42a9befcb704f26d079c9025d","740d6fefc24f2d76dfb72f27a298351160866f671d6f344cf56e4050a501f30b","a543a3dc6a07db81e43c3a883194c2e0ef68318fcdf850c0daf6895d5d9d580d","ac27bad9d596d9058e8c2a90913464913aa729acf04d3450e9c827204a70675c","8a43e2edba6810eeae21cc23658e578abca448dae863a499a674cc060abf9e13","332fff1f24c3ab927eae14f310b6eeb2edd47148fcca58839c03bb4aec7dc764","8713a1daf81ae90f2e856579a11786a7240efc8d2dcea8c8365a2b1f183e05a2","21aed6d78571d22df89003e47266404c1606b59aee7db4316a62adf66ed68c47","4829b5d40f0c0eac81925df2d8a06e6866a8f14f5c3c84b6f2960c535038ad0f","f821e5b74fb6bcb786d4bf5e99a4059454b47f9bc8352a134d3aada98936641d","f8b56a31d599d8ac97ab2e82282b9a5e10741e045e09f7715150f6d7805b4930","21c11846959580cee9ee2b5575a97d6bee0a2a312277a8e7c9be65bf384ee077","a214dde9a6ffc94e46822b6c617da695740c8a27957c60497a60ce5e9018322c","acf11e3741c7fd3f0e817c449db26e38e9880ed42a9befcb704f26d079c9025d","b527df0142b18c1d5d41f6602b377f3117342026c4ec5654df57d77bfd0bc59b","736097ddbb2903bef918bb3b5811ef1c9c5656f2a73bd39b22a91b9cc2525e50","4340936f4e937c452ae783514e7c7bbb7fc06d0c97993ff4865370d0962bb9cf","5fc6e6b8232254d80ed6b802372dba7f426f0a596f5fe26b7773acfdc8232926","d259cd3eb326cd792648aacb78226510b5cd43c03584b103860acddd8f3223fe","2212cdd51f47aef84d374eca667b7e1088386d453dc12e335d43b11b6ec83ac2","b7f6cc9fcf17340bf4f8421a34befdd12e53500bf0c4c65151b8129cbd6815d9","a286250d11357e4d68a5d6363070a07ef5b5f61d8ed5b3ed9ed938b9fda22e9c","4b81668675d145b75b9516a74b4c5e33d4b0a64fa381a66b7413fcda3bbdac16","584f63101c3733028c1f6c403a9a294c07459e8464766f66470c421e33e2d468","e67d14a92d9624ae790ef4218984b25d20f9c2085e9a7a3012aa2306aa2b1442","4f502d6b8a9d35304a439413f1c0e578510fe60168abb88ea18123d9d20e9f84","522cb15ff9bef5a65c2f3dbd10dbba9e7ecae4de32f90f5c0b4198132be63ae4","b066891be498cb582eaa68ac6af8776535d6e20d81a680f20ac9e168dca92e6c","ec2bc868c6869e58a0963998998c41fc464d0377058cc0224a266ad4d964aa18","acf11e3741c7fd3f0e817c449db26e38e9880ed42a9befcb704f26d079c9025d","1f306bc3ba6ce0486bbd05912b7e8ef78356a91d3de2d7b3336994be45a73ed2","a3a7229dea45fec3b66fb3db95ea86b6f79456d53b01124be574234b855e7f33","68ab2c8431d98d2050e4acff729c2a2fc9d780d7be4aa0c48137abdb041e9495","5fe8ea60d97acf3715dfdd51762579c6e45d564c791d7efcc9ef231e13e1fcee","c14b6c4e01e0e97530fb728d87c38518593b3a226210597843a705d0997adae8","11650c5bddaa406f3d38215ee50e9b7ef974a4cd547c232d318e440ec9765b6b","30d0676ca3e94d7aa946f0fa8af9ae45bb19fdbb59e52a7ba2fbb8e2bc62dc10","4f2a8b9949619452c5ddcca481a9bbe9169b3ab43e5b70a7a632744392a8795a","ccabb7c015e846707548007b8f088292a16ab4388f8d1be805d1fe6d87d9f000","304b541f8854265cf52a16085ac5e11ac88ca9edbe7d0d60a976f28cb00a44fd","d6d314f5004a170d71ab74f4ed161a29b2441afe4702c7df86cdbfbd33d4cf8d","c28f3faf67f36f4872c9a10f42ffcef0076a09f94751ed59f0732331278a53d3","50a35911adea0f1b9f2b5fdb69c38e281e5f84327d52d009efc49acac3b8d8ec","f981e167d39a27a8b4ac10cc8cd2dd26c784a3a6f6366fc467ffa004a01a7f3c","db3387802a18f6fcb38c5d7c46bfd2b1a7dd3de399827f9c4cbe7648e0faf0f9","062ef3aaaeb0bde8f7e5f011415677d9b3db2babd81ba55dd8ec0f0569d6f922","091f417275a51ab3c47b949723e9e8a193012157ecc64a96e2d7b1505e82f395","0e35192e28c443a2b3f0695d910778b2773b648822045312d1b1f561b88572ce",{"version":"c809979f4b12b480d26fc8c158be16e3e2bc55430088d36ca71c3db919fc48e7","affectsGlobalScope":true},"a43b0fd9346cc0a6fa65fae01c61503a36beb0619a51feb7dacfab41ec214163","87303ad8c498800b81bba3defe79a8555eeee5c6a739fe0ef9ba81b4921954ae","f0e4a60d7fb7fc61328bef5c28659d0918e4a7f5370520b0fe0779759573f963","bc35c1e332da3bc76f493ffc4e5f95251217fb1b920422d17ff0b8db06e56ca9","7002b009678cf1a0e0d9bc2ae13958b72e8ec7b8d9bbff1f785aa199344e7c4c","2560027853ef223ec888d7d333bae95e0dc8090d7bfc72b56d188f8435485891","eb719ac7cb6dcc14e83550f2bd1497b3389d2600226eb346bcfda0c5f49251ef","e34843f28551575bfbaf1f18311ba49b61a3cbef6e4eea9e93d0c0231b2812f6","b0f2d94e5e9d4a33d411a93129f35b7c07651810728b66c99178ad174be82ac4","fc5a5c7b822c085b8d01823c3cde9a74881ba022528b9285c34d8e42a6d556fa","8be3a5397ccb10e43c176bd4ead8d4ad6de38f184e2354320e666e47e453f747","52d9ae6fa74e450fae31484bc30c1fcd2832df5369748b73e385ca57677502da","6495b9cfbb5a322343986add738994d82c05a24575b1685473b8c3d95cc88417","5e1575598c0a1d1aa2115748939d0d03953c8deb74316ce85e326865d429cc88","d228da549581aca78326931a9707631e1e576922c9dc4cef57c86c3847ef4cd4","2a7aedd322a84c05fd00201b8b2ebab441b652695f44bbc0aa9b2949abb56bde","eea24f7fac616e730bb8058340da46875251d67cdd509e0fd7b0fa3aaf4fa99c","146ba4b99c5feb82663e17a671bf9f53bb39c704cd76345d6c5a801c26372f44","34dee92b153f992275b7392e5d29758d85493770e74f4163769e478c262e83a4","6d2437ef88f882256b80ba819165091193f4ad8023722bab7397cefe220de688","dff84fe16d4ab8598eb05939c3a41e37e3bc748cf657b3f03b777c99251fea91","b3fc13023d7df1f742d68f24ff64395eec09a99b3120d5705980bbc3a0210569","0745545e747c5fd3e2fe175ddd34e682560d74cdfca7743e3682c2e457074591","e51cc455bc3f4c8649bf2b83807c63db17a9d0e3e12e1d7e7df08ee4c7447036","199b69bc097e6f08fcdc98545c4fa0950b5fffa8df903c00ba61553dc2faa4b8","f9851ced26c549916616ad08373e1d407ad7d389b6d6888a43d68972dfa9fc99","eaf246a4d73564d87ce6255030d4423f66f950c79621273d61ed0a35ae7f7418","8824ebf4bec9beb5b4b6b66d97911a1808bf96b51ef1ccebc8c0999ad9be84e9","043ae9f13b51a9f1e42c72787a7ec95eeda0edb4fec888678b3357640a7f6098","5b17e207ba951ea90f04e73f96e485da991771dfa14d5789ffcc61480aefa834","6ed9178a096a43c035fd2651823545a4a494792403d7864334d1401a1f502a9b","1aa48a2d95c15f71bf9fd96c0dcd316cf08a52dd132c942ed16213267be23703","e766c554a08fb1ea1d7c7c45ef08e09027f66b6cc766ef3dbd76ac412a0f5fb0","7f24905c24b3e8aca9ed7cfc5566308797501fc62da6358e3ff57812604b31d7","9ea17613515e1fb6517e8d5c567425504326e4cf520c941c2f29436fcd694983","a546a348076efdba3b2e0cf3b91eee945765041778cc7ed79dea94868fbccb54","db49fc2ab455a34290feaeac6657f2ade2f3084b5125311da9884ecdb71ae3b2","bd95ec6dfec8e111e8c11b56ac405c35b4fe2fa71d5e14fd1c1b1858473f0e99","b49583ec575b460ea680a34a792fb72f993ef93b5a27bca89a83ca81232e390a","13e44f1c49e5251ed27e3467bde2d3398a5d4cd3443864e6ad2d5df63f2e24eb","cebc4f9c184a0ea1e36d8993778e93f787f2d8e84cefd178f336342e0a44b209","402ab8e3133e9ba3770ffd571a416fa563ff3f12ef4e48f1149f896e32a15e32","6c3183eba539fa21b8a6fb3ecd407bf7e8e47cc0652ae0dd26f578ce0a78c00a","14afce1296e564cf037f7aa4d2287c0c1c9337faab63ffdd5ddc9bd491bab354","327aad999ae3dd9481a9dd9a1265d2e4a8281fbbde03af519aeeac1a2122da13","b8e83a7addbe0ee5650a2db8a92db94a260d183c9bc298345783d6c2f12c9d84","ea58d49b12a8d73b748ef974290efc21ca7a1416fb21600b09fc9454297aab71","a9719dd4a00d40aa641e332ac1e9bbe352f05d42be476a4adc9d3a5a02d1c889","80505047f796ae6fdaad80f7309ddff6e310a2c947f97bb9921f5847baac59e7","caded5de5e814c6aae0d62850870944caf0c232b26085401253c559e4cb79f66","5b6e94a263905441fb48c1f2c70443ca85bcf71c63348e9d3cb60d5d244af3d4","97cc0d00a5d9ba26dc0f9039d5ef3e8f2f87aaf392d07cb7741fcc411bb40ba1","e932bbc249898f5faaf243a4207215d8a32e43490612b5d4ed2b5d6cbdb0b396","0a82989749caa5c07d4ade88d0a1430abfca78929fa9821354282397784f1485","6fe541bba2f7646e2b416552f609d06f1792e16029702a582164cb9f080dca95","52aa5d545a96e374c89ef603bbbbc446b350691a2dc0f7f878be0494a8053ea3","580cf7cb1db43ae489b4b19422557ac3a560130bfcf8f0832ca3ec9295332940","076ba3774a16befde97d253f8cfec826ab649e9c974c1bc4a10dd1fffc8be635","dbe81e637194192e28331bbd82befefd097d279e76f8c95983f467f5078f1a61","89890e86416bd9ed3d69baebd7c76cc1a2dd2f0f9d3143469269f3dc3fb3a1fe","40aecba93cb110a040ec1fa7198bde496dc098ade407f9312f03346bd0c4386d","41c690db4080755961b1444d818aab92e8f2a6d859242e0c1fe73f729ca0f6bc","0957d068377b9f2b45a9ddb224d5da6f3887d8d381cdfe65150fe9664a5103d0","875448154b214e2783dd0a4c3412c1bf1cd3993eb8b8b7dfbc58442e649d7aea","6b16df80be1117862e187c11476f5bc207b173c02a7b651fe70b38f055f3ed74","9f580121ca97bc912d4d993c444e33a90b5bfc7318bdce406b750e42a27feac7","4111303495901ecf20b018e4c64f7527ab97280d52e6c61a8240a60082883fa0","bda3692f9fe51ba9e213c9368bcd099dc8c40891436a32dd396c5b4308f73c32","d752de61df5db208a448247cd73f8c987f5b7748a90c677cbe48f101acfbd23c","7f13e6736d694f9073176666c18847cdcbd81917c814b95ae4682013d118414b","e15ba85cfefc4635fe7e7c56fe93ec363bbd0c046126c4dc303a315d75f2929c","bbf471a8a9cfe3e8d27182edc49d3aa662f46e01457d1e92028ed420ff730141","e222104af6cb9415238ad358488b74d76eceeff238c1268ec6e85655b05341da","69da61a7b5093dac77fa3bec8be95dcf9a74c95a0e9161edb98bb24e30e439d2","eba230221317c985ab1953ccc3edc517f248b37db4fef7875cb2c8d08aff7be7","b83e796810e475da3564c6515bc0ae9577070596a33d89299b7d99f94ecfd921","b4439890c168d646357928431100daac5cbdee1d345a34e6bf6eca9f3abe22bc","5d72971a459517c44c1379dab9ed248e87a61ba0a1e0f25c9d67e1e640cd9a09","02d734976af36f4273d930bea88b3e62adf6b078cf120c1c63d49aa8d8427c5c",{"version":"f624e578325b8c58e55b30c998b1f4c3ec1b61a9fa66373da4250c89b7880d44","affectsGlobalScope":true},{"version":"d3002f620eab4bf6476c9da5c0efb2041d46f7df8b3032a5631bd206abef2c75","affectsGlobalScope":true}],"options":{"allowSyntheticDefaultImports":true,"declaration":true,"declarationMap":true,"emitDecoratorMetadata":true,"esModuleInterop":true,"experimentalDecorators":true,"module":99,"noImplicitAny":true,"noUnusedLocals":true,"noUnusedParameters":true,"sourceMap":true,"target":1},"fileIdsList":[[1232,1443],[47,1232,1443],[274,1232,1443],[273,1232,1443],[273,274,275,1232,1443],[406,561,569,570,571,1232,1443],[570,572,1232,1443],[398,406,1232,1443],[483,484,1232,1443],[398,457,483,1232,1443],[481,482,1232,1443],[443,455,480,1232,1443],[479,1232,1443],[443,455,1232,1443],[421,422,423,424,425,426,427,428,429,430,431,432,433,435,436,437,438,439,440,441,442,1232,1443],[376,377,378,379,380,381,382,383,384,385,386,387,388,390,391,392,393,394,395,396,397,1232,1443],[456,1232,1443],[398,455,1232,1443],[473,474,1232,1443],[398,457,472,1232,1443],[398,462,1232,1443],[398,1232,1443],[398,460,1232,1443],[458,461,462,463,464,465,466,467,468,469,470,471,1232,1443],[375,399,402,405,1232,1443],[398,404,406,1232,1443],[398,400,1232,1443],[399,400,401,1232,1443],[487,488,490,491,492,493,494,495,496,497,499,500,560,1232,1443],[472,487,1232,1443],[485,487,1232,1443],[406,475,487,1232,1443],[487,498,559,561,1232,1443],[487,498,561,1232,1443],[498,561,1232,1443],[406,1232,1443],[406,485,486,1232,1443],[459,1232,1443],[443,445,1232,1443],[443,1232,1443],[420,443,1232,1443],[418,444,445,446,447,448,449,450,451,452,453,454,1232,1443],[419,1232,1443],[427,428,430,433,437,1232,1443],[421,422,426,427,1232,1443],[427,431,432,433,435,1232,1443],[421,422,427,1232,1443],[425,426,430,434,1232,1443],[422,429,1232,1443],[427,430,433,435,436,1232,1443],[421,422,425,426,1232,1443],[422,425,426,1232,1443],[423,424,1232,1443],[438,1232,1443],[408,1232,1443],[406,408,409,410,1232,1443],[407,1232,1443],[398,406,407,1232,1443],[398,412,1232,1443],[398,413,1232,1443],[398,403,1232,1443],[382,383,385,388,392,1232,1443],[376,377,381,382,1232,1443],[382,386,387,388,390,1232,1443],[376,377,382,1232,1443],[380,381,385,389,1232,1443],[377,384,1232,1443],[382,385,388,390,391,1232,1443],[376,377,380,381,1232,1443],[377,380,381,1232,1443],[378,379,1232,1443],[393,1232,1443],[565,1232,1443],[564,565,566,568,1232,1443],[567,569,1232,1443],[563,1232,1443],[404,562,563,564,1232,1443],[501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,1232,1443],[503,1232,1443],[503,507,1232,1443],[501,503,505,1232,1443],[501,503,1232,1443],[503,509,1232,1443],[502,503,1232,1443],[514,1232,1443],[503,520,521,522,1232,1443],[503,524,1232,1443],[503,525,526,527,528,529,530,531,532,533,534,535,536,537,1232,1443],[503,506,1232,1443],[503,505,1232,1443],[503,514,1232,1443],[47,284,605,606,607,1232,1443],[47,605,1232,1443],[1232,1371,1443],[1232,1443,1566,1568],[1232,1443,1562,1563],[1232,1443,1562,1563,1564,1565],[1232,1443,1567],[1232,1443,1569],[202,228,236,1232,1443,1456,1457],[150,1232,1443],[186,1232,1443],[187,192,220,1232,1443],[188,199,200,207,217,228,1232,1443],[188,189,199,207,1232,1443],[190,229,1232,1443],[191,192,200,208,1232,1443],[192,217,225,1232,1443],[193,195,199,207,1232,1443],[186,194,1232,1443],[195,196,1232,1443],[199,1232,1443],[197,199,1232,1443],[186,199,1232,1443],[199,200,201,217,228,1232,1443],[199,200,201,214,217,220,1232,1443],[184,233,1232,1443],[195,199,202,207,217,228,1232,1443],[199,200,202,203,207,217,225,228,1232,1443],[202,204,217,225,228,1232,1443],[150,151,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,1232,1443],[199,205,1232,1443],[206,228,233,1232,1443],[195,199,207,217,1232,1443],[208,1232,1443],[209,1232,1443],[186,210,1232,1443],[211,227,233,1232,1443],[212,1232,1443],[213,1232,1443],[199,214,215,1232,1443],[214,216,229,231,1232,1443],[187,199,217,218,219,220,1232,1443],[187,217,219,1232,1443],[217,218,1232,1443],[220,1232,1443],[221,1232,1443],[186,217,1232,1443],[199,223,224,1232,1443],[223,224,1232,1443],[192,207,217,225,1232,1443],[226,1232,1443],[207,227,1232,1443],[187,202,213,228,1232,1443],[192,229,1232,1443],[217,230,1232,1443],[206,231,1232,1443],[232,1232,1443],[187,192,199,201,210,217,228,231,233,1232,1443],[217,234,1232,1443],[1149,1232,1443],[1189,1211,1232,1443],[1189,1220,1232,1443],[1189,1214,1220,1232,1443],[236,1189,1213,1214,1215,1216,1217,1218,1219,1232,1443],[236,1189,1213,1214,1220,1221,1222,1232,1443],[236,1189,1213,1214,1220,1221,1232,1443],[236,1189,1201,1212,1232,1443],[1189,1213,1214,1223,1232,1443],[1205,1206,1210,1232,1443],[1206,1232,1443],[1205,1206,1207,1208,1209,1232,1443],[1205,1206,1232,1443],[1205,1232,1443],[1202,1203,1204,1232,1443],[1202,1232,1443],[1189,1232,1443],[1188,1232,1443],[1187,1232,1443],[1189,1193,1194,1195,1196,1197,1198,1199,1232,1443],[1187,1189,1232,1443],[1189,1192,1232,1443],[202,217,236,1232,1443],[1232,1412,1443],[1232,1372,1373,1388,1391,1411,1443],[1232,1410,1443],[1232,1371,1372,1373,1383,1391,1409,1443],[1232,1372,1373,1443],[1232,1384,1385,1443],[1232,1384,1443],[1232,1371,1372,1373,1377,1383,1443],[1232,1376,1443],[1232,1374,1443],[1232,1374,1375,1443],[1187,1189,1190,1191,1200,1232,1443],[1190,1232,1443],[618,1232,1443],[618,619,620,1232,1443],[617,1232,1443],[236,1232,1443],[404,405,406,411,414,487,488,490,491,492,493,494,495,496,497,561,569,570,572,1232,1443],[415,573,1232,1443],[404,405,406,411,414,1232,1443],[1232,1393,1443],[1232,1392,1393,1443],[1232,1392,1443],[1232,1392,1393,1394,1401,1402,1405,1406,1407,1408,1443],[1232,1393,1402,1443],[1232,1392,1393,1394,1401,1402,1403,1404,1443],[1232,1392,1402,1443],[1232,1402,1406,1443],[1232,1393,1394,1395,1400,1443],[1232,1394,1443],[1232,1392,1393,1402,1443],[1232,1399,1443],[1232,1396,1397,1398,1443],[1232,1378,1379,1380,1381,1382,1443],[1232,1378,1379,1443],[1232,1378,1443],[161,165,228,1232,1443],[161,217,228,1232,1443],[156,1232,1443],[158,161,225,228,1232,1443],[207,225,1232,1443],[156,236,1232,1443],[158,161,207,228,1232,1443],[153,154,157,160,187,199,217,228,1232,1443],[153,159,1232,1443],[157,161,187,220,228,236,1232,1443],[187,236,1232,1443],[177,187,236,1232,1443],[155,156,236,1232,1443],[161,1232,1443],[155,156,157,158,159,160,161,162,163,165,166,167,168,169,170,171,172,173,174,175,176,178,179,180,181,182,183,1232,1443],[161,168,169,1232,1443],[159,161,169,170,1232,1443],[160,1232,1443],[153,156,161,1232,1443],[161,165,169,170,1232,1443],[165,1232,1443],[159,161,164,228,1232,1443],[153,158,159,161,165,168,1232,1443],[187,217,1232,1443],[156,161,177,187,233,236,1232,1443],[1232,1387,1443],[1232,1390,1443],[1232,1371,1388,1389,1391,1443],[43,51,134,265,266,267,268,269,270,1232,1443],[43,44,51,200,209,210,262,1232,1443],[43,51,200,209,262,1232,1443],[51,1232,1443],[51,58,59,63,134,137,141,144,149,237,238,239,244,245,247,249,251,253,259,260,261,1232,1443],[51,291,301,1232,1443],[51,291,301,303,304,1232,1443],[51,301,306,1232,1443],[51,301,309,1232,1443],[51,291,301,312,1232,1443],[51,250,1232,1443],[51,293,294,296,297,298,299,300,1232,1443],[51,291,314,318,1232,1443],[51,291,306,318,1232,1443],[51,252,1232,1443],[51,58,258,281,293,296,299,315,316,317,1232,1443],[51,258,1232,1443],[51,303,304,333,1232,1443],[51,291,333,335,1232,1443],[51,291,333,1232,1443],[51,291,333,338,1232,1443],[51,333,340,1232,1443],[291,333,1232,1443],[51,291,333,346,347,348,1232,1443],[51,306,333,1232,1443],[51,210,303,333,352,1232,1443],[51,246,1232,1443],[51,293,296,297,321,322,324,326,328,329,330,331,332,1232,1443],[51,291,303,304,358,1232,1443],[51,291,358,360,1232,1443],[291,358,1232,1443],[291,358,363,1232,1443],[51,291,358,1232,1443],[51,358,368,369,1232,1443],[51,306,358,1232,1443],[51,210,303,358,372,1232,1443],[51,248,1232,1443],[51,293,296,297,299,354,355,356,357,1232,1443],[51,288,291,1232,1443],[51,58,282,1232,1443],[47,51,284,1232,1443],[51,285,286,1232,1443],[51,58,258,281,283,287,1232,1443],[577,579,1232,1443],[51,241,1232,1443],[241,1232,1443],[51,240,1232,1443],[51,374,574,575,576,1232,1443],[51,576,577,578,1232,1443],[51,577,1232,1443],[51,575,576,1232,1443],[51,291,599,1232,1443],[51,58,596,597,598,1232,1443],[47,51,58,596,1232,1443],[43,51,603,1232,1443],[47,51,58,601,602,1232,1443],[47,51,58,209,1232,1443],[47,613,1232,1443],[615,1232,1443],[624,1232,1443],[51,303,626,628,629,1232,1443],[51,615,626,627,628,1232,1443],[47,51,632,638,1232,1443],[47,51,291,303,632,638,1232,1443],[51,284,632,633,1232,1443],[47,51,284,291,632,633,1232,1443],[47,284,609,612,613,1232,1443],[51,622,1232,1443],[47,284,612,1232,1443],[47,51,284,612,1232,1443],[636,1232,1443],[611,1232,1443],[47,284,635,1232,1443],[47,284,651,1232,1443],[47,51,1232,1443],[47,51,582,1232,1443],[581,582,583,584,586,587,588,589,590,591,592,593,594,595,1232,1443],[51,593,1232,1443],[47,51,591,1232,1443],[47,51,582,585,1232,1443],[47,51,58,612,1232,1443],[47,51,58,609,612,618,622,623,653,1232,1443],[609,612,613,615,622,623,624,626,629,632,633,635,636,638,1232,1443],[626,1232,1443],[51,58,615,623,626,627,628,1232,1443],[51,58,615,623,626,629,1232,1443],[632,1232,1443],[47,51,58,609,612,613,632,633,634,637,1232,1443],[47,51,54,58,612,632,1232,1443],[47,51,58,608,609,610,611,653,1232,1443],[47,51,612,615,1232,1443],[51,58,1232,1443],[47,51,291,665,666,1232,1443],[51,291,1232,1443],[51,291,663,664,666,674,1232,1443],[51,325,1232,1443],[47,51,58,586,596,663,664,1232,1443],[51,58,209,596,1232,1443],[51,58,596,1232,1443],[51,291,656,657,1232,1443],[51,291,654,655,657,1232,1443],[51,291,655,657,1232,1443],[51,295,1232,1443],[47,51,58,209,596,654,655,1232,1443],[51,58,209,596,654,1232,1443],[51,596,1232,1443],[51,291,678,1232,1443],[51,58,596,676,677,1232,1443],[51,58,209,258,291,296,596,676,1232,1443],[51,291,682,1232,1443],[51,291,680,1232,1443],[47,51,284,291,685,1232,1443],[47,51,596,684,1232,1443],[51,291,687,1232,1443],[47,51,291,689,1232,1443],[47,51,58,1232,1443],[47,51,291,692,1232,1443],[51,58,691,1232,1443],[47,51,596,608,1232,1443],[720,1232,1443],[712,1232,1443],[709,711,1232,1443],[715,716,718,725,1232,1443],[47,284,727,1232,1443],[47,51,719,725,1232,1443],[47,51,291,1232,1443],[730,1232,1443],[47,51,291,725,734,1232,1443],[47,51,284,733,1232,1443],[719,1232,1443],[715,1232,1443],[51,108,109,110,112,117,120,121,123,1232,1443],[51,125,1232,1443],[108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,1232,1443],[51,126,127,128,129,130,1232,1443],[51,694,695,696,698,703,706,713,718,720,1232,1443],[51,715,716,717,1232,1443],[707,719,1232,1443],[694,695,696,697,698,699,700,701,702,703,704,705,706,708,713,714,720,1232,1443],[51,712,719,1232,1443],[47,51,58,717,718,719,730,733,1232,1443],[47,51,58,596,605,718,719,727,732,1232,1443],[47,730,1232,1443],[47,51,596,1232,1443],[51,709,710,711,1232,1443],[47,51,58,596,718,1232,1443],[47,51,58,209,596,741,1232,1443],[51,744,1232,1443],[47,51,58,209,596,743,1232,1443],[47,51,284,747,1232,1443],[51,58,209,596,746,1232,1443],[1050,1232,1443],[51,1018,1232,1443],[750,751,752,753,1232,1443],[755,756,1010,1232,1443],[1038,1232,1443],[1018,1232,1443],[1031,1032,1035,1232,1443],[1010,1013,1046,1232,1443],[1046,1232,1443],[1010,1232,1443],[756,1050,1051,1232,1443],[1051,1232,1443],[1027,1232,1443],[890,1027,1232,1443],[890,1232,1443],[756,1012,1013,1038,1050,1232,1443],[1031,1035,1232,1443],[1045,1232,1443],[187,1051,1232,1443],[51,1008,1232,1443],[51,1022,1023,1232,1443],[1044,1232,1443],[756,1050,1232,1443],[1076,1232,1443],[1018,1076,1232,1443],[928,1232,1443],[759,763,795,808,826,830,839,844,895,905,973,980,1232,1443],[1007,1038,1232,1443],[1031,1033,1035,1232,1443],[1031,1034,1232,1443],[932,1232,1443],[890,932,1232,1443],[1027,1050,1051,1088,1232,1443],[1037,1232,1443],[47,284,1046,1232,1443],[749,1007,1232,1443],[1038,1046,1232,1443],[755,1232,1443],[1050,1051,1232,1443],[825,1232,1443],[1036,1051,1232,1443],[200,209,1031,1232,1443],[755,1010,1013,1046,1232,1443],[974,1232,1443],[983,985,986,987,989,990,992,993,996,1001,1002,1003,1004,1232,1443],[51,93,1232,1443],[89,90,92,93,94,95,96,97,98,99,100,101,102,103,1232,1443],[91,1232,1443],[51,91,1232,1443],[1017,1028,1232,1443],[51,749,756,1007,1008,1009,1232,1443],[51,1017,1232,1443],[51,756,1232,1443],[1026,1232,1443],[51,1031,1032,1033,1034,1232,1443],[1031,1232,1443],[755,756,1007,1008,1010,1013,1014,1015,1024,1025,1030,1038,1045,1046,1232,1443],[51,1016,1018,1021,1022,1023,1232,1443],[51,1019,1020,1232,1443],[749,1232,1443],[749,853,1232,1443],[749,750,751,752,753,846,847,848,849,850,851,852,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1232,1443],[749,757,758,759,760,761,762,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,1232,1443],[763,1232,1443],[749,955,1232,1443],[749,960,1232,1443],[51,756,1007,1232,1443],[51,756,1007,1008,1012,1232,1443],[1016,1232,1443],[51,749,1232,1443],[47,51,58,756,1008,1010,1012,1013,1044,1045,1232,1443],[51,749,755,1007,1008,1010,1012,1013,1014,1015,1017,1018,1024,1025,1027,1029,1030,1035,1036,1037,1232,1443],[51,291,1111,1232,1443],[51,58,209,596,1110,1232,1443],[51,291,1114,1232,1443],[47,51,58,596,1113,1232,1443],[51,291,1118,1119,1232,1443],[51,323,1232,1443],[47,51,58,586,596,1116,1117,1232,1443],[47,51,58,596,1116,1232,1443],[51,291,1127,1128,1232,1443],[51,327,1232,1443],[47,51,58,596,1124,1125,1126,1232,1443],[47,51,58,1124,1125,1232,1443],[47,51,58,1124,1232,1443],[51,291,1134,1135,1232,1443],[1133,1232,1443],[47,51,58,596,1133,1232,1443],[47,596,1232,1443],[51,291,1140,1232,1443],[47,51,291,1144,1145,1232,1443],[51,303,1232,1443],[51,58,596,1142,1143,1232,1443],[47,51,291,1147,1232,1443],[1152,1232,1443],[51,58,1150,1151,1232,1443],[1155,1232,1443],[51,58,1150,1154,1232,1443],[1158,1232,1443],[51,58,1150,1154,1157,1232,1443],[1161,1232,1443],[51,58,1150,1160,1232,1443],[1163,1232,1443],[44,51,268,269,270,1182,1183,1232,1443],[62,142,143,1232,1443],[51,62,251,293,296,297,298,299,1178,1179,1180,1181,1232,1443],[44,51,270,1185,1226,1230,1232,1443],[44,51,1185,1186,1226,1227,1228,1232,1443],[62,145,146,147,148,1232,1443],[51,62,253,293,296,299,1185,1186,1224,1225,1232,1443],[209,1443],[51,58,209,299,1223,1232,1443],[605,1232,1443],[51,605,1232,1236,1443],[1232,1233,1234,1443],[43,51,1232,1248,1306,1443],[51,1232,1282,1283,1443],[51,1232,1272,1443],[1232,1274,1443],[51,1232,1271,1443],[51,1232,1269,1443],[51,605,1232,1270,1443],[51,1232,1276,1443],[51,1232,1285,1287,1443],[51,1232,1275,1443],[51,1232,1272,1273,1443],[1232,1234,1265,1267,1278,1284,1286,1288,1291,1292,1293,1294,1295,1296,1297,1298,1299,1319,1443],[43,44,51,267,268,269,270,1232,1306,1333,1334,1335,1443],[47,51,284,1232,1277,1443],[51,1232,1256,1443],[1232,1296,1443],[43,51,269,303,1232,1304,1443],[47,284,1232,1246,1443],[47,51,284,1232,1250,1443],[51,1232,1300,1443],[51,62,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,104,105,106,107,131,132,133,1232,1443],[51,132,1232,1443],[51,1232,1257,1258,1259,1260,1261,1262,1263,1443],[51,1232,1233,1234,1235,1443],[51,1232,1263,1281,1282,1443],[51,1232,1268,1443],[51,1232,1235,1267,1269,1443],[51,1232,1268,1288,1443],[51,131,1232,1443],[51,1232,1268,1284,1443],[1232,1272,1443],[51,1232,1271,1272,1273,1274,1443],[51,58,131,1232,1443],[51,58,131,1232,1245,1443],[51,62,104,131,247,293,296,297,355,1232,1236,1239,1240,1241,1242,1243,1244,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1264,1266,1270,1275,1276,1277,1279,1280,1282,1283,1284,1285,1286,1287,1288,1289,1300,1301,1302,1303,1304,1305,1443],[51,1232,1263,1268,1281,1286,1443],[51,1232,1235,1265,1443],[47,51,58,131,247,258,284,293,296,297,355,596,1232,1239,1240,1241,1242,1243,1244,1247,1249,1251,1252,1277,1443],[51,1232,1268,1278,1443],[51,58,209,281,291,1232,1304,1443],[47,51,58,131,1232,1245,1443],[47,51,58,596,1232,1249,1443],[51,1232,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1443],[51,1232,1263,1268,1281,1443],[43,44,268,270,1232,1337,1338,1343,1443],[62,138,139,140,1232,1443],[51,62,249,293,296,299,355,1232,1338,1339,1340,1341,1342,1443],[43,44,51,268,269,270,1227,1232,1345,1349,1443],[60,61,62,1232,1443],[51,62,247,293,296,297,299,355,1232,1240,1346,1347,1348,1443],[43,44,51,268,270,1232,1351,1355,1443],[62,135,136,1232,1443],[62,249,293,296,297,299,355,1232,1339,1352,1353,1354,1443],[51,1165,1167,1232,1443],[51,291,1167,1169,1232,1443],[43,51,291,1167,1171,1172,1232,1443],[43,51,1167,1169,1175,1232,1443],[43,51,58,1166,1232,1443],[51,58,291,1167,1169,1232,1443],[51,58,293,596,1166,1169,1171,1232,1443],[51,58,209,281,293,297,355,1165,1166,1169,1172,1174,1232,1443],[51,58,209,291,293,297,1232,1443],[43,51,200,209,1232,1357,1359,1360,1443],[51,1232,1358,1359,1443],[51,242,1232,1443],[51,1232,1362,1443],[51,326,355,1232,1443],[44,51,134,291,1232,1364,1443],[47,51,247,258,284,296,596,1232,1443],[47,51,1232,1367,1443],[51,293,297,355,1232,1368,1443],[51,1232,1443,1492],[51,1232,1443,1493],[47,51,58,1232,1370,1386,1413,1415,1443],[51,1232,1370,1414,1443],[51,1232,1418,1443],[51,297,324,355,1232,1417,1443],[51,1232,1421,1422,1443],[51,297,328,355,1232,1417,1420,1443],[51,297,328,1232,1346,1420,1443],[43,51,134,1232,1431,1443],[51,1232,1424,1431,1443],[51,1232,1425,1426,1427,1428,1429,1430,1443],[1232,1435,1436,1443],[1232,1434,1436,1443],[51,374,1232,1433,1434,1443],[200,209,1232,1440,1441,1443],[51,1232,1439,1443],[209,1232],[51,200,374,1232,1443],[51,1232,1443,1445,1446,1447,1448],[51,243,1232,1443],[51,1232,1443,1444,1445],[51,242,1232,1443,1444],[1232,1443,1451,1453,1454],[51,1232,1443,1450,1451,1452],[51,237,374,1232,1443,1450,1451],[1232,1443,1464,1465],[192,1232,1443,1458],[51,1232,1443,1461,1463],[51,204,1232,1443,1458,1459,1460,1461,1462],[200,209,1232,1443,1469,1470],[51,236,1232,1443],[51,1232,1443,1468],[51,1232,1443,1467],[1232,1443,1472,1473],[1232,1443,1473],[43,51,291,1232,1443,1480,1481],[52,53,54,55,56,57,1232,1443],[1232,1443,1472,1473,1476,1477,1478,1480],[51,209,1232,1443],[1232,1443,1472],[51,209,1232,1443,1473,1479],[51,200,209,247,249,251,306,1232,1443],[51,59,63,134,137,141,144,261,1232,1443,1484,1485],[134,200,209,210,1232,1443,1485,1487],[51,200,209,210,265,266,1232,1443,1485,1487,1490,1491,1494,1495,1496,1497,1498,1499],[51,1232,1443,1485,1490,1494],[46,47,1232,1443],[46,48,49,50,1232,1443],[45,1232,1443],[45,46,1232,1443],[47,670,1232,1443],[670,671,672,673,1232,1443],[669,1232,1443],[669,670,1232,1443],[51,1232,1443,1502],[51,1232,1443,1502,1504],[289,290,1232,1443],[1232,1443,1502,1504],[51,291,1232,1443,1509,1527],[51,291,1232,1443,1513],[291,1232,1443,1520,1521],[291,1232,1443,1522],[51,291,1232,1443,1512],[51,291,1232,1443,1520,1524],[51,291,1232,1443,1511],[1232,1443,1517],[1232,1443,1516],[51,1232,1443,1519],[51,291,1232,1443,1508,1524],[51,254,255,256,257,1232,1443],[51,1232,1443,1508,1511,1520,1521],[51,58,1232,1443,1508,1510,1511,1512,1514,1519],[51,1232,1443,1509],[51,1232,1443,1513],[51,1232,1443,1508],[51,58,1232,1443,1508],[1232,1443,1515],[51,1232,1443,1516,1517,1518],[51,58,1232,1443,1507],[51,1232,1443,1537],[51,1232,1443,1539,1540,1541,1542,1543,1544],[291,1232,1443,1544],[51,291,1232,1443,1544,1552,1553,1554,1555,1556,1557,1558,1559,1560],[51,276,1232,1443],[272,277,278,279,280,1232,1443],[51,276,1232,1443,1537],[276,1232,1443],[1232,1443,1547,1548],[51,276,1232,1443,1537,1547],[51,276,1232,1443,1536],[1232,1443,1537,1544,1547,1548,1551],[51,1232,1443,1549,1550]],"referencedMap":[[1227,1],[314,1],[304,1],[303,1],[1228,1],[270,1],[268,1],[43,1],[267,1],[269,1],[1230,1],[1498,1],[306,1],[1495,1],[1499,1],[1485,1],[1496,1],[44,1],[1497,1],[605,2],[47,1],[275,3],[274,4],[276,5],[273,1],[572,6],[571,7],[570,8],[485,9],[484,10],[483,11],[482,1],[481,12],[480,13],[479,14],[478,15],[477,16],[457,17],[456,18],[417,16],[475,19],[474,1],[473,20],[466,21],[464,22],[471,22],[470,22],[465,21],[463,21],[461,23],[472,24],[467,21],[469,21],[468,21],[462,1],[458,1],[416,16],[406,25],[405,26],[401,27],[402,28],[400,22],[561,29],[492,30],[491,31],[497,30],[496,30],[488,32],[490,30],[494,30],[493,30],[495,30],[560,33],[499,34],[498,1],[500,35],[486,36],[487,37],[476,25],[489,24],[460,38],[459,1],[449,39],[447,40],[454,40],[453,40],[448,39],[446,39],[444,41],[455,42],[450,39],[452,39],[451,39],[445,1],[418,1],[420,43],[419,1],[438,44],[431,45],[436,46],[428,47],[423,1],[435,48],[442,1],[443,15],[430,49],[439,1],[426,1],[437,50],[421,1],[432,51],[427,52],[425,53],[429,1],[433,1],[424,1],[440,54],[422,1],[441,1],[434,1],[409,55],[407,22],[411,56],[410,57],[408,58],[413,59],[412,22],[414,60],[404,61],[403,22],[399,22],[393,62],[386,63],[391,64],[383,65],[378,1],[390,66],[397,1],[398,16],[385,67],[394,1],[381,1],[392,68],[376,1],[387,69],[382,70],[380,71],[384,1],[388,1],[379,1],[395,72],[377,1],[396,1],[389,1],[562,1],[563,1],[566,73],[564,1],[569,74],[568,75],[567,76],[565,77],[1459,1],[501,1],[502,1],[503,1],[559,78],[504,79],[548,80],[506,81],[505,82],[507,79],[508,79],[510,83],[509,79],[511,84],[512,84],[513,79],[515,85],[516,79],[517,85],[518,79],[520,79],[521,79],[522,79],[523,86],[519,79],[524,1],[525,87],[526,87],[527,87],[528,87],[529,87],[538,88],[530,87],[531,87],[532,87],[533,87],[535,87],[534,87],[536,87],[537,87],[539,79],[540,79],[514,79],[542,89],[541,79],[543,79],[544,79],[545,90],[547,79],[546,79],[549,79],[551,79],[552,91],[550,79],[553,79],[554,79],[555,79],[556,79],[557,79],[558,79],[608,92],[284,2],[606,93],[607,2],[1372,94],[1569,95],[1562,1],[1564,96],[1566,97],[1565,96],[1563,1],[1568,98],[1567,1],[1570,99],[1457,1],[1458,100],[150,101],[151,101],[186,102],[187,103],[188,104],[189,105],[190,106],[191,107],[192,108],[193,109],[194,110],[195,111],[196,111],[198,112],[197,113],[199,114],[200,115],[201,116],[185,117],[235,1],[202,118],[203,119],[204,120],[236,121],[205,122],[206,123],[207,124],[208,125],[209,126],[210,127],[211,128],[212,129],[213,130],[214,131],[215,131],[216,132],[217,133],[219,134],[218,135],[220,136],[221,137],[222,138],[223,139],[224,140],[225,141],[226,142],[227,143],[228,144],[229,145],[230,146],[231,147],[232,148],[233,149],[234,150],[1149,1],[1154,151],[1151,151],[1157,151],[1160,151],[1150,151],[1371,1],[1460,1],[375,1],[152,1],[1487,1],[1212,152],[1215,153],[1218,153],[1219,153],[1217,154],[1216,154],[1220,155],[1223,156],[1222,157],[1213,158],[1221,159],[1214,153],[374,1],[1211,160],[1209,1],[1207,161],[1210,162],[1208,163],[1206,164],[1205,165],[1203,166],[1204,166],[1202,1],[617,1],[1507,1],[1192,167],[1187,1],[1189,168],[1188,169],[1199,167],[1198,167],[1200,170],[1197,171],[1195,167],[1196,167],[1193,172],[1194,167],[1456,173],[1413,174],[1412,175],[1411,176],[1410,177],[1373,178],[1386,179],[1385,180],[1384,181],[1377,182],[1375,183],[1376,184],[1374,1],[1201,185],[1191,186],[1190,1],[619,187],[620,187],[621,188],[618,189],[1467,190],[1417,1],[573,191],[574,192],[415,193],[1394,194],[1408,195],[1392,1],[1393,196],[1409,197],[1404,198],[1405,199],[1403,200],[1407,201],[1401,202],[1395,203],[1406,204],[1402,195],[1400,205],[1398,1],[1399,206],[1396,1],[1397,1],[1383,207],[1380,208],[1381,1],[1382,1],[1378,1],[1379,209],[8,1],[10,1],[9,1],[2,1],[11,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[3,1],[4,1],[22,1],[19,1],[20,1],[21,1],[23,1],[24,1],[25,1],[5,1],[26,1],[27,1],[28,1],[29,1],[6,1],[33,1],[30,1],[31,1],[32,1],[34,1],[7,1],[35,1],[40,1],[41,1],[36,1],[37,1],[38,1],[39,1],[1,1],[42,1],[168,210],[175,211],[167,210],[182,212],[159,213],[158,214],[181,190],[176,215],[179,216],[161,217],[160,218],[156,219],[155,220],[178,221],[157,222],[162,223],[163,1],[166,223],[153,1],[184,224],[183,223],[170,225],[171,226],[173,227],[169,228],[172,229],[177,190],[164,230],[165,231],[174,232],[154,233],[180,234],[1388,235],[1387,94],[1391,236],[1390,237],[1389,1],[271,238],[263,239],[264,240],[1490,241],[262,242],[260,1],[302,243],[305,244],[307,245],[308,243],[310,246],[311,243],[313,247],[312,1],[309,1],[250,1],[251,248],[300,1],[301,249],[319,250],[320,251],[253,252],[252,241],[318,253],[317,254],[334,255],[336,256],[337,257],[339,258],[341,259],[342,257],[343,257],[344,257],[345,260],[349,261],[340,1],[346,1],[350,262],[335,1],[338,1],[347,1],[348,1],[351,257],[352,1],[353,263],[247,264],[246,241],[333,265],[332,241],[359,266],[361,267],[362,268],[364,269],[365,270],[366,268],[367,268],[370,271],[369,1],[371,272],[360,1],[363,1],[368,1],[372,1],[373,273],[249,274],[248,241],[358,275],[357,241],[292,276],[293,241],[283,277],[282,241],[286,241],[285,278],[287,279],[288,280],[580,281],[240,282],[242,283],[241,284],[575,1],[577,285],[579,286],[576,287],[578,288],[600,289],[294,241],[598,241],[599,290],[597,291],[604,292],[1178,241],[602,241],[603,293],[601,294],[614,295],[616,296],[625,297],[630,298],[631,299],[639,300],[640,301],[641,302],[642,303],[643,304],[644,305],[645,306],[646,307],[647,308],[648,305],[649,309],[650,310],[652,311],[581,312],[584,241],[583,313],[596,314],[594,315],[593,241],[595,316],[591,312],[592,316],[586,317],[588,312],[582,1],[590,241],[587,241],[585,1],[589,2],[613,318],[615,241],[624,319],[637,320],[628,321],[629,322],[626,241],[627,323],[634,324],[638,325],[632,312],[633,326],[653,1],[612,327],[623,328],[609,1],[636,329],[622,329],[611,1],[610,1],[635,2],[651,312],[667,330],[668,330],[666,331],[675,332],[326,333],[325,241],[665,334],[663,335],[664,336],[658,337],[659,337],[657,331],[660,337],[661,338],[662,339],[296,340],[295,241],[656,341],[655,342],[654,343],[679,344],[315,241],[676,1],[678,345],[677,346],[683,347],[316,241],[682,336],[681,348],[297,241],[680,343],[686,349],[1240,241],[685,350],[684,291],[688,351],[322,241],[687,291],[690,352],[1239,241],[689,353],[693,354],[330,241],[692,355],[691,356],[721,357],[722,358],[723,359],[724,359],[726,360],[728,361],[729,362],[725,363],[731,364],[735,365],[736,366],[737,367],[738,368],[128,241],[130,369],[126,370],[116,1],[115,1],[121,1],[114,1],[122,1],[125,371],[120,1],[110,1],[112,1],[109,1],[108,1],[124,1],[113,1],[111,1],[119,1],[117,1],[123,241],[118,1],[131,372],[129,241],[127,241],[730,329],[739,1],[717,373],[718,374],[702,367],[701,367],[720,375],[700,367],[708,375],[715,376],[706,367],[696,367],[698,367],[695,367],[694,367],[714,367],[699,367],[697,367],[705,367],[703,367],[713,377],[704,367],[707,1],[727,2],[734,378],[733,379],[740,380],[732,381],[710,1],[711,241],[712,382],[709,1],[719,383],[716,1],[1243,241],[742,384],[741,291],[745,385],[1242,241],[744,386],[743,381],[748,387],[1241,241],[747,388],[746,291],[1051,389],[1076,390],[754,391],[1011,392],[1039,393],[1040,394],[1041,394],[1042,395],[1043,395],[1047,396],[1048,397],[1049,398],[1052,399],[1053,400],[1054,401],[1055,401],[1056,401],[1057,402],[1058,401],[1059,401],[1060,403],[1061,403],[1062,404],[1063,400],[1064,405],[1065,406],[1066,397],[1067,389],[1068,407],[1069,1],[1070,393],[1071,408],[1072,400],[1073,409],[1074,410],[1075,411],[1077,412],[1078,394],[1079,413],[1080,414],[1081,415],[1082,416],[1083,417],[1084,418],[1085,397],[1086,419],[1087,420],[1089,421],[1090,422],[1091,423],[1092,424],[1093,425],[1094,426],[1095,389],[1096,427],[1097,426],[1098,428],[1099,429],[1100,397],[1101,397],[1102,397],[1103,397],[1104,430],[1105,431],[1106,432],[1107,433],[1108,389],[97,434],[96,1],[99,241],[104,435],[101,241],[92,436],[91,1],[100,1],[103,1],[95,434],[94,434],[98,241],[93,437],[102,241],[89,241],[90,241],[1029,438],[1010,439],[1018,440],[1012,441],[1027,442],[1035,443],[1032,444],[1033,444],[1034,444],[1031,241],[755,1],[1008,241],[1050,445],[1023,241],[1022,241],[1016,241],[1024,446],[1019,241],[1021,447],[1020,1],[1044,241],[753,448],[847,448],[750,448],[848,448],[751,448],[849,448],[752,448],[850,448],[854,449],[855,449],[856,449],[853,1],[857,449],[858,449],[859,449],[860,449],[851,448],[852,448],[861,448],[862,448],[863,448],[864,448],[865,448],[866,448],[867,448],[868,448],[869,448],[870,448],[871,448],[872,448],[873,448],[874,448],[875,448],[876,448],[877,448],[878,448],[879,448],[880,448],[881,448],[889,448],[890,448],[891,448],[892,448],[893,448],[894,448],[882,448],[883,448],[895,448],[896,448],[897,448],[898,448],[899,448],[900,448],[901,448],[902,448],[903,448],[904,448],[905,448],[906,448],[907,448],[908,448],[909,448],[910,448],[888,448],[887,448],[886,448],[885,448],[884,448],[911,448],[912,448],[913,448],[914,448],[915,448],[916,448],[917,448],[918,448],[919,448],[920,448],[922,448],[923,448],[924,448],[921,448],[925,448],[926,448],[1007,450],[846,451],[757,448],[758,448],[759,448],[760,448],[761,448],[762,448],[764,452],[765,452],[766,452],[767,448],[768,452],[769,452],[770,448],[771,448],[772,448],[773,448],[774,452],[775,448],[776,448],[777,452],[778,452],[779,448],[780,448],[781,448],[782,452],[783,448],[784,448],[763,448],[785,448],[786,448],[787,448],[788,448],[789,452],[790,448],[791,448],[792,448],[793,452],[794,448],[795,448],[796,452],[797,452],[798,452],[799,448],[800,448],[801,452],[802,448],[803,448],[804,448],[805,452],[806,452],[807,452],[808,448],[809,452],[810,448],[811,448],[812,452],[813,448],[814,452],[815,448],[816,448],[817,448],[818,448],[819,448],[820,452],[821,452],[822,452],[823,452],[824,452],[825,448],[826,448],[827,452],[828,452],[829,448],[830,448],[831,452],[832,452],[833,448],[834,448],[835,452],[836,448],[837,448],[838,448],[839,448],[840,452],[841,448],[842,452],[843,452],[844,448],[845,448],[927,448],[928,448],[929,448],[930,448],[931,448],[932,448],[933,448],[934,448],[935,448],[936,448],[937,448],[938,448],[939,448],[940,448],[941,448],[942,448],[943,448],[944,448],[945,448],[946,448],[947,448],[948,448],[949,448],[950,448],[951,448],[952,448],[953,448],[955,1],[954,448],[956,453],[957,453],[958,448],[959,448],[960,1],[961,454],[962,448],[963,448],[964,454],[965,448],[966,448],[967,448],[968,448],[969,448],[970,448],[971,448],[972,448],[973,448],[974,448],[975,448],[976,448],[977,448],[978,448],[979,448],[980,448],[749,1],[981,448],[982,448],[983,448],[984,448],[985,448],[986,448],[987,448],[988,448],[989,448],[990,448],[991,448],[992,448],[993,448],[994,448],[995,448],[996,448],[997,448],[998,448],[999,448],[1000,448],[1001,448],[1002,448],[1003,448],[1004,448],[1005,448],[1006,448],[1109,1],[1028,1],[1037,1],[1015,1],[1030,1],[1014,455],[1036,1],[1013,456],[1088,1],[1026,1],[1017,457],[1045,241],[756,458],[1025,241],[1009,1],[1046,459],[1038,460],[1112,461],[1346,241],[1111,462],[1110,381],[1115,463],[321,241],[1113,241],[1114,464],[1120,465],[1121,465],[1119,312],[1122,465],[1123,465],[324,466],[323,241],[1118,467],[1117,468],[1116,291],[1129,469],[1130,469],[1128,331],[1131,469],[1132,469],[328,470],[327,241],[1124,241],[1127,471],[1126,472],[1125,473],[1136,474],[1137,474],[1135,241],[1138,474],[1139,475],[329,241],[1134,476],[1133,477],[1141,478],[1352,241],[1140,294],[1146,479],[1145,480],[354,241],[1143,1],[1144,481],[1142,291],[1148,482],[1339,241],[1147,381],[1153,483],[299,241],[1152,484],[1156,485],[355,241],[1155,486],[1159,487],[331,241],[1158,488],[1162,489],[298,241],[1161,490],[1164,491],[356,241],[1163,329],[1184,492],[1183,1],[142,241],[144,493],[143,241],[1180,241],[1179,1],[1182,494],[1181,241],[1231,495],[1229,496],[148,241],[149,497],[146,241],[147,241],[145,1],[1186,241],[1226,498],[1232,499],[1224,500],[1225,329],[1185,1],[1319,501],[1237,502],[1238,503],[1307,504],[1308,505],[1309,506],[1310,507],[1311,508],[1312,509],[1313,510],[1314,511],[1315,504],[1316,512],[1317,513],[1318,514],[1320,515],[1336,516],[1333,1],[1334,1],[1335,1],[1321,517],[1322,504],[1323,518],[1324,504],[1325,519],[1326,506],[1327,520],[1328,521],[1329,521],[1330,506],[1331,522],[1332,523],[68,241],[69,241],[76,1],[75,241],[83,1],[79,241],[71,241],[87,241],[88,241],[81,1],[77,241],[70,241],[72,241],[85,241],[107,241],[66,241],[67,241],[134,524],[105,241],[106,241],[86,241],[82,1],[78,241],[84,241],[64,241],[132,241],[65,241],[74,241],[73,241],[133,525],[80,241],[1259,241],[1262,241],[1257,1],[1260,241],[1264,526],[1258,241],[1261,241],[1236,527],[1234,1],[1233,1],[1281,241],[1235,241],[1282,1],[1283,528],[1267,1],[1269,529],[1270,530],[1288,1],[1289,531],[1276,241],[1253,241],[1254,532],[1284,1],[1285,533],[1274,534],[1272,241],[1271,241],[1273,241],[1275,535],[1277,312],[1302,241],[1252,353],[1255,353],[1245,536],[1256,537],[1306,538],[1251,312],[1249,312],[1303,343],[1286,1],[1287,539],[1301,329],[1265,1],[1266,540],[1247,241],[1263,241],[1304,541],[1248,241],[1278,1],[1280,329],[1279,542],[1305,543],[1246,544],[1268,241],[1250,545],[1244,291],[1292,1],[1299,1],[1298,1],[1294,1],[1295,1],[1297,1],[1300,546],[1296,1],[1290,547],[1291,1],[1293,1],[1344,548],[1337,1],[140,241],[141,549],[138,241],[139,1],[1338,241],[1343,550],[1341,241],[1342,1],[1340,312],[1350,551],[1345,1],[63,552],[61,241],[60,241],[1349,553],[1348,241],[1347,241],[1356,554],[1351,1],[137,555],[135,241],[136,241],[1355,556],[1353,241],[1354,241],[1168,557],[1170,558],[1173,559],[1176,560],[1167,561],[1177,562],[62,241],[1165,241],[1166,241],[1172,563],[1175,564],[1174,291],[1171,1],[1169,565],[1361,566],[1357,1],[59,241],[1359,241],[1360,567],[1358,568],[265,241],[1363,569],[1362,570],[1365,571],[1364,241],[259,254],[1366,572],[1368,573],[1369,574],[1367,477],[1493,575],[1494,576],[1492,241],[1414,577],[1415,1],[1416,578],[1370,241],[1491,241],[1419,579],[1418,580],[266,241],[1420,1],[1423,581],[1421,582],[1422,583],[1432,584],[1429,585],[1424,1],[1426,585],[1431,586],[1425,585],[1430,585],[1427,585],[1428,585],[1437,587],[1436,241],[1438,588],[245,241],[1433,1],[1435,589],[1434,241],[1442,590],[1441,1],[261,241],[1440,591],[1443,592],[1439,593],[1448,1],[1449,594],[1447,1],[244,595],[243,568],[1446,596],[1444,568],[1445,597],[1455,598],[1454,1],[239,241],[1450,1],[1451,1],[1453,599],[1452,600],[1466,601],[1465,241],[238,241],[1462,602],[1464,603],[1461,241],[1463,604],[1471,605],[1470,1],[237,606],[1469,607],[1468,608],[1474,609],[1475,610],[1481,1],[1482,611],[52,241],[58,612],[55,241],[56,1],[57,1],[53,1],[54,241],[1476,241],[1479,613],[1477,614],[1472,1],[1478,1],[1473,615],[1480,616],[1483,617],[1484,1],[1486,618],[1488,619],[1489,1],[1500,620],[1501,621],[49,1],[48,622],[45,1],[51,623],[46,624],[50,625],[672,1],[671,626],[669,1],[674,627],[670,628],[673,629],[1503,630],[1505,631],[290,241],[291,632],[289,241],[1502,241],[1506,633],[1504,241],[1527,331],[1528,634],[1529,635],[1530,636],[1523,637],[1524,1],[1531,638],[1525,639],[1532,640],[1533,641],[1534,642],[1535,643],[1526,644],[255,241],[258,645],[254,241],[256,241],[257,241],[1521,241],[1522,646],[1520,647],[1510,648],[1509,329],[1514,649],[1513,241],[1512,650],[1511,651],[1518,1],[1517,652],[1516,652],[1515,1],[1519,653],[1508,654],[1538,655],[1543,1],[1542,1],[1545,656],[1546,657],[1539,1],[1540,1],[1541,1],[1553,1],[1555,1],[1554,1],[1560,1],[1561,658],[1557,1],[1559,1],[1558,1],[1556,1],[279,659],[280,659],[277,659],[281,660],[272,241],[278,241],[1547,661],[1536,662],[1549,663],[1548,664],[1537,665],[1552,666],[1544,329],[1551,667],[1550,329]],"exportedModulesMap":[[1227,1],[314,1],[304,1],[303,1],[1228,1],[270,1],[268,1],[43,1],[267,1],[269,1],[1230,1],[1498,1],[306,1],[1495,1],[1499,1],[1485,1],[1496,1],[44,1],[1497,1],[605,2],[47,1],[275,3],[274,4],[276,5],[273,1],[572,6],[571,7],[570,8],[485,9],[484,10],[483,11],[482,1],[481,12],[480,13],[479,14],[478,15],[477,16],[457,17],[456,18],[417,16],[475,19],[474,1],[473,20],[466,21],[464,22],[471,22],[470,22],[465,21],[463,21],[461,23],[472,24],[467,21],[469,21],[468,21],[462,1],[458,1],[416,16],[406,25],[405,26],[401,27],[402,28],[400,22],[561,29],[492,30],[491,31],[497,30],[496,30],[488,32],[490,30],[494,30],[493,30],[495,30],[560,33],[499,34],[498,1],[500,35],[486,36],[487,37],[476,25],[489,24],[460,38],[459,1],[449,39],[447,40],[454,40],[453,40],[448,39],[446,39],[444,41],[455,42],[450,39],[452,39],[451,39],[445,1],[418,1],[420,43],[419,1],[438,44],[431,45],[436,46],[428,47],[423,1],[435,48],[442,1],[443,15],[430,49],[439,1],[426,1],[437,50],[421,1],[432,51],[427,52],[425,53],[429,1],[433,1],[424,1],[440,54],[422,1],[441,1],[434,1],[409,55],[407,22],[411,56],[410,57],[408,58],[413,59],[412,22],[414,60],[404,61],[403,22],[399,22],[393,62],[386,63],[391,64],[383,65],[378,1],[390,66],[397,1],[398,16],[385,67],[394,1],[381,1],[392,68],[376,1],[387,69],[382,70],[380,71],[384,1],[388,1],[379,1],[395,72],[377,1],[396,1],[389,1],[562,1],[563,1],[566,73],[564,1],[569,74],[568,75],[567,76],[565,77],[1459,1],[501,1],[502,1],[503,1],[559,78],[504,79],[548,80],[506,81],[505,82],[507,79],[508,79],[510,83],[509,79],[511,84],[512,84],[513,79],[515,85],[516,79],[517,85],[518,79],[520,79],[521,79],[522,79],[523,86],[519,79],[524,1],[525,87],[526,87],[527,87],[528,87],[529,87],[538,88],[530,87],[531,87],[532,87],[533,87],[535,87],[534,87],[536,87],[537,87],[539,79],[540,79],[514,79],[542,89],[541,79],[543,79],[544,79],[545,90],[547,79],[546,79],[549,79],[551,79],[552,91],[550,79],[553,79],[554,79],[555,79],[556,79],[557,79],[558,79],[608,92],[284,2],[606,93],[607,2],[1372,94],[1569,95],[1562,1],[1564,96],[1566,97],[1565,96],[1563,1],[1568,98],[1567,1],[1570,99],[1457,1],[1458,100],[150,101],[151,101],[186,102],[187,103],[188,104],[189,105],[190,106],[191,107],[192,108],[193,109],[194,110],[195,111],[196,111],[198,112],[197,113],[199,114],[200,115],[201,116],[185,117],[235,1],[202,118],[203,119],[204,120],[236,121],[205,122],[206,123],[207,124],[208,125],[209,126],[210,127],[211,128],[212,129],[213,130],[214,131],[215,131],[216,132],[217,133],[219,134],[218,135],[220,136],[221,137],[222,138],[223,139],[224,140],[225,141],[226,142],[227,143],[228,144],[229,145],[230,146],[231,147],[232,148],[233,149],[234,150],[1149,1],[1154,151],[1151,151],[1157,151],[1160,151],[1150,151],[1371,1],[1460,1],[375,1],[152,1],[1487,1],[1212,152],[1215,153],[1218,153],[1219,153],[1217,154],[1216,154],[1220,155],[1223,156],[1222,157],[1213,158],[1221,159],[1214,153],[374,1],[1211,160],[1209,1],[1207,161],[1210,162],[1208,163],[1206,164],[1205,165],[1203,166],[1204,166],[1202,1],[617,1],[1507,1],[1192,167],[1187,1],[1189,168],[1188,169],[1199,167],[1198,167],[1200,170],[1197,171],[1195,167],[1196,167],[1193,172],[1194,167],[1456,173],[1413,174],[1412,175],[1411,176],[1410,177],[1373,178],[1386,179],[1385,180],[1384,181],[1377,182],[1375,183],[1376,184],[1374,1],[1201,185],[1191,186],[1190,1],[619,187],[620,187],[621,188],[618,189],[1467,190],[1417,1],[573,191],[574,192],[415,193],[1394,194],[1408,195],[1392,1],[1393,196],[1409,197],[1404,198],[1405,199],[1403,200],[1407,201],[1401,202],[1395,203],[1406,204],[1402,195],[1400,205],[1398,1],[1399,206],[1396,1],[1397,1],[1383,207],[1380,208],[1381,1],[1382,1],[1378,1],[1379,209],[8,1],[10,1],[9,1],[2,1],[11,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[3,1],[4,1],[22,1],[19,1],[20,1],[21,1],[23,1],[24,1],[25,1],[5,1],[26,1],[27,1],[28,1],[29,1],[6,1],[33,1],[30,1],[31,1],[32,1],[34,1],[7,1],[35,1],[40,1],[41,1],[36,1],[37,1],[38,1],[39,1],[1,1],[42,1],[168,210],[175,211],[167,210],[182,212],[159,213],[158,214],[181,190],[176,215],[179,216],[161,217],[160,218],[156,219],[155,220],[178,221],[157,222],[162,223],[163,1],[166,223],[153,1],[184,224],[183,223],[170,225],[171,226],[173,227],[169,228],[172,229],[177,190],[164,230],[165,231],[174,232],[154,233],[180,234],[1388,235],[1387,94],[1391,236],[1390,237],[1389,1],[271,238],[263,239],[264,240],[1490,241],[262,242],[260,1],[302,243],[305,244],[307,245],[308,243],[310,246],[311,243],[313,247],[312,1],[309,1],[250,1],[251,248],[300,1],[301,249],[319,250],[320,251],[253,252],[252,241],[318,253],[317,254],[334,255],[336,256],[337,257],[339,258],[341,259],[342,257],[343,257],[344,257],[345,260],[349,261],[340,1],[346,1],[350,262],[335,1],[338,1],[347,1],[348,1],[351,257],[352,1],[353,263],[247,264],[246,241],[333,265],[332,241],[359,266],[361,267],[362,268],[364,269],[365,270],[366,268],[367,268],[370,271],[369,1],[371,272],[360,1],[363,1],[368,1],[372,1],[373,273],[249,274],[248,241],[358,275],[357,241],[292,276],[293,241],[283,277],[282,241],[286,241],[285,278],[287,279],[288,280],[580,281],[240,282],[242,283],[241,284],[575,1],[577,285],[579,286],[576,287],[578,288],[600,289],[294,241],[598,241],[599,290],[597,291],[604,292],[1178,241],[602,241],[603,293],[601,294],[614,295],[616,296],[625,297],[630,298],[631,299],[639,300],[640,301],[641,302],[642,303],[643,304],[644,305],[645,306],[646,307],[647,308],[648,305],[649,309],[650,310],[652,311],[581,312],[584,241],[583,313],[596,314],[594,315],[593,241],[595,316],[591,312],[592,316],[586,317],[588,312],[582,1],[590,241],[587,241],[585,1],[589,2],[613,318],[615,241],[624,319],[637,320],[628,321],[629,322],[626,241],[627,323],[634,324],[638,325],[632,312],[633,326],[653,1],[612,327],[623,328],[609,1],[636,329],[622,329],[611,1],[610,1],[635,2],[651,312],[667,330],[668,330],[666,331],[675,332],[326,333],[325,241],[665,334],[663,335],[664,336],[658,337],[659,337],[657,331],[660,337],[661,338],[662,339],[296,340],[295,241],[656,341],[655,342],[654,343],[679,344],[315,241],[676,1],[678,345],[677,346],[683,347],[316,241],[682,336],[681,348],[297,241],[680,343],[686,349],[1240,241],[685,350],[684,291],[688,351],[322,241],[687,291],[690,352],[1239,241],[689,353],[693,354],[330,241],[692,355],[691,356],[721,357],[722,358],[723,359],[724,359],[726,360],[728,361],[729,362],[725,363],[731,364],[735,365],[736,366],[737,367],[738,368],[128,241],[130,369],[126,370],[116,1],[115,1],[121,1],[114,1],[122,1],[125,371],[120,1],[110,1],[112,1],[109,1],[108,1],[124,1],[113,1],[111,1],[119,1],[117,1],[123,241],[118,1],[131,372],[129,241],[127,241],[730,329],[739,1],[717,373],[718,374],[702,367],[701,367],[720,375],[700,367],[708,375],[715,376],[706,367],[696,367],[698,367],[695,367],[694,367],[714,367],[699,367],[697,367],[705,367],[703,367],[713,377],[704,367],[707,1],[727,2],[734,378],[733,379],[740,380],[732,381],[710,1],[711,241],[712,382],[709,1],[719,383],[716,1],[1243,241],[742,384],[741,291],[745,385],[1242,241],[744,386],[743,381],[748,387],[1241,241],[747,388],[746,291],[1051,389],[1076,390],[754,391],[1011,392],[1039,393],[1040,394],[1041,394],[1042,395],[1043,395],[1047,396],[1048,397],[1049,398],[1052,399],[1053,400],[1054,401],[1055,401],[1056,401],[1057,402],[1058,401],[1059,401],[1060,403],[1061,403],[1062,404],[1063,400],[1064,405],[1065,406],[1066,397],[1067,389],[1068,407],[1069,1],[1070,393],[1071,408],[1072,400],[1073,409],[1074,410],[1075,411],[1077,412],[1078,394],[1079,413],[1080,414],[1081,415],[1082,416],[1083,417],[1084,418],[1085,397],[1086,419],[1087,420],[1089,421],[1090,422],[1091,423],[1092,424],[1093,425],[1094,426],[1095,389],[1096,427],[1097,426],[1098,428],[1099,429],[1100,397],[1101,397],[1102,397],[1103,397],[1104,430],[1105,431],[1106,432],[1107,433],[1108,389],[97,434],[96,1],[99,241],[104,435],[101,241],[92,436],[91,1],[100,1],[103,1],[95,434],[94,434],[98,241],[93,437],[102,241],[89,241],[90,241],[1029,438],[1010,439],[1018,440],[1012,441],[1027,442],[1035,443],[1032,444],[1033,444],[1034,444],[1031,241],[755,1],[1008,241],[1050,445],[1023,241],[1022,241],[1016,241],[1024,446],[1019,241],[1021,447],[1020,1],[1044,241],[753,448],[847,448],[750,448],[848,448],[751,448],[849,448],[752,448],[850,448],[854,449],[855,449],[856,449],[853,1],[857,449],[858,449],[859,449],[860,449],[851,448],[852,448],[861,448],[862,448],[863,448],[864,448],[865,448],[866,448],[867,448],[868,448],[869,448],[870,448],[871,448],[872,448],[873,448],[874,448],[875,448],[876,448],[877,448],[878,448],[879,448],[880,448],[881,448],[889,448],[890,448],[891,448],[892,448],[893,448],[894,448],[882,448],[883,448],[895,448],[896,448],[897,448],[898,448],[899,448],[900,448],[901,448],[902,448],[903,448],[904,448],[905,448],[906,448],[907,448],[908,448],[909,448],[910,448],[888,448],[887,448],[886,448],[885,448],[884,448],[911,448],[912,448],[913,448],[914,448],[915,448],[916,448],[917,448],[918,448],[919,448],[920,448],[922,448],[923,448],[924,448],[921,448],[925,448],[926,448],[1007,450],[846,451],[757,448],[758,448],[759,448],[760,448],[761,448],[762,448],[764,452],[765,452],[766,452],[767,448],[768,452],[769,452],[770,448],[771,448],[772,448],[773,448],[774,452],[775,448],[776,448],[777,452],[778,452],[779,448],[780,448],[781,448],[782,452],[783,448],[784,448],[763,448],[785,448],[786,448],[787,448],[788,448],[789,452],[790,448],[791,448],[792,448],[793,452],[794,448],[795,448],[796,452],[797,452],[798,452],[799,448],[800,448],[801,452],[802,448],[803,448],[804,448],[805,452],[806,452],[807,452],[808,448],[809,452],[810,448],[811,448],[812,452],[813,448],[814,452],[815,448],[816,448],[817,448],[818,448],[819,448],[820,452],[821,452],[822,452],[823,452],[824,452],[825,448],[826,448],[827,452],[828,452],[829,448],[830,448],[831,452],[832,452],[833,448],[834,448],[835,452],[836,448],[837,448],[838,448],[839,448],[840,452],[841,448],[842,452],[843,452],[844,448],[845,448],[927,448],[928,448],[929,448],[930,448],[931,448],[932,448],[933,448],[934,448],[935,448],[936,448],[937,448],[938,448],[939,448],[940,448],[941,448],[942,448],[943,448],[944,448],[945,448],[946,448],[947,448],[948,448],[949,448],[950,448],[951,448],[952,448],[953,448],[955,1],[954,448],[956,453],[957,453],[958,448],[959,448],[960,1],[961,454],[962,448],[963,448],[964,454],[965,448],[966,448],[967,448],[968,448],[969,448],[970,448],[971,448],[972,448],[973,448],[974,448],[975,448],[976,448],[977,448],[978,448],[979,448],[980,448],[749,1],[981,448],[982,448],[983,448],[984,448],[985,448],[986,448],[987,448],[988,448],[989,448],[990,448],[991,448],[992,448],[993,448],[994,448],[995,448],[996,448],[997,448],[998,448],[999,448],[1000,448],[1001,448],[1002,448],[1003,448],[1004,448],[1005,448],[1006,448],[1109,1],[1028,1],[1037,1],[1015,1],[1030,1],[1014,455],[1036,1],[1013,456],[1088,1],[1026,1],[1017,457],[1045,241],[756,458],[1025,241],[1009,1],[1046,459],[1038,460],[1112,461],[1346,241],[1111,462],[1110,381],[1115,463],[321,241],[1113,241],[1114,464],[1120,465],[1121,465],[1119,312],[1122,465],[1123,465],[324,466],[323,241],[1118,467],[1117,468],[1116,291],[1129,469],[1130,469],[1128,331],[1131,469],[1132,469],[328,470],[327,241],[1124,241],[1127,471],[1126,472],[1125,473],[1136,474],[1137,474],[1135,241],[1138,474],[1139,475],[329,241],[1134,476],[1133,477],[1141,478],[1352,241],[1140,294],[1146,479],[1145,480],[354,241],[1143,1],[1144,481],[1142,291],[1148,482],[1339,241],[1147,381],[1153,483],[299,241],[1152,484],[1156,485],[355,241],[1155,486],[1159,487],[331,241],[1158,488],[1162,489],[298,241],[1161,490],[1164,491],[356,241],[1163,329],[1184,492],[1183,1],[142,241],[144,493],[143,241],[1180,241],[1179,1],[1182,494],[1181,241],[1231,495],[1229,496],[148,241],[149,497],[146,241],[147,241],[145,1],[1186,241],[1226,498],[1232,499],[1224,500],[1225,329],[1185,1],[1319,501],[1237,502],[1238,503],[1307,504],[1308,505],[1309,506],[1310,507],[1311,508],[1312,509],[1313,510],[1314,511],[1315,504],[1316,512],[1317,513],[1318,514],[1320,515],[1336,516],[1333,1],[1334,1],[1335,1],[1321,517],[1322,504],[1323,518],[1324,504],[1325,519],[1326,506],[1327,520],[1328,521],[1329,521],[1330,506],[1331,522],[1332,523],[68,241],[69,241],[76,1],[75,241],[83,1],[79,241],[71,241],[87,241],[88,241],[81,1],[77,241],[70,241],[72,241],[85,241],[107,241],[66,241],[67,241],[134,524],[105,241],[106,241],[86,241],[82,1],[78,241],[84,241],[64,241],[132,241],[65,241],[74,241],[73,241],[133,525],[80,241],[1259,241],[1262,241],[1257,1],[1260,241],[1264,526],[1258,241],[1261,241],[1236,527],[1234,1],[1233,1],[1281,241],[1235,241],[1282,1],[1283,528],[1267,1],[1269,529],[1270,530],[1288,1],[1289,531],[1276,241],[1253,241],[1254,532],[1284,1],[1285,533],[1274,534],[1272,241],[1271,241],[1273,241],[1275,535],[1277,312],[1302,241],[1252,353],[1255,353],[1245,536],[1256,537],[1306,538],[1251,312],[1249,312],[1303,343],[1286,1],[1287,539],[1301,329],[1265,1],[1266,540],[1247,241],[1263,241],[1304,541],[1248,241],[1278,1],[1280,329],[1279,542],[1305,543],[1246,544],[1268,241],[1250,545],[1244,291],[1292,1],[1299,1],[1298,1],[1294,1],[1295,1],[1297,1],[1300,546],[1296,1],[1290,547],[1291,1],[1293,1],[1344,548],[1337,1],[140,241],[141,549],[138,241],[139,1],[1338,241],[1343,550],[1341,241],[1342,1],[1340,312],[1350,551],[1345,1],[63,552],[61,241],[60,241],[1349,553],[1348,241],[1347,241],[1356,554],[1351,1],[137,555],[135,241],[136,241],[1355,556],[1353,241],[1354,241],[1168,557],[1170,558],[1173,559],[1176,560],[1167,561],[1177,562],[62,241],[1165,241],[1166,241],[1172,563],[1175,564],[1174,291],[1171,1],[1169,565],[1361,566],[1357,1],[59,241],[1359,241],[1360,567],[1358,568],[265,241],[1363,569],[1362,570],[1365,571],[1364,241],[259,254],[1366,572],[1368,573],[1369,574],[1367,477],[1493,575],[1494,576],[1492,241],[1414,577],[1415,1],[1416,578],[1370,241],[1491,241],[1419,579],[1418,580],[266,241],[1420,1],[1423,581],[1421,582],[1422,583],[1432,584],[1429,585],[1424,1],[1426,585],[1431,586],[1425,585],[1430,585],[1427,585],[1428,585],[1437,587],[1436,241],[1438,588],[245,241],[1433,1],[1435,589],[1434,241],[1442,590],[1441,1],[261,241],[1440,591],[1443,592],[1439,593],[1448,1],[1449,594],[1447,1],[244,595],[243,568],[1446,596],[1444,568],[1445,597],[1455,598],[1454,1],[239,241],[1450,1],[1451,1],[1453,599],[1452,600],[1466,601],[1465,241],[238,241],[1462,602],[1464,603],[1461,241],[1463,604],[1471,605],[1470,1],[237,606],[1469,607],[1468,608],[1474,609],[1475,610],[1481,1],[1482,611],[52,241],[58,612],[55,241],[56,1],[57,1],[53,1],[54,241],[1476,241],[1479,613],[1477,614],[1472,1],[1478,1],[1473,615],[1480,616],[1483,617],[1484,1],[1486,618],[1488,619],[1489,1],[1500,620],[1501,621],[49,1],[48,622],[45,1],[51,623],[46,624],[50,625],[672,1],[671,626],[669,1],[674,627],[670,628],[673,629],[1503,630],[1505,631],[290,241],[291,632],[289,241],[1502,241],[1506,633],[1504,241],[1527,331],[1528,634],[1529,635],[1530,636],[1523,637],[1524,1],[1531,638],[1525,639],[1532,640],[1533,641],[1534,642],[1535,643],[1526,644],[255,241],[258,645],[254,241],[256,241],[257,241],[1521,241],[1522,646],[1520,647],[1510,648],[1509,329],[1514,649],[1513,241],[1512,650],[1511,651],[1518,1],[1517,652],[1516,652],[1515,1],[1519,653],[1508,654],[1538,655],[1543,1],[1542,1],[1545,656],[1546,657],[1539,1],[1540,1],[1541,1],[1553,1],[1555,1],[1554,1],[1560,1],[1561,658],[1557,1],[1559,1],[1558,1],[1556,1],[279,659],[280,659],[277,659],[281,660],[272,241],[278,241],[1547,661],[1536,662],[1549,663],[1548,664],[1537,665],[1552,666],[1544,329],[1551,667],[1550,329]],"semanticDiagnosticsPerFile":[1227,314,304,303,1228,270,268,43,267,269,1230,1498,306,1495,1499,1485,1496,44,1497,605,47,275,274,276,273,572,571,570,485,484,483,482,481,480,479,478,477,457,456,417,475,474,473,466,464,471,470,465,463,461,472,467,469,468,462,458,416,406,405,401,402,400,561,492,491,497,496,488,490,494,493,495,560,499,498,500,486,487,476,489,460,459,449,447,454,453,448,446,444,455,450,452,451,445,418,420,419,438,431,436,428,423,435,442,443,430,439,426,437,421,432,427,425,429,433,424,440,422,441,434,409,407,411,410,408,413,412,414,404,403,399,393,386,391,383,378,390,397,398,385,394,381,392,376,387,382,380,384,388,379,395,377,396,389,562,563,566,564,569,568,567,565,1459,501,502,503,559,504,548,506,505,507,508,510,509,511,512,513,515,516,517,518,520,521,522,523,519,524,525,526,527,528,529,538,530,531,532,533,535,534,536,537,539,540,514,542,541,543,544,545,547,546,549,551,552,550,553,554,555,556,557,558,608,284,606,607,1372,1569,1562,1564,1566,1565,1563,1568,1567,1570,1457,1458,150,151,186,187,188,189,190,191,192,193,194,195,196,198,197,199,200,201,185,235,202,203,204,236,205,206,207,208,209,210,211,212,213,214,215,216,217,219,218,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,1149,1154,1151,1157,1160,1150,1371,1460,375,152,1487,1212,1215,1218,1219,1217,1216,1220,1223,1222,1213,1221,1214,374,1211,1209,1207,1210,1208,1206,1205,1203,1204,1202,617,1507,1192,1187,1189,1188,1199,1198,1200,1197,1195,1196,1193,1194,1456,1413,1412,1411,1410,1373,1386,1385,1384,1377,1375,1376,1374,1201,1191,1190,619,620,621,618,1467,1417,573,574,415,1394,1408,1392,1393,1409,1404,1405,1403,1407,1401,1395,1406,1402,1400,1398,1399,1396,1397,1383,1380,1381,1382,1378,1379,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42,168,175,167,182,159,158,181,176,179,161,160,156,155,178,157,162,163,166,153,184,183,170,171,173,169,172,177,164,165,174,154,180,1388,1387,1391,1390,1389,[271,[{"file":"./packages/teleport-code-generator/__tests__/end2end/index.ts","start":460,"length":78,"messageText":"'uidlSample' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-code-generator/__tests__/end2end/index.ts","start":539,"length":118,"messageText":"'uidlSampleWithExternalDependencies' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-code-generator/__tests__/end2end/index.ts","start":658,"length":102,"messageText":"'uidlSampleWithJustTokens' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-code-generator/__tests__/end2end/index.ts","start":761,"length":93,"messageText":"'invalidUidlSample' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],263,264,1490,262,260,302,305,307,308,310,311,313,312,309,250,251,300,301,319,320,253,252,318,317,334,336,337,[339,[{"file":"./packages/teleport-component-generator-react/__tests__/integration/component-dependency.ts","start":699,"length":10,"messageText":"Parameter 'dependency' implicitly has an 'any' type.","category":1,"code":7006}]],341,342,343,344,345,349,340,346,350,335,338,347,348,351,352,[353,[{"file":"./packages/teleport-component-generator-react/__tests__/performance/index.ts","start":429,"length":29,"code":2559,"category":1,"messageText":"Type 'ReactStyleVariation.StyledJSX' has no properties in common with type 'GeneratorFactoryParams'."},{"file":"./packages/teleport-component-generator-react/__tests__/performance/index.ts","start":701,"length":23,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ assetsPrefix: string; }' is not assignable to parameter of type 'GeneratorOptions'.","category":1,"code":2345,"next":[{"messageText":"Object literal may only specify known properties, and 'assetsPrefix' does not exist in type 'GeneratorOptions'.","category":1,"code":2353}]}},{"file":"./packages/teleport-component-generator-react/__tests__/performance/index.ts","start":1141,"length":23,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ assetsPrefix: string; }' is not assignable to parameter of type 'GeneratorOptions'.","category":1,"code":2345,"next":[{"messageText":"Object literal may only specify known properties, and 'assetsPrefix' does not exist in type 'GeneratorOptions'.","category":1,"code":2353}]}},{"file":"./packages/teleport-component-generator-react/__tests__/performance/index.ts","start":3380,"length":173,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ type: \"element\"; content: { elementType: string; events: { onClick: undefined[]; }; children: { type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ ...; } | ... 1 more ... | { ...; })[]; style: { ...; }; }; }[]; }; }' is not assignable to parameter of type 'UIDLNode'.","category":1,"code":2345,"next":[{"messageText":"The types of 'content.children' are incompatible between these types.","category":1,"code":2200,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }[]' is not assignable to type 'UIDLNode[]'.","category":1,"code":2322,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }' is not assignable to type 'UIDLNode'.","category":1,"code":2322,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }' is not assignable to type 'UIDLDateTimeNode'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'type' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type 'string' is not assignable to type '\"date-time-node\"'.","category":1,"code":2322}]}]}]}]}]}]}}]],247,246,333,332,359,361,362,[364,[{"file":"./packages/teleport-component-generator-vue/__tests__/integration/component-dependency.ts","start":495,"length":10,"messageText":"Parameter 'dependency' implicitly has an 'any' type.","category":1,"code":7006}]],365,366,367,370,369,371,360,363,368,372,[373,[{"file":"./packages/teleport-component-generator-vue/__tests__/performance/index.ts","start":671,"length":23,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ assetsPrefix: string; }' is not assignable to parameter of type 'GeneratorOptions'.","category":1,"code":2345,"next":[{"messageText":"Object literal may only specify known properties, and 'assetsPrefix' does not exist in type 'GeneratorOptions'.","category":1,"code":2353}]}},{"file":"./packages/teleport-component-generator-vue/__tests__/performance/index.ts","start":1111,"length":23,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ assetsPrefix: string; }' is not assignable to parameter of type 'GeneratorOptions'.","category":1,"code":2345,"next":[{"messageText":"Object literal may only specify known properties, and 'assetsPrefix' does not exist in type 'GeneratorOptions'.","category":1,"code":2353}]}},{"file":"./packages/teleport-component-generator-vue/__tests__/performance/index.ts","start":3350,"length":173,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ type: \"element\"; content: { elementType: string; events: { onClick: undefined[]; }; children: { type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ ...; } | ... 1 more ... | { ...; })[]; style: { ...; }; }; }[]; }; }' is not assignable to parameter of type 'UIDLNode'.","category":1,"code":2345,"next":[{"messageText":"The types of 'content.children' are incompatible between these types.","category":1,"code":2200,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }[]' is not assignable to type 'UIDLNode[]'.","category":1,"code":2322,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }' is not assignable to type 'UIDLNode'.","category":1,"code":2322,"next":[{"messageText":"Type '{ type: string; content: { elementType: string; attrs: { 'data-attr': { type: string; content: string; }; }; children: ({ type: string; content: { elementType: string; attrs: { url: { type: string; content: string; }; }; }; } | { ...; } | { ...; })[]; style: { ...; }; }; }' is not assignable to type 'UIDLDateTimeNode'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'type' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type 'string' is not assignable to type '\"date-time-node\"'.","category":1,"code":2322}]}]}]}]}]}]}}]],249,248,358,357,292,293,283,282,286,285,287,288,580,240,242,241,575,577,579,576,578,600,294,598,599,597,604,1178,602,603,601,[614,[{"file":"./packages/teleport-plugin-common/__tests__/builders/ast-builders.ts","start":2244,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Identifier | StringLiteral'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'StringLiteral'.","category":1,"code":2339}]}}]],616,625,630,[631,[{"file":"./packages/teleport-plugin-common/__tests__/node-handlers/node-to-html/utils.ts","start":749,"length":6,"code":2739,"category":1,"messageText":"Type '{ dependencies: {}; dataObject: {}; methodsObject: {}; templateLookup: {}; }' is missing the following properties from type 'HTMLTemplateGenerationParams': propDefinitions, stateDefinitions"}]],639,[640,[{"file":"./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/index.ts","start":2019,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-common/__tests__/node-handlers/node-to-jsx/index.ts","start":2826,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}}]],641,642,643,644,645,646,647,[648,[{"file":"./packages/teleport-plugin-common/__tests__/utils/style-utils.ts","start":604,"length":4,"code":2322,"category":1,"messageText":"Type '\"nested-style\"' is not assignable to type '\"dynamic\" | \"static\"'.","relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/uidl.d.ts","start":18956,"length":4,"messageText":"The expected type comes from property 'type' which is declared here on type 'UIDLStyleValue'","category":3,"code":6500}]}]],649,650,652,581,584,583,596,594,593,595,591,592,586,588,582,590,587,585,589,613,615,624,637,628,629,626,627,634,638,632,633,653,612,623,609,636,622,611,610,635,651,[667,[{"file":"./packages/teleport-plugin-css-modules/__tests__/component-scoped.ts","start":2736,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'JSXAttribute | JSXSpreadAttribute'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXSpreadAttribute'.","category":1,"code":2339}]}}]],[668,[{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":1312,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":1395,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":2155,"length":14,"code":2339,"category":1,"messageText":"Property 'openingElement' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":2238,"length":14,"code":2339,"category":1,"messageText":"Property 'openingElement' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":3038,"length":14,"code":2339,"category":1,"messageText":"Property 'openingElement' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":3121,"length":14,"code":2339,"category":1,"messageText":"Property 'openingElement' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":4389,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":4468,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":4727,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":4816,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":4906,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":5548,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":5631,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":5899,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":6158,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":6247,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":6337,"length":4,"code":2339,"category":1,"messageText":{"messageText":"Property 'name' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'name' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":8990,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css-modules/__tests__/index.ts","start":9118,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."}]],666,675,326,325,665,663,664,[658,[{"file":"./packages/teleport-plugin-css/__tests__/component-scoped.ts","start":2772,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css/__tests__/component-scoped.ts","start":2952,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css/__tests__/component-scoped.ts","start":4386,"length":60,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type '\"class\"' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"Property 'class' does not exist on type '{}'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-css/__tests__/component-scoped.ts","start":4511,"length":67,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type '\"v-bind:class\"' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"Property 'v-bind:class' does not exist on type '{}'.","category":1,"code":2339}]}}]],[659,[{"file":"./packages/teleport-plugin-css/__tests__/index.ts","start":1960,"length":5,"code":2339,"category":1,"messageText":"Property 'class' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css/__tests__/index.ts","start":3400,"length":10,"code":2339,"category":1,"messageText":"Property 'expression' does not exist on type 'unknown'."}]],657,[660,[{"file":"./packages/teleport-plugin-css/__tests__/referenced-styles.ts","start":1076,"length":16,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ '5ed659b1732f9b804f7b6381': { type: \"style-map\"; content: { mapType: \"inlined\"; conditions: { conditionType: string; maxWidth: number; }[]; styles: { display: UIDLStaticValue; }; }; }; }' is not assignable to parameter of type 'UIDLReferencedStyles'.","category":1,"code":2345,"next":[{"messageText":"Property ''5ed659b1732f9b804f7b6381'' is incompatible with index signature.","category":1,"code":2530,"next":[{"messageText":"Type '{ type: \"style-map\"; content: { mapType: \"inlined\"; conditions: { conditionType: string; maxWidth: number; }[]; styles: { display: UIDLStaticValue; }; }; }' is not assignable to type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2322,"next":[{"messageText":"Type '{ type: \"style-map\"; content: { mapType: \"inlined\"; conditions: { conditionType: string; maxWidth: number; }[]; styles: { display: UIDLStaticValue; }; }; }' is not assignable to type 'UIDLElementNodeCompReferencedStyle'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'content' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Property 'content' is missing in type '{ mapType: \"inlined\"; conditions: { conditionType: string; maxWidth: number; }[]; styles: { display: UIDLStaticValue; }; }' but required in type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; }'.","category":1,"code":2741}]}]}]}]}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/uidl.d.ts","start":32890,"length":7,"messageText":"'content' is declared here.","category":3,"code":2728}]},{"file":"./packages/teleport-plugin-css/__tests__/referenced-styles.ts","start":1800,"length":5,"code":2339,"category":1,"messageText":"Property 'class' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-css/__tests__/referenced-styles.ts","start":3476,"length":5,"code":2339,"category":1,"messageText":"Property 'class' does not exist on type 'unknown'."}]],661,662,296,295,656,655,654,679,315,676,678,677,683,316,682,681,297,680,[686,[{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":1896,"length":66,"code":2352,"category":1,"messageText":{"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.","category":1,"code":2352,"next":[{"messageText":"Type 'Record' is missing the following properties from type 'JSXElement': type, openingElement, children","category":1,"code":2739}]}},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":3006,"length":66,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":4718,"length":66,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":6965,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":8501,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":10128,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":11352,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":13330,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":15200,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":16013,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":17532,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":18414,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":20572,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":21899,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":22803,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."},{"file":"./packages/teleport-plugin-jsx-head-config/__tests__/index.ts","start":23863,"length":57,"code":2352,"category":1,"messageText":"Conversion of type 'Record' to type 'JSXElement' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first."}]],1240,685,684,[688,[{"file":"./packages/teleport-plugin-jsx-inline-styles/__tests__/index.ts","start":1891,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-jsx-inline-styles/__tests__/index.ts","start":1970,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."}]],322,687,690,1239,689,693,330,692,691,721,722,723,724,726,728,729,725,731,735,736,737,738,128,130,126,116,115,121,114,122,125,120,110,112,109,108,124,113,111,119,117,123,118,131,129,127,730,739,717,718,702,701,720,700,708,715,706,696,698,695,694,714,699,697,705,703,713,704,707,727,734,733,740,732,710,711,712,709,719,716,1243,742,741,745,1242,744,743,748,1241,747,746,1051,1076,[754,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/account-node-output-contract.test.ts","start":1872,"length":10,"messageText":"Object literal's property 'user' implicitly has an 'any' type.","category":1,"code":7018}]],1011,1039,1040,1041,1042,1043,1047,[1048,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/component-scope-trigger-routing.test.ts","start":1450,"length":14,"messageText":"Object literal's property 'argument' implicitly has an 'any' type.","category":1,"code":7018}]],1049,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,[1062,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts","start":17062,"length":14,"messageText":"Object literal's property 'parameters' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts","start":17897,"length":9,"messageText":"Object literal's property 'value' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/data-node-not-awaited.test.ts","start":19535,"length":15,"messageText":"Function expression, which lacks return-type annotation, implicitly has an 'any' return type.","category":1,"code":7011}]],1063,1064,1065,[1066,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/element-visible-trigger-scoping.test.ts","start":2784,"length":12,"messageText":"Object literal's property 'children' implicitly has an 'any[]' type.","category":1,"code":7018}]],1067,1068,1069,1070,1071,1072,1073,1074,1075,1077,1078,1079,1080,1081,1082,[1083,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/order-number-generator.test.ts","start":6605,"length":109,"code":2352,"category":1,"messageText":{"messageText":"Conversion of type 'Record' to type 'Record' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.","category":1,"code":2352,"next":[{"messageText":"'string' index signatures are incompatible.","category":1,"code":2634,"next":[{"messageText":"Type 'UIDLWorkflow' is not comparable to type '{ nodes: { config: { code: string; }; }[]; }'.","category":1,"code":2678}]}]}}]],1084,[1085,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/page-loaded-scoping-skip.test.ts","start":1303,"length":14,"messageText":"Object literal's property 'argument' implicitly has an 'any' type.","category":1,"code":7018}]],1086,1087,[1089,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/raw-query-param-binding.test.ts","start":7280,"length":8,"messageText":"Object literal's property 'rows' implicitly has an 'any[]' type.","category":1,"code":7018}]],[1090,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/raw-sql-param-binding.test.ts","start":4092,"length":83,"code":2352,"category":1,"messageText":{"messageText":"Conversion of type '{ query: string; queryVariables: { name: string; value: { type: \"workflowContext\"; nodeId: string; path: string[]; }; }[]; }' to type '{ query: string; params: unknown[]; }' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.","category":1,"code":2352,"next":[{"messageText":"Property 'params' is missing in type '{ query: string; queryVariables: { name: string; value: { type: \"workflowContext\"; nodeId: string; path: string[]; }; }[]; }' but required in type '{ query: string; params: unknown[]; }'.","category":1,"code":2741}]},"relatedInformation":[{"file":"./packages/teleport-plugin-next-workflows/__tests__/raw-sql-param-binding.test.ts","start":4156,"length":6,"messageText":"'params' is declared here.","category":3,"code":2728}]}]],1091,1092,[1093,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/route-changed-trigger.test.ts","start":1372,"length":14,"messageText":"Object literal's property 'argument' implicitly has an 'any' type.","category":1,"code":7018}]],1094,1095,[1096,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/runtime-template-token-resolution.test.ts","start":5344,"length":11,"messageText":"Object literal's property 'value' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/runtime-template-token-resolution.test.ts","start":7425,"length":8,"messageText":"Object literal's property 'rows' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/runtime-template-token-resolution.test.ts","start":10183,"length":2,"code":2339,"category":1,"messageText":"Property 'id' does not exist on type 'unknown'."}]],1097,1098,[1099,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/security-runtime-shadow.test.ts","start":2764,"length":13,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ workflows: { w: { nodes: { id: string; type: string; config: { url: string; }; }[]; }; }; }' is not assignable to parameter of type 'WorkflowsContainer'.","category":1,"code":2345,"next":[{"messageText":"Types of property 'workflows' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ w: { nodes: { id: string; type: string; config: { url: string; }; }[]; }; }' is not assignable to type 'Record'.","category":1,"code":2322,"next":[{"messageText":"Property 'w' is incompatible with index signature.","category":1,"code":2530,"next":[{"messageText":"Type '{ nodes: { id: string; type: string; config: { url: string; }; }[]; }' is not assignable to type 'WorkflowLike'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'nodes' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ id: string; type: string; config: { url: string; }; }[]' is not assignable to type 'WorkflowNodeLike[]'.","category":1,"code":2322,"next":[{"messageText":"Type '{ id: string; type: string; config: { url: string; }; }' is not assignable to type 'WorkflowNodeLike'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'config' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ url: string; }' has no properties in common with type '{ code?: string; }'.","category":1,"code":2559}]}]}]}]}]}]}]}]}]}}]],1100,[1101,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/state-update-array-type-guard.test.ts","start":1873,"length":9,"messageText":"Object literal's property 'value' implicitly has an 'any[]' type.","category":1,"code":7018}]],1102,1103,[1104,[{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":27198,"length":9,"messageText":"Object literal's property 'edges' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":27282,"length":2,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ id: string; name: string; nodes: { id: string; type: string; config: { code: string; }; }[]; edges: any[]; }' is not assignable to parameter of type '{ id: string; name: string; nodes: ({ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { ...; })[]; edges: ({ ...; } | { ...; })[]; }'.","category":1,"code":2345,"next":[{"messageText":"Types of property 'nodes' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ id: string; type: string; config: { code: string; }; }[]' is not assignable to type '({ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { id: string; type: string; config: { ...; }; label: string; })[]'.","category":1,"code":2322,"next":[{"messageText":"Type '{ id: string; type: string; config: { code: string; }; }' is not assignable to type '{ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { id: string; type: string; config: { ...; }; label: string; }'.","category":1,"code":2322,"next":[{"messageText":"Property 'label' is missing in type '{ id: string; type: string; config: { code: string; }; }' but required in type '{ id: string; type: string; config: { code: string; tableName?: undefined; }; label: string; }'.","category":1,"code":2741}]}]}]}]},"relatedInformation":[{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":21284,"length":34,"messageText":"'label' is declared here.","category":3,"code":2728}]},{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":29690,"length":9,"messageText":"Object literal's property 'edges' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":29747,"length":2,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ id: string; name: string; nodes: { id: string; type: string; config: { code: string; }; }[]; edges: any[]; }' is not assignable to parameter of type '{ id: string; name: string; nodes: ({ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { ...; })[]; edges: ({ ...; } | { ...; })[]; }'.","category":1,"code":2345,"next":[{"messageText":"Types of property 'nodes' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ id: string; type: string; config: { code: string; }; }[]' is not assignable to type '({ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { id: string; type: string; config: { ...; }; label: string; })[]'.","category":1,"code":2322,"next":[{"messageText":"Type '{ id: string; type: string; config: { code: string; }; }' is not assignable to type '{ id: string; type: string; config: { tableName?: undefined; code?: undefined; }; label: string; } | { id: string; type: string; config: { tableName: string; code?: undefined; }; label: string; } | { id: string; type: string; config: { ...; }; label: string; }'.","category":1,"code":2322,"next":[{"messageText":"Property 'label' is missing in type '{ id: string; type: string; config: { code: string; }; }' but required in type '{ id: string; type: string; config: { code: string; tableName?: undefined; }; label: string; }'.","category":1,"code":2741}]}]}]}]},"relatedInformation":[{"file":"./packages/teleport-plugin-next-workflows/__tests__/stock-decrement-audit.test.ts","start":21284,"length":34,"messageText":"'label' is declared here.","category":3,"code":2728}]}]],1105,1106,1107,1108,97,96,99,104,101,92,91,100,103,95,94,98,93,102,89,90,1029,1010,1018,1012,[1027,[{"file":"./packages/teleport-plugin-next-workflows/src/data-api-route-generator.ts","start":929,"length":13,"messageText":"Type 'Set' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802}]],1035,1032,1033,1034,1031,755,1008,1050,[1023,[{"file":"./packages/teleport-plugin-next-workflows/src/invoice/api-routes-code.ts","start":391,"length":12,"messageText":"'autoGenerate' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],1022,1016,1024,1019,1021,1020,1044,[753,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/account/account-compare-passwords.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],847,750,[848,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/account/account-hash-password.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],751,849,752,850,[854,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-custom-prompt.ts","start":655,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[855,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-detect-language.ts","start":705,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[856,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-generate-text-embedding.ts","start":305,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],853,[857,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-sentiment-analysis.ts","start":708,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[858,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-summarization.ts","start":655,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[859,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-text-classifier.ts","start":705,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[860,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/ai/ai-text-transform.ts","start":656,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],851,852,861,862,863,864,[865,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-get-media-devices.ts","start":187,"length":11,"messageText":"Object literal's property 'devices' implicitly has an 'any[]' type.","category":1,"code":7018}]],866,[867,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-pick-files.ts","start":2340,"length":9,"messageText":"Object literal's property 'files' implicitly has an 'any[]' type.","category":1,"code":7018}]],868,869,870,871,872,[873,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/browser/browser-subscribe-to-push.ts","start":266,"length":18,"messageText":"Object literal's property 'subscription' implicitly has an 'any' type.","category":1,"code":7018}]],874,875,876,877,878,879,880,881,889,890,[891,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-delete-item.ts","start":1522,"length":15,"messageText":"Object literal's property 'deletedId' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-delete-item.ts","start":2239,"length":15,"messageText":"Object literal's property 'deletedId' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-delete-item.ts","start":2783,"length":15,"messageText":"Object literal's property 'deletedId' implicitly has an 'any' type.","category":1,"code":7018}]],[892,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-raw-query.ts","start":1026,"length":8,"messageText":"Object literal's property 'rows' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-raw-query.ts","start":1036,"length":10,"messageText":"Object literal's property 'result' implicitly has an 'any[]' type.","category":1,"code":7018}]],[893,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-select.ts","start":3363,"length":8,"messageText":"Object literal's property 'rows' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/data/data-select.ts","start":4180,"length":8,"messageText":"Object literal's property 'rows' implicitly has an 'any[]' type.","category":1,"code":7018}]],894,882,883,[895,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-add-class.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],896,[897,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-get-classes.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[898,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-get-input-value.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[899,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-hide.ts","start":107,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[900,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-remove-class.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[901,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-scroll-to.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[902,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-set-attribute.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[903,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-set-text.ts","start":111,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[904,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-show.ts","start":107,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[905,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/element/element-toggle-class.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[906,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/email/email-mailersend.ts","start":111,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[907,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/email/email-mailgun.ts","start":108,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[908,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/email/email-postmark.ts","start":109,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[909,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/email/email-resend.ts","start":107,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[910,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/email/email-sendgrid.ts","start":109,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[888,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/event/event-workflow-error.ts","start":102,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/event/event-workflow-error.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],887,886,[885,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-list.ts","start":1762,"length":9,"messageText":"Object literal's property 'files' implicitly has an 'any[]' type.","category":1,"code":7018}]],[884,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-upload.ts","start":1165,"length":9,"messageText":"Object literal's property 'files' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/file-storage/file-storage-upload.ts","start":4087,"length":9,"messageText":"Object literal's property 'files' implicitly has an 'any[]' type.","category":1,"code":7018}]],[911,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/form/form-blur.ts","start":104,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[912,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/form/form-focus.ts","start":105,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[913,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/form/form-reset.ts","start":105,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[914,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/form/form-set-value.ts","start":109,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],915,[916,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-custom-node.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[917,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-delay.ts","start":496,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[918,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-emit-custom-event.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],919,[920,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-http-request.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-http-request.ts","start":3149,"length":20,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-http-request.ts","start":4273,"length":10,"messageText":"Object literal's property 'body' implicitly has an 'any' type.","category":1,"code":7018}]],[922,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-if-statement.ts","start":102,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-if-statement.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[923,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-loop.ts","start":94,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-loop.ts","start":107,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[924,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-parallel.ts","start":98,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-parallel.ts","start":111,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-parallel.ts","start":158,"length":11,"messageText":"Object literal's property 'results' implicitly has an 'any[]' type.","category":1,"code":7018}]],921,[925,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-switch.ts","start":96,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-switch.ts","start":109,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[926,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/general/general-trigger-download.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],1007,846,[757,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-activecampaign.ts","start":128,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[758,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-airtable.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[759,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":376,"length":3,"messageText":"Parameter 'key' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":381,"length":9,"messageText":"Parameter 'dateStamp' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":392,"length":10,"messageText":"Parameter 'regionName' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":404,"length":11,"messageText":"Parameter 'serviceName' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1424,"length":4,"messageText":"Parameter 'data' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1767,"length":6,"messageText":"Parameter 'method' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1775,"length":4,"messageText":"Parameter 'path' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1781,"length":11,"messageText":"Parameter 'queryString' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1794,"length":7,"messageText":"Parameter 'headers' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amazon-s3.ts","start":1803,"length":7,"messageText":"Parameter 'payload' implicitly has an 'any' type.","category":1,"code":7006}]],[760,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-amplitude.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[761,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-apollo.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[762,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-asana.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],764,765,766,[767,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-bannerbear.ts","start":124,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],768,769,[770,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-bitbucket.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[771,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-calendly.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[772,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-clickup.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[773,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-coda.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],774,[775,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-copper.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[776,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-discord.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],777,778,[779,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-dropbox.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[780,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-eventbrite.ts","start":124,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[781,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-excel.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],782,[783,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-figma.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[784,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gainsight.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],763,[785,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-github.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[786,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gmail.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[787,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-gong.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[788,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-analytics.ts","start":130,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],789,[790,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-calendar.ts","start":129,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[791,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-docs.ts","start":125,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[792,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-drive.ts","start":126,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],793,[794,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-google-sheets.ts","start":127,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[795,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-greenhouse.ts","start":124,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],796,797,798,[799,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-hubspot.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[800,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-insightly.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],801,[802,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-intercom.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[803,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-jira.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-jira.ts","start":1962,"length":1,"messageText":"Parameter 'c' implicitly has an 'any' type.","category":1,"code":7006}]],[804,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-keap.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],805,806,807,[808,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-mailchimp.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],809,[810,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-mixpanel.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-mixpanel.ts","start":1646,"length":3,"messageText":"Parameter 'evt' implicitly has an 'any' type.","category":1,"code":7006}]],[811,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-monday.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-monday.ts","start":974,"length":5,"messageText":"Parameter 'query' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-monday.ts","start":981,"length":9,"messageText":"Parameter 'variables' implicitly has an 'any' type.","category":1,"code":7006}]],812,[813,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-notion.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],814,[815,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outlook.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outlook.ts","start":1239,"length":5,"messageText":"Parameter 'email' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outlook.ts","start":1400,"length":5,"messageText":"Parameter 'email' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outlook.ts","start":1563,"length":5,"messageText":"Parameter 'email' implicitly has an 'any' type.","category":1,"code":7006}]],[816,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-outreach.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[817,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pandadoc.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[818,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pardot.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[819,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-pipedrive.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],820,821,822,823,824,[825,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-salesforce.ts","start":124,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[826,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-segment.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],827,828,[829,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-shopify.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[830,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-slack.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],831,832,[833,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-stripe.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-stripe.ts","start":990,"length":10,"messageText":"'toFormData' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.","category":1,"code":7023}]],[834,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-tableau.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],835,[836,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-trello.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-trello.ts","start":1072,"length":3,"messageText":"Parameter 'url' implicitly has an 'any' type.","category":1,"code":7006}]],[837,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-typeform.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[838,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-whatsapp.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-whatsapp.ts","start":2958,"length":18,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ messaging_product: string; recipient_type: string; to: any; type: any; }'."},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-whatsapp.ts","start":3037,"length":18,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ messaging_product: string; recipient_type: string; to: any; type: any; }'."}]],[839,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-woocommerce.ts","start":125,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],840,[841,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-wrike.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],842,843,[844,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-youtube.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[845,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/integrations/integration-zendesk.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[927,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-go-back.ts","start":100,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-go-back.ts","start":113,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],928,[929,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-navigate-to-url.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[930,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-refresh-page.ts","start":105,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/navigation/navigation-refresh-page.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[931,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-cancel-plan.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[932,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-charge-user.ts","start":16050,"length":14,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252}]],933,[934,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-create-product.ts","start":117,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[935,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-create-subscription.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[936,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-customer.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-customer.ts","start":504,"length":14,"messageText":"Object literal's property 'customer' implicitly has an 'any' type.","category":1,"code":7018}]],[937,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-product.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-get-product.ts","start":499,"length":13,"messageText":"Object literal's property 'product' implicitly has an 'any' type.","category":1,"code":7018}]],[938,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-customers.ts","start":117,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-customers.ts","start":694,"length":13,"messageText":"Object literal's property 'customers' implicitly has an 'any[]' type.","category":1,"code":7018}]],[939,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-plans.ts","start":113,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-plans.ts","start":687,"length":9,"messageText":"Object literal's property 'plans' implicitly has an 'any[]' type.","category":1,"code":7018}]],[940,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-products.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-products.ts","start":692,"length":12,"messageText":"Object literal's property 'products' implicitly has an 'any[]' type.","category":1,"code":7018}]],[941,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-subscriptions.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-list-subscriptions.ts","start":791,"length":17,"messageText":"Object literal's property 'subscriptions' implicitly has an 'any[]' type.","category":1,"code":7018}]],[942,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-subscribe-to-plan.ts","start":120,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[943,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-update-customer.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/payment/payment-update-customer.ts","start":1134,"length":14,"messageText":"Object literal's property 'customer' implicitly has an 'any' type.","category":1,"code":7018}]],944,945,[946,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-list-channel-members.ts","start":712,"length":11,"messageText":"Object literal's property 'members' implicitly has an 'any[]' type.","category":1,"code":7018}]],[947,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-list-channels.ts","start":831,"length":12,"messageText":"Object literal's property 'channels' implicitly has an 'any[]' type.","category":1,"code":7018}]],[948,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-send-channel-event.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[949,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/realtime/realtime-send-channel-message.ts","start":124,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[950,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-infobip.ts","start":106,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[951,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-smsapi.ts","start":105,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[952,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-textmagic.ts","start":108,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[953,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/sms/sms-twilio.ts","start":105,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],955,954,956,957,958,959,960,961,[962,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-local-remove.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[963,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-local-set.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],964,[965,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-session-remove.ts","start":117,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[966,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/storage/storage-session-set.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],967,[968,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-array.ts","start":110,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-array.ts","start":7310,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[969,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-calculate.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-calculate.ts","start":759,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[970,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":110,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":577,"length":3,"messageText":"Parameter 'hex' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":869,"length":1,"messageText":"Parameter 'r' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":872,"length":1,"messageText":"Parameter 'g' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":875,"length":1,"messageText":"Parameter 'b' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1270,"length":1,"messageText":"Parameter 'r' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1273,"length":1,"messageText":"Parameter 'g' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1276,"length":1,"messageText":"Parameter 'b' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1987,"length":1,"messageText":"Parameter 'h' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1990,"length":1,"messageText":"Parameter 's' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":1993,"length":1,"messageText":"Parameter 'l' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":2899,"length":1,"messageText":"Parameter 'c' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":3406,"length":1,"messageText":"Parameter 'r' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":3409,"length":1,"messageText":"Parameter 'g' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":3412,"length":1,"messageText":"Parameter 'b' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-color.ts","start":9025,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[971,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-convert.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-convert.ts","start":908,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[972,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-currency.ts","start":113,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-currency.ts","start":758,"length":3,"messageText":"Parameter 'val' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-currency.ts","start":763,"length":3,"messageText":"Parameter 'dec' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-currency.ts","start":1901,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[973,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":668,"length":3,"messageText":"Parameter 'val' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":897,"length":1,"messageText":"Parameter 'd' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":900,"length":3,"messageText":"Parameter 'fmt' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":1524,"length":1,"messageText":"Parameter 'd' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":1527,"length":3,"messageText":"Parameter 'amt' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":1532,"length":1,"messageText":"Parameter 'u' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-date-time.ts","start":2700,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[974,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3663,"length":32,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'."},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3723,"length":32,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'."},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3799,"length":32,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'."},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3861,"length":32,"code":7053,"category":1,"messageText":"Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'."},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3940,"length":11,"messageText":"Object literal's property 'value' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-generate.ts","start":3953,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[975,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":893,"length":3,"messageText":"Parameter 'deg' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":955,"length":3,"messageText":"Parameter 'rad' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1029,"length":3,"messageText":"Parameter 'la1' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1034,"length":3,"messageText":"Parameter 'lo1' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1039,"length":3,"messageText":"Parameter 'la2' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1044,"length":3,"messageText":"Parameter 'lo2' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1402,"length":2,"messageText":"Parameter 'km' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":1406,"length":1,"messageText":"Parameter 'u' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-geolocation.ts","start":2239,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[976,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-image.ts","start":110,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-image.ts","start":991,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[977,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":110,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":441,"length":6,"messageText":"Parameter 'target' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":449,"length":6,"messageText":"Parameter 'source' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":573,"length":17,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":781,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":1005,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":1156,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":1215,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":1410,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":1467,"length":11,"code":7053,"category":1,"messageText":{"messageText":"Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.","category":1,"code":7053,"next":[{"messageText":"No index signature with a parameter of type 'string' was found on type '{}'.","category":1,"code":7054}]}},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-merge.ts","start":5459,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[978,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-object.ts","start":111,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-object.ts","start":4711,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[979,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-string.ts","start":111,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-string.ts","start":3356,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[980,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/transform/transform-validate.ts","start":113,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],749,[981,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/url/url-get-current-url.ts","start":101,"length":6,"messageText":"'config' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/url/url-get-current-url.ts","start":114,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[982,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/url/url-get-query-parameter.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[983,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-anonymize-data.ts","start":495,"length":14,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-anonymize-data.ts","start":3638,"length":15,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-anonymize-data.ts","start":117,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-anonymize-data.ts","start":376,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[984,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-barcode-generate.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-barcode-generate.ts","start":757,"length":14,"messageText":"Object literal's property 'imageUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-barcode-generate.ts","start":773,"length":15,"messageText":"Object literal's property 'imageData' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-barcode-generate.ts","start":2113,"length":14,"messageText":"Object literal's property 'imageUrl' implicitly has an 'any' type.","category":1,"code":7018}]],[985,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-csv-parse.ts","start":1630,"length":11,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-csv-parse.ts","start":6738,"length":9,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-csv-parse.ts","start":7454,"length":11,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-csv-parse.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[986,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-encode-decode.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-encode-decode.ts","start":366,"length":11,"messageText":"Object literal's property 'error' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-encode-decode.ts","start":2713,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[987,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":847,"length":10,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":650,"length":12,"messageText":"Object literal's property 'contacts' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":664,"length":10,"messageText":"Object literal's property 'emails' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":676,"length":10,"messageText":"Object literal's property 'phones' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":688,"length":8,"messageText":"Object literal's property 'urls' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":698,"length":10,"messageText":"Object literal's property 'social' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":4312,"length":12,"messageText":"Object literal's property 'contacts' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":4332,"length":10,"messageText":"Object literal's property 'emails' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":4350,"length":10,"messageText":"Object literal's property 'phones' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":4368,"length":8,"messageText":"Object literal's property 'urls' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-contacts.ts","start":4384,"length":10,"messageText":"Object literal's property 'social' implicitly has an 'any[]' type.","category":1,"code":7018}]],[988,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":988,"length":10,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":1592,"length":14,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":2494,"length":7,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":521,"length":9,"messageText":"Object literal's property 'links' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-extract-links.ts","start":4126,"length":9,"messageText":"Object literal's property 'links' implicitly has an 'any[]' type.","category":1,"code":7018}]],[989,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-format-phone-number.ts","start":122,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-format-phone-number.ts","start":320,"length":15,"messageText":"Object literal's property 'formatted' implicitly has an 'any' type.","category":1,"code":7018}]],[990,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":975,"length":11,"messageText":"Object literal's property 'results' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":1003,"length":10,"messageText":"Object literal's property 'scores' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":1015,"length":14,"messageText":"Object literal's property 'queryTerms' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":14064,"length":8,"messageText":"'strValue' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":17360,"length":11,"messageText":"Object literal's property 'results' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":17388,"length":10,"messageText":"Object literal's property 'scores' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-full-text-search.ts","start":17400,"length":14,"messageText":"Object literal's property 'queryTerms' implicitly has an 'any[]' type.","category":1,"code":7018}]],[991,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","start":1827,"length":12,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","start":123,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","start":7758,"length":12,"messageText":"Object literal's property 'pdfUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","start":8073,"length":12,"messageText":"Object literal's property 'pdfUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-generate-invoice-pdf.ts","start":8087,"length":13,"messageText":"Object literal's property 'pdfData' implicitly has an 'any' type.","category":1,"code":7018}]],[992,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hash-data.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hash-data.ts","start":837,"length":10,"messageText":"Object literal's property 'hash' implicitly has an 'any' type.","category":1,"code":7018}]],[993,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hybrid-search.ts","start":968,"length":13,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hybrid-search.ts","start":2245,"length":16,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hybrid-search.ts","start":116,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-hybrid-search.ts","start":790,"length":11,"messageText":"Object literal's property 'results' implicitly has an 'any[]' type.","category":1,"code":7018}]],[994,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-markdown-to-html.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-markdown-to-html.ts","start":1441,"length":10,"messageText":"Object literal's property 'html' implicitly has an 'any' type.","category":1,"code":7018}]],[995,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-ocr-extract-text.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-ocr-extract-text.ts","start":382,"length":10,"messageText":"Object literal's property 'text' implicitly has an 'any' type.","category":1,"code":7018}]],[996,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":213,"length":14,"messageText":"Object literal's property 'protocol' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":235,"length":10,"messageText":"Object literal's property 'host' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":253,"length":14,"messageText":"Object literal's property 'hostname' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":275,"length":10,"messageText":"Object literal's property 'port' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":293,"length":14,"messageText":"Object literal's property 'pathname' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":315,"length":12,"messageText":"Object literal's property 'search' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":335,"length":10,"messageText":"Object literal's property 'hash' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-parse-url.ts","start":353,"length":12,"messageText":"Object literal's property 'origin' implicitly has an 'any' type.","category":1,"code":7018}]],[997,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-extract-text.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-extract-text.ts","start":365,"length":10,"messageText":"Object literal's property 'text' implicitly has an 'any' type.","category":1,"code":7018}]],[998,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-generate.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-generate.ts","start":5154,"length":12,"messageText":"Object literal's property 'pdfUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-generate.ts","start":5253,"length":12,"messageText":"Object literal's property 'pdfUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-pdf-generate.ts","start":5267,"length":13,"messageText":"Object literal's property 'pdfData' implicitly has an 'any' type.","category":1,"code":7018}]],[999,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","start":119,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","start":567,"length":14,"messageText":"Object literal's property 'imageUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","start":583,"length":15,"messageText":"Object literal's property 'imageData' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","start":1307,"length":14,"messageText":"Object literal's property 'imageUrl' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-qr-code-generate.ts","start":1546,"length":14,"messageText":"Object literal's property 'imageUrl' implicitly has an 'any' type.","category":1,"code":7018}]],[1000,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","start":117,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","start":3350,"length":10,"messageText":"Object literal's property 'html' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","start":3814,"length":11,"messageText":"Object literal's property 'error' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","start":7739,"length":10,"messageText":"'baseDomain' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-scrape-website.ts","start":9257,"length":13,"messageText":"Object literal's property 'content' implicitly has an 'any' type.","category":1,"code":7018}]],[1001,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-semantic-search.ts","start":746,"length":16,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-semantic-search.ts","start":1427,"length":12,"messageText":"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.","category":1,"code":1252},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-semantic-search.ts","start":118,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-semantic-search.ts","start":550,"length":11,"messageText":"Object literal's property 'results' implicitly has an 'any[]' type.","category":1,"code":7018}]],[1002,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-similarity-scoring.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[1003,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-verify-email.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[1004,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-verify-phone.ts","start":115,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],[1005,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-xml-parse.ts","start":112,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-xml-parse.ts","start":1178,"length":12,"messageText":"Object literal's property 'result' implicitly has an 'any' type.","category":1,"code":7018}]],[1006,[{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-youtube-transcript.ts","start":121,"length":7,"messageText":"'context' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-youtube-transcript.ts","start":1171,"length":16,"messageText":"Object literal's property 'transcript' implicitly has an 'any' type.","category":1,"code":7018},{"file":"./packages/teleport-plugin-next-workflows/src/nodes/utility/utility-youtube-transcript.ts","start":1197,"length":12,"messageText":"Object literal's property 'segments' implicitly has an 'any[]' type.","category":1,"code":7018}]],1109,1028,1037,1015,[1030,[{"file":"./packages/teleport-plugin-next-workflows/src/runtime-storage-generator.ts","start":251,"length":13,"messageText":"Type 'Set' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802}]],1014,1036,[1013,[{"file":"./packages/teleport-plugin-next-workflows/src/segment-splitter.ts","start":3525,"length":111,"messageText":"Type 'Set' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/segment-splitter.ts","start":3905,"length":63,"messageText":"Type 'Set' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802}]],1088,1026,1017,1045,756,1025,1009,[1046,[{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":42126,"length":15,"messageText":"Type 'Map' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":42454,"length":6,"messageText":"Type 'Map' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":43042,"length":4,"messageText":"Parameter 'attr' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":52651,"length":9,"messageText":"Type 'Map>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":52961,"length":1,"messageText":"Parameter 't' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-component-plugin.ts","start":53163,"length":1,"messageText":"Parameter 't' implicitly has an 'any' type.","category":1,"code":7006}]],[1038,[{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":8293,"length":17,"messageText":"Type 'Set' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":29468,"length":20,"messageText":"'injectToasterIntoApp' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":29625,"length":15,"messageText":"Type 'IterableIterator<[string, InMemoryFileRecord]>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":34808,"length":15,"messageText":"Type 'IterableIterator<[string, InMemoryFileRecord]>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":40396,"length":8,"messageText":"'strategy' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":62133,"length":13,"messageText":"'appFileRecord' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-plugin-next-workflows/src/workflow-project-plugin.ts","start":62220,"length":15,"messageText":"Type 'IterableIterator<[string, InMemoryFileRecord]>' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802}]],[1112,[{"file":"./packages/teleport-plugin-react-app-routing/__tests__/index.ts","start":650,"length":6,"code":2339,"category":1,"messageText":"Property 'values' does not exist on type 'UIDLStateDefinition'."}]],1346,1111,1110,1115,321,1113,1114,[1120,[{"file":"./packages/teleport-plugin-react-jss/__tests__/component-referenced.ts","start":1185,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-jss/__tests__/component-referenced.ts","start":2498,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."}]],1121,1119,1122,1123,324,323,1118,1117,1116,[1129,[{"file":"./packages/teleport-plugin-react-styled-components/__tests__/component-scoped.ts","start":1217,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-components/__tests__/component-scoped.ts","start":2441,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."}]],1130,1128,[1131,[{"file":"./packages/teleport-plugin-react-styled-components/__tests__/referenced-styles.ts","start":1622,"length":4,"code":2339,"category":1,"messageText":"Property 'type' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-components/__tests__/referenced-styles.ts","start":1713,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-components/__tests__/referenced-styles.ts","start":3889,"length":4,"code":2339,"category":1,"messageText":"Property 'type' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-components/__tests__/referenced-styles.ts","start":3980,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."}]],[1132,[{"file":"./packages/teleport-plugin-react-styled-components/__tests__/style-sheet.ts","start":3423,"length":11,"code":2339,"category":1,"messageText":"Property 'declaration' does not exist on type 'unknown'."}]],328,327,1124,1127,1126,1125,[1136,[{"file":"./packages/teleport-plugin-react-styled-jsx/__tests__/component-scoped.ts","start":1152,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-jsx/__tests__/component-scoped.ts","start":2762,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-react-styled-jsx/__tests__/component-scoped.ts","start":2834,"length":10,"code":2339,"category":1,"messageText":"Property 'attributes' does not exist on type 'unknown'."}]],1137,1135,[1138,[{"file":"./packages/teleport-plugin-react-styled-jsx/__tests__/referenced-styles.ts","start":1571,"length":12,"code":2339,"category":1,"messageText":"Property 'declarations' does not exist on type 'unknown'."}]],1139,329,1134,1133,[1141,[{"file":"./packages/teleport-plugin-vue-app-routing/__tests__/index.ts","start":590,"length":6,"code":2339,"category":1,"messageText":"Property 'values' does not exist on type 'UIDLStateDefinition'."},{"file":"./packages/teleport-plugin-vue-app-routing/__tests__/index.ts","start":1886,"length":6,"code":2339,"category":1,"messageText":"Property 'length' does not exist on type 'unknown'."}]],1352,1140,1146,[1145,[{"file":"./packages/teleport-plugin-vue-base-component/__tests__/mocks.ts","start":176,"length":10,"messageText":"Object literal's property 'chunks' implicitly has an 'any[]' type.","category":1,"code":7018}]],354,1143,1144,1142,[1148,[{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":1489,"length":11,"code":2339,"category":1,"messageText":"Property 'declaration' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":1782,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":2721,"length":11,"code":2339,"category":1,"messageText":"Property 'declaration' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":3012,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXElement'.","category":1,"code":2339}]}},{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":3840,"length":11,"code":2339,"category":1,"messageText":"Property 'declaration' does not exist on type 'unknown'."},{"file":"./packages/teleport-plugin-vue-head-config/__tests__/index.ts","start":4131,"length":5,"code":2339,"category":1,"messageText":{"messageText":"Property 'value' does not exist on type 'Expression | PrivateName'.","category":1,"code":2339,"next":[{"messageText":"Property 'value' does not exist on type 'JSXElement'.","category":1,"code":2339}]}}]],1339,1147,1153,299,1152,1156,355,1155,1159,331,1158,1162,298,1161,1164,356,1163,1184,1183,142,144,143,1180,1179,1182,1181,1231,1229,148,149,146,147,145,1186,1226,[1232,[{"file":"./packages/teleport-project-generator-html/src/path-browserisify.d.ts","start":78,"length":4,"messageText":"Duplicate identifier 'path'.","category":1,"code":2300,"relatedInformation":[{"file":"./packages/teleport-publisher-disk/src/path-browserisify.d.ts","start":78,"length":4,"messageText":"'path' was also declared here.","category":3,"code":6203}]}]],1224,1225,1185,1319,1237,1238,[1307,[{"file":"./packages/teleport-project-generator-next/__tests__/calendarkit-end2end.test.ts","start":1112,"length":12,"messageText":"Object literal's property 'children' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-project-generator-next/__tests__/calendarkit-end2end.test.ts","start":2102,"length":23,"code":2345,"category":1,"messageText":{"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'.","category":1,"code":2345,"next":[{"messageText":"Index signature for type 'string' is missing in type 'ProjectUIDL'.","category":1,"code":2329}]}},{"file":"./packages/teleport-project-generator-next/__tests__/calendarkit-end2end.test.ts","start":3314,"length":53,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."}]],1308,1309,1310,1311,1312,1313,1314,[1315,[{"file":"./packages/teleport-project-generator-next/__tests__/dragdrop-kanban-end2end.test.ts","start":2600,"length":12,"messageText":"Object literal's property 'children' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-project-generator-next/__tests__/dragdrop-kanban-end2end.test.ts","start":3590,"length":11,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."},{"file":"./packages/teleport-project-generator-next/__tests__/dragdrop-kanban-end2end.test.ts","start":5665,"length":53,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."}]],1316,1317,1318,1320,1336,1333,1334,1335,1321,[1322,[{"file":"./packages/teleport-project-generator-next/__tests__/form-file-input-end2end.test.ts","start":1157,"length":12,"messageText":"Object literal's property 'children' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-project-generator-next/__tests__/form-file-input-end2end.test.ts","start":2152,"length":28,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."},{"file":"./packages/teleport-project-generator-next/__tests__/form-file-input-end2end.test.ts","start":4256,"length":4,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."}]],1323,[1324,[{"file":"./packages/teleport-project-generator-next/__tests__/motion-end2end.test.ts","start":1123,"length":12,"messageText":"Object literal's property 'children' implicitly has an 'any[]' type.","category":1,"code":7018},{"file":"./packages/teleport-project-generator-next/__tests__/motion-end2end.test.ts","start":2120,"length":21,"code":2345,"category":1,"messageText":"Argument of type 'ProjectUIDL' is not assignable to parameter of type 'Record'."}]],[1325,[{"file":"./packages/teleport-project-generator-next/__tests__/motion-stagger-repeater.test.ts","start":2904,"length":10,"messageText":"Function expression, which lacks return-type annotation, implicitly has an 'any' return type.","category":1,"code":7011}]],[1326,[{"file":"./packages/teleport-project-generator-next/__tests__/order-notification-template-rendering.test.ts","start":7725,"length":5,"messageText":"'ITEMS' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],1327,1328,1329,1330,1331,[1332,[{"file":"./packages/teleport-project-generator-next/__tests__/widget-project-plugins.test.ts","start":11331,"length":10,"messageText":"'contentFor' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],68,69,76,75,83,79,71,87,88,81,77,70,72,85,107,66,67,134,105,106,86,82,78,84,64,132,65,74,73,133,80,1259,1262,1257,1260,1264,1258,1261,1236,1234,1233,1281,1235,1282,1283,1267,1269,1270,1288,1289,1276,1253,1254,1284,1285,1274,1272,1271,1273,1275,1277,1302,1252,1255,1245,1256,1306,1251,1249,1303,1286,1287,1301,1265,1266,1247,1263,1304,1248,1278,1280,1279,1305,1246,1268,1250,1244,1292,1299,1298,1294,1295,1297,1300,1296,1290,1291,1293,1344,1337,140,141,138,139,1338,1343,1341,1342,1340,1350,1345,63,61,60,1349,1348,1347,1356,1351,137,135,136,1355,1353,1354,1168,1170,1173,1176,[1167,[{"file":"./packages/teleport-project-generator/__tests__/mocks.ts","start":2058,"length":33,"code":2322,"category":1,"messageText":{"messageText":"Type '{ generator: () => { addMapping: jest.Mock; addPlugin: jest.Mock; addPostProcessor: jest.Mock; generateComponent: jest.Mock; linkCodeChunks: jest.Mock<...>; resolveElement: jest.Mock<...>; }; path: string[]; plugins: undefined[]; postprocessors: undefined[]; mappings: undefine...' is not assignable to type '{ postprocessors?: PostProcessor[]; mappings?: Mapping[]; path: string[]; fileName?: string; chunkGenerationFunction?: (uidl: ProjectUIDL, options: EntryFileOptions) => Record<...>; options?: { ...; }; }'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'generator' does not exist in type '{ postprocessors?: PostProcessor[]; mappings?: Mapping[]; path: string[]; fileName?: string; chunkGenerationFunction?: (uidl: ProjectUIDL, options: EntryFileOptions) => Record<...>; options?: { ...; }; }'.","category":1,"code":2353}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/generators.d.ts","start":8679,"length":5,"messageText":"The expected type comes from property 'entry' which is declared here on type 'ProjectStrategy'","category":3,"code":6500}]},{"file":"./packages/teleport-project-generator/__tests__/mocks.ts","start":2895,"length":33,"code":2322,"category":1,"messageText":{"messageText":"Type '{ generator: () => { addMapping: jest.Mock; addPlugin: jest.Mock; addPostProcessor: jest.Mock; generateComponent: jest.Mock; linkCodeChunks: jest.Mock<...>; resolveElement: jest.Mock<...>; }; ... 4 more ...; mappings: undefined[]; }' is not assignable to type '{ postprocessors?: PostProcessor[]; mappings?: Mapping[]; path: string[]; fileName?: string; chunkGenerationFunction?: (uidl: ProjectUIDL, options: EntryFileOptions) => Record<...>; options?: { ...; }; }'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'generator' does not exist in type '{ postprocessors?: PostProcessor[]; mappings?: Mapping[]; path: string[]; fileName?: string; chunkGenerationFunction?: (uidl: ProjectUIDL, options: EntryFileOptions) => Record<...>; options?: { ...; }; }'.","category":1,"code":2353}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/generators.d.ts","start":8679,"length":5,"messageText":"The expected type comes from property 'entry' which is declared here on type 'ProjectStrategy'","category":3,"code":6500}]}]],[1177,[{"file":"./packages/teleport-project-generator/__tests__/utils.ts","start":131,"length":19,"messageText":"'UIDLStateDefinition' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],62,1165,1166,1172,1175,1174,1171,1169,[1361,[{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":1896,"length":16,"code":2322,"category":1,"messageText":{"messageText":"Type '{ provider: \"github\"; username: string; repo: string; }' is not assignable to type 'RemoteTemplateDefinition'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'username' does not exist in type 'RemoteTemplateDefinition'.","category":1,"code":2353}]},"relatedInformation":[{"file":"./packages/teleport-project-packer/src/index.ts","start":467,"length":24,"messageText":"The expected type comes from property 'remoteTemplateDefinition' which is declared here on type 'PackerFactoryParams'","category":3,"code":6500}]},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":2142,"length":9,"code":2739,"category":1,"messageText":"Type '{ setAssets: Mock; addMapping: Mock; getAssetsPath: Mock; generateProject: (uidl: Record, template: GeneratedFolder) => Promise<...>; }' is missing the following properties from type 'ProjectGenerator': cleanPlugins, addPlugin, getStrategy, updateStrategy","relatedInformation":[{"file":"./packages/teleport-project-packer/src/index.ts","start":407,"length":9,"messageText":"The expected type comes from property 'generator' which is declared here on type 'PackerFactoryParams'","category":3,"code":6500}]},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":2539,"length":9,"code":2322,"category":1,"messageText":"Type '{ setAssets: jest.Mock; addMapping: jest.Mock; getAssetsPath: jest.Mock; generateProject: (uidl: Record, template: GeneratedFolder) => Promise<...>; }' is not assignable to type 'ProjectGenerator'.","relatedInformation":[{"file":"./packages/teleport-project-packer/src/index.ts","start":407,"length":9,"messageText":"The expected type comes from property 'generator' which is declared here on type 'PackerFactoryParams'","category":3,"code":6500}]},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":2772,"length":7,"messageText":"Property 'project' does not exist on type '{}'.","category":1,"code":2339},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":2843,"length":9,"messageText":"Parameter 'subFolder' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":3371,"length":9,"code":2322,"category":1,"messageText":"Type '{ setAssets: jest.Mock; addMapping: jest.Mock; getAssetsPath: jest.Mock; generateProject: (uidl: Record, template: GeneratedFolder) => Promise<...>; }' is not assignable to type 'ProjectGenerator'.","relatedInformation":[{"file":"./packages/teleport-project-packer/src/index.ts","start":407,"length":9,"messageText":"The expected type comes from property 'generator' which is declared here on type 'PackerFactoryParams'","category":3,"code":6500}]},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":3613,"length":7,"messageText":"Property 'project' does not exist on type '{}'.","category":1,"code":2339},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":3683,"length":9,"messageText":"Parameter 'subFolder' implicitly has an 'any' type.","category":1,"code":7006},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":4082,"length":7,"messageText":"Variable 'project' implicitly has type 'any' in some locations where its type cannot be determined.","category":1,"code":7034},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":4278,"length":7,"messageText":"Variable 'project' implicitly has an 'any' type.","category":1,"code":7005},{"file":"./packages/teleport-project-packer/__tests__/index.ts","start":4391,"length":7,"code":2322,"category":1,"messageText":{"messageText":"Type '(projectUIDL: ProjectUIDL) => Promise<{ success: boolean; payload: { name: string; globals: UIDLGlobalProjectValues; root: UIDLRootComponent; components?: Record<...>; ... 10 more ...; analytics?: UIDLAnalytics; }; }>' is not assignable to type '(options?: ProjectUIDL) => Promise>'.","category":1,"code":2322,"next":[{"messageText":"Type 'Promise<{ success: boolean; payload: { name: string; globals: UIDLGlobalProjectValues; root: UIDLRootComponent; components?: Record; ... 10 more ...; analytics?: UIDLAnalytics; }; }>' is not assignable to type 'Promise>'.","category":1,"code":2322,"next":[{"messageText":"Type '{ success: boolean; payload: { name: string; globals: UIDLGlobalProjectValues; root: UIDLRootComponent; components?: Record; ... 10 more ...; analytics?: UIDLAnalytics; }; }' is not assignable to type 'PublisherResponse'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'payload' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '{ name: string; globals: UIDLGlobalProjectValues; root: UIDLRootComponent; components?: Record; ... 10 more ...; analytics?: UIDLAnalytics; }' is not assignable to type 'string'.","category":1,"code":2322}]}]}]}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/generators.d.ts","start":11918,"length":7,"messageText":"The expected type comes from property 'publish' which is declared here on type 'Publisher'","category":3,"code":6500}]}]],1357,59,1359,1360,1358,265,1363,1362,[1365,[{"file":"./packages/teleport-project-plugin-custom-files/__tests__/index.ts","start":1216,"length":155,"code":2345,"category":1,"messageText":{"messageText":"Argument of type 'ComponentUIDL' is not assignable to parameter of type 'UIDLRootComponent'.","category":1,"code":2345,"next":[{"messageText":"Type 'ComponentUIDL' is not assignable to type '{ stateDefinitions: { [x: string]: UIDLStateDefinition; route: UIDLRouteDefinitions; }; }'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'stateDefinitions' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Property 'route' is missing in type 'Record' but required in type '{ [x: string]: UIDLStateDefinition; route: UIDLRouteDefinitions; }'.","category":1,"code":2741}]}]}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/uidl.d.ts","start":123,"length":5,"messageText":"'route' is declared here.","category":3,"code":2728}]}]],1364,259,1366,1368,1369,1367,1493,1494,1492,1414,1415,1416,1370,1491,1419,1418,266,1420,1423,1421,1422,1432,1429,1424,1426,1431,1425,1430,1427,1428,1437,1436,1438,245,1433,1435,1434,[1442,[{"file":"./packages/teleport-publisher-disk/__tests__/index.ts","start":119,"length":9,"messageText":"'chmodSync' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-publisher-disk/__tests__/index.ts","start":132,"length":5,"messageText":"'mkdir' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true},{"file":"./packages/teleport-publisher-disk/__tests__/index.ts","start":141,"length":9,"messageText":"'constants' is declared but its value is never read.","category":1,"code":6133,"reportsUnnecessary":true}]],1441,261,1440,[1443,[{"file":"./packages/teleport-publisher-disk/src/path-browserisify.d.ts","start":78,"length":4,"messageText":"Duplicate identifier 'path'.","category":1,"code":2300,"relatedInformation":[{"file":"./packages/teleport-project-generator-html/src/path-browserisify.d.ts","start":78,"length":4,"messageText":"'path' was also declared here.","category":3,"code":6203}]}]],1439,1448,1449,1447,244,243,1446,1444,1445,1455,1454,239,1450,1451,1453,1452,1466,1465,238,1462,1464,1461,1463,1471,1470,237,1469,1468,[1474,[{"file":"./packages/teleport-shared/__tests__/utils/js-identifiers.ts","start":4020,"length":23,"messageText":"Type 'ReadonlySet' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.","category":1,"code":2802}]],1475,1481,[1482,[{"file":"./packages/teleport-shared/__tests__/utils/uidl-utils.ts","start":8661,"length":4,"code":2345,"category":1,"messageText":"Argument of type 'ComponentUIDL' is not assignable to parameter of type 'UIDLRootComponent'."}]],52,58,55,56,57,53,54,1476,1479,1477,1472,1478,1473,1480,1483,1484,[1486,[{"file":"./packages/teleport-test/src/packer.ts","start":721,"length":16,"messageText":"Cannot find module '../config.json' or its corresponding type declarations.","category":1,"code":2307},{"file":"./packages/teleport-test/src/packer.ts","start":1347,"length":8,"code":2322,"category":1,"messageText":{"messageText":"Type '{ username: string; repo: string; provider: \"github\"; }' is not assignable to type 'RemoteTemplateDefinition'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'username' does not exist in type 'RemoteTemplateDefinition'.","category":1,"code":2353}]}}]],1488,1489,1500,1501,49,48,45,51,46,50,672,671,669,674,670,673,[1503,[{"file":"./packages/teleport-uidl-builders/__tests__/component-builders.ts","start":491,"length":9,"code":2345,"category":1,"messageText":{"messageText":"Argument of type 'UIDLStaticValue' is not assignable to parameter of type 'UIDLElementNode'.","category":1,"code":2345,"next":[{"messageText":"Types of property 'type' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '\"static\"' is not assignable to type '\"element\"'.","category":1,"code":2322}]}]}},{"file":"./packages/teleport-uidl-builders/__tests__/component-builders.ts","start":734,"length":9,"code":2345,"category":1,"messageText":"Argument of type 'UIDLStaticValue' is not assignable to parameter of type 'UIDLElementNode'."},{"file":"./packages/teleport-uidl-builders/__tests__/component-builders.ts","start":1939,"length":10,"code":2345,"category":1,"messageText":{"messageText":"Argument of type '{ type: string; path: string; }' is not assignable to parameter of type 'UIDLDependency'.","category":1,"code":2345,"next":[{"messageText":"Property 'version' is missing in type '{ type: string; path: string; }' but required in type 'UIDLExternalDependency'.","category":1,"code":2741}]},"relatedInformation":[{"file":"./packages/teleport-types/dist/cjs/uidl.d.ts","start":31681,"length":7,"messageText":"'version' is declared here.","category":3,"code":2728}]},{"file":"./packages/teleport-uidl-builders/__tests__/component-builders.ts","start":2911,"length":2,"code":2339,"category":1,"messageText":{"messageText":"Property 'id' does not exist on type 'string | { referenceType: ReferenceType; refPath?: string[]; id: string; fallback?: string | number | boolean; valueMapper?: string; } | { referenceType: \"global\"; id: \"locale\" | ... 4 more ... | \"cart\"; refPath?: string[]; } | { ...; }'.","category":1,"code":2339,"next":[{"messageText":"Property 'id' does not exist on type 'string'.","category":1,"code":2339}]}}]],[1505,[{"file":"./packages/teleport-uidl-builders/__tests__/project-builders.ts","start":403,"length":9,"code":2345,"category":1,"messageText":"Argument of type 'UIDLStaticValue' is not assignable to parameter of type 'UIDLElementNode'."},{"file":"./packages/teleport-uidl-builders/__tests__/project-builders.ts","start":482,"length":9,"code":2345,"category":1,"messageText":"Argument of type 'UIDLStaticValue' is not assignable to parameter of type 'UIDLElementNode'."},{"file":"./packages/teleport-uidl-builders/__tests__/project-builders.ts","start":886,"length":18,"code":2345,"category":1,"messageText":"Argument of type 'ComponentUIDL' is not assignable to parameter of type 'UIDLRootComponent'."}]],290,291,289,1502,1506,1504,1527,[1528,[{"file":"./packages/teleport-uidl-resolver/__tests__/abilities/utils.ts","start":10426,"length":13,"code":2322,"category":1,"messageText":{"messageText":"Type '{ id: string; type: \"style-map\"; content: { mapType: \"project-referenced\"; referenceId: string; }; }' is not assignable to type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'id' does not exist in type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2353}]}},{"file":"./packages/teleport-uidl-resolver/__tests__/abilities/utils.ts","start":10686,"length":12,"code":2322,"category":1,"messageText":{"messageText":"Type '{ id: string; type: \"style-map\"; content: { mapType: \"project-referenced\"; referenceId: string; }; }' is not assignable to type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'id' does not exist in type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2353}]}},{"file":"./packages/teleport-uidl-resolver/__tests__/abilities/utils.ts","start":11685,"length":12,"code":2322,"category":1,"messageText":{"messageText":"Type '{ id: string; type: \"style-map\"; content: { mapType: \"project-referenced\"; referenceId: string; }; }' is not assignable to type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2322,"next":[{"messageText":"Object literal may only specify known properties, and 'id' does not exist in type 'UIDLElementNodeReferenceStyles'.","category":1,"code":2353}]}}]],1529,1530,1523,1524,[1531,[{"file":"./packages/teleport-uidl-resolver/__tests__/referenced-styles/index.ts","start":1316,"length":28,"messageText":"Expected 2 arguments, but got 1.","category":1,"code":2554,"relatedInformation":[{"file":"./packages/teleport-uidl-resolver/src/resolvers/referenced-styles/index.ts","start":710,"length":25,"messageText":"An argument for 'options' was not provided.","category":3,"code":6210}]},{"file":"./packages/teleport-uidl-resolver/__tests__/referenced-styles/index.ts","start":1452,"length":10,"code":2339,"category":1,"messageText":{"messageText":"Property 'conditions' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; } | { mapType: \"project-referenced\"; referenceId: string; condition?: UIDLDynamicCondition; } | { ...; }'.","category":1,"code":2339,"next":[{"messageText":"Property 'conditions' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; }'.","category":1,"code":2339}]}},{"file":"./packages/teleport-uidl-resolver/__tests__/referenced-styles/index.ts","start":1571,"length":10,"code":2339,"category":1,"messageText":{"messageText":"Property 'conditions' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; } | { mapType: \"project-referenced\"; referenceId: string; condition?: UIDLDynamicCondition; } | { ...; }'.","category":1,"code":2339,"next":[{"messageText":"Property 'conditions' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; }'.","category":1,"code":2339}]}},{"file":"./packages/teleport-uidl-resolver/__tests__/referenced-styles/index.ts","start":2369,"length":28,"messageText":"Expected 2 arguments, but got 1.","category":1,"code":2554,"relatedInformation":[{"file":"./packages/teleport-uidl-resolver/src/resolvers/referenced-styles/index.ts","start":710,"length":25,"messageText":"An argument for 'options' was not provided.","category":3,"code":6210}]}]],1525,1532,1533,1534,1535,1526,255,258,254,256,257,1521,1522,1520,1510,1509,1514,1513,1512,1511,1518,1517,1516,1515,1519,1508,1538,1543,1542,[1545,[{"file":"./packages/teleport-uidl-validator/__tests__/parser/component-parsing.ts","start":2839,"length":6,"code":2339,"category":1,"messageText":{"messageText":"Property 'styles' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; } | { mapType: \"project-referenced\"; referenceId: string; condition?: UIDLDynamicCondition; } | { ...; }'.","category":1,"code":2339,"next":[{"messageText":"Property 'styles' does not exist on type '{ mapType: \"component-referenced\"; content: UIDLStaticValue | UIDLCompDynamicReference; }'.","category":1,"code":2339}]}},{"file":"./packages/teleport-uidl-validator/__tests__/parser/component-parsing.ts","start":3885,"length":2,"code":2339,"category":1,"messageText":{"messageText":"Property 'id' does not exist on type 'string | { referenceType: ReferenceType; refPath?: string[]; id: string; fallback?: string | number | boolean; valueMapper?: string; } | { referenceType: \"global\"; id: \"locale\" | ... 4 more ... | \"cart\"; refPath?: string[]; } | { ...; }'.","category":1,"code":2339,"next":[{"messageText":"Property 'id' does not exist on type 'string'.","category":1,"code":2339}]}}]],1546,1539,1540,1541,1553,1555,1554,1560,1561,1557,1559,1558,1556,279,280,277,281,272,278,1547,1536,1549,1548,1537,1552,1544,1551,1550],"affectedFilesPendingEmit":[[1227,1],[314,1],[304,1],[303,1],[1228,1],[270,1],[268,1],[43,1],[267,1],[269,1],[1230,1],[1498,1],[306,1],[1495,1],[1499,1],[1485,1],[1496,1],[44,1],[1497,1],[605,1],[47,1],[275,1],[274,1],[276,1],[273,1],[572,1],[571,1],[570,1],[485,1],[484,1],[483,1],[482,1],[481,1],[480,1],[479,1],[478,1],[477,1],[457,1],[456,1],[417,1],[475,1],[474,1],[473,1],[466,1],[464,1],[471,1],[470,1],[465,1],[463,1],[461,1],[472,1],[467,1],[469,1],[468,1],[462,1],[458,1],[416,1],[406,1],[405,1],[401,1],[402,1],[400,1],[561,1],[492,1],[491,1],[497,1],[496,1],[488,1],[490,1],[494,1],[493,1],[495,1],[560,1],[499,1],[498,1],[500,1],[486,1],[487,1],[476,1],[489,1],[460,1],[459,1],[449,1],[447,1],[454,1],[453,1],[448,1],[446,1],[444,1],[455,1],[450,1],[452,1],[451,1],[445,1],[418,1],[420,1],[419,1],[438,1],[431,1],[436,1],[428,1],[423,1],[435,1],[442,1],[443,1],[430,1],[439,1],[426,1],[437,1],[421,1],[432,1],[427,1],[425,1],[429,1],[433,1],[424,1],[440,1],[422,1],[441,1],[434,1],[409,1],[407,1],[411,1],[410,1],[408,1],[413,1],[412,1],[414,1],[404,1],[403,1],[399,1],[393,1],[386,1],[391,1],[383,1],[378,1],[390,1],[397,1],[398,1],[385,1],[394,1],[381,1],[392,1],[376,1],[387,1],[382,1],[380,1],[384,1],[388,1],[379,1],[395,1],[377,1],[396,1],[389,1],[562,1],[563,1],[566,1],[564,1],[569,1],[568,1],[567,1],[565,1],[1459,1],[501,1],[502,1],[503,1],[559,1],[504,1],[548,1],[506,1],[505,1],[507,1],[508,1],[510,1],[509,1],[511,1],[512,1],[513,1],[515,1],[516,1],[517,1],[518,1],[520,1],[521,1],[522,1],[523,1],[519,1],[524,1],[525,1],[526,1],[527,1],[528,1],[529,1],[538,1],[530,1],[531,1],[532,1],[533,1],[535,1],[534,1],[536,1],[537,1],[539,1],[540,1],[514,1],[542,1],[541,1],[543,1],[544,1],[545,1],[547,1],[546,1],[549,1],[551,1],[552,1],[550,1],[553,1],[554,1],[555,1],[556,1],[557,1],[558,1],[608,1],[284,1],[606,1],[607,1],[1372,1],[1569,1],[1562,1],[1564,1],[1566,1],[1565,1],[1563,1],[1568,1],[1567,1],[1570,1],[1457,1],[1458,1],[150,1],[151,1],[186,1],[187,1],[188,1],[189,1],[190,1],[191,1],[192,1],[193,1],[194,1],[195,1],[196,1],[198,1],[197,1],[199,1],[200,1],[201,1],[185,1],[235,1],[202,1],[203,1],[204,1],[236,1],[205,1],[206,1],[207,1],[208,1],[209,1],[210,1],[211,1],[212,1],[213,1],[214,1],[215,1],[216,1],[217,1],[219,1],[218,1],[220,1],[221,1],[222,1],[223,1],[224,1],[225,1],[226,1],[227,1],[228,1],[229,1],[230,1],[231,1],[232,1],[233,1],[234,1],[1149,1],[1154,1],[1151,1],[1157,1],[1160,1],[1150,1],[1371,1],[1460,1],[375,1],[152,1],[1487,1],[1212,1],[1215,1],[1218,1],[1219,1],[1217,1],[1216,1],[1220,1],[1223,1],[1222,1],[1213,1],[1221,1],[1214,1],[374,1],[1211,1],[1209,1],[1207,1],[1210,1],[1208,1],[1206,1],[1205,1],[1203,1],[1204,1],[1202,1],[617,1],[1507,1],[1192,1],[1187,1],[1189,1],[1188,1],[1199,1],[1198,1],[1200,1],[1197,1],[1195,1],[1196,1],[1193,1],[1194,1],[1456,1],[1413,1],[1412,1],[1411,1],[1410,1],[1373,1],[1386,1],[1385,1],[1384,1],[1377,1],[1375,1],[1376,1],[1374,1],[1201,1],[1191,1],[1190,1],[619,1],[620,1],[621,1],[618,1],[1467,1],[1417,1],[573,1],[574,1],[415,1],[1394,1],[1408,1],[1392,1],[1393,1],[1409,1],[1404,1],[1405,1],[1403,1],[1407,1],[1401,1],[1395,1],[1406,1],[1402,1],[1400,1],[1398,1],[1399,1],[1396,1],[1397,1],[1383,1],[1380,1],[1381,1],[1382,1],[1378,1],[1379,1],[2,1],[3,1],[4,1],[5,1],[6,1],[7,1],[168,1],[175,1],[167,1],[182,1],[159,1],[158,1],[181,1],[176,1],[179,1],[161,1],[160,1],[156,1],[155,1],[178,1],[157,1],[162,1],[163,1],[166,1],[153,1],[184,1],[183,1],[170,1],[171,1],[173,1],[169,1],[172,1],[177,1],[164,1],[165,1],[174,1],[154,1],[180,1],[1388,1],[1387,1],[1391,1],[1390,1],[1389,1],[271,1],[263,1],[264,1],[1490,1],[262,1],[260,1],[302,1],[305,1],[307,1],[308,1],[310,1],[311,1],[313,1],[312,1],[309,1],[250,1],[251,1],[300,1],[301,1],[319,1],[320,1],[253,1],[252,1],[318,1],[317,1],[334,1],[336,1],[337,1],[339,1],[341,1],[342,1],[343,1],[344,1],[345,1],[349,1],[340,1],[346,1],[350,1],[335,1],[338,1],[347,1],[348,1],[351,1],[352,1],[353,1],[247,1],[246,1],[333,1],[332,1],[359,1],[361,1],[362,1],[364,1],[365,1],[366,1],[367,1],[370,1],[369,1],[371,1],[360,1],[363,1],[368,1],[372,1],[373,1],[249,1],[248,1],[358,1],[357,1],[292,1],[293,1],[283,1],[282,1],[286,1],[285,1],[287,1],[288,1],[580,1],[240,1],[242,1],[241,1],[575,1],[577,1],[579,1],[576,1],[578,1],[600,1],[294,1],[598,1],[599,1],[597,1],[604,1],[1178,1],[602,1],[603,1],[601,1],[614,1],[616,1],[625,1],[630,1],[631,1],[639,1],[640,1],[641,1],[642,1],[643,1],[644,1],[645,1],[646,1],[647,1],[648,1],[649,1],[650,1],[652,1],[581,1],[584,1],[583,1],[596,1],[594,1],[593,1],[595,1],[591,1],[592,1],[586,1],[588,1],[582,1],[590,1],[587,1],[585,1],[589,1],[613,1],[615,1],[624,1],[637,1],[628,1],[629,1],[626,1],[627,1],[634,1],[638,1],[632,1],[633,1],[653,1],[612,1],[623,1],[609,1],[636,1],[622,1],[611,1],[610,1],[635,1],[651,1],[667,1],[668,1],[666,1],[675,1],[326,1],[325,1],[665,1],[663,1],[664,1],[658,1],[659,1],[657,1],[660,1],[661,1],[662,1],[296,1],[295,1],[656,1],[655,1],[654,1],[679,1],[315,1],[676,1],[678,1],[677,1],[683,1],[316,1],[682,1],[681,1],[297,1],[680,1],[686,1],[1240,1],[685,1],[684,1],[688,1],[322,1],[687,1],[690,1],[1239,1],[689,1],[693,1],[330,1],[692,1],[691,1],[721,1],[722,1],[723,1],[724,1],[726,1],[728,1],[729,1],[725,1],[731,1],[735,1],[736,1],[737,1],[738,1],[128,1],[130,1],[126,1],[116,1],[115,1],[121,1],[114,1],[122,1],[125,1],[120,1],[110,1],[112,1],[109,1],[108,1],[124,1],[113,1],[111,1],[119,1],[117,1],[123,1],[118,1],[131,1],[129,1],[127,1],[730,1],[739,1],[717,1],[718,1],[702,1],[701,1],[720,1],[700,1],[708,1],[715,1],[706,1],[696,1],[698,1],[695,1],[694,1],[714,1],[699,1],[697,1],[705,1],[703,1],[713,1],[704,1],[707,1],[727,1],[734,1],[733,1],[740,1],[732,1],[710,1],[711,1],[712,1],[709,1],[719,1],[716,1],[1243,1],[742,1],[741,1],[745,1],[1242,1],[744,1],[743,1],[748,1],[1241,1],[747,1],[746,1],[1051,1],[1076,1],[754,1],[1011,1],[1039,1],[1040,1],[1041,1],[1042,1],[1043,1],[1047,1],[1048,1],[1049,1],[1052,1],[1053,1],[1054,1],[1055,1],[1056,1],[1057,1],[1058,1],[1059,1],[1060,1],[1061,1],[1062,1],[1063,1],[1064,1],[1065,1],[1066,1],[1067,1],[1068,1],[1069,1],[1070,1],[1071,1],[1072,1],[1073,1],[1074,1],[1075,1],[1077,1],[1078,1],[1079,1],[1080,1],[1081,1],[1082,1],[1083,1],[1084,1],[1085,1],[1086,1],[1087,1],[1089,1],[1090,1],[1091,1],[1092,1],[1093,1],[1094,1],[1095,1],[1096,1],[1097,1],[1098,1],[1099,1],[1100,1],[1101,1],[1102,1],[1103,1],[1104,1],[1105,1],[1106,1],[1107,1],[1108,1],[97,1],[96,1],[99,1],[104,1],[101,1],[92,1],[91,1],[100,1],[103,1],[95,1],[94,1],[98,1],[93,1],[102,1],[89,1],[90,1],[1029,1],[1010,1],[1018,1],[1012,1],[1027,1],[1035,1],[1032,1],[1033,1],[1034,1],[1031,1],[755,1],[1008,1],[1050,1],[1023,1],[1022,1],[1016,1],[1024,1],[1019,1],[1021,1],[1020,1],[1044,1],[753,1],[847,1],[750,1],[848,1],[751,1],[849,1],[752,1],[850,1],[854,1],[855,1],[856,1],[853,1],[857,1],[858,1],[859,1],[860,1],[851,1],[852,1],[861,1],[862,1],[863,1],[864,1],[865,1],[866,1],[867,1],[868,1],[869,1],[870,1],[871,1],[872,1],[873,1],[874,1],[875,1],[876,1],[877,1],[878,1],[879,1],[880,1],[881,1],[889,1],[890,1],[891,1],[892,1],[893,1],[894,1],[882,1],[883,1],[895,1],[896,1],[897,1],[898,1],[899,1],[900,1],[901,1],[902,1],[903,1],[904,1],[905,1],[906,1],[907,1],[908,1],[909,1],[910,1],[888,1],[887,1],[886,1],[885,1],[884,1],[911,1],[912,1],[913,1],[914,1],[915,1],[916,1],[917,1],[918,1],[919,1],[920,1],[922,1],[923,1],[924,1],[921,1],[925,1],[926,1],[1007,1],[846,1],[757,1],[758,1],[759,1],[760,1],[761,1],[762,1],[764,1],[765,1],[766,1],[767,1],[768,1],[769,1],[770,1],[771,1],[772,1],[773,1],[774,1],[775,1],[776,1],[777,1],[778,1],[779,1],[780,1],[781,1],[782,1],[783,1],[784,1],[763,1],[785,1],[786,1],[787,1],[788,1],[789,1],[790,1],[791,1],[792,1],[793,1],[794,1],[795,1],[796,1],[797,1],[798,1],[799,1],[800,1],[801,1],[802,1],[803,1],[804,1],[805,1],[806,1],[807,1],[808,1],[809,1],[810,1],[811,1],[812,1],[813,1],[814,1],[815,1],[816,1],[817,1],[818,1],[819,1],[820,1],[821,1],[822,1],[823,1],[824,1],[825,1],[826,1],[827,1],[828,1],[829,1],[830,1],[831,1],[832,1],[833,1],[834,1],[835,1],[836,1],[837,1],[838,1],[839,1],[840,1],[841,1],[842,1],[843,1],[844,1],[845,1],[927,1],[928,1],[929,1],[930,1],[931,1],[932,1],[933,1],[934,1],[935,1],[936,1],[937,1],[938,1],[939,1],[940,1],[941,1],[942,1],[943,1],[944,1],[945,1],[946,1],[947,1],[948,1],[949,1],[950,1],[951,1],[952,1],[953,1],[955,1],[954,1],[956,1],[957,1],[958,1],[959,1],[960,1],[961,1],[962,1],[963,1],[964,1],[965,1],[966,1],[967,1],[968,1],[969,1],[970,1],[971,1],[972,1],[973,1],[974,1],[975,1],[976,1],[977,1],[978,1],[979,1],[980,1],[749,1],[981,1],[982,1],[983,1],[984,1],[985,1],[986,1],[987,1],[988,1],[989,1],[990,1],[991,1],[992,1],[993,1],[994,1],[995,1],[996,1],[997,1],[998,1],[999,1],[1000,1],[1001,1],[1002,1],[1003,1],[1004,1],[1005,1],[1006,1],[1109,1],[1028,1],[1037,1],[1015,1],[1030,1],[1014,1],[1036,1],[1013,1],[1088,1],[1026,1],[1017,1],[1045,1],[756,1],[1025,1],[1009,1],[1046,1],[1038,1],[1112,1],[1346,1],[1111,1],[1110,1],[1115,1],[321,1],[1113,1],[1114,1],[1120,1],[1121,1],[1119,1],[1122,1],[1123,1],[324,1],[323,1],[1118,1],[1117,1],[1116,1],[1129,1],[1130,1],[1128,1],[1131,1],[1132,1],[328,1],[327,1],[1124,1],[1127,1],[1126,1],[1125,1],[1136,1],[1137,1],[1135,1],[1138,1],[1139,1],[329,1],[1134,1],[1133,1],[1141,1],[1352,1],[1140,1],[1146,1],[1145,1],[354,1],[1143,1],[1144,1],[1142,1],[1148,1],[1339,1],[1147,1],[1153,1],[299,1],[1152,1],[1156,1],[355,1],[1155,1],[1159,1],[331,1],[1158,1],[1162,1],[298,1],[1161,1],[1164,1],[356,1],[1163,1],[1184,1],[1183,1],[142,1],[144,1],[143,1],[1180,1],[1179,1],[1182,1],[1181,1],[1231,1],[1229,1],[148,1],[149,1],[146,1],[147,1],[145,1],[1186,1],[1226,1],[1232,1],[1224,1],[1225,1],[1185,1],[1319,1],[1237,1],[1238,1],[1307,1],[1308,1],[1309,1],[1310,1],[1311,1],[1312,1],[1313,1],[1314,1],[1315,1],[1316,1],[1317,1],[1318,1],[1320,1],[1336,1],[1333,1],[1334,1],[1335,1],[1321,1],[1322,1],[1323,1],[1324,1],[1325,1],[1326,1],[1327,1],[1328,1],[1329,1],[1330,1],[1331,1],[1332,1],[68,1],[69,1],[76,1],[75,1],[83,1],[79,1],[71,1],[87,1],[88,1],[81,1],[77,1],[70,1],[72,1],[85,1],[107,1],[66,1],[67,1],[134,1],[105,1],[106,1],[86,1],[82,1],[78,1],[84,1],[64,1],[132,1],[65,1],[74,1],[73,1],[133,1],[80,1],[1259,1],[1262,1],[1257,1],[1260,1],[1264,1],[1258,1],[1261,1],[1236,1],[1234,1],[1233,1],[1281,1],[1235,1],[1282,1],[1283,1],[1267,1],[1269,1],[1270,1],[1288,1],[1289,1],[1276,1],[1253,1],[1254,1],[1284,1],[1285,1],[1274,1],[1272,1],[1271,1],[1273,1],[1275,1],[1277,1],[1302,1],[1252,1],[1255,1],[1245,1],[1256,1],[1306,1],[1251,1],[1249,1],[1303,1],[1286,1],[1287,1],[1301,1],[1265,1],[1266,1],[1247,1],[1263,1],[1304,1],[1248,1],[1278,1],[1280,1],[1279,1],[1305,1],[1246,1],[1268,1],[1250,1],[1244,1],[1292,1],[1299,1],[1298,1],[1294,1],[1295,1],[1297,1],[1300,1],[1296,1],[1290,1],[1291,1],[1293,1],[1344,1],[1337,1],[140,1],[141,1],[138,1],[139,1],[1338,1],[1343,1],[1341,1],[1342,1],[1340,1],[1350,1],[1345,1],[63,1],[61,1],[60,1],[1349,1],[1348,1],[1347,1],[1356,1],[1351,1],[137,1],[135,1],[136,1],[1355,1],[1353,1],[1354,1],[1168,1],[1170,1],[1173,1],[1176,1],[1167,1],[1177,1],[62,1],[1165,1],[1166,1],[1172,1],[1175,1],[1174,1],[1171,1],[1169,1],[1361,1],[1357,1],[59,1],[1359,1],[1360,1],[1358,1],[265,1],[1363,1],[1362,1],[1365,1],[1364,1],[259,1],[1366,1],[1368,1],[1369,1],[1367,1],[1493,1],[1494,1],[1492,1],[1414,1],[1415,1],[1416,1],[1370,1],[1491,1],[1419,1],[1418,1],[266,1],[1420,1],[1423,1],[1421,1],[1422,1],[1432,1],[1429,1],[1424,1],[1426,1],[1431,1],[1425,1],[1430,1],[1427,1],[1428,1],[1437,1],[1436,1],[1438,1],[245,1],[1433,1],[1435,1],[1434,1],[1442,1],[1441,1],[261,1],[1440,1],[1443,1],[1439,1],[1448,1],[1449,1],[1447,1],[244,1],[243,1],[1446,1],[1444,1],[1445,1],[1455,1],[1454,1],[239,1],[1450,1],[1451,1],[1453,1],[1452,1],[1466,1],[1465,1],[238,1],[1462,1],[1464,1],[1461,1],[1463,1],[1471,1],[1470,1],[237,1],[1469,1],[1468,1],[1474,1],[1475,1],[1481,1],[1482,1],[52,1],[58,1],[55,1],[56,1],[57,1],[53,1],[54,1],[1476,1],[1479,1],[1477,1],[1472,1],[1478,1],[1473,1],[1480,1],[1483,1],[1484,1],[1486,1],[1488,1],[1489,1],[1500,1],[1501,1],[49,1],[48,1],[45,1],[51,1],[46,1],[50,1],[672,1],[671,1],[669,1],[674,1],[670,1],[673,1],[1503,1],[1505,1],[290,1],[291,1],[289,1],[1502,1],[1506,1],[1504,1],[1527,1],[1528,1],[1529,1],[1530,1],[1523,1],[1524,1],[1531,1],[1525,1],[1532,1],[1533,1],[1534,1],[1535,1],[1526,1],[255,1],[258,1],[254,1],[256,1],[257,1],[1521,1],[1522,1],[1520,1],[1510,1],[1509,1],[1514,1],[1513,1],[1512,1],[1511,1],[1518,1],[1517,1],[1516,1],[1515,1],[1519,1],[1508,1],[1538,1],[1543,1],[1542,1],[1545,1],[1546,1],[1539,1],[1540,1],[1541,1],[1553,1],[1555,1],[1554,1],[1560,1],[1561,1],[1557,1],[1559,1],[1558,1],[1556,1],[279,1],[280,1],[277,1],[281,1],[272,1],[278,1],[1547,1],[1536,1],[1549,1],[1548,1],[1537,1],[1552,1],[1544,1],[1551,1],[1550,1]]},"version":"4.9.5"} \ No newline at end of file