@uipath/codedapp-convert-sdk 0.1.0-beta.1

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 (41) hide show
  1. package/LICENSE.txt +3 -0
  2. package/README.md +54 -0
  3. package/dist/index.d.ts +62 -0
  4. package/dist/index.js +30770 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/roslyn-bridge/Microsoft.CodeAnalysis.VisualBasic.dll +0 -0
  7. package/dist/roslyn-bridge/Microsoft.CodeAnalysis.dll +0 -0
  8. package/dist/roslyn-bridge/Newtonsoft.Json.dll +0 -0
  9. package/dist/roslyn-bridge/cs/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  10. package/dist/roslyn-bridge/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
  11. package/dist/roslyn-bridge/de/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  12. package/dist/roslyn-bridge/de/Microsoft.CodeAnalysis.resources.dll +0 -0
  13. package/dist/roslyn-bridge/es/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  14. package/dist/roslyn-bridge/es/Microsoft.CodeAnalysis.resources.dll +0 -0
  15. package/dist/roslyn-bridge/fr/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  16. package/dist/roslyn-bridge/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
  17. package/dist/roslyn-bridge/it/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  18. package/dist/roslyn-bridge/it/Microsoft.CodeAnalysis.resources.dll +0 -0
  19. package/dist/roslyn-bridge/ja/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  20. package/dist/roslyn-bridge/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
  21. package/dist/roslyn-bridge/ko/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  22. package/dist/roslyn-bridge/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
  23. package/dist/roslyn-bridge/pl/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  24. package/dist/roslyn-bridge/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
  25. package/dist/roslyn-bridge/pt-BR/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  26. package/dist/roslyn-bridge/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
  27. package/dist/roslyn-bridge/roslyn-bridge +0 -0
  28. package/dist/roslyn-bridge/roslyn-bridge.deps.json +157 -0
  29. package/dist/roslyn-bridge/roslyn-bridge.dll +0 -0
  30. package/dist/roslyn-bridge/roslyn-bridge.pdb +0 -0
  31. package/dist/roslyn-bridge/roslyn-bridge.runtimeconfig.json +14 -0
  32. package/dist/roslyn-bridge/ru/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  33. package/dist/roslyn-bridge/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
  34. package/dist/roslyn-bridge/tr/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  35. package/dist/roslyn-bridge/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
  36. package/dist/roslyn-bridge/zh-Hans/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  37. package/dist/roslyn-bridge/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
  38. package/dist/roslyn-bridge/zh-Hant/Microsoft.CodeAnalysis.VisualBasic.resources.dll +0 -0
  39. package/dist/roslyn-bridge/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
  40. package/dist/skills/fix-converted-app/SKILL.md +333 -0
  41. package/package.json +39 -0
Binary file
@@ -0,0 +1,157 @@
1
+ {
2
+ "runtimeTarget": {
3
+ "name": ".NETCoreApp,Version=v10.0",
4
+ "signature": ""
5
+ },
6
+ "compilationOptions": {},
7
+ "targets": {
8
+ ".NETCoreApp,Version=v10.0": {
9
+ "roslyn-bridge/1.0.0": {
10
+ "dependencies": {
11
+ "Microsoft.CodeAnalysis.VisualBasic": "5.6.0",
12
+ "Newtonsoft.Json": "13.0.3"
13
+ },
14
+ "runtime": {
15
+ "roslyn-bridge.dll": {}
16
+ }
17
+ },
18
+ "Microsoft.CodeAnalysis.Common/5.6.0": {
19
+ "runtime": {
20
+ "lib/net10.0/Microsoft.CodeAnalysis.dll": {
21
+ "assemblyVersion": "5.6.0.0",
22
+ "fileVersion": "5.600.26.26310"
23
+ }
24
+ },
25
+ "resources": {
26
+ "lib/net10.0/cs/Microsoft.CodeAnalysis.resources.dll": {
27
+ "locale": "cs"
28
+ },
29
+ "lib/net10.0/de/Microsoft.CodeAnalysis.resources.dll": {
30
+ "locale": "de"
31
+ },
32
+ "lib/net10.0/es/Microsoft.CodeAnalysis.resources.dll": {
33
+ "locale": "es"
34
+ },
35
+ "lib/net10.0/fr/Microsoft.CodeAnalysis.resources.dll": {
36
+ "locale": "fr"
37
+ },
38
+ "lib/net10.0/it/Microsoft.CodeAnalysis.resources.dll": {
39
+ "locale": "it"
40
+ },
41
+ "lib/net10.0/ja/Microsoft.CodeAnalysis.resources.dll": {
42
+ "locale": "ja"
43
+ },
44
+ "lib/net10.0/ko/Microsoft.CodeAnalysis.resources.dll": {
45
+ "locale": "ko"
46
+ },
47
+ "lib/net10.0/pl/Microsoft.CodeAnalysis.resources.dll": {
48
+ "locale": "pl"
49
+ },
50
+ "lib/net10.0/pt-BR/Microsoft.CodeAnalysis.resources.dll": {
51
+ "locale": "pt-BR"
52
+ },
53
+ "lib/net10.0/ru/Microsoft.CodeAnalysis.resources.dll": {
54
+ "locale": "ru"
55
+ },
56
+ "lib/net10.0/tr/Microsoft.CodeAnalysis.resources.dll": {
57
+ "locale": "tr"
58
+ },
59
+ "lib/net10.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll": {
60
+ "locale": "zh-Hans"
61
+ },
62
+ "lib/net10.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll": {
63
+ "locale": "zh-Hant"
64
+ }
65
+ }
66
+ },
67
+ "Microsoft.CodeAnalysis.VisualBasic/5.6.0": {
68
+ "dependencies": {
69
+ "Microsoft.CodeAnalysis.Common": "5.6.0"
70
+ },
71
+ "runtime": {
72
+ "lib/net10.0/Microsoft.CodeAnalysis.VisualBasic.dll": {
73
+ "assemblyVersion": "5.6.0.0",
74
+ "fileVersion": "5.600.26.26310"
75
+ }
76
+ },
77
+ "resources": {
78
+ "lib/net10.0/cs/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
79
+ "locale": "cs"
80
+ },
81
+ "lib/net10.0/de/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
82
+ "locale": "de"
83
+ },
84
+ "lib/net10.0/es/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
85
+ "locale": "es"
86
+ },
87
+ "lib/net10.0/fr/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
88
+ "locale": "fr"
89
+ },
90
+ "lib/net10.0/it/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
91
+ "locale": "it"
92
+ },
93
+ "lib/net10.0/ja/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
94
+ "locale": "ja"
95
+ },
96
+ "lib/net10.0/ko/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
97
+ "locale": "ko"
98
+ },
99
+ "lib/net10.0/pl/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
100
+ "locale": "pl"
101
+ },
102
+ "lib/net10.0/pt-BR/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
103
+ "locale": "pt-BR"
104
+ },
105
+ "lib/net10.0/ru/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
106
+ "locale": "ru"
107
+ },
108
+ "lib/net10.0/tr/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
109
+ "locale": "tr"
110
+ },
111
+ "lib/net10.0/zh-Hans/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
112
+ "locale": "zh-Hans"
113
+ },
114
+ "lib/net10.0/zh-Hant/Microsoft.CodeAnalysis.VisualBasic.resources.dll": {
115
+ "locale": "zh-Hant"
116
+ }
117
+ }
118
+ },
119
+ "Newtonsoft.Json/13.0.3": {
120
+ "runtime": {
121
+ "lib/net6.0/Newtonsoft.Json.dll": {
122
+ "assemblyVersion": "13.0.0.0",
123
+ "fileVersion": "13.0.3.27908"
124
+ }
125
+ }
126
+ }
127
+ }
128
+ },
129
+ "libraries": {
130
+ "roslyn-bridge/1.0.0": {
131
+ "type": "project",
132
+ "serviceable": false,
133
+ "sha512": ""
134
+ },
135
+ "Microsoft.CodeAnalysis.Common/5.6.0": {
136
+ "type": "package",
137
+ "serviceable": true,
138
+ "sha512": "sha512-eWYNB5e92PSdkQ0xcmy2aLtrvBXNydnVi0Hj/VjaAely6XBqA3By+ClGAJaj4d16pzQmrXPLLK9RDVuS1Ec9xQ==",
139
+ "path": "microsoft.codeanalysis.common/5.6.0",
140
+ "hashPath": "microsoft.codeanalysis.common.5.6.0.nupkg.sha512"
141
+ },
142
+ "Microsoft.CodeAnalysis.VisualBasic/5.6.0": {
143
+ "type": "package",
144
+ "serviceable": true,
145
+ "sha512": "sha512-biaSTpVc2aVkqg1fQsVmKGqxLnckzdJEOV0aUVPqpV9GczuwtxONyVrlQ2AzZNE6741FkO75tyj0VS6qlxJ/PA==",
146
+ "path": "microsoft.codeanalysis.visualbasic/5.6.0",
147
+ "hashPath": "microsoft.codeanalysis.visualbasic.5.6.0.nupkg.sha512"
148
+ },
149
+ "Newtonsoft.Json/13.0.3": {
150
+ "type": "package",
151
+ "serviceable": true,
152
+ "sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
153
+ "path": "newtonsoft.json/13.0.3",
154
+ "hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "runtimeOptions": {
3
+ "tfm": "net10.0",
4
+ "framework": {
5
+ "name": "Microsoft.NETCore.App",
6
+ "version": "10.0.0"
7
+ },
8
+ "configProperties": {
9
+ "System.Globalization.Invariant": false,
10
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
11
+ "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,333 @@
1
+ ---
2
+ name: fix-converted-app
3
+ description: Finish a converted Apps project — the generated React code in an output directory. Fixes what `conversion-report.json` reports, anything the developer found by testing the app by hand, and anything a screenshot of the original next to the converted app shows. Fixes it in the generated code whether the fault is this app's or the converter's, and writes the systemic ones up so they can be fixed at the source. Use after `npm run convert`.
4
+ argument-hint: <output directory, e.g. out/MyApp or .> [what is wrong, in your own words, or a screenshot of the original]
5
+ ---
6
+
7
+ # Fix a converted app
8
+
9
+ The converter wrote a React + TypeScript project into the output directory and a
10
+ `conversion-report.json` beside it. Your job is to make that app behave and look like the Apps
11
+ app it came from: what the report already knows about, what the developer found by using the
12
+ app, and what a screenshot of the two side by side shows.
13
+
14
+ The output directory is the first part of `$ARGUMENTS` (`.` means the current directory).
15
+ Anything else in `$ARGUMENTS` is the developer telling you what is wrong. Pick the path that
16
+ matches what you were given, and more than one can apply:
17
+
18
+ - nothing but a directory → **Path A**, work the report;
19
+ - a description of something that misbehaves → **Path B**;
20
+ - a screenshot of the original app, or "it does not look right" → **Path C**.
21
+
22
+ ## Hard rules
23
+
24
+ 1. **Edit only files inside the output directory.** Never edit the converter itself
25
+ (`packages/`, `tools/`), even when the real defect is there — you are almost certainly not
26
+ in that repository anyway. Fix it in the generated code and write it up (rules 5 and 6).
27
+ 2. **Never modify `conversion-report.json` or `conversion-log.ndjson`.** They are the record
28
+ handed back to the converter team. The report is read-only on disk; leave its permissions.
29
+ 3. **Never edit `node_modules`, `dist`, `uipath.json` or `.env*`.**
30
+ 4. **The original app is the specification.** Translate what it does; do not improve it, and
31
+ do not invent behaviour you have not checked. If you cannot establish what Apps does, say
32
+ so in the log rather than guessing.
33
+ 5. **Fix everything you can in this project, whoever is at fault.** A defect the converter
34
+ would repeat on every app is still fixed HERE, in the generated code, because that is what
35
+ unblocks the developer today. The difference the blame makes is only what you write down.
36
+ 6. **Write `conversion-fixes.md`** in the output directory, with three parts: what you changed
37
+ and why; what you could not fix; and a section headed `## For the converter team` listing
38
+ every defect that is systemic, each with the file and symbol you patched, the VB or the
39
+ Apps behaviour it should match, and a minimal example. That section is what the developer
40
+ sends back to us, and it is also what they will need when a future conversion overwrites
41
+ your patch — so write it even when the fix here was easy.
42
+
43
+ ## Path A — the report
44
+
45
+ 1. Read `<out>/conversion-report.json` and work through `issues` where `blame` is
46
+ `"converter"`. `blame: "source-app"` is the only kind you do NOT fix — not out of
47
+ deference, but because the app itself is broken (an expression naming a control that does
48
+ not exist) and only its author knows what it was meant to say; report those and move on.
49
+ `by-design` needs nothing. `expressionRows` lists deliberate, measured approximations —
50
+ read them for context, act on them only if asked.
51
+ 2. Some reports also carry `runtime`-scoped issues and a `runtime` block: those come from the
52
+ converter team driving both apps through the same steps, and they are the most concrete
53
+ issues in the file because each one states what Apps did and what this app did. Treat them
54
+ like any other converter issue. Neither you nor the developer can re-run that comparison —
55
+ it is internal tooling — so note in the log that the fix is unconfirmed by it.
56
+ 3. Fix, then `npm run build` in the output directory (it typechecks and bundles). A freshly
57
+ converted project has no `node_modules` — the converter does not install anything — so run
58
+ `npm install` there first if the directory is absent. If installing is not possible
59
+ (offline), skip the build and say in the log that the fix is unverified. A generated app is
60
+ expected to compile with zero errors; if it does not, that is a defect worth writing up
61
+ even when it is not what you were asked to fix.
62
+ 4. Write the log and report back.
63
+
64
+ ### Where each issue lives
65
+
66
+ | issue code | what you will find | what to do |
67
+ |---|---|---|
68
+ | `expression-no-rule`, `expression-unbound` (property) | In `src/pages/<Page>.tsx` the prop reads `notConvertedValue("<VB>")` or `notConvertedFlag("<VB>", <default>)`; `where` and `location` name page, control and prop. | Replace the marker with TypeScript computing the VB's value. Read state through the accessors already imported in that page. |
69
+ | `expression-no-rule` (source binding, column, page, tab) | `src/pages/<Page>.bindings.ts` has a `TODO` block returning empty rows or `undefined`. | Implement the binding with the helpers in `src/lib/data.ts` and `src/lib/compat.ts`. |
70
+ | `rule-unimplemented`, `rule-expression-unconverted` | In `<Page>.bindings.ts`, the handler `<control>_<event>` holds a `// TODO` or a `notConvertedInput("<VB>")`. | Implement the statement the rule describes (`method` names the Apps rule kind, e.g. `vb-set-value`). |
71
+ | `rule-bad-target` | Same handler; the assignment target was not understood. | Write the assignment the VB intends. |
72
+ | `event-undeliverable` | The handler exists but the component never calls it. | Wire the prop the message names, in `src/components/ui/`. |
73
+ | `property-unmapped` | An authored property reached no component prop. | Add the prop to the component and pass it from the page — unless Apps' own control ignores that property too, in which case log it and change nothing. |
74
+ | `style-unmapped` | An authored style produced no CSS. | Add the rule to the control's class in `src/pages/<Page>.module.css`. |
75
+ | `control-unsupported` | An inert placeholder. | Implement it only if the message gives enough to go on; otherwise leave it and say why. |
76
+ | `emit-inconsistent` | Described in the message. | Fix as described. |
77
+ | `runtime-*` | The app was driven beside the low-code app: `step` is what was done, `expected` what Apps showed or sent, `actual` what this app did. | Make the code produce `expected`. For `runtime-request-differs` compare the bodies field by field. For `runtime-text-differs` find the binding behind the control. For `runtime-request-missing`/`-extra` look at the control's source hook and its handler. |
78
+
79
+ ### Resolving what an unconverted expression REFERS to
80
+
81
+ Rewriting a refused expression needs more than its VB text: what an identifier in it
82
+ denotes, and what that thing holds. Most of it is already in the output directory.
83
+
84
+ | you need to know | read |
85
+ |---|---|
86
+ | an entity's fields and what each holds | `src/types/entities.ts` — the doc comment on each interface lists every field with its declared type (`Guid`, `Decimal`, `DateTimeOffset`, `file attachment`, `list of number`, or a related entity). The shape is open, so the compiler will not tell you; this table will. |
87
+ | which entity a control's rows came from | the control's `entity` prop in `src/pages/<Page>.tsx`, and `src/lib/entity-ids.ts` |
88
+ | a process's real key, a bucket's real name, the folder any resource was authored in | `src/lib/resource-folders.ts` |
89
+ | what a media name resolves to | `src/lib/app-media.ts` |
90
+ | a control's authored literal defaults | `src/store/defaults.ts`, keyed `<Page>/<Control>` |
91
+ | a control's id in the original app | `src/components/ui/provenance.ts` |
92
+ | an action app's arguments and outcomes | `src/lib/action-schema.ts` |
93
+ | the VB that failed, and where it sat | the issue's `vb`, `where` and `location`; `expressionRows` for expressions that converted with a measured approximation |
94
+
95
+ **The `.uiapp` is NOT in the output directory.** The report's `generatedFrom` names the
96
+ file; ask the developer for it when the tables above are not enough — a rule's nesting, a
97
+ property you cannot find, or an expression whose identifiers resolve to nothing you can
98
+ see. It is JSON, and the parts worth knowing are:
99
+
100
+ - `models[]` — one per page (`type: "form"`) and one container per Data Service
101
+ connection (`type: "entity"`). A page carries `controls`, keyed by control id, each with
102
+ `name`, `component`, `config`, `properties` and `ruleInstances`.
103
+ - `models[].instances[]` on an entity container — the entities themselves, each with typed
104
+ `fields[]`. This is where `src/types/entities.ts` gets its table, so you rarely need it.
105
+ - `models[].expressions` — the VB. Every scope holds
106
+ `expressions: { "<expressionId>": { "expression": "<VB text>" } }`.
107
+ - A bound property is `properties.<name> = { valueType: "vb-expression", value: {
108
+ expressionId } }`. Follow the id into the expression map to read what was authored.
109
+
110
+ **An expression id with no text is a slot the designer never filled in.** Apps writes an
111
+ id for every bindable property whether or not anything was authored there, so the presence
112
+ of an id proves nothing — only text does. That distinction is load-bearing and easy to get
113
+ backwards: an image control with no `url` text renders nothing in Apps, while one whose
114
+ `url` was authored but evaluates to nothing renders its "unable to render" placeholder.
115
+ Where the emitted code omits a prop entirely, the slot was blank; where it passes one that
116
+ happens to be undefined at run time, it was authored.
117
+
118
+
119
+ ## Path B — a bug the developer found by hand
120
+
121
+ This is the common case once the app runs, and the report will not mention it. Work in this
122
+ order; skipping step 2 is how a wrong "fix" gets written.
123
+
124
+ 1. **Get the evidence, from the developer's browser.** You can start the app
125
+ (`npm run dev` in the output directory, `npm install` first if there is no
126
+ `node_modules`) but you cannot see it; they can. Ask for the three things that decide
127
+ most of these: the browser console output while the problem happens, the control's name
128
+ from the inspector — every control carries `data-uiapp-name="<authored name>"`, which is
129
+ exactly the name to search for in `src/pages/` — and a screenshot. A control that threw
130
+ while rendering leaves a marked placeholder instead of disappearing, and names itself in
131
+ the console, so that alone often identifies it. If the app says it is not configured, the
132
+ dev server was started BEFORE the project was written or re-written: restart it, because
133
+ the platform settings are injected into the page at startup.
134
+ 2. **Establish what the original does** before changing anything. In order of authority: the
135
+ low-code app itself, if the developer can open it or screenshot it; the `.uiapp` export
136
+ (the report's `generatedFrom` names the file) — its `models[].controls` hold each control's
137
+ authored properties and expressions under the same names; the report's `expressionRows`.
138
+ A difference is not automatically a converter bug: Apps has its own quirks, and a converted
139
+ app that is *more* correct than Apps is still a difference worth recording rather than
140
+ "fixing".
141
+ 3. **Locate the code.** The map is in the next section.
142
+ 4. **Fix it here either way, and say which kind it is.** Wrong for THIS app only — a value, a
143
+ binding, a missing wire — is a local fix and a line in the log. Wrong for EVERY app — a
144
+ helper in `src/lib/`, a component that never accepts a property, a rule that mistranslates
145
+ — is fixed in this project exactly the same way, and additionally written under
146
+ `## For the converter team` so it can be fixed at the source. Never leave the developer
147
+ with a broken app because the real defect is upstream.
148
+ 5. **Fix the smallest thing that makes it behave like the original.**
149
+ 6. **Verify what you can, and be honest about the rest.** `npm run build` is yours to run and
150
+ proves the code compiles; it proves nothing about behaviour. For that, ask the developer
151
+ to repeat their steps and send the console output or a screenshot. Never report a
152
+ behavioural fix as confirmed on the strength of having written it.
153
+ 7. **Log it**, including what you verified, how, and what is still unconfirmed.
154
+
155
+ ## Path C — two screenshots, side by side
156
+
157
+ The developer gives you a picture of the low-code app and a picture of the converted one, and
158
+ you find the differences by LOOKING at them. There is no harness and no browser automation
159
+ here: those are internal tools the developer does not have. Everything below works from two
160
+ images and, when a measurement is needed, one line they paste into their browser.
161
+
162
+ Use this whenever the complaint is about how a page looks, and whenever you are about to tell
163
+ someone a page "looks right".
164
+
165
+ 1. **Check the two pictures are comparable.** Same page, same data, same window width. If
166
+ they are not, ask for a matching pair rather than reading meaning into the mismatch — a
167
+ narrower window re-wraps a layout and invents differences that are not there. If you were
168
+ given only the low-code picture, ask for the converted one; you cannot take it yourself.
169
+ 2. **Read both in the same order, top to bottom and left to right, and write every
170
+ difference down before explaining any of them.** Explaining as you go makes you stop at
171
+ the first one. Work the list: is every control present, and in the same order; is each
172
+ one's text identical, character for character; are heading and label colour, weight and
173
+ size the same; do the fields have the same frame; is spacing and alignment the same; is
174
+ anything cut off, overlapping or missing a scrollbar; do empty states match ("No data" on
175
+ one side against real rows on the other); are images shown or placeholdered.
176
+ 3. **Turn each difference into a hypothesis before touching code.** Text present on one side
177
+ and absent on the other is usually invisible rather than missing — an authored colour that
178
+ matches the background. Text at a different size or weight is usually a named heading or
179
+ label style overriding the authored typography. A different STRING is an expression or a
180
+ format helper, not CSS. A missing row is a data call. A control in the wrong place is
181
+ layout; a control that is not there at all is the component.
182
+ 4. **Measure rather than squint, without any tooling.** The eye cannot separate 28px from
183
+ 32px, and white text on a white page looks exactly like a control that failed to render.
184
+ Ask the developer to open each app, press F12, paste this into the Console and send you
185
+ both answers — it works in the low-code app and the converted one alike:
186
+
187
+ ```js
188
+ (function (text) {
189
+ const all = [...document.querySelectorAll('*')].filter(
190
+ (e) => e.children.length === 0 && (e.textContent || '').trim() === text);
191
+ const el = all[all.length - 1];
192
+ if (!el) return 'no element with exactly that text';
193
+ const c = getComputedStyle(el);
194
+ const p = el.parentElement ? getComputedStyle(el.parentElement) : c;
195
+ return { text, color: c.color, fontWeight: c.fontWeight, fontSize: c.fontSize,
196
+ fontFamily: c.fontFamily, background: c.backgroundColor, behind: p.backgroundColor,
197
+ textAlign: c.textAlign, box: el.getBoundingClientRect().toJSON() };
198
+ })('the exact text you can see')
199
+ ```
200
+
201
+ Two answers side by side settle colour, weight, size, font, the background behind the
202
+ text and the box, in seconds. That is how a heading that looked "missing" turned out to be
203
+ the authored white being applied where Apps ignores it and renders 32px.
204
+ 5. **Fix in the generated code, then ask for one more screenshot of that page.** A visual fix
205
+ is not finished until the second pair agrees. List in the log the differences that remain
206
+ and why, and put anything systemic under `## For the converter team`.
207
+
208
+ Things this comparison catches that nothing else does: invisible text, a heading at the wrong
209
+ size or weight, a control that rendered off-screen, a grid whose columns do not line up, a
210
+ page that cannot scroll, an image placeholder where the original shows a picture, and text
211
+ that is right but formatted differently. Every one of those has happened on a real app.
212
+
213
+ ### Symptom → where to look
214
+
215
+ | What the developer sees | Look at | Usually |
216
+ |---|---|---|
217
+ | A page is blank, or blank until a refresh | the console; `src/routes.tsx` | something threw while rendering OR while unmounting the previous page; each route is wrapped in a boundary, so read which one it names |
218
+ | A control renders but shows nothing / "No data" | the `use…Source` hook in `<Page>.bindings.ts`, then `src/lib/data.ts` | the query's filter or expansion fields, entity-id resolution, the folder id, or a list source handed on where an array was expected |
219
+ | A dropdown or grid editor has no options | the column's `options` in the page, `dropdownValues` in the grid component | a `{ data, totalRecords }` list source where an array was expected |
220
+ | A button does nothing, or only part of what it should | `<control>_<event>` in `<Page>.bindings.ts` | the handler is a TODO, its guard is false (an unset variable), one rule in the chain threw and stopped the rest, or the component never calls it |
221
+ | Typing behaves differently: a mask, decimals, a prefix, separators | the control in `src/components/ui/`, then the authored property in `<Page>.tsx` | an authored input property that reaches no component prop — the page shows what was authored, the component decides whether it is honoured |
222
+ | An image or document does not appear | `src/lib/app-media.ts` and `assetUrl` in `src/lib/runtime.ts`; the Network tab | a media asset resolved by title, an entity attachment that has to be downloaded before it can be shown, or an external URL the host refuses |
223
+ | A value set on one page is not there on another | `src/store/` and the `setAppVar` call in the first page's handler | an app variable written to the wrong name, or a page that re-runs its load rules and overwrites it |
224
+ | The value is right but reads wrong | `src/lib/compat.ts` | a VB-vs-JavaScript formatting difference — see the idioms below |
225
+ | Fonts, colour, weight or size differ | `src/pages/<Page>.module.css` | a control with a NAMED heading or label style takes its typography from Apps' preset, not from the authored properties; only `customized` uses what the designer set |
226
+ | The page does not scroll, or is cut off | `src/styles/tokens.css` | the page host scrolls and the page is as tall as its content |
227
+ | A backend call fails (400/403/404) | the Network tab, then `src/lib/data.ts` and `src/lib/resource-folders.ts` | a process needs its RELEASE key rather than the package id, a bucket its real Orchestrator name rather than the VB identifier, a choice set the tenant-wide flag — or `uipath.json` is missing a scope |
228
+ | Session values are empty (`CurrentUser.*`) | `src/lib/sdk.ts` | the claims the token actually carries |
229
+ | A validation message differs | `useControlValidation` in `src/lib/runtime.ts` | Apps checks by control KIND, only once a value is filled, and a pattern rule outranks a length rule on the same field |
230
+ | A popup, toast or spinner behaves differently | `src/lib/rules.ts`, `src/lib/overlays.tsx` | the rule's own options (modal, position, seconds) |
231
+
232
+ ### Differences that are not bugs
233
+
234
+ Measured on real apps. Reporting one of these as fixed, or "fixing" it, makes the converted
235
+ app wrong:
236
+
237
+ - A control with a named heading or label style shows Apps' preset, not the authored font,
238
+ size, weight or colour. Only `customized` uses what the designer set.
239
+ - Apps' own button ignores an authored `url`, and its image an authored `icon`.
240
+ - A label authored white on a white page is invisible in BOTH apps. That is the app's own
241
+ styling, not a conversion fault.
242
+ - Apps' grid shows an unexpanded relationship cell as `[object Object`; the converted grid
243
+ shows the related record's name. Ours is better; leave it.
244
+ - Apps does not always re-render a label after a load rule changes what it reads, so the
245
+ low-code app can show a stale value where the converted app shows the current one.
246
+ - Apps' Preview can fail to render the lower part of a long page, and can fail to fetch
247
+ documents. An empty area on the Apps side is not proof the converted side is wrong.
248
+ - Apps does not draw what is below the fold until the page is scrolled to it, and it shows
249
+ "Loading your app" for several seconds first. A screenshot of the Apps side is only
250
+ evidence once it has been scrolled to the bottom and back and the page has settled —
251
+ otherwise a whole section reads as something the converter invented.
252
+ - Apps wraps every control in a panel named after it (`forms-host-table-panel` around
253
+ `forms-host-table-control`); the converted app has no such wrapper. Extra elements in the
254
+ Apps DOM are not missing elements in ours.
255
+
256
+ ### Defects already found and fixed at least once
257
+
258
+ Every row happened on a real app. If what the developer describes matches one, check that
259
+ first — and if this project still has it, fix it here and put it under
260
+ `## For the converter team`, because it means the version that converted this app predates
261
+ the fix.
262
+
263
+ | Area | What it looked like | Where it was | What it needed |
264
+ |---|---|---|---|
265
+ | Data | Starting a process fails, 400 "Undefined process" | `src/lib/data.ts` | the SDK's `processKey` is the RELEASE key, not the package id — list the folder's releases, match the package id, start with the match's `key` |
266
+ | Data | A bucket upload or download says the bucket does not exist | `src/lib/data.ts`, `resource-folders.ts` | send the bucket's real Orchestrator name, not the VB identifier the expressions use |
267
+ | Data | A choice set is "not found" once deployed | `src/lib/data.ts` | list with the tenant-wide flag, not scoped to the app's install folder |
268
+ | Data | An entity query is refused for "not supplying expansion fields" | `src/lib/data.ts` | every fetch has to pass expansion fields |
269
+ | Data | A dropdown or grid shows only the first page of rows | `src/lib/data.ts` | follow the cursor to the end; Apps asks for everything |
270
+ | Data | `FetchOne` pulls the whole table | the page's binding | ask for one record, and express the authored start as a page |
271
+ | Data | A failed read leaves a silent "No data" | `src/store/controls.ts` | Apps shows an error toast; say what failed |
272
+ | Session | `CurrentUser.*` is empty | `src/lib/sdk.ts` | read the signed-in user from the access token's claims |
273
+ | Session | Signing in loses the page the user opened | `src/lib/sdk.ts` | stash the path before initialising, restore it after the callback |
274
+ | Session | Data calls fail right after sign-in, then recover | `src/lib/sdk.ts` | hold the first render until the SDK is authenticated |
275
+ | Expressions | A date renders as `Sun Mar 01 2026 00:00:00 GMT…` | `src/lib/compat.ts` | .NET's default, which is the invariant `MM/dd/yyyy` |
276
+ | Expressions | A date or number looks different on another machine | `src/lib/compat.ts` | Apps is invariant-culture; never `toLocaleString` |
277
+ | Expressions | A page is blank and the console says "unsupported .NET format specifier" | `formatDate` / `formatNumber` | implement the standard specifiers (`C`, `D3`, `E`, `G`, `N2`, `P1`, `X`, `s`, `u`, `o`…) |
278
+ | Expressions | `42 + 19.99` shows `61.989999999999995` | `src/lib/compat.ts` | decimal arithmetic through the `dec*` helpers |
279
+ | Expressions | `"…" & True` shows `true` | the concatenation | VB renders a Boolean as `True`/`False` |
280
+ | Expressions | A grid cell shows `True` where Apps shows `true` | the grid's cell text | a grid cell is not a text field |
281
+ | Expressions | `.join` or a spread throws on an unset list variable | the store default | an unset list variable is an empty list |
282
+ | Components | A mask, prefix, decimals or separators are ignored while typing | `src/components/ui/` | the authored property reached no component prop |
283
+ | Components | A grid's dropdown editor has no options | the grid component | unwrap the `{ data }` list source |
284
+ | Components | A bold button renders regular | `src/styles/tokens.css` | a zero-specificity reset, so the authored weight wins |
285
+ | Components | A heading is invisible, or the wrong font or size | the page's CSS module | a named heading or label style overrides the authored typography |
286
+ | Components | Leaving a page with a document viewer blanks the app | the viewer component, `src/routes.tsx` | guard the unmount cleanup, and keep every route in its own boundary |
287
+ | Components | An entity attachment shows no image | the image component | download the attachment and show it through an object URL |
288
+ | Layout | A long page cannot scroll | `src/styles/tokens.css` | the page host scrolls; the page is as tall as its content |
289
+ | Components | An icon draws at 24px whatever size the author set | `src/styles/tokens.css` | Material Icons pins `font-size` on its own class; the glyph must inherit from the control, and everything under a mis-sized icon sits too high |
290
+ | Components | An open dropdown has no blue ring | `src/styles/tokens.css` | Apps draws 2px `#0067DF` on the trigger while its panel is open, and 1px on the grid's search box |
291
+ | Components | A grid's row icons grey out while another row is being edited | the edit grid component | Apps keeps them lit; only a disabled grid dims them |
292
+ | Components | A grid's rows stop short of the right edge | the edit grid component | a column with no authored width takes `flex: 1` and shares the free space, as Apps' grid does |
293
+ | Components | A dropdown, multi-select or uploader is invisible to an end-to-end selector | the component registry | Apps tags both the dropdown and the multi-select `forms-host-combo-box-control`, and its uploader `upload-file-input` on the file input — there is no `forms-host-file-picker-control` in its vocabulary |
294
+ | Project | The whole app is blank and the console shows an unresolved import | the emitted imports | an import naming a file the project does not contain |
295
+ | Project | The app runs but `npm run build` fails | the pages and components | a prop passed to a component that never declared it, or a name used without importing it |
296
+
297
+ ## The generated project
298
+
299
+ | Path | What it is |
300
+ |---|---|
301
+ | `src/pages/<Page>.tsx` | the page's JSX: one element per control, `ctl` is the authored name |
302
+ | `src/pages/<Page>.bindings.ts` | that page's event handlers and source hooks — where rules live |
303
+ | `src/pages/<Page>.module.css` | that page's authored styles, one class per control |
304
+ | `src/components/ui/` | the control components, plus `ui-base.tsx` (shared props, `Guarded`) |
305
+ | `src/lib/runtime.ts` | the accessors expressions call: `getAppVar`/`setAppVar`, control props, validation |
306
+ | `src/lib/rules.ts` | navigation, toasts, spinners, confirmations |
307
+ | `src/lib/data.ts` | every backend call: entities, choice sets, processes, queues, buckets, tasks |
308
+ | `src/lib/compat.ts` | the VB-vs-JavaScript behaviour differences. Read this before writing a formatting fix |
309
+ | `src/lib/resource-folders.ts` | which folder each backend resource lives in, and the keys to reach it |
310
+ | `src/store/` | app variables, control state and data sources (Redux Toolkit) |
311
+ | `src/styles/tokens.css` | every colour and font, plus the app-wide layout rules |
312
+
313
+ ## VB → TypeScript, as the generated code does it
314
+
315
+ - `&` concatenates with `Nothing` as `""`; a Boolean in a concatenation is `True`/`False`
316
+ (`boolText`), a date is the invariant `MM/dd/yyyy` (`formatDate`).
317
+ - Apps' VB engine runs under the invariant culture: dates and numbers render the same for
318
+ every viewer. Never reach for `toLocaleString`.
319
+ - A grid CELL prints a boolean as `true`/`false`; a text field prints `True`/`False`.
320
+ - `.ToString(format)` on a date or number goes through `formatDate` / `formatNumber`, which
321
+ implement the .NET format strings; `String.Format` goes through `formatString`.
322
+ - Decimals are exact: `dec`, `decAdd`, `decMul`, `decRound` from `src/lib/compat.ts`.
323
+ - `If(c, a, b)` is `c ? a : b`; `Nothing` is `null`; an unset list variable reads as `[]`.
324
+ - LINQ maps onto array methods: `Where`→`filter`, `Select`→`map`, `First`→`firstOrThrow`,
325
+ `Any`→`some`, `Sum`→`reduce`. `ThisRow` inside a list template is the `row` parameter.
326
+
327
+ ## What you must not do
328
+
329
+ - Do not change the report, the log, or the converter.
330
+ - Do not rename generated symbols, reorder files, or reformat code you did not need to touch.
331
+ - Do not remove a `notConverted…` marker without replacing it with a real implementation.
332
+ - Do not fix `source-app` or `by-design` issues.
333
+ - Do not claim a fix works because it should. Say what you ran and what you saw.
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@uipath/codedapp-convert-sdk",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Convert a UiPath Apps export (.uiapp) into a React + TypeScript coded app. The SDK behind `uip codedapp convert`.",
5
+ "license": "SEE LICENSE IN LICENSE.txt",
6
+ "author": "UiPath",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/UiPath/apps-dev-tools.git",
25
+ "directory": "lowcode-to-procode-migration/packages/sdk"
26
+ },
27
+ "publishConfig": {
28
+ "registry": "https://registry.npmjs.org/",
29
+ "access": "public"
30
+ },
31
+ "scripts": {
32
+ "build": "tsx build.mts",
33
+ "smoke": "node -e \"import('./dist/index.js').then((m) => console.log(Object.keys(m).sort().join(', ')))\""
34
+ },
35
+ "dependencies": {
36
+ "decimal.js": "10.6.0",
37
+ "typescript": "^5.4.0"
38
+ }
39
+ }