@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.
Files changed (48) hide show
  1. package/__tests__/builders/style-builders.ts +12 -1
  2. package/__tests__/node-handlers/node-to-jsx/index.ts +3 -2
  3. package/dist/cjs/builders/style-builders.d.ts +3 -3
  4. package/dist/cjs/builders/style-builders.d.ts.map +1 -1
  5. package/dist/cjs/builders/style-builders.js +16 -9
  6. package/dist/cjs/builders/style-builders.js.map +1 -1
  7. package/dist/cjs/node-handlers/node-to-html/utils.d.ts.map +1 -1
  8. package/dist/cjs/node-handlers/node-to-html/utils.js.map +1 -1
  9. package/dist/cjs/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  10. package/dist/cjs/node-handlers/node-to-jsx/index.js +208 -69
  11. package/dist/cjs/node-handlers/node-to-jsx/index.js.map +1 -1
  12. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts +2 -1
  13. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  14. package/dist/cjs/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  15. package/dist/cjs/node-handlers/node-to-jsx/utils.js +18 -7
  16. package/dist/cjs/node-handlers/node-to-jsx/utils.js.map +1 -1
  17. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  18. package/dist/cjs/utils/ast-utils.d.ts +15 -2
  19. package/dist/cjs/utils/ast-utils.d.ts.map +1 -1
  20. package/dist/cjs/utils/ast-utils.js +322 -11
  21. package/dist/cjs/utils/ast-utils.js.map +1 -1
  22. package/dist/esm/builders/style-builders.d.ts +3 -3
  23. package/dist/esm/builders/style-builders.d.ts.map +1 -1
  24. package/dist/esm/builders/style-builders.js +16 -9
  25. package/dist/esm/builders/style-builders.js.map +1 -1
  26. package/dist/esm/node-handlers/node-to-html/utils.d.ts.map +1 -1
  27. package/dist/esm/node-handlers/node-to-html/utils.js.map +1 -1
  28. package/dist/esm/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  29. package/dist/esm/node-handlers/node-to-jsx/index.js +209 -70
  30. package/dist/esm/node-handlers/node-to-jsx/index.js.map +1 -1
  31. package/dist/esm/node-handlers/node-to-jsx/types.d.ts +2 -1
  32. package/dist/esm/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  33. package/dist/esm/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  34. package/dist/esm/node-handlers/node-to-jsx/utils.js +18 -7
  35. package/dist/esm/node-handlers/node-to-jsx/utils.js.map +1 -1
  36. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  37. package/dist/esm/utils/ast-utils.d.ts +15 -2
  38. package/dist/esm/utils/ast-utils.d.ts.map +1 -1
  39. package/dist/esm/utils/ast-utils.js +314 -10
  40. package/dist/esm/utils/ast-utils.js.map +1 -1
  41. package/package.json +7 -5
  42. package/src/builders/style-builders.ts +33 -10
  43. package/src/node-handlers/node-to-html/utils.ts +0 -1
  44. package/src/node-handlers/node-to-jsx/index.ts +443 -85
  45. package/src/node-handlers/node-to-jsx/types.ts +7 -1
  46. package/src/node-handlers/node-to-jsx/utils.ts +21 -7
  47. package/src/types.d.ts +2 -0
  48. 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(`set${StringUtils.capitalize(stateKey)}`), [newStateValue])
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 refType = identifier.content.referenceType as 'prop' | 'state' | 'local'
149
- const prefix = options.dynamicReferencePrefixMap[refType] || ''
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(identifier.content.id)
152
- : t.memberExpression(t.identifier(prefix), t.identifier(identifier.content.id))
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
@@ -1 +1,3 @@
1
1
  declare module 'jss-preset-default'
2
+ declare module 'qs'
3
+ declare module '@babel/preset-react'
@@ -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 { UIDLStateDefinition, UIDLPropDefinition, UIDLRawValue } from '@teleporthq/teleport-types'
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, t = types) => {
141
- const formmattedString = `
142
- ${str}
143
- `
144
- return t.templateLiteral(
145
- [
146
- t.templateElement(
147
- {
148
- raw: formmattedString,
149
- cooked: formmattedString,
150
- },
151
- true
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(`set${StringUtils.capitalize(stateKey)}`),
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
+ }