@teleporthq/teleport-plugin-common 0.31.6 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/builders/style-builders.ts +12 -1
- package/__tests__/node-handlers/node-to-jsx/index.ts +3 -2
- package/dist/cjs/builders/style-builders.d.ts +3 -3
- package/dist/cjs/builders/style-builders.d.ts.map +1 -1
- package/dist/cjs/builders/style-builders.js +16 -9
- package/dist/cjs/builders/style-builders.js.map +1 -1
- package/dist/cjs/node-handlers/node-to-html/utils.d.ts.map +1 -1
- package/dist/cjs/node-handlers/node-to-html/utils.js.map +1 -1
- package/dist/cjs/node-handlers/node-to-jsx/index.d.ts.map +1 -1
- package/dist/cjs/node-handlers/node-to-jsx/index.js +208 -69
- package/dist/cjs/node-handlers/node-to-jsx/index.js.map +1 -1
- package/dist/cjs/node-handlers/node-to-jsx/types.d.ts +2 -1
- package/dist/cjs/node-handlers/node-to-jsx/types.d.ts.map +1 -1
- package/dist/cjs/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
- package/dist/cjs/node-handlers/node-to-jsx/utils.js +18 -7
- package/dist/cjs/node-handlers/node-to-jsx/utils.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils/ast-utils.d.ts +15 -2
- package/dist/cjs/utils/ast-utils.d.ts.map +1 -1
- package/dist/cjs/utils/ast-utils.js +322 -11
- package/dist/cjs/utils/ast-utils.js.map +1 -1
- package/dist/esm/builders/style-builders.d.ts +3 -3
- package/dist/esm/builders/style-builders.d.ts.map +1 -1
- package/dist/esm/builders/style-builders.js +16 -9
- package/dist/esm/builders/style-builders.js.map +1 -1
- package/dist/esm/node-handlers/node-to-html/utils.d.ts.map +1 -1
- package/dist/esm/node-handlers/node-to-html/utils.js.map +1 -1
- package/dist/esm/node-handlers/node-to-jsx/index.d.ts.map +1 -1
- package/dist/esm/node-handlers/node-to-jsx/index.js +209 -70
- package/dist/esm/node-handlers/node-to-jsx/index.js.map +1 -1
- package/dist/esm/node-handlers/node-to-jsx/types.d.ts +2 -1
- package/dist/esm/node-handlers/node-to-jsx/types.d.ts.map +1 -1
- package/dist/esm/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
- package/dist/esm/node-handlers/node-to-jsx/utils.js +18 -7
- package/dist/esm/node-handlers/node-to-jsx/utils.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils/ast-utils.d.ts +15 -2
- package/dist/esm/utils/ast-utils.d.ts.map +1 -1
- package/dist/esm/utils/ast-utils.js +314 -10
- package/dist/esm/utils/ast-utils.js.map +1 -1
- package/package.json +7 -5
- package/src/builders/style-builders.ts +33 -10
- package/src/node-handlers/node-to-html/utils.ts +0 -1
- package/src/node-handlers/node-to-jsx/index.ts +443 -85
- package/src/node-handlers/node-to-jsx/types.ts +7 -1
- package/src/node-handlers/node-to-jsx/utils.ts +21 -7
- package/src/types.d.ts +2 -0
- package/src/utils/ast-utils.ts +562 -18
|
@@ -124,7 +124,9 @@ const createStateChangeStatement = (
|
|
|
124
124
|
switch (options.stateHandling) {
|
|
125
125
|
case 'hooks':
|
|
126
126
|
return t.expressionStatement(
|
|
127
|
-
t.callExpression(t.identifier(
|
|
127
|
+
t.callExpression(t.identifier(StringUtils.createStateStoringFunction(stateKey)), [
|
|
128
|
+
newStateValue,
|
|
129
|
+
])
|
|
128
130
|
)
|
|
129
131
|
case 'function':
|
|
130
132
|
return t.expressionStatement(
|
|
@@ -145,15 +147,22 @@ export const createDynamicValueExpression = (
|
|
|
145
147
|
options: JSXGenerationOptions,
|
|
146
148
|
t = types
|
|
147
149
|
) => {
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
+
const identifierContent = identifier.content
|
|
151
|
+
const { referenceType, id } = identifierContent
|
|
152
|
+
|
|
153
|
+
if (referenceType === 'attr' || referenceType === 'children' || referenceType === 'token') {
|
|
154
|
+
throw new Error(`Dynamic reference type "${referenceType}" is not supported yet`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const prefix =
|
|
158
|
+
options.dynamicReferencePrefixMap[referenceType as 'prop' | 'state' | 'local'] || ''
|
|
150
159
|
return prefix === ''
|
|
151
|
-
? t.identifier(
|
|
152
|
-
: t.memberExpression(t.identifier(prefix), t.identifier(
|
|
160
|
+
? t.identifier(id)
|
|
161
|
+
: t.memberExpression(t.identifier(prefix), t.identifier(id))
|
|
153
162
|
}
|
|
154
163
|
|
|
155
|
-
// Prepares an identifier (from props or state) to be used as a conditional rendering identifier
|
|
156
|
-
// Assumes the type from the corresponding props/state definitions
|
|
164
|
+
// Prepares an identifier (from props or state or an expr) to be used as a conditional rendering identifier
|
|
165
|
+
// Assumes the type from the corresponding props/state definitions if not expr. Expressions are expected to have a boolean return here
|
|
157
166
|
export const createConditionIdentifier = (
|
|
158
167
|
dynamicReference: UIDLDynamicReference,
|
|
159
168
|
params: JSXGenerationParams,
|
|
@@ -177,6 +186,11 @@ export const createConditionIdentifier = (
|
|
|
177
186
|
type: params.stateDefinitions[referenceRoot].type,
|
|
178
187
|
prefix: options.dynamicReferencePrefixMap.state,
|
|
179
188
|
}
|
|
189
|
+
case 'expr':
|
|
190
|
+
return {
|
|
191
|
+
key: id,
|
|
192
|
+
type: 'boolean',
|
|
193
|
+
}
|
|
180
194
|
default:
|
|
181
195
|
throw new Error(
|
|
182
196
|
`createConditionIdentifier encountered an invalid reference type: ${JSON.stringify(
|
package/src/types.d.ts
CHANGED
package/src/utils/ast-utils.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import * as types from '@babel/types'
|
|
2
|
+
import { parse } from '@babel/core'
|
|
2
3
|
import ParsedASTNode from './parsed-ast'
|
|
3
4
|
import { StringUtils } from '@teleporthq/teleport-shared'
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
UIDLStateDefinition,
|
|
7
|
+
UIDLPropDefinition,
|
|
8
|
+
UIDLRawValue,
|
|
9
|
+
UIDLStaticValue,
|
|
10
|
+
UIDLResourceItem,
|
|
11
|
+
UIDLENVValue,
|
|
12
|
+
UIDLPropValue,
|
|
13
|
+
UIDLExpressionValue,
|
|
14
|
+
UIDLStateValue,
|
|
15
|
+
} from '@teleporthq/teleport-types'
|
|
16
|
+
import babelPresetReact from '@babel/preset-react'
|
|
17
|
+
import { ASTUtils } from '..'
|
|
18
|
+
|
|
5
19
|
/**
|
|
6
20
|
* Adds a class definition string to an existing string of classes
|
|
7
21
|
*/
|
|
@@ -98,6 +112,50 @@ export const addDynamicAttributeToJSXTag = (
|
|
|
98
112
|
)
|
|
99
113
|
}
|
|
100
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Make code expressions happen in AST
|
|
117
|
+
* Replace variables that are found in AST with
|
|
118
|
+
* the corresponding value from the contexts for now
|
|
119
|
+
* and in the future with other sources.
|
|
120
|
+
*/
|
|
121
|
+
export const addDynamicExpressionAttributeToJSXTag = (
|
|
122
|
+
jsxASTNode: types.JSXElement,
|
|
123
|
+
dynamicRef: UIDLExpressionValue,
|
|
124
|
+
attrKey: string,
|
|
125
|
+
t = types
|
|
126
|
+
) => {
|
|
127
|
+
const dynamicContent = dynamicRef.content
|
|
128
|
+
if (dynamicRef.type !== 'expr') {
|
|
129
|
+
throw new Error(`This method only works with dynamic nodes that have code expressions`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const code = dynamicContent
|
|
133
|
+
const options = {
|
|
134
|
+
sourceType: 'module' as const,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const ast = parse(code, options)
|
|
138
|
+
|
|
139
|
+
if (!('program' in ast)) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`The AST does not have a program node in the expression inside addDynamicExpressionAttributeToJSXTag`
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const theStatementOnlyWihtoutTheProgram = ast.program.body[0]
|
|
146
|
+
|
|
147
|
+
if (theStatementOnlyWihtoutTheProgram.type !== 'ExpressionStatement') {
|
|
148
|
+
throw new Error(`Expr dynamic attribute only support expressions statements at the moment.`)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
jsxASTNode.openingElement.attributes.push(
|
|
152
|
+
t.jsxAttribute(
|
|
153
|
+
t.jsxIdentifier(attrKey),
|
|
154
|
+
t.jsxExpressionContainer(theStatementOnlyWihtoutTheProgram.expression)
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
101
159
|
/*
|
|
102
160
|
Use, when we need to add a mix of dynamic and static values to
|
|
103
161
|
the same attribute at the same time.
|
|
@@ -137,22 +195,23 @@ export const addMultipleDynamicAttributesToJSXTag = (
|
|
|
137
195
|
)
|
|
138
196
|
}
|
|
139
197
|
|
|
140
|
-
export const stringAsTemplateLiteral = (str: string
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
[]
|
|
155
|
-
|
|
198
|
+
export const stringAsTemplateLiteral = (str: string): types.TemplateLiteral => {
|
|
199
|
+
const ast = parse('<style jsx>{`' + str + '`}</style>', {
|
|
200
|
+
presets: [babelPresetReact],
|
|
201
|
+
sourceType: 'module',
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
if (!('program' in ast)) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
`The AST does not have a program node in the expression inside addDynamicExpressionAttributeToJSXTag`
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const theStatementOnlyWihtoutTheProgram = ast.program.body[0] as types.ExpressionStatement
|
|
211
|
+
const container = (theStatementOnlyWihtoutTheProgram.expression as types.JSXElement)
|
|
212
|
+
.children[0] as types.JSXExpressionContainer
|
|
213
|
+
|
|
214
|
+
return container.expression as types.TemplateLiteral
|
|
156
215
|
}
|
|
157
216
|
|
|
158
217
|
export const addAttributeToJSXTag = (
|
|
@@ -472,7 +531,7 @@ export const createStateHookAST = (
|
|
|
472
531
|
t.variableDeclarator(
|
|
473
532
|
t.arrayPattern([
|
|
474
533
|
t.identifier(stateKey),
|
|
475
|
-
t.identifier(
|
|
534
|
+
t.identifier(StringUtils.createStateStoringFunction(stateKey)),
|
|
476
535
|
]),
|
|
477
536
|
t.callExpression(t.identifier('useState'), [defaultValueArgument])
|
|
478
537
|
),
|
|
@@ -496,3 +555,488 @@ export const generateDynamicWindowImport = (
|
|
|
496
555
|
|
|
497
556
|
export const wrapObjectPropertiesWithExpression = (properties: types.ObjectProperty[]) =>
|
|
498
557
|
types.objectExpression(properties)
|
|
558
|
+
|
|
559
|
+
export const generateRemoteResourceASTs = (resource: UIDLResourceItem) => {
|
|
560
|
+
const fetchUrl = computeFetchUrl(resource)
|
|
561
|
+
const authHeaderAST = computeAuthorizationHeaderAST(resource?.headers)
|
|
562
|
+
const headersASTs = resource?.headers ? generateRESTHeadersAST(resource.headers) : []
|
|
563
|
+
|
|
564
|
+
const queryParams = generateURLParamsAST(resource?.params)
|
|
565
|
+
const fetchUrlQuasis = fetchUrl.quasis
|
|
566
|
+
const queryParamsQuasis = queryParams?.quasis || [types.templateElement({ raw: '', cooked: '' })]
|
|
567
|
+
|
|
568
|
+
if (queryParams?.expressions.length > 0) {
|
|
569
|
+
fetchUrlQuasis[fetchUrlQuasis.length - 1].value.raw =
|
|
570
|
+
fetchUrlQuasis[fetchUrlQuasis.length - 1].value.raw + '?'
|
|
571
|
+
|
|
572
|
+
fetchUrlQuasis[fetchUrlQuasis.length - 1].value.cooked =
|
|
573
|
+
fetchUrlQuasis[fetchUrlQuasis.length - 1].value.cooked + '?'
|
|
574
|
+
|
|
575
|
+
queryParamsQuasis.pop()
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const paramsDeclerations: Array<types.ObjectProperty | types.SpreadElement> = Object.keys(
|
|
579
|
+
resource?.params || {}
|
|
580
|
+
).reduce((acc: Array<types.ObjectProperty | types.SpreadElement>, item) => {
|
|
581
|
+
const prop = resource.params[item]
|
|
582
|
+
if (prop.type === 'static') {
|
|
583
|
+
acc.push(types.objectProperty(types.stringLiteral(item), ASTUtils.resolveObjectValue(prop)))
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (prop.type === 'expr') {
|
|
587
|
+
acc.push(
|
|
588
|
+
types.objectProperty(
|
|
589
|
+
types.stringLiteral(item),
|
|
590
|
+
ASTUtils.getExpressionFromUIDLExpressionNode(prop)
|
|
591
|
+
)
|
|
592
|
+
)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (prop.type === 'dynamic') {
|
|
596
|
+
acc.push(
|
|
597
|
+
types.spreadElement(
|
|
598
|
+
types.logicalExpression(
|
|
599
|
+
'&&',
|
|
600
|
+
types.memberExpression(
|
|
601
|
+
types.identifier('params'),
|
|
602
|
+
types.stringLiteral(prop.content.id),
|
|
603
|
+
true,
|
|
604
|
+
false
|
|
605
|
+
),
|
|
606
|
+
types.objectExpression([
|
|
607
|
+
types.objectProperty(
|
|
608
|
+
types.stringLiteral(item),
|
|
609
|
+
types.memberExpression(
|
|
610
|
+
types.identifier('params'),
|
|
611
|
+
types.stringLiteral(prop.content.id),
|
|
612
|
+
true,
|
|
613
|
+
false
|
|
614
|
+
)
|
|
615
|
+
),
|
|
616
|
+
])
|
|
617
|
+
)
|
|
618
|
+
)
|
|
619
|
+
)
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
return acc
|
|
623
|
+
}, [])
|
|
624
|
+
|
|
625
|
+
const paramsAST = types.variableDeclaration('const', [
|
|
626
|
+
types.variableDeclarator(
|
|
627
|
+
types.identifier('urlParams'),
|
|
628
|
+
types.objectExpression(paramsDeclerations)
|
|
629
|
+
),
|
|
630
|
+
])
|
|
631
|
+
|
|
632
|
+
const url = queryParams?.quasis
|
|
633
|
+
? types.templateLiteral(
|
|
634
|
+
[...fetchUrlQuasis, ...queryParamsQuasis],
|
|
635
|
+
[...fetchUrl.expressions.concat(queryParams.expressions)]
|
|
636
|
+
)
|
|
637
|
+
: fetchUrl
|
|
638
|
+
|
|
639
|
+
const method = types.objectProperty(
|
|
640
|
+
types.identifier('method'),
|
|
641
|
+
types.stringLiteral(resource.method)
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
let allHeaders: types.ObjectProperty[] = []
|
|
645
|
+
|
|
646
|
+
if (authHeaderAST) {
|
|
647
|
+
allHeaders.push(authHeaderAST)
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (headersASTs.length) {
|
|
651
|
+
allHeaders = allHeaders.concat(headersASTs)
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const headers = types.objectProperty(
|
|
655
|
+
types.identifier('headers'),
|
|
656
|
+
types.objectExpression(allHeaders)
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
const fetchAST = types.variableDeclaration('const', [
|
|
660
|
+
types.variableDeclarator(
|
|
661
|
+
types.identifier('data'),
|
|
662
|
+
types.awaitExpression(
|
|
663
|
+
types.callExpression(types.identifier('fetch'), [
|
|
664
|
+
url,
|
|
665
|
+
types.objectExpression([method, headers]),
|
|
666
|
+
])
|
|
667
|
+
)
|
|
668
|
+
),
|
|
669
|
+
])
|
|
670
|
+
|
|
671
|
+
const responseType = resource?.response?.type ?? 'json'
|
|
672
|
+
let responseJSONAST
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Responce types can be of json, text and we might be reading just headers
|
|
676
|
+
* So, with the response type of the resource. We are returning either
|
|
677
|
+
* - data.json()
|
|
678
|
+
* - data.text()
|
|
679
|
+
* - data.headers
|
|
680
|
+
* back to the caller, from the fetch response.
|
|
681
|
+
*/
|
|
682
|
+
|
|
683
|
+
switch (responseType) {
|
|
684
|
+
case 'json':
|
|
685
|
+
responseJSONAST = types.variableDeclaration('const', [
|
|
686
|
+
types.variableDeclarator(
|
|
687
|
+
types.identifier('response'),
|
|
688
|
+
types.awaitExpression(
|
|
689
|
+
types.callExpression(
|
|
690
|
+
types.memberExpression(types.identifier('data'), types.identifier('json'), false),
|
|
691
|
+
[]
|
|
692
|
+
)
|
|
693
|
+
)
|
|
694
|
+
),
|
|
695
|
+
])
|
|
696
|
+
break
|
|
697
|
+
|
|
698
|
+
case 'text': {
|
|
699
|
+
responseJSONAST = types.variableDeclaration('const', [
|
|
700
|
+
types.variableDeclarator(
|
|
701
|
+
types.identifier('response'),
|
|
702
|
+
types.awaitExpression(
|
|
703
|
+
types.callExpression(
|
|
704
|
+
types.memberExpression(types.identifier('data'), types.identifier('text'), false),
|
|
705
|
+
[]
|
|
706
|
+
)
|
|
707
|
+
)
|
|
708
|
+
),
|
|
709
|
+
])
|
|
710
|
+
break
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
case 'headers': {
|
|
714
|
+
responseJSONAST = types.variableDeclaration('const', [
|
|
715
|
+
types.variableDeclarator(
|
|
716
|
+
types.identifier('response'),
|
|
717
|
+
types.memberExpression(types.identifier('data'), types.identifier('headers'))
|
|
718
|
+
),
|
|
719
|
+
])
|
|
720
|
+
break
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
case 'none': {
|
|
724
|
+
responseJSONAST = types.variableDeclaration('const', [
|
|
725
|
+
types.variableDeclarator(types.identifier('response'), types.identifier('data')),
|
|
726
|
+
])
|
|
727
|
+
break
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
default: {
|
|
731
|
+
responseJSONAST = types.variableDeclaration('const', [
|
|
732
|
+
types.variableDeclarator(types.identifier('response'), types.identifier('data')),
|
|
733
|
+
])
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
return [paramsAST, fetchAST, responseJSONAST]
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const generateRESTHeadersAST = (headers: UIDLResourceItem['headers']): types.ObjectProperty[] => {
|
|
741
|
+
return Object.keys(headers)
|
|
742
|
+
.filter((header) => header !== 'authToken')
|
|
743
|
+
.map((header) => {
|
|
744
|
+
const headerResolved = resolveResourceValue(headers[header])
|
|
745
|
+
const value =
|
|
746
|
+
headers[header].type === 'static'
|
|
747
|
+
? types.stringLiteral(String(headerResolved))
|
|
748
|
+
: types.identifier(String(headerResolved))
|
|
749
|
+
return types.objectProperty(types.stringLiteral(header), value)
|
|
750
|
+
})
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
export const generateMemberExpressionASTFromBase = (
|
|
754
|
+
base: types.OptionalMemberExpression | types.MemberExpression | types.Identifier,
|
|
755
|
+
path: string[]
|
|
756
|
+
): types.OptionalMemberExpression => {
|
|
757
|
+
if (path.length === 1) {
|
|
758
|
+
return types.optionalMemberExpression(base, types.identifier(path[0]), false, true)
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
const pathClone = [...path]
|
|
762
|
+
pathClone.pop()
|
|
763
|
+
|
|
764
|
+
return types.optionalMemberExpression(
|
|
765
|
+
generateMemberExpressionASTFromBase(base, pathClone),
|
|
766
|
+
types.identifier(path[path.length - 1]),
|
|
767
|
+
false,
|
|
768
|
+
true
|
|
769
|
+
)
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
export const generateMemberExpressionASTFromPath = (
|
|
773
|
+
path: Array<string | number>
|
|
774
|
+
): types.OptionalMemberExpression | types.Identifier => {
|
|
775
|
+
const pathClone = [...path]
|
|
776
|
+
if (path.length === 1) {
|
|
777
|
+
return types.identifier(path[0].toString())
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
pathClone.pop()
|
|
781
|
+
|
|
782
|
+
const currentPath = path[path.length - 1]
|
|
783
|
+
if (typeof currentPath === 'number') {
|
|
784
|
+
return types.optionalMemberExpression(
|
|
785
|
+
generateMemberExpressionASTFromPath(pathClone),
|
|
786
|
+
types.numericLiteral(currentPath),
|
|
787
|
+
false,
|
|
788
|
+
true
|
|
789
|
+
)
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
const containsSpecial = currentPath.indexOf('.') !== -1 || currentPath.indexOf('-') !== -1
|
|
793
|
+
|
|
794
|
+
return types.optionalMemberExpression(
|
|
795
|
+
generateMemberExpressionASTFromPath(pathClone),
|
|
796
|
+
containsSpecial ? types.stringLiteral(currentPath) : types.identifier(currentPath),
|
|
797
|
+
containsSpecial,
|
|
798
|
+
true
|
|
799
|
+
)
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
export const generateURLParamsAST = (
|
|
803
|
+
urlParams: Record<string, UIDLStaticValue | UIDLStateValue | UIDLPropValue | UIDLExpressionValue>
|
|
804
|
+
): types.TemplateLiteral | null => {
|
|
805
|
+
if (!urlParams) {
|
|
806
|
+
return null
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const queryString: Record<string, types.Expression> = {}
|
|
810
|
+
Object.keys(urlParams).forEach((key) => {
|
|
811
|
+
resolveDynamicValuesFromUrlParams(urlParams[key], queryString, key)
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
return types.templateLiteral(
|
|
815
|
+
[
|
|
816
|
+
types.templateElement({ raw: '', cooked: '' }, false),
|
|
817
|
+
types.templateElement({ raw: '', cooked: '' }, true),
|
|
818
|
+
],
|
|
819
|
+
[types.newExpression(types.identifier('URLSearchParams'), [types.identifier('urlParams')])]
|
|
820
|
+
)
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const resolveDynamicValuesFromUrlParams = (
|
|
824
|
+
field: UIDLStaticValue | UIDLPropValue | UIDLStateValue | UIDLExpressionValue,
|
|
825
|
+
query: Record<string, types.Expression>,
|
|
826
|
+
prefix: string = null
|
|
827
|
+
) => {
|
|
828
|
+
if (field.type === 'dynamic' || field.type === 'static') {
|
|
829
|
+
query[prefix] = resolveUrlParamsValue(field)
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const resolveUrlParamsValue = (urlParam: UIDLStaticValue | UIDLPropValue | UIDLStateValue) => {
|
|
834
|
+
if (urlParam.type === 'static') {
|
|
835
|
+
return types.stringLiteral(`${urlParam.content}`)
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (urlParam.content.referenceType !== 'prop' && urlParam.content.referenceType !== 'state') {
|
|
839
|
+
throw new Error('Only prop and state references are supported for url params')
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
const paramPath = [
|
|
843
|
+
...(urlParam.content.referenceType === 'prop' ? ['params'] : ['']),
|
|
844
|
+
urlParam.content.id,
|
|
845
|
+
]
|
|
846
|
+
|
|
847
|
+
const templateLiteralElements = paramPath
|
|
848
|
+
.map((_, index) => {
|
|
849
|
+
const isTail = index === paramPath.length - 1
|
|
850
|
+
return types.templateElement(
|
|
851
|
+
{
|
|
852
|
+
cooked: '',
|
|
853
|
+
raw: '',
|
|
854
|
+
},
|
|
855
|
+
isTail
|
|
856
|
+
)
|
|
857
|
+
})
|
|
858
|
+
.filter((el) => el)
|
|
859
|
+
|
|
860
|
+
return types.templateLiteral(templateLiteralElements, [
|
|
861
|
+
generateMemberExpressionASTFromPath(paramPath),
|
|
862
|
+
])
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const computeAuthorizationHeaderAST = (headers: UIDLResourceItem['headers']) => {
|
|
866
|
+
const authToken = resolveResourceValue(headers.authToken)
|
|
867
|
+
if (!authToken) {
|
|
868
|
+
return null
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const authTokenType = headers.authToken?.type
|
|
872
|
+
|
|
873
|
+
return types.objectProperty(
|
|
874
|
+
types.identifier('Authorization'),
|
|
875
|
+
types.templateLiteral(
|
|
876
|
+
[
|
|
877
|
+
types.templateElement(
|
|
878
|
+
{
|
|
879
|
+
cooked: authTokenType === 'static' ? `Bearer ${authToken}` : 'Bearer ',
|
|
880
|
+
raw: authTokenType === 'static' ? `Bearer ${authToken}` : 'Bearer ',
|
|
881
|
+
},
|
|
882
|
+
false
|
|
883
|
+
),
|
|
884
|
+
...(authTokenType === 'static'
|
|
885
|
+
? []
|
|
886
|
+
: [
|
|
887
|
+
types.templateElement(
|
|
888
|
+
{
|
|
889
|
+
cooked: '',
|
|
890
|
+
raw: '',
|
|
891
|
+
},
|
|
892
|
+
true
|
|
893
|
+
),
|
|
894
|
+
]),
|
|
895
|
+
],
|
|
896
|
+
[...(authTokenType === 'static' ? [] : [types.identifier(String(authToken))])]
|
|
897
|
+
),
|
|
898
|
+
false,
|
|
899
|
+
false
|
|
900
|
+
)
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
const computeFetchUrl = (resource: UIDLResourceItem) => {
|
|
904
|
+
const { path } = resource
|
|
905
|
+
const fetchBaseUrl = resolveResourceValue(path.baseUrl)
|
|
906
|
+
const resourceRoute = resolveResourceValue(path.route)
|
|
907
|
+
|
|
908
|
+
const baseUrlType = path.baseUrl?.type
|
|
909
|
+
const routeType = path.route?.type
|
|
910
|
+
|
|
911
|
+
if (baseUrlType === 'static' && routeType === 'static') {
|
|
912
|
+
const stringsToJoin = [fetchBaseUrl, resourceRoute].filter((item) => item).join('/')
|
|
913
|
+
return types.templateLiteral(
|
|
914
|
+
[types.templateElement({ cooked: `${stringsToJoin}`, raw: `${stringsToJoin}` }, true)],
|
|
915
|
+
[]
|
|
916
|
+
)
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if (!routeType) {
|
|
920
|
+
return baseUrlType === 'static'
|
|
921
|
+
? types.templateLiteral(
|
|
922
|
+
[types.templateElement({ cooked: `${fetchBaseUrl}`, raw: `${fetchBaseUrl}` }, true)],
|
|
923
|
+
[]
|
|
924
|
+
)
|
|
925
|
+
: types.templateLiteral(
|
|
926
|
+
[
|
|
927
|
+
types.templateElement(
|
|
928
|
+
{
|
|
929
|
+
cooked: '',
|
|
930
|
+
raw: '',
|
|
931
|
+
},
|
|
932
|
+
false
|
|
933
|
+
),
|
|
934
|
+
types.templateElement(
|
|
935
|
+
{
|
|
936
|
+
cooked: '',
|
|
937
|
+
raw: '',
|
|
938
|
+
},
|
|
939
|
+
true
|
|
940
|
+
),
|
|
941
|
+
],
|
|
942
|
+
[types.identifier(String(fetchBaseUrl))]
|
|
943
|
+
)
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
return types.templateLiteral(
|
|
947
|
+
[
|
|
948
|
+
types.templateElement(
|
|
949
|
+
{
|
|
950
|
+
cooked: '',
|
|
951
|
+
raw: '',
|
|
952
|
+
},
|
|
953
|
+
false
|
|
954
|
+
),
|
|
955
|
+
types.templateElement(
|
|
956
|
+
{
|
|
957
|
+
cooked: routeType === 'static' ? `/${resourceRoute}` : '/',
|
|
958
|
+
raw: routeType === 'static' ? `/${resourceRoute}` : '/',
|
|
959
|
+
},
|
|
960
|
+
false
|
|
961
|
+
),
|
|
962
|
+
...(routeType === 'static'
|
|
963
|
+
? []
|
|
964
|
+
: [
|
|
965
|
+
types.templateElement(
|
|
966
|
+
{
|
|
967
|
+
cooked: '',
|
|
968
|
+
raw: '',
|
|
969
|
+
},
|
|
970
|
+
false
|
|
971
|
+
),
|
|
972
|
+
]),
|
|
973
|
+
],
|
|
974
|
+
[
|
|
975
|
+
types.identifier(String(fetchBaseUrl)),
|
|
976
|
+
...(routeType === 'static' ? [] : [types.identifier(String(resourceRoute))]),
|
|
977
|
+
]
|
|
978
|
+
)
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const resolveResourceValue = (value: UIDLStaticValue | UIDLENVValue) => {
|
|
982
|
+
if (!value) {
|
|
983
|
+
return ''
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (value.type === 'static') {
|
|
987
|
+
return value.content
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
return `process.env.${value.content}`
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
export const resolveObjectValue = (
|
|
994
|
+
prop: UIDLStaticValue | UIDLExpressionValue
|
|
995
|
+
):
|
|
996
|
+
| types.Identifier
|
|
997
|
+
| types.StringLiteral
|
|
998
|
+
| types.NumericLiteral
|
|
999
|
+
| types.BooleanLiteral
|
|
1000
|
+
| types.ObjectExpression
|
|
1001
|
+
| types.Expression => {
|
|
1002
|
+
if (prop.type === 'static') {
|
|
1003
|
+
const value =
|
|
1004
|
+
typeof prop.content === 'string'
|
|
1005
|
+
? types.stringLiteral(prop.content)
|
|
1006
|
+
: typeof prop.content === 'boolean'
|
|
1007
|
+
? types.booleanLiteral(prop.content)
|
|
1008
|
+
: typeof prop.content === 'number'
|
|
1009
|
+
? types.numericLiteral(prop.content)
|
|
1010
|
+
: typeof prop.content === 'object'
|
|
1011
|
+
? objectToObjectExpression(prop.content as unknown as Record<string, unknown>)
|
|
1012
|
+
: types.identifier(String(prop.content))
|
|
1013
|
+
|
|
1014
|
+
return value
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
if (prop.type === 'expr') {
|
|
1018
|
+
return getExpressionFromUIDLExpressionNode(prop)
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
export const getExpressionFromUIDLExpressionNode = (
|
|
1023
|
+
node: UIDLExpressionValue
|
|
1024
|
+
): types.Expression => {
|
|
1025
|
+
const ast = parse(node.content, {
|
|
1026
|
+
sourceType: 'module' as const,
|
|
1027
|
+
})
|
|
1028
|
+
|
|
1029
|
+
if (!('program' in ast)) {
|
|
1030
|
+
throw new Error(
|
|
1031
|
+
`The AST does not have a program node in the expression inside addDynamicExpressionAttributeToJSXTag`
|
|
1032
|
+
)
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const theStatementOnlyWihtoutTheProgram = ast.program.body[0]
|
|
1036
|
+
|
|
1037
|
+
if (theStatementOnlyWihtoutTheProgram.type !== 'ExpressionStatement') {
|
|
1038
|
+
throw new Error(`Expr dynamic attribute only support expressions statements at the moment.`)
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
return theStatementOnlyWihtoutTheProgram.expression
|
|
1042
|
+
}
|