@planningcenter/tapestry-migration-cli 3.2.2-rc.9 → 3.2.2

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 (29) hide show
  1. package/package.json +3 -3
  2. package/src/components/shared/helpers/unsupportedPropsHelpers.ts +24 -0
  3. package/src/components/shared/transformFactories/stylePropTransformFactory.test.ts +330 -0
  4. package/src/components/shared/transformFactories/stylePropTransformFactory.ts +156 -15
  5. package/src/components/shared/transformFactories/ternaryConditionalToPropFactory.ts +17 -12
  6. package/src/components/time-field/index.ts +48 -0
  7. package/src/components/time-field/transforms/auditSpreadProps.test.ts +76 -0
  8. package/src/components/time-field/transforms/auditSpreadProps.ts +10 -0
  9. package/src/components/time-field/transforms/convertStyleProps.test.ts +43 -0
  10. package/src/components/time-field/transforms/convertStyleProps.ts +10 -0
  11. package/src/components/time-field/transforms/flagMinMax.test.ts +103 -0
  12. package/src/components/time-field/transforms/flagMinMax.ts +31 -0
  13. package/src/components/time-field/transforms/mergeFieldIntoTimeField.test.ts +106 -0
  14. package/src/components/time-field/transforms/mergeFieldIntoTimeField.ts +5 -0
  15. package/src/components/time-field/transforms/moveTimeFieldImport.test.ts +153 -0
  16. package/src/components/time-field/transforms/moveTimeFieldImport.ts +14 -0
  17. package/src/components/time-field/transforms/sizeMapping.test.ts +173 -0
  18. package/src/components/time-field/transforms/sizeMapping.ts +15 -0
  19. package/src/components/time-field/transforms/stateToInvalid.test.ts +87 -0
  20. package/src/components/time-field/transforms/stateToInvalid.ts +56 -0
  21. package/src/components/time-field/transforms/stateToInvalidTernary.test.ts +100 -0
  22. package/src/components/time-field/transforms/stateToInvalidTernary.ts +11 -0
  23. package/src/components/time-field/transforms/tupleToTime.test.ts +182 -0
  24. package/src/components/time-field/transforms/tupleToTime.ts +107 -0
  25. package/src/components/time-field/transforms/twelveHourClockToHourCycle.test.ts +117 -0
  26. package/src/components/time-field/transforms/twelveHourClockToHourCycle.ts +65 -0
  27. package/src/components/time-field/transforms/unsupportedProps.test.ts +160 -0
  28. package/src/components/time-field/transforms/unsupportedProps.ts +37 -0
  29. package/src/index.ts +2 -1
@@ -35,27 +35,32 @@ export function ternaryConditionalToPropFactory({
35
35
  const expr = attr.value.expression
36
36
  if (expr.type !== "ConditionalExpression") return false
37
37
 
38
- if (
39
- expr.consequent.type !== "StringLiteral" ||
40
- expr.consequent.value !== matchValue
41
- ) {
42
- return false
43
- }
38
+ const isNullish = (node: Expression) =>
39
+ node.type === "NullLiteral" ||
40
+ (node.type === "Identifier" && node.name === "undefined")
44
41
 
45
- const isNullAlternate = expr.alternate.type === "NullLiteral"
46
- const isUndefinedAlternate =
47
- expr.alternate.type === "Identifier" &&
48
- expr.alternate.name === "undefined"
42
+ const isMatchString = (node: Expression) =>
43
+ node.type === "StringLiteral" && node.value === matchValue
49
44
 
50
- if (!isNullAlternate && !isUndefinedAlternate) return false
45
+ const matchInConsequent =
46
+ isMatchString(expr.consequent as Expression) &&
47
+ isNullish(expr.alternate as Expression)
48
+ const matchInAlternate =
49
+ isMatchString(expr.alternate as Expression) &&
50
+ isNullish(expr.consequent as Expression)
51
+
52
+ if (!matchInConsequent && !matchInAlternate) return false
51
53
 
52
54
  const testExpr = expr.test as Expression
55
+ const propValue = matchInConsequent
56
+ ? testExpr
57
+ : j.unaryExpression("!", testExpr)
53
58
 
54
59
  removeAttribute(fromProp, { element, j, source })
55
60
  element.openingElement.attributes.push(
56
61
  j.jsxAttribute(
57
62
  j.jsxIdentifier(toProp),
58
- j.jsxExpressionContainer(testExpr)
63
+ j.jsxExpressionContainer(propValue)
59
64
  )
60
65
  )
61
66
 
@@ -0,0 +1,48 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import auditSpreadProps from "./transforms/auditSpreadProps"
4
+ import convertStyleProps from "./transforms/convertStyleProps"
5
+ import flagMinMax from "./transforms/flagMinMax"
6
+ import mergeFieldIntoTimeField from "./transforms/mergeFieldIntoTimeField"
7
+ import moveTimeFieldImport from "./transforms/moveTimeFieldImport"
8
+ import sizeMapping from "./transforms/sizeMapping"
9
+ import stateToInvalid from "./transforms/stateToInvalid"
10
+ import stateToInvalidTernary from "./transforms/stateToInvalidTernary"
11
+ import tupleToTime from "./transforms/tupleToTime"
12
+ import twelveHourClockToHourCycle from "./transforms/twelveHourClockToHourCycle"
13
+ import unsupportedProps from "./transforms/unsupportedProps"
14
+
15
+ const transform: Transform = (fileInfo, api, options) => {
16
+ let currentSource = fileInfo.source
17
+ let hasAnyChanges = false
18
+
19
+ const transforms = [
20
+ mergeFieldIntoTimeField,
21
+ auditSpreadProps,
22
+ sizeMapping,
23
+ stateToInvalidTernary,
24
+ stateToInvalid,
25
+ twelveHourClockToHourCycle,
26
+ tupleToTime,
27
+ flagMinMax,
28
+ convertStyleProps,
29
+ unsupportedProps,
30
+ moveTimeFieldImport,
31
+ ]
32
+
33
+ for (const individualTransform of transforms) {
34
+ const result = individualTransform(
35
+ { ...fileInfo, source: currentSource },
36
+ api,
37
+ options
38
+ )
39
+ if (result && result !== currentSource) {
40
+ currentSource = result as string
41
+ hasAnyChanges = true
42
+ }
43
+ }
44
+
45
+ return hasAnyChanges ? currentSource : null
46
+ }
47
+
48
+ export default transform
@@ -0,0 +1,76 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./auditSpreadProps"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ const AUDIT_COMMENT =
9
+ "TODO: tapestry-migration (spreadAttribute): Spread props can contain unsupported props, please explore usages and migrate as needed."
10
+
11
+ function applyTransform(source: string) {
12
+ const fileInfo = { path: "test.tsx", source }
13
+ return transform(
14
+ fileInfo,
15
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
16
+ {}
17
+ ) as string | null
18
+ }
19
+
20
+ describe("auditSpreadProps transform", () => {
21
+ it("adds comment to TimeField with spread props", () => {
22
+ const input = `
23
+ import { TimeField } from "@planningcenter/tapestry-react"
24
+
25
+ export default function Test() {
26
+ const props = { onChange: handleChange }
27
+ return <TimeField {...props} value={time} onChange={setTime} />
28
+ }
29
+ `.trim()
30
+
31
+ const result = applyTransform(input)
32
+ expect(result).toContain(AUDIT_COMMENT)
33
+ expect(result).toContain("{...props}")
34
+ })
35
+
36
+ it("returns null when TimeField has no spread props", () => {
37
+ const input = `
38
+ import { TimeField } from "@planningcenter/tapestry-react"
39
+
40
+ export default function Test() {
41
+ return <TimeField value={time} onChange={setTime} />
42
+ }
43
+ `.trim()
44
+
45
+ const result = applyTransform(input)
46
+ expect(result).toBe(null)
47
+ })
48
+
49
+ it("returns null when TimeField is from another package", () => {
50
+ const input = `
51
+ import { TimeField } from "other-library"
52
+
53
+ export default function Test() {
54
+ const props = { onChange: handleChange }
55
+ return <TimeField {...props} value={time} />
56
+ }
57
+ `.trim()
58
+
59
+ const result = applyTransform(input)
60
+ expect(result).toBe(null)
61
+ })
62
+
63
+ it("returns null when TimeField is not imported at all", () => {
64
+ const input = `
65
+ import { Button } from "@planningcenter/tapestry-react"
66
+
67
+ export default function Test() {
68
+ const props = { onClick: handleClick }
69
+ return <Button {...props}>Save</Button>
70
+ }
71
+ `.trim()
72
+
73
+ const result = applyTransform(input)
74
+ expect(result).toBe(null)
75
+ })
76
+ })
@@ -0,0 +1,10 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import { commentOnSpreadPropsFactory } from "../../shared/transformFactories/commentOnSpreadPropsFactory"
4
+
5
+ const transform: Transform = commentOnSpreadPropsFactory({
6
+ targetComponent: "TimeField",
7
+ targetPackage: "@planningcenter/tapestry-react",
8
+ })
9
+
10
+ export default transform
@@ -0,0 +1,43 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./convertStyleProps"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string | null {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ return transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ }
16
+
17
+ describe("convertStyleProps transform", () => {
18
+ it("returns null when TimeField has no style props", () => {
19
+ const input = `
20
+ import { TimeField } from "@planningcenter/tapestry-react"
21
+
22
+ function Test() {
23
+ return <TimeField value={time} onChange={setTime} />
24
+ }
25
+ `.trim()
26
+
27
+ const result = applyTransform(input)
28
+ expect(result).toBeNull()
29
+ })
30
+
31
+ it("does not affect TimeField from other packages", () => {
32
+ const input = `
33
+ import { TimeField } from "some-other-lib"
34
+
35
+ function Test() {
36
+ return <TimeField p={2} value={time} onChange={setTime} />
37
+ }
38
+ `.trim()
39
+
40
+ const result = applyTransform(input)
41
+ expect(result).toBeNull()
42
+ })
43
+ })
@@ -0,0 +1,10 @@
1
+ import { stackViewPlugin } from "../../../stubs/stackViewPlugin"
2
+ import { stylePropTransformFactory } from "../../shared/transformFactories/stylePropTransformFactory"
3
+
4
+ export default stylePropTransformFactory({
5
+ plugin: stackViewPlugin,
6
+ stylesToKeep: [],
7
+ stylesToRemove: [],
8
+ targetComponent: "TimeField",
9
+ targetPackage: "@planningcenter/tapestry-react",
10
+ })
@@ -0,0 +1,103 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./flagMinMax"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string | null {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ return transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ }
16
+
17
+ describe("flagMinMax transform", () => {
18
+ it("adds TODO comment to min prop", () => {
19
+ const input = `
20
+ import { TimeField } from "@planningcenter/tapestry-react"
21
+
22
+ function Test() {
23
+ return <TimeField min={9} value={time} onChange={setTime} />
24
+ }
25
+ `.trim()
26
+
27
+ const result = applyTransform(input)
28
+ expect(result).not.toBeNull()
29
+ expect(result).toContain("TODO: tapestry-migration (min)")
30
+ expect(result).toContain("TimeValue")
31
+ expect(result).toContain("min={9}")
32
+ })
33
+
34
+ it("adds TODO comment to max prop", () => {
35
+ const input = `
36
+ import { TimeField } from "@planningcenter/tapestry-react"
37
+
38
+ function Test() {
39
+ return <TimeField max={17} value={time} onChange={setTime} />
40
+ }
41
+ `.trim()
42
+
43
+ const result = applyTransform(input)
44
+ expect(result).not.toBeNull()
45
+ expect(result).toContain("TODO: tapestry-migration (max)")
46
+ expect(result).toContain("TimeValue")
47
+ expect(result).toContain("max={17}")
48
+ })
49
+
50
+ it("flags both min and max when present", () => {
51
+ const input = `
52
+ import { TimeField } from "@planningcenter/tapestry-react"
53
+
54
+ function Test() {
55
+ return <TimeField min={9} max={17} value={time} onChange={setTime} />
56
+ }
57
+ `.trim()
58
+
59
+ const result = applyTransform(input)
60
+ expect(result).not.toBeNull()
61
+ expect(result).toContain("TODO: tapestry-migration (min)")
62
+ expect(result).toContain("TODO: tapestry-migration (max)")
63
+ })
64
+
65
+ it("returns null when neither min nor max is present", () => {
66
+ const input = `
67
+ import { TimeField } from "@planningcenter/tapestry-react"
68
+
69
+ function Test() {
70
+ return <TimeField value={time} onChange={setTime} />
71
+ }
72
+ `.trim()
73
+
74
+ const result = applyTransform(input)
75
+ expect(result).toBeNull()
76
+ })
77
+
78
+ it("does not affect other components", () => {
79
+ const input = `
80
+ import { Input } from "@planningcenter/tapestry-react"
81
+
82
+ function Test() {
83
+ return <Input min={1} max={10} label="Count" />
84
+ }
85
+ `.trim()
86
+
87
+ const result = applyTransform(input)
88
+ expect(result).toBeNull()
89
+ })
90
+
91
+ it("does not affect TimeField from other packages", () => {
92
+ const input = `
93
+ import { TimeField } from "some-other-lib"
94
+
95
+ function Test() {
96
+ return <TimeField min={9} max={17} value={time} onChange={setTime} />
97
+ }
98
+ `.trim()
99
+
100
+ const result = applyTransform(input)
101
+ expect(result).toBeNull()
102
+ })
103
+ })
@@ -0,0 +1,31 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import { addCommentToAttribute } from "../../shared/actions/addCommentToAttribute"
4
+ import { getAttribute } from "../../shared/actions/getAttribute"
5
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
6
+
7
+ const TIME_PROPS = ["min", "max"]
8
+
9
+ const transform: Transform = attributeTransformFactory({
10
+ targetComponent: "TimeField",
11
+ targetPackage: "@planningcenter/tapestry-react",
12
+ transform: (element, { j }) => {
13
+ let hasChanges = false
14
+
15
+ for (const propName of TIME_PROPS) {
16
+ const attr = getAttribute({ element, name: propName })
17
+ if (!attr) continue
18
+
19
+ addCommentToAttribute({
20
+ attribute: attr,
21
+ j,
22
+ text: `'${propName}' previously accepted an hour number (0–23). TimeField now expects a TimeValue (e.g. new Time(hour, minute)) from @internationalized/date. Migrate this value manually.`,
23
+ })
24
+ hasChanges = true
25
+ }
26
+
27
+ return hasChanges
28
+ },
29
+ })
30
+
31
+ export default transform
@@ -0,0 +1,106 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./mergeFieldIntoTimeField"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string | null {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ return transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ }
16
+
17
+ describe("mergeFieldIntoTimeField transform", () => {
18
+ it("merges Field label into TimeField and unwraps Field", () => {
19
+ const input = `
20
+ import { Field, TimeField } from "@planningcenter/tapestry-react"
21
+
22
+ function Test() {
23
+ return (
24
+ <Field label="Start time"><TimeField value={time} onChange={setTime} /></Field>
25
+ )
26
+ }
27
+ `.trim()
28
+
29
+ const result = applyTransform(input)
30
+ expect(result).not.toBeNull()
31
+ expect(result).not.toContain("<Field")
32
+ expect(result).toContain('label="Start time"')
33
+ expect(result).toContain("<TimeField")
34
+ })
35
+
36
+ it("renames feedbackText to description on TimeField", () => {
37
+ const input = `
38
+ import { Field, TimeField } from "@planningcenter/tapestry-react"
39
+
40
+ function Test() {
41
+ return (
42
+ <Field feedbackText="Required"><TimeField value={time} onChange={setTime} /></Field>
43
+ )
44
+ }
45
+ `.trim()
46
+
47
+ const result = applyTransform(input)
48
+ expect(result).not.toBeNull()
49
+ expect(result).not.toContain("<Field")
50
+ expect(result).not.toContain("feedbackText")
51
+ expect(result).toContain('description="Required"')
52
+ })
53
+
54
+ it("flags helpContent as unsupported and removes Field", () => {
55
+ const input = `
56
+ import { Field, TimeField } from "@planningcenter/tapestry-react"
57
+
58
+ function Test() {
59
+ return (
60
+ <Field helpContent="Help"><TimeField value={time} onChange={setTime} /></Field>
61
+ )
62
+ }
63
+ `.trim()
64
+
65
+ const result = applyTransform(input)
66
+ expect(result).not.toBeNull()
67
+ expect(result).not.toContain("<Field")
68
+ expect(result).toContain(
69
+ "TODO: tapestry-migration (mergeFieldIntoTimeField)"
70
+ )
71
+ expect(result).toContain("helpContent")
72
+ expect(result).toContain("not supported by TimeField")
73
+ })
74
+
75
+ it("returns null when Field is not imported from tapestry-react", () => {
76
+ const input = `
77
+ import { Field } from "some-other-library"
78
+ import { TimeField } from "@planningcenter/tapestry-react"
79
+
80
+ function Test() {
81
+ return (
82
+ <Field label="Time"><TimeField value={time} onChange={setTime} /></Field>
83
+ )
84
+ }
85
+ `.trim()
86
+
87
+ const result = applyTransform(input)
88
+ expect(result).toBeNull()
89
+ })
90
+
91
+ it("returns null when TimeField is not imported from tapestry-react", () => {
92
+ const input = `
93
+ import { Field } from "@planningcenter/tapestry-react"
94
+ import { TimeField } from "some-other-library"
95
+
96
+ function Test() {
97
+ return (
98
+ <Field label="Time"><TimeField value={time} onChange={setTime} /></Field>
99
+ )
100
+ }
101
+ `.trim()
102
+
103
+ const result = applyTransform(input)
104
+ expect(result).toBeNull()
105
+ })
106
+ })
@@ -0,0 +1,5 @@
1
+ import { mergeFieldFactory } from "../../shared/transformFactories/mergeFieldFactory"
2
+
3
+ export default mergeFieldFactory({
4
+ targetComponent: "TimeField",
5
+ })
@@ -0,0 +1,153 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./moveTimeFieldImport"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ const result = transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ return result || source
16
+ }
17
+
18
+ describe("moveTimeFieldImport transform", () => {
19
+ describe("import migration", () => {
20
+ it("should change import package and keep TimeField name", () => {
21
+ const input = `
22
+ import { TimeField } from "@planningcenter/tapestry-react"
23
+
24
+ function Test() {
25
+ return <TimeField value={time} onChange={setTime} />
26
+ }
27
+ `.trim()
28
+
29
+ const result = applyTransform(input)
30
+ expect(result).toContain(
31
+ 'import { TimeField } from "@planningcenter/tapestry"'
32
+ )
33
+ expect(result).not.toContain("@planningcenter/tapestry-react")
34
+ expect(result).toContain("<TimeField")
35
+ })
36
+
37
+ it("should only move TimeField, leaving other tapestry-react imports", () => {
38
+ const input = `
39
+ import { Button } from "@planningcenter/tapestry-react"
40
+ import { TimeField } from "@planningcenter/tapestry-react"
41
+
42
+ function Test() {
43
+ return (
44
+ <div>
45
+ <Button>Click</Button>
46
+ <TimeField value={time} onChange={setTime} />
47
+ </div>
48
+ )
49
+ }
50
+ `.trim()
51
+
52
+ const result = applyTransform(input)
53
+ expect(result).toContain(
54
+ 'import { Button } from "@planningcenter/tapestry-react"'
55
+ )
56
+ expect(result).toContain(
57
+ 'import { TimeField } from "@planningcenter/tapestry"'
58
+ )
59
+ expect(result).toContain("<TimeField")
60
+ })
61
+ })
62
+
63
+ describe("import conflict handling", () => {
64
+ it("should use TdsTimeField alias when TimeField is already imported elsewhere", () => {
65
+ const input = `
66
+ import { TimeField } from "some-other-library"
67
+ import { TimeField as LegacyTimeField } from "@planningcenter/tapestry-react"
68
+
69
+ function Test() {
70
+ return (
71
+ <div>
72
+ <TimeField />
73
+ <LegacyTimeField value={time} onChange={setTime} />
74
+ </div>
75
+ )
76
+ }
77
+ `.trim()
78
+
79
+ const result = applyTransform(input)
80
+ expect(result).toContain('import { TimeField } from "some-other-library"')
81
+ expect(result).toContain(
82
+ 'import { TimeField as TdsTimeField } from "@planningcenter/tapestry"'
83
+ )
84
+ expect(result).toContain("<TdsTimeField")
85
+ })
86
+ })
87
+
88
+ describe("edge cases", () => {
89
+ it("should not affect other components", () => {
90
+ const input = `
91
+ import { Button } from "@planningcenter/tapestry-react"
92
+
93
+ function Test() {
94
+ return <Button>Click me</Button>
95
+ }
96
+ `.trim()
97
+
98
+ const result = applyTransform(input)
99
+ expect(result).toContain(
100
+ 'import { Button } from "@planningcenter/tapestry-react"'
101
+ )
102
+ })
103
+
104
+ it("should handle no imports", () => {
105
+ const input = `
106
+ function Test() {
107
+ return <div>No imports</div>
108
+ }
109
+ `.trim()
110
+
111
+ const result = applyTransform(input)
112
+ expect(result).toBe(input)
113
+ })
114
+
115
+ it("should preserve all attributes", () => {
116
+ const input = `
117
+ import { TimeField } from "@planningcenter/tapestry-react"
118
+
119
+ function Test() {
120
+ return (
121
+ <TimeField
122
+ value={time}
123
+ onChange={setTime}
124
+ disabled
125
+ />
126
+ )
127
+ }
128
+ `.trim()
129
+
130
+ const result = applyTransform(input)
131
+ expect(result).toContain(
132
+ 'import { TimeField } from "@planningcenter/tapestry"'
133
+ )
134
+ expect(result).toContain("value={time}")
135
+ expect(result).toContain("onChange={setTime}")
136
+ expect(result).toContain("disabled")
137
+ })
138
+
139
+ it("should handle alias import", () => {
140
+ const input = `
141
+ import { TimeField as TapestryTimeField } from "@planningcenter/tapestry-react"
142
+
143
+ function Test() {
144
+ return <TapestryTimeField value={time} onChange={setTime} />
145
+ }
146
+ `.trim()
147
+
148
+ const result = applyTransform(input)
149
+ expect(result).toContain("@planningcenter/tapestry")
150
+ expect(result).not.toContain("@planningcenter/tapestry-react")
151
+ })
152
+ })
153
+ })
@@ -0,0 +1,14 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import { componentTransformFactory } from "../../shared/transformFactories/componentTransformFactory"
4
+
5
+ const transform: Transform = componentTransformFactory({
6
+ condition: () => true,
7
+ conflictAlias: "TdsTimeField",
8
+ fromComponent: "TimeField",
9
+ fromPackage: "@planningcenter/tapestry-react",
10
+ toComponent: "TimeField",
11
+ toPackage: "@planningcenter/tapestry",
12
+ })
13
+
14
+ export default transform