@pega/sdk 0.0.5 → 0.0.6
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/README.md +10 -3
- package/dist/index.js +764 -165
- package/package.json +1 -1
- package/templates/react-native-sdk-reference/.claude/settings.json +5 -0
- package/templates/react-native-sdk-reference/.prettierignore +17 -0
- package/templates/react-native-sdk-reference/.vscode/extensions.json +1 -0
- package/templates/react-native-sdk-reference/.vscode/settings.json +7 -0
- package/templates/react-native-sdk-reference/AGENTS.md +3 -0
- package/templates/react-native-sdk-reference/CLAUDE.md +1 -0
- package/templates/react-native-sdk-reference/README.md +56 -0
- package/templates/react-native-sdk-reference/app.json +40 -5
- package/templates/react-native-sdk-reference/assets/expo.icon/Assets/expo-symbol 2.svg +3 -0
- package/templates/react-native-sdk-reference/assets/expo.icon/Assets/grid.png +0 -0
- package/templates/react-native-sdk-reference/assets/expo.icon/icon.json +35 -0
- package/templates/react-native-sdk-reference/assets/icons/bell.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/clock.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/cross.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/donut.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/gear.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/globe.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/internet.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/music.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/right-arrow.png +0 -0
- package/templates/react-native-sdk-reference/assets/icons/speed.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/MediaCo.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/adaptive-icon.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/android-icon-background.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/android-icon-foreground.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/android-icon-monochrome.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/expo-badge-white.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/expo-badge.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/expo-logo.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/favicon.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/icon.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/logo-glow.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/partial-react-logo.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/react-logo.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/react-logo@2x.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/react-logo@3x.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/splash-icon.png +0 -0
- package/templates/react-native-sdk-reference/assets/images/tutorial-web.png +0 -0
- package/templates/react-native-sdk-reference/eslint.config.mjs +68 -0
- package/templates/react-native-sdk-reference/package.json +59 -14
- package/templates/react-native-sdk-reference/pega-constellationjs-0.26.3.tgz +0 -0
- package/templates/react-native-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
- package/templates/react-native-sdk-reference/pega-sdk-types-0.1.0.tgz +0 -0
- package/templates/react-native-sdk-reference/sdk-config.json +31 -9
- package/templates/react-native-sdk-reference/src/app/_layout.tsx +38 -0
- package/templates/react-native-sdk-reference/src/app/home/_layout.tsx +39 -0
- package/templates/react-native-sdk-reference/src/app/home/contact.tsx +11 -0
- package/templates/react-native-sdk-reference/src/app/home/index.tsx +36 -0
- package/templates/react-native-sdk-reference/src/app/home/shop.tsx +11 -0
- package/templates/react-native-sdk-reference/src/app/home/your-services.tsx +11 -0
- package/templates/react-native-sdk-reference/src/app/index.tsx +72 -0
- package/templates/react-native-sdk-reference/src/app/workarea.tsx +135 -0
- package/templates/react-native-sdk-reference/src/bridge/Context/StoreContext.ts +4 -0
- package/templates/react-native-sdk-reference/src/bridge/RootComponent.tsx +12 -0
- package/templates/react-native-sdk-reference/src/bridge/react_pconnect.jsx +334 -0
- package/templates/react-native-sdk-reference/src/components/common/DisplayField.tsx +29 -0
- package/templates/react-native-sdk-reference/src/components/common/FormFieldWrapper.tsx +5 -0
- package/templates/react-native-sdk-reference/src/components/common/HelperText.tsx +11 -0
- package/templates/react-native-sdk-reference/src/components/common/LabelText.tsx +22 -0
- package/templates/react-native-sdk-reference/src/components/common/inputTheme.ts +17 -0
- package/templates/react-native-sdk-reference/src/components/design-system/AutoComplete.tsx +126 -0
- package/templates/react-native-sdk-reference/src/components/design-system/FieldGroup.tsx +72 -0
- package/templates/react-native-sdk-reference/src/components/design-system/Radio.tsx +61 -0
- package/templates/react-native-sdk-reference/src/components/field/AutoComplete/AutoComplete.tsx +196 -0
- package/templates/react-native-sdk-reference/src/components/field/AutoComplete/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Checkbox/Checkbox.tsx +89 -0
- package/templates/react-native-sdk-reference/src/components/field/Checkbox/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Currency/Currency.tsx +84 -0
- package/templates/react-native-sdk-reference/src/components/field/Currency/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Date/Date.tsx +94 -0
- package/templates/react-native-sdk-reference/src/components/field/Date/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Dropdown/Dropdown.tsx +211 -0
- package/templates/react-native-sdk-reference/src/components/field/Dropdown/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Email/Email.tsx +81 -0
- package/templates/react-native-sdk-reference/src/components/field/Email/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Group/Group.tsx +47 -0
- package/templates/react-native-sdk-reference/src/components/field/Group/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Integer/Integer.tsx +84 -0
- package/templates/react-native-sdk-reference/src/components/field/Integer/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/Phone/Phone.tsx +85 -0
- package/templates/react-native-sdk-reference/src/components/field/Phone/index.ts +1 -0
- package/templates/react-native-sdk-reference/src/components/field/RadioButtons/RadioButtons.tsx +118 -0
- package/templates/react-native-sdk-reference/src/components/field/RadioButtons/index.ts +1 -0
- package/templates/react-native-sdk-reference/src/components/field/TextArea/TextArea.tsx +86 -0
- package/templates/react-native-sdk-reference/src/components/field/TextArea/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/TextInput/TextInput.tsx +84 -0
- package/templates/react-native-sdk-reference/src/components/field/TextInput/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/field/URL/URL.tsx +86 -0
- package/templates/react-native-sdk-reference/src/components/field/URL/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/helpers/data_page.ts +20 -0
- package/templates/react-native-sdk-reference/src/components/helpers/event-utils.ts +20 -0
- package/templates/react-native-sdk-reference/src/components/helpers/instructions-utils.ts +57 -0
- package/templates/react-native-sdk-reference/src/components/helpers/state-utils.tsx +46 -0
- package/templates/react-native-sdk-reference/src/components/helpers/template-utils.ts +75 -0
- package/templates/react-native-sdk-reference/src/components/helpers/utils.ts +339 -0
- package/templates/react-native-sdk-reference/src/components/infra/ActionButtons/ActionButtons.tsx +63 -0
- package/templates/react-native-sdk-reference/src/components/infra/ActionButtons/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Assignment/Assignment.tsx +348 -0
- package/templates/react-native-sdk-reference/src/components/infra/Assignment/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/AssignmentCard/AssignmentCard.tsx +56 -0
- package/templates/react-native-sdk-reference/src/components/infra/AssignmentCard/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/FlowContainer/FlowContainer.tsx +57 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/FlowContainer/helpers.ts +137 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/FlowContainer/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/RootContainer/RootContainer.tsx +52 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/RootContainer/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/SimpleView/helper.ts +128 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/SimpleView/index.tsx +59 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/ViewContainer/ViewContainer.tsx +31 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/ViewContainer/helper.ts +39 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/ViewContainer/index.ts +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Containers/helper.ts +9 -0
- package/templates/react-native-sdk-reference/src/components/infra/ErrorBoundary/ErrorBoundary.tsx +53 -0
- package/templates/react-native-sdk-reference/src/components/infra/ErrorBoundary/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/MultiStep/MultiStep.tsx +24 -0
- package/templates/react-native-sdk-reference/src/components/infra/MultiStep/index.ts +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Reference/Reference.tsx +68 -0
- package/templates/react-native-sdk-reference/src/components/infra/Reference/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/Reference/utils.ts +16 -0
- package/templates/react-native-sdk-reference/src/components/infra/Region/Region.tsx +10 -0
- package/templates/react-native-sdk-reference/src/components/infra/Region/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/infra/View/View.tsx +49 -0
- package/templates/react-native-sdk-reference/src/components/template/DefaultForm/DefaultForm.tsx +38 -0
- package/templates/react-native-sdk-reference/src/components/template/DefaultForm/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/template/DefaultForm/utils/index.ts +28 -0
- package/templates/react-native-sdk-reference/src/components/template/Details/Details.tsx +82 -0
- package/templates/react-native-sdk-reference/src/components/template/Details/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/components/template/OneColumn/OneColumn.tsx +29 -0
- package/templates/react-native-sdk-reference/src/components/template/OneColumn/index.tsx +1 -0
- package/templates/react-native-sdk-reference/src/context/LoaderContext.tsx +42 -0
- package/templates/react-native-sdk-reference/src/mediaco/AdvBanner.tsx +62 -0
- package/templates/react-native-sdk-reference/src/mediaco/Header.tsx +60 -0
- package/templates/react-native-sdk-reference/src/mediaco/HomeScreen.tsx +78 -0
- package/templates/react-native-sdk-reference/src/mediaco/QuickActions.tsx +68 -0
- package/templates/react-native-sdk-reference/src/mediaco/ResolutionScreen.tsx +48 -0
- package/templates/react-native-sdk-reference/src/mediaco/SafeArea.tsx +11 -0
- package/templates/react-native-sdk-reference/src/mediaco/TabBar.tsx +102 -0
- package/templates/react-native-sdk-reference/src/mediaco/YourServices.tsx +90 -0
- package/templates/react-native-sdk-reference/src/sdk-pega-component-map.ts +64 -0
- package/templates/react-native-sdk-reference/src/types/PConnProps.d.ts +41 -0
- package/templates/react-native-sdk-reference/src/utils/auth.ts +62 -0
- package/templates/react-native-sdk-reference/src/utils/init-pcore.ts +37 -0
- package/templates/react-native-sdk-reference/src/utils/pcore-polyfills.ts +66 -0
- package/templates/react-native-sdk-reference/tsconfig.json +9 -8
- package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +171 -0
- package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +25 -26
- package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions-embedded.md +119 -0
- package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +70 -121
- package/templates/react-sdk-reference/.ai-common/instructions/component-map.md +7 -19
- package/templates/react-sdk-reference/.ai-common/instructions/dse-component.md +10 -40
- package/templates/react-sdk-reference/.ai-common/instructions/embedded-component.md +134 -0
- package/templates/react-sdk-reference/.ai-common/instructions/field-component.md +15 -43
- package/templates/react-sdk-reference/.ai-common/instructions/template-component.md +11 -63
- package/templates/react-sdk-reference/.ai-common/instructions/widget-component.md +12 -57
- package/templates/react-sdk-reference/.ai-common/prompts/add-component.md +45 -71
- package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +98 -0
- package/templates/react-sdk-reference/.ai-common/prompts/embedded-component-manifest.md +155 -0
- package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +67 -237
- package/templates/react-sdk-reference/.ai-common/prompts/generate-dse-components.md +26 -77
- package/templates/react-sdk-reference/.ai-common/prompts/generate-embedded-components.md +315 -0
- package/templates/react-sdk-reference/.ai-common/prompts/generate-field-components.md +31 -80
- package/templates/react-sdk-reference/.ai-common/prompts/generate-template-components.md +43 -99
- package/templates/react-sdk-reference/.ai-common/prompts/generate-widget-components.md +33 -83
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/AlertBanner.md +60 -74
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Banner.md +64 -84
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/CaseSummaryFields.md +76 -109
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/DetailsFields.md +84 -101
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/FieldGroup.md +62 -87
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/FieldGroupList.md +56 -76
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/FieldValueList.md +61 -85
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Operator.md +84 -107
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Pulse.md +36 -44
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/RichTextEditor.md +125 -189
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/WssQuickCreate.md +34 -50
- package/templates/react-sdk-reference/.ai-common/skills/design-system-extension.md +57 -179
- package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/analyze-customer-repo.md +130 -0
- package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/authenticate.md +311 -0
- package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/run-and-verify-integration.md +156 -0
- package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/wire-integration.md +476 -0
- package/templates/react-sdk-reference/.ai-common/skills/field-components.md +120 -242
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/AutoComplete.md +71 -212
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/CancelAlert.md +47 -209
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Checkbox.md +90 -259
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Currency.md +75 -169
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Date.md +65 -160
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/DateTime.md +59 -157
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Decimal.md +55 -134
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Dropdown.md +61 -185
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Email.md +60 -138
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Group.md +40 -99
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Integer.md +44 -111
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Location.md +57 -165
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Multiselect.md +41 -122
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/ObjectReference.md +32 -130
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Percentage.md +48 -112
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Phone.md +43 -153
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/RadioButtons.md +76 -183
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/RichText.md +59 -176
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/ScalarList.md +30 -123
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/SelectableCard.md +47 -178
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/SemanticLink.md +31 -117
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/TextArea.md +51 -106
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/TextContent.md +22 -75
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/TextInput.md +54 -116
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/Time.md +46 -100
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/URL.md +44 -93
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/UserReference.md +40 -167
- package/templates/react-sdk-reference/.ai-common/skills/infra-components.md +165 -0
- package/templates/react-sdk-reference/.ai-common/skills/infra-skills/ActionButtons.md +122 -0
- package/templates/react-sdk-reference/.ai-common/skills/infra-skills/MultiStep.md +178 -0
- package/templates/react-sdk-reference/.ai-common/skills/infra-skills/Stages.md +140 -0
- package/templates/react-sdk-reference/.ai-common/skills/template-components.md +74 -228
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/AdvancedSearch.md +66 -167
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/AppShell.md +57 -170
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/BannerPage.md +41 -76
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/CaseSummary.md +53 -109
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/CaseView.md +86 -289
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/CaseViewActionsMenu.md +60 -185
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/Confirmation.md +66 -115
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DataReference.md +33 -68
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DefaultForm.md +53 -133
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DefaultPage.md +39 -82
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/Details.md +38 -91
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DetailsSubTabs.md +47 -101
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DetailsThreeColumn.md +27 -34
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DetailsTwoColumn.md +25 -40
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/DynamicTabs.md +34 -104
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/FieldGroupTemplate.md +46 -147
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/HierarchicalForm.md +139 -100
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/InlineDashboard.md +43 -82
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/InlineDashboardPage.md +47 -80
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListPage.md +16 -29
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListView.md +43 -228
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/MultiReferenceReadOnly.md +20 -65
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/NarrowWide.md +49 -97
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/OneColumn.md +37 -71
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/PromotedFilters.md +58 -148
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/SelfServiceCaseView.md +82 -107
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/SimpleTable.md +21 -60
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/SingleReferenceReadOnly.md +43 -100
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/SubTabs.md +36 -76
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/TwoColumn.md +41 -90
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/WideNarrow.md +36 -43
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/WssNavBar.md +25 -115
- package/templates/react-sdk-reference/.ai-common/skills/widget-components.md +38 -174
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/AppAnnouncement.md +30 -57
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/Attachment.md +55 -101
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/CaseHistory.md +38 -121
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/FileUtility.md +37 -98
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/Followers.md +18 -33
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/QuickCreate.md +26 -91
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/SummaryItem.md +28 -120
- package/templates/react-sdk-reference/.ai-common/skills/widget-skills/ToDo.md +41 -272
- package/templates/react-sdk-reference/package.json +1 -1
- package/templates/react-sdk-reference/pega-auth-0.2.44.tgz +0 -0
- package/templates/react-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
- package/templates/react-sdk-reference/src/components/helpers/formatters/index.ts +13 -3
- package/templates/react-native-sdk-reference/.github/AGENTS.md +0 -23
- package/templates/react-native-sdk-reference/.github/copilot-instructions.md +0 -40
- package/templates/react-native-sdk-reference/.github/skills/pega-sdk-component.md +0 -48
- package/templates/react-native-sdk-reference/App.tsx +0 -49
- package/templates/react-native-sdk-reference/expo-env.d.ts +0 -3
- package/templates/react-sdk-reference/pega-auth-0.2.42.tgz +0 -0
package/dist/index.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import * as p from "@clack/prompts";
|
|
5
5
|
import pc from "picocolors";
|
|
6
|
-
import
|
|
6
|
+
import path3 from "path";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
|
|
9
9
|
// src/scaffold.ts
|
|
10
|
-
import
|
|
11
|
-
import
|
|
10
|
+
import fs2 from "fs";
|
|
11
|
+
import path2 from "path";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
13
|
import { spawn } from "child_process";
|
|
14
14
|
|
|
@@ -302,15 +302,134 @@ export function registerSampleComponents(registry: ComponentRegistry<React.Compo
|
|
|
302
302
|
return body;
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
// src/merge.ts
|
|
306
|
+
import fs from "fs";
|
|
307
|
+
import path from "path";
|
|
308
|
+
var PEGA_BEGIN = "<!-- BEGIN PEGA SDK \u2014 generated by @pega/sdk. Do not edit inside this block. -->";
|
|
309
|
+
var PEGA_END = "<!-- END PEGA SDK -->";
|
|
310
|
+
var PEGA_BLOCK_RE = new RegExp(`${escapeRegExp(PEGA_BEGIN)}[\\s\\S]*?${escapeRegExp(PEGA_END)}`);
|
|
311
|
+
function escapeRegExp(value) {
|
|
312
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
313
|
+
}
|
|
314
|
+
function hasPegaBlock(content) {
|
|
315
|
+
return PEGA_BLOCK_RE.test(content);
|
|
316
|
+
}
|
|
317
|
+
function wrapPegaBlock(body) {
|
|
318
|
+
return `${PEGA_BEGIN}
|
|
319
|
+
${body.replace(/\s+$/, "")}
|
|
320
|
+
${PEGA_END}
|
|
321
|
+
`;
|
|
322
|
+
}
|
|
323
|
+
function splitFrontmatter(content) {
|
|
324
|
+
const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);
|
|
325
|
+
if (!match) return { frontmatter: "", body: content };
|
|
326
|
+
return { frontmatter: match[0], body: content.slice(match[0].length) };
|
|
327
|
+
}
|
|
328
|
+
function writeManagedMarkdown(destPath, input) {
|
|
329
|
+
const { frontmatter, body, policy, markers = true } = input;
|
|
330
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
331
|
+
if (!markers) {
|
|
332
|
+
const existed = fs.existsSync(destPath);
|
|
333
|
+
fs.writeFileSync(destPath, frontmatter + body);
|
|
334
|
+
return existed ? "overwritten" : "created";
|
|
335
|
+
}
|
|
336
|
+
const block = wrapPegaBlock(body);
|
|
337
|
+
if (!fs.existsSync(destPath)) {
|
|
338
|
+
fs.writeFileSync(destPath, frontmatter + block);
|
|
339
|
+
return "created";
|
|
340
|
+
}
|
|
341
|
+
const existing = fs.readFileSync(destPath, "utf-8");
|
|
342
|
+
if (hasPegaBlock(existing)) {
|
|
343
|
+
const outside = existing.replace(PEGA_BLOCK_RE, "");
|
|
344
|
+
const { body: outsideBody } = splitFrontmatter(outside);
|
|
345
|
+
if (outsideBody.trim() === "") {
|
|
346
|
+
fs.writeFileSync(destPath, frontmatter + block);
|
|
347
|
+
return "block-replaced";
|
|
348
|
+
}
|
|
349
|
+
fs.writeFileSync(destPath, existing.replace(PEGA_BLOCK_RE, block.replace(/\n$/, "")));
|
|
350
|
+
return "block-replaced";
|
|
351
|
+
}
|
|
352
|
+
if (policy === "override") {
|
|
353
|
+
fs.writeFileSync(destPath, frontmatter + block);
|
|
354
|
+
return "overwritten";
|
|
355
|
+
}
|
|
356
|
+
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
357
|
+
fs.writeFileSync(destPath, existing + separator + block);
|
|
358
|
+
return "appended";
|
|
359
|
+
}
|
|
360
|
+
function isPlainObject(value) {
|
|
361
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
362
|
+
}
|
|
363
|
+
function deepMergeJson(existing, incoming, incomingWins = [], basePath = "") {
|
|
364
|
+
if (!isPlainObject(existing) || !isPlainObject(incoming)) {
|
|
365
|
+
return existing === void 0 ? incoming : existing;
|
|
366
|
+
}
|
|
367
|
+
const result = { ...existing };
|
|
368
|
+
for (const [key, incomingValue] of Object.entries(incoming)) {
|
|
369
|
+
const keyPath = basePath ? `${basePath}.${key}` : key;
|
|
370
|
+
if (!(key in result)) {
|
|
371
|
+
result[key] = incomingValue;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const existingValue = result[key];
|
|
375
|
+
if (isPlainObject(existingValue) && isPlainObject(incomingValue)) {
|
|
376
|
+
result[key] = deepMergeJson(existingValue, incomingValue, incomingWins, keyPath);
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (incomingWins.includes(keyPath) || incomingWins.includes(key)) {
|
|
380
|
+
result[key] = incomingValue;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
function writeManagedJson(destPath, incoming, policy, incomingWins = []) {
|
|
386
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
387
|
+
if (!fs.existsSync(destPath)) {
|
|
388
|
+
fs.writeFileSync(destPath, JSON.stringify(incoming, null, 2) + "\n");
|
|
389
|
+
return "created";
|
|
390
|
+
}
|
|
391
|
+
if (policy === "merge") {
|
|
392
|
+
try {
|
|
393
|
+
const existing = JSON.parse(fs.readFileSync(destPath, "utf-8"));
|
|
394
|
+
const merged = deepMergeJson(existing, incoming, incomingWins);
|
|
395
|
+
fs.writeFileSync(destPath, JSON.stringify(merged, null, 2) + "\n");
|
|
396
|
+
return "appended";
|
|
397
|
+
} catch {
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
fs.writeFileSync(destPath, JSON.stringify(incoming, null, 2) + "\n");
|
|
401
|
+
return "overwritten";
|
|
402
|
+
}
|
|
403
|
+
function isConflict(destPath, incomingJson, incomingWins = []) {
|
|
404
|
+
if (!fs.existsSync(destPath)) return false;
|
|
405
|
+
let existing;
|
|
406
|
+
try {
|
|
407
|
+
existing = fs.readFileSync(destPath, "utf-8");
|
|
408
|
+
} catch {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
if (/\.json$/i.test(destPath)) {
|
|
412
|
+
if (incomingJson === void 0) return true;
|
|
413
|
+
try {
|
|
414
|
+
const parsed = JSON.parse(existing);
|
|
415
|
+
const merged = deepMergeJson(parsed, incomingJson, incomingWins);
|
|
416
|
+
return JSON.stringify(merged) !== JSON.stringify(parsed);
|
|
417
|
+
} catch {
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return !hasPegaBlock(existing);
|
|
422
|
+
}
|
|
423
|
+
|
|
305
424
|
// src/scaffold.ts
|
|
306
|
-
var __dirname =
|
|
307
|
-
var MONOREPO_SAMPLES_DIR =
|
|
308
|
-
var PACKAGED_TEMPLATES_DIR =
|
|
425
|
+
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
426
|
+
var MONOREPO_SAMPLES_DIR = path2.resolve(__dirname, "..", "..", "..", "samples");
|
|
427
|
+
var PACKAGED_TEMPLATES_DIR = path2.resolve(__dirname, "..", "templates");
|
|
309
428
|
function resolveTemplateSourceRoot() {
|
|
310
|
-
if (
|
|
429
|
+
if (fs2.existsSync(MONOREPO_SAMPLES_DIR)) {
|
|
311
430
|
return MONOREPO_SAMPLES_DIR;
|
|
312
431
|
}
|
|
313
|
-
if (
|
|
432
|
+
if (fs2.existsSync(PACKAGED_TEMPLATES_DIR)) {
|
|
314
433
|
return PACKAGED_TEMPLATES_DIR;
|
|
315
434
|
}
|
|
316
435
|
throw new Error(
|
|
@@ -330,64 +449,86 @@ var CATEGORY_DIR_MAP = {
|
|
|
330
449
|
infra: "infra",
|
|
331
450
|
designSystemExtension: "designSystemExtension"
|
|
332
451
|
};
|
|
333
|
-
var SKIP_ENTRIES = /* @__PURE__ */ new Set([
|
|
452
|
+
var SKIP_ENTRIES = /* @__PURE__ */ new Set([
|
|
453
|
+
"node_modules",
|
|
454
|
+
"dist",
|
|
455
|
+
".DS_Store",
|
|
456
|
+
".next",
|
|
457
|
+
".expo",
|
|
458
|
+
".angular",
|
|
459
|
+
"build",
|
|
460
|
+
".pnpm-store"
|
|
461
|
+
]);
|
|
334
462
|
async function scaffold(choices, targetDir, onProgress) {
|
|
335
463
|
const report = (message) => onProgress?.(message);
|
|
336
|
-
|
|
464
|
+
let { framework, aiTool, includeTemplates, componentCategories, projectName } = choices;
|
|
465
|
+
if (framework === "react-native") {
|
|
466
|
+
includeTemplates = true;
|
|
467
|
+
componentCategories = ["fields", "templates", "infra"];
|
|
468
|
+
}
|
|
337
469
|
report("Preparing project directory\u2026");
|
|
338
|
-
if (
|
|
339
|
-
const files =
|
|
470
|
+
if (fs2.existsSync(targetDir)) {
|
|
471
|
+
const files = fs2.readdirSync(targetDir);
|
|
340
472
|
if (files.length > 0) {
|
|
341
473
|
throw new Error(`Directory "${targetDir}" is not empty.`);
|
|
342
474
|
}
|
|
343
475
|
} else {
|
|
344
|
-
|
|
476
|
+
fs2.mkdirSync(targetDir, { recursive: true });
|
|
345
477
|
}
|
|
346
478
|
const templateSourceRoot = resolveTemplateSourceRoot();
|
|
347
479
|
const sampleName = FRAMEWORK_SAMPLE_MAP[framework];
|
|
348
|
-
const sampleDir =
|
|
349
|
-
if (!
|
|
480
|
+
const sampleDir = path2.join(templateSourceRoot, sampleName);
|
|
481
|
+
if (!fs2.existsSync(sampleDir)) {
|
|
350
482
|
throw new Error(`Template "${sampleName}" not found at ${sampleDir}.`);
|
|
351
483
|
}
|
|
352
484
|
report(`Copying ${sampleName} reference app\u2026`);
|
|
353
485
|
copyDir(sampleDir, targetDir);
|
|
354
486
|
report("Configuring component set\u2026");
|
|
355
|
-
const componentsDir =
|
|
356
|
-
if (
|
|
487
|
+
const componentsDir = path2.join(targetDir, "src", "components");
|
|
488
|
+
if (fs2.existsSync(componentsDir)) {
|
|
489
|
+
const allowedCategories = framework === "react-native" ? ["fields", "templates", "infra"] : ["fields", "templates", "widgets", "infra", "designSystemExtension"];
|
|
357
490
|
if (!includeTemplates || componentCategories.length === 0) {
|
|
358
491
|
for (const cat of Object.values(CATEGORY_DIR_MAP)) {
|
|
359
|
-
const catDir =
|
|
360
|
-
if (
|
|
361
|
-
|
|
492
|
+
const catDir = path2.join(componentsDir, cat);
|
|
493
|
+
if (fs2.existsSync(catDir)) {
|
|
494
|
+
fs2.rmSync(catDir, { recursive: true });
|
|
362
495
|
}
|
|
363
496
|
}
|
|
364
|
-
|
|
497
|
+
fs2.writeFileSync(path2.join(componentsDir, "component-map.ts"), generateMinimalComponentMap(framework));
|
|
365
498
|
if (framework === "react") {
|
|
366
|
-
|
|
367
|
-
const muiThemeAugmentation =
|
|
368
|
-
if (
|
|
369
|
-
|
|
499
|
+
fs2.writeFileSync(path2.join(targetDir, "src", "AppProviders.tsx"), generateMinimalReactProviders());
|
|
500
|
+
const muiThemeAugmentation = path2.join(targetDir, "src", "mui-theme-augmentation.d.ts");
|
|
501
|
+
if (fs2.existsSync(muiThemeAugmentation)) {
|
|
502
|
+
fs2.rmSync(muiThemeAugmentation);
|
|
370
503
|
}
|
|
371
504
|
}
|
|
372
505
|
} else {
|
|
373
|
-
const
|
|
374
|
-
for (const cat of allCategories) {
|
|
506
|
+
for (const cat of allowedCategories) {
|
|
375
507
|
if (!componentCategories.includes(cat)) {
|
|
376
|
-
const catDir =
|
|
377
|
-
if (
|
|
378
|
-
|
|
508
|
+
const catDir = path2.join(componentsDir, CATEGORY_DIR_MAP[cat]);
|
|
509
|
+
if (fs2.existsSync(catDir)) {
|
|
510
|
+
fs2.rmSync(catDir, { recursive: true });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (framework === "react-native") {
|
|
515
|
+
const unsupportedCats = ["widgets", "designSystemExtension"];
|
|
516
|
+
for (const cat of unsupportedCats) {
|
|
517
|
+
const catDir = path2.join(componentsDir, CATEGORY_DIR_MAP[cat]);
|
|
518
|
+
if (fs2.existsSync(catDir)) {
|
|
519
|
+
fs2.rmSync(catDir, { recursive: true });
|
|
379
520
|
}
|
|
380
521
|
}
|
|
381
522
|
}
|
|
382
523
|
const componentMapContent = generateComponentMap(componentCategories, framework);
|
|
383
|
-
|
|
524
|
+
fs2.writeFileSync(path2.join(componentsDir, "component-map.ts"), componentMapContent);
|
|
384
525
|
}
|
|
385
526
|
}
|
|
386
527
|
if (!aiTool) {
|
|
387
528
|
for (const dir of [".github", ".cursor", "AGENTS.md", ".claude", ".ai-common"]) {
|
|
388
|
-
const target =
|
|
389
|
-
if (
|
|
390
|
-
|
|
529
|
+
const target = path2.join(targetDir, dir);
|
|
530
|
+
if (fs2.existsSync(target)) {
|
|
531
|
+
fs2.rmSync(target, { recursive: true });
|
|
391
532
|
}
|
|
392
533
|
}
|
|
393
534
|
} else {
|
|
@@ -400,9 +541,9 @@ async function scaffold(choices, targetDir, onProgress) {
|
|
|
400
541
|
const keepPaths = AI_TOOL_PATHS[aiTool];
|
|
401
542
|
for (const dir of allAiPaths) {
|
|
402
543
|
if (!keepPaths.includes(dir)) {
|
|
403
|
-
const target =
|
|
404
|
-
if (
|
|
405
|
-
|
|
544
|
+
const target = path2.join(targetDir, dir);
|
|
545
|
+
if (fs2.existsSync(target)) {
|
|
546
|
+
fs2.rmSync(target, { recursive: true });
|
|
406
547
|
}
|
|
407
548
|
}
|
|
408
549
|
}
|
|
@@ -410,9 +551,12 @@ async function scaffold(choices, targetDir, onProgress) {
|
|
|
410
551
|
}
|
|
411
552
|
report("Finalizing project configuration\u2026");
|
|
412
553
|
selectReactPackageManifest(targetDir, framework, includeTemplates, componentCategories);
|
|
413
|
-
transformPackageJson(
|
|
414
|
-
transformTsConfig(
|
|
415
|
-
transformSdkConfig(
|
|
554
|
+
transformPackageJson(path2.join(targetDir, "package.json"), projectName);
|
|
555
|
+
transformTsConfig(path2.join(targetDir, "tsconfig.json"));
|
|
556
|
+
transformSdkConfig(path2.join(targetDir, "sdk-config.json"));
|
|
557
|
+
if (framework === "react-native") {
|
|
558
|
+
transformExpoConfig(path2.join(targetDir, "app.json"), projectName);
|
|
559
|
+
}
|
|
416
560
|
report("Installing dependencies (this may take a minute)\u2026");
|
|
417
561
|
try {
|
|
418
562
|
await runInstall(targetDir);
|
|
@@ -434,27 +578,27 @@ function runInstall(cwd) {
|
|
|
434
578
|
});
|
|
435
579
|
}
|
|
436
580
|
function transformPackageJson(pkgJsonPath, projectName) {
|
|
437
|
-
if (!
|
|
438
|
-
const pkgJson = JSON.parse(
|
|
581
|
+
if (!fs2.existsSync(pkgJsonPath)) return;
|
|
582
|
+
const pkgJson = JSON.parse(fs2.readFileSync(pkgJsonPath, "utf-8"));
|
|
439
583
|
pkgJson.name = projectName;
|
|
440
584
|
delete pkgJson.private;
|
|
441
|
-
|
|
585
|
+
fs2.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
442
586
|
}
|
|
443
587
|
function selectReactPackageManifest(targetDir, framework, includeTemplates, componentCategories) {
|
|
444
588
|
if (framework !== "react") return;
|
|
445
|
-
const pkgJsonPath =
|
|
446
|
-
const minimalPkgJsonPath =
|
|
589
|
+
const pkgJsonPath = path2.join(targetDir, "package.json");
|
|
590
|
+
const minimalPkgJsonPath = path2.join(targetDir, "package.minimal.json");
|
|
447
591
|
const hasSampleComponents = includeTemplates && componentCategories.length > 0;
|
|
448
|
-
if (!hasSampleComponents &&
|
|
449
|
-
|
|
592
|
+
if (!hasSampleComponents && fs2.existsSync(minimalPkgJsonPath)) {
|
|
593
|
+
fs2.copyFileSync(minimalPkgJsonPath, pkgJsonPath);
|
|
450
594
|
}
|
|
451
|
-
if (
|
|
452
|
-
|
|
595
|
+
if (fs2.existsSync(minimalPkgJsonPath)) {
|
|
596
|
+
fs2.rmSync(minimalPkgJsonPath);
|
|
453
597
|
}
|
|
454
598
|
}
|
|
455
599
|
function transformTsConfig(tsconfigPath) {
|
|
456
|
-
if (!
|
|
457
|
-
const tsconfig = JSON.parse(
|
|
600
|
+
if (!fs2.existsSync(tsconfigPath)) return;
|
|
601
|
+
const tsconfig = JSON.parse(fs2.readFileSync(tsconfigPath, "utf-8"));
|
|
458
602
|
if (tsconfig.compilerOptions) {
|
|
459
603
|
if (tsconfig.compilerOptions.paths) {
|
|
460
604
|
const cleanedPaths = {};
|
|
@@ -474,11 +618,11 @@ function transformTsConfig(tsconfigPath) {
|
|
|
474
618
|
tsconfig.compilerOptions.typeRoots = ["./node_modules/@types", "./node_modules/@pega"];
|
|
475
619
|
}
|
|
476
620
|
}
|
|
477
|
-
|
|
621
|
+
fs2.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n");
|
|
478
622
|
}
|
|
479
623
|
function transformSdkConfig(sdkConfigPath) {
|
|
480
|
-
if (!
|
|
481
|
-
const sdkConfig = JSON.parse(
|
|
624
|
+
if (!fs2.existsSync(sdkConfigPath)) return;
|
|
625
|
+
const sdkConfig = JSON.parse(fs2.readFileSync(sdkConfigPath, "utf-8"));
|
|
482
626
|
if (sdkConfig.serverConfig) {
|
|
483
627
|
if ("infinityRestServerUrl" in sdkConfig.serverConfig) sdkConfig.serverConfig.infinityRestServerUrl = "";
|
|
484
628
|
if ("appAlias" in sdkConfig.serverConfig) sdkConfig.serverConfig.appAlias = "";
|
|
@@ -489,9 +633,45 @@ function transformSdkConfig(sdkConfigPath) {
|
|
|
489
633
|
if ("mashupUserIdentifier" in sdkConfig.authConfig) sdkConfig.authConfig.mashupUserIdentifier = "";
|
|
490
634
|
if ("portalClientId" in sdkConfig.authConfig) sdkConfig.authConfig.portalClientId = "";
|
|
491
635
|
}
|
|
492
|
-
|
|
636
|
+
fs2.writeFileSync(sdkConfigPath, JSON.stringify(sdkConfig, null, 2) + "\n");
|
|
637
|
+
}
|
|
638
|
+
function transformExpoConfig(appJsonPath, projectName) {
|
|
639
|
+
if (!fs2.existsSync(appJsonPath)) return;
|
|
640
|
+
const appJson = JSON.parse(fs2.readFileSync(appJsonPath, "utf-8"));
|
|
641
|
+
if (appJson.expo) {
|
|
642
|
+
appJson.expo.name = projectName;
|
|
643
|
+
appJson.expo.slug = projectName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
644
|
+
}
|
|
645
|
+
fs2.writeFileSync(appJsonPath, JSON.stringify(appJson, null, 2) + "\n");
|
|
646
|
+
}
|
|
647
|
+
function generateMinimalComponentMap(framework) {
|
|
648
|
+
if (framework === "react-native") {
|
|
649
|
+
return `import { sdkComponents } from '@pega/sdk-react';
|
|
650
|
+
import type { ComponentRegistry } from '@pega/sdk-types';
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Returns a map of Pega component names \u2192 React Native components.
|
|
654
|
+
* Add your own components here as you build them.
|
|
655
|
+
*/
|
|
656
|
+
function getSampleComponentMap(): Record<string, React.ComponentType<Record<string, unknown>>> {
|
|
657
|
+
return {
|
|
658
|
+
...sdkComponents,
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Registers all components into the given registry.
|
|
664
|
+
*/
|
|
665
|
+
export function registerComponents(
|
|
666
|
+
registry: ComponentRegistry<React.ComponentType<Record<string, unknown>>>,
|
|
667
|
+
) {
|
|
668
|
+
const map = getSampleComponentMap();
|
|
669
|
+
for (const [name, component] of Object.entries(map)) {
|
|
670
|
+
registry.register(name, component);
|
|
671
|
+
}
|
|
493
672
|
}
|
|
494
|
-
|
|
673
|
+
`;
|
|
674
|
+
}
|
|
495
675
|
return `import { sdkComponents } from '@pega/sdk-react';
|
|
496
676
|
import type { ComponentRegistry } from '@pega/sdk-types';
|
|
497
677
|
|
|
@@ -539,6 +719,7 @@ var AI_GEN_CONFIGS = {
|
|
|
539
719
|
tokens: {
|
|
540
720
|
"{{PROMPT_DIR}}": ".github/prompts",
|
|
541
721
|
"{{SKILL_DIR}}": ".github/skills",
|
|
722
|
+
"{{INSTRUCTIONS_DIR}}": ".github/instructions",
|
|
542
723
|
"{{PROMPT_EXT}}": ".prompt.md",
|
|
543
724
|
"{{SKILL_EXT}}": ".md",
|
|
544
725
|
"{{AI_FILE_EXT}}": ".instructions.md"
|
|
@@ -556,6 +737,7 @@ var AI_GEN_CONFIGS = {
|
|
|
556
737
|
tokens: {
|
|
557
738
|
"{{PROMPT_DIR}}": ".claude/prompts",
|
|
558
739
|
"{{SKILL_DIR}}": ".claude/skills",
|
|
740
|
+
"{{INSTRUCTIONS_DIR}}": ".claude/instructions",
|
|
559
741
|
"{{PROMPT_EXT}}": ".md",
|
|
560
742
|
"{{SKILL_EXT}}": ".md",
|
|
561
743
|
"{{AI_FILE_EXT}}": ".md"
|
|
@@ -573,6 +755,7 @@ var AI_GEN_CONFIGS = {
|
|
|
573
755
|
tokens: {
|
|
574
756
|
"{{PROMPT_DIR}}": ".cursor/rules/prompts",
|
|
575
757
|
"{{SKILL_DIR}}": ".cursor/rules/skills",
|
|
758
|
+
"{{INSTRUCTIONS_DIR}}": ".cursor/rules",
|
|
576
759
|
"{{PROMPT_EXT}}": ".mdrules",
|
|
577
760
|
"{{SKILL_EXT}}": ".mdrules",
|
|
578
761
|
"{{AI_FILE_EXT}}": ".mdrules"
|
|
@@ -611,22 +794,21 @@ function cursorSkillDescription(relPath) {
|
|
|
611
794
|
}
|
|
612
795
|
return relPath.replace(/\.md$/, "").split("/").pop();
|
|
613
796
|
}
|
|
614
|
-
function
|
|
615
|
-
|
|
616
|
-
if (!fs.existsSync(aiCommonDir)) return;
|
|
797
|
+
function planAiConfigs(aiCommonDir, targetDir, aiTool, options = {}) {
|
|
798
|
+
if (!fs2.existsSync(aiCommonDir)) return [];
|
|
617
799
|
const cfg = AI_GEN_CONFIGS[aiTool];
|
|
618
800
|
const { tokens } = cfg;
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
801
|
+
const planned = [];
|
|
802
|
+
const skillsSrc = path2.join(aiCommonDir, "skills");
|
|
803
|
+
if (fs2.existsSync(skillsSrc)) {
|
|
804
|
+
const walkSkills = (srcDir, relDir = "") => {
|
|
805
|
+
for (const entry of fs2.readdirSync(srcDir, { withFileTypes: true })) {
|
|
623
806
|
const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
624
|
-
const srcPath =
|
|
807
|
+
const srcPath = path2.join(srcDir, entry.name);
|
|
625
808
|
if (entry.isDirectory()) {
|
|
626
|
-
|
|
809
|
+
walkSkills(srcPath, relPath);
|
|
627
810
|
} else if (entry.name.endsWith(".md")) {
|
|
628
|
-
const { body } = parseAiMeta(
|
|
629
|
-
const outContent = applyTokens(body, tokens);
|
|
811
|
+
const { body } = parseAiMeta(fs2.readFileSync(srcPath, "utf-8"));
|
|
630
812
|
let frontmatter = "";
|
|
631
813
|
if (aiTool === "cursor") {
|
|
632
814
|
const desc = cursorSkillDescription(relPath);
|
|
@@ -638,26 +820,31 @@ alwaysApply: false
|
|
|
638
820
|
`;
|
|
639
821
|
}
|
|
640
822
|
const outName = `${entry.name.replace(/\.md$/, "")}.${cfg.skillExt}`;
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
823
|
+
planned.push({
|
|
824
|
+
destPath: path2.join(targetDir, cfg.skillDir, relDir, outName),
|
|
825
|
+
frontmatter,
|
|
826
|
+
body: applyTokens(body, tokens),
|
|
827
|
+
kind: "md"
|
|
828
|
+
});
|
|
644
829
|
}
|
|
645
830
|
}
|
|
646
831
|
};
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
-
for (const entry of fs.readdirSync(promptsSrc, { withFileTypes: true })) {
|
|
655
|
-
const srcPath = path.join(promptsSrc, entry.name);
|
|
832
|
+
walkSkills(skillsSrc);
|
|
833
|
+
}
|
|
834
|
+
const promptsSrc = path2.join(aiCommonDir, "prompts");
|
|
835
|
+
if (fs2.existsSync(promptsSrc)) {
|
|
836
|
+
const promptsDest = path2.join(targetDir, cfg.promptDir);
|
|
837
|
+
for (const entry of fs2.readdirSync(promptsSrc, { withFileTypes: true })) {
|
|
838
|
+
const srcPath = path2.join(promptsSrc, entry.name);
|
|
656
839
|
if (entry.name === "component-manifest.json") {
|
|
657
|
-
|
|
840
|
+
planned.push({
|
|
841
|
+
destPath: path2.join(promptsDest, entry.name),
|
|
842
|
+
frontmatter: "",
|
|
843
|
+
body: fs2.readFileSync(srcPath, "utf-8"),
|
|
844
|
+
kind: "json"
|
|
845
|
+
});
|
|
658
846
|
} else if (entry.name.endsWith(".md")) {
|
|
659
|
-
const { meta, body } = parseAiMeta(
|
|
660
|
-
const outContent = applyTokens(body, tokens);
|
|
847
|
+
const { meta, body } = parseAiMeta(fs2.readFileSync(srcPath, "utf-8"));
|
|
661
848
|
const basename = entry.name.replace(/\.md$/, "");
|
|
662
849
|
let frontmatter = "";
|
|
663
850
|
if (aiTool === "copilot") {
|
|
@@ -675,18 +862,21 @@ alwaysApply: false
|
|
|
675
862
|
|
|
676
863
|
`;
|
|
677
864
|
}
|
|
678
|
-
|
|
865
|
+
planned.push({
|
|
866
|
+
destPath: path2.join(promptsDest, `${basename}.${cfg.promptExt}`),
|
|
867
|
+
frontmatter,
|
|
868
|
+
body: applyTokens(body, tokens),
|
|
869
|
+
kind: "md"
|
|
870
|
+
});
|
|
679
871
|
}
|
|
680
872
|
}
|
|
681
873
|
}
|
|
682
|
-
const instructionsSrc =
|
|
683
|
-
if (
|
|
684
|
-
const instructionsDest =
|
|
685
|
-
|
|
686
|
-
for (const entry of fs.readdirSync(instructionsSrc, { withFileTypes: true })) {
|
|
874
|
+
const instructionsSrc = path2.join(aiCommonDir, "instructions");
|
|
875
|
+
if (fs2.existsSync(instructionsSrc)) {
|
|
876
|
+
const instructionsDest = path2.join(targetDir, cfg.instructionsDir);
|
|
877
|
+
for (const entry of fs2.readdirSync(instructionsSrc, { withFileTypes: true })) {
|
|
687
878
|
if (!entry.name.endsWith(".md")) continue;
|
|
688
|
-
const { meta, body } = parseAiMeta(
|
|
689
|
-
const outContent = applyTokens(body, tokens);
|
|
879
|
+
const { meta, body } = parseAiMeta(fs2.readFileSync(path2.join(instructionsSrc, entry.name), "utf-8"));
|
|
690
880
|
const basename = entry.name.replace(/\.md$/, "");
|
|
691
881
|
let frontmatter = "";
|
|
692
882
|
if (aiTool === "cursor") {
|
|
@@ -706,19 +896,21 @@ applyTo: '${meta.globs}'
|
|
|
706
896
|
|
|
707
897
|
`;
|
|
708
898
|
}
|
|
709
|
-
|
|
899
|
+
planned.push({
|
|
900
|
+
destPath: path2.join(instructionsDest, `${basename}.${cfg.instructionsExt}`),
|
|
901
|
+
frontmatter,
|
|
902
|
+
body: applyTokens(body, tokens),
|
|
903
|
+
kind: "md"
|
|
904
|
+
});
|
|
710
905
|
}
|
|
711
906
|
}
|
|
712
|
-
const agentsSrc =
|
|
713
|
-
if (
|
|
714
|
-
const agentsDest =
|
|
715
|
-
|
|
716
|
-
for (const entry of fs.readdirSync(agentsSrc, { withFileTypes: true })) {
|
|
907
|
+
const agentsSrc = path2.join(aiCommonDir, "agents");
|
|
908
|
+
if (fs2.existsSync(agentsSrc)) {
|
|
909
|
+
const agentsDest = path2.join(targetDir, cfg.agentsDir);
|
|
910
|
+
for (const entry of fs2.readdirSync(agentsSrc, { withFileTypes: true })) {
|
|
717
911
|
if (!entry.name.endsWith(".md")) continue;
|
|
718
912
|
const basename = entry.name.replace(/\.md$/, "");
|
|
719
|
-
const
|
|
720
|
-
const { meta, body } = parseAiMeta(fs.readFileSync(srcPath, "utf-8"));
|
|
721
|
-
const outContent = applyTokens(body, tokens);
|
|
913
|
+
const { meta, body } = parseAiMeta(fs2.readFileSync(path2.join(agentsSrc, entry.name), "utf-8"));
|
|
722
914
|
let frontmatter = "";
|
|
723
915
|
if (aiTool === "copilot") {
|
|
724
916
|
const description = applyTokens(meta.description || "", tokens);
|
|
@@ -726,7 +918,6 @@ applyTo: '${meta.globs}'
|
|
|
726
918
|
frontmatter = `---
|
|
727
919
|
description: "${description}"
|
|
728
920
|
name: '${name}'
|
|
729
|
-
tools: [read, edit, search, execute, agent, vscode_askQuestions]
|
|
730
921
|
user-invocable: true
|
|
731
922
|
disable-model-invocation: false
|
|
732
923
|
---
|
|
@@ -739,40 +930,262 @@ description: ${description}
|
|
|
739
930
|
alwaysApply: false
|
|
740
931
|
---
|
|
741
932
|
|
|
933
|
+
`;
|
|
934
|
+
} else if (aiTool === "claude-code") {
|
|
935
|
+
const description = applyTokens(meta.description || `Agent config: ${basename}`, tokens);
|
|
936
|
+
frontmatter = `---
|
|
937
|
+
name: ${basename}
|
|
938
|
+
description: "${description}"
|
|
939
|
+
---
|
|
940
|
+
|
|
742
941
|
`;
|
|
743
942
|
}
|
|
744
|
-
|
|
943
|
+
planned.push({
|
|
944
|
+
destPath: path2.join(agentsDest, `${basename}.${cfg.agentExt}`),
|
|
945
|
+
frontmatter,
|
|
946
|
+
body: applyTokens(body, tokens),
|
|
947
|
+
kind: "md"
|
|
948
|
+
});
|
|
745
949
|
}
|
|
746
950
|
}
|
|
747
|
-
const globalSrc =
|
|
748
|
-
if (
|
|
749
|
-
const
|
|
750
|
-
if (
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
951
|
+
const globalSrc = path2.join(aiCommonDir, "global", options.globalFile ?? "ai-agent-instructions.md");
|
|
952
|
+
if (fs2.existsSync(globalSrc)) {
|
|
953
|
+
const body = applyTokens(fs2.readFileSync(globalSrc, "utf-8"), tokens);
|
|
954
|
+
if (aiTool === "copilot") {
|
|
955
|
+
planned.push({
|
|
956
|
+
destPath: path2.join(targetDir, ".github", "copilot-instructions.md"),
|
|
957
|
+
frontmatter: "",
|
|
958
|
+
body,
|
|
959
|
+
kind: "md"
|
|
960
|
+
});
|
|
961
|
+
} else if (aiTool === "cursor") {
|
|
962
|
+
planned.push({
|
|
963
|
+
destPath: path2.join(targetDir, ".cursor", "rules", "pega-sdk.mdrules"),
|
|
964
|
+
frontmatter: "---\ndescription: Core rules for working with Pega SDK components\nalwaysApply: true\n---\n\n",
|
|
965
|
+
body,
|
|
966
|
+
kind: "md"
|
|
967
|
+
});
|
|
968
|
+
} else if (aiTool === "claude-code") {
|
|
969
|
+
planned.push({
|
|
970
|
+
destPath: path2.join(targetDir, "AGENTS.md"),
|
|
971
|
+
frontmatter: "",
|
|
972
|
+
body,
|
|
973
|
+
kind: "md"
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return planned;
|
|
978
|
+
}
|
|
979
|
+
function applyPlannedFiles(files, policy, options = {}) {
|
|
980
|
+
const { markers = true } = options;
|
|
981
|
+
const counts = {
|
|
982
|
+
created: 0,
|
|
983
|
+
"block-replaced": 0,
|
|
984
|
+
appended: 0,
|
|
985
|
+
overwritten: 0
|
|
986
|
+
};
|
|
987
|
+
for (const file of files) {
|
|
988
|
+
let outcome;
|
|
989
|
+
if (file.kind === "json") {
|
|
990
|
+
let parsed;
|
|
991
|
+
try {
|
|
992
|
+
parsed = markers ? JSON.parse(file.body) : void 0;
|
|
993
|
+
} catch {
|
|
994
|
+
parsed = void 0;
|
|
995
|
+
}
|
|
996
|
+
if (parsed === void 0) {
|
|
997
|
+
fs2.mkdirSync(path2.dirname(file.destPath), { recursive: true });
|
|
998
|
+
const existed = fs2.existsSync(file.destPath);
|
|
999
|
+
fs2.writeFileSync(file.destPath, file.body);
|
|
1000
|
+
counts[existed ? "overwritten" : "created"] += 1;
|
|
1001
|
+
continue;
|
|
761
1002
|
}
|
|
1003
|
+
outcome = writeManagedJson(file.destPath, parsed, policy);
|
|
1004
|
+
} else {
|
|
1005
|
+
outcome = writeManagedMarkdown(file.destPath, {
|
|
1006
|
+
frontmatter: file.frontmatter,
|
|
1007
|
+
body: file.body,
|
|
1008
|
+
policy,
|
|
1009
|
+
markers
|
|
1010
|
+
});
|
|
762
1011
|
}
|
|
1012
|
+
counts[outcome] += 1;
|
|
763
1013
|
}
|
|
764
|
-
|
|
1014
|
+
return counts;
|
|
1015
|
+
}
|
|
1016
|
+
function generateAiConfigs(targetDir, aiTool) {
|
|
1017
|
+
const aiCommonDir = path2.join(targetDir, ".ai-common");
|
|
1018
|
+
if (!fs2.existsSync(aiCommonDir)) return;
|
|
1019
|
+
applyPlannedFiles(planAiConfigs(aiCommonDir, targetDir, aiTool), "override", { markers: false });
|
|
1020
|
+
fs2.rmSync(aiCommonDir, { recursive: true });
|
|
1021
|
+
}
|
|
1022
|
+
var EMBEDDED_GLOBAL_FILE = "ai-agent-instructions-embedded.md";
|
|
1023
|
+
function resolveEmbeddedSource() {
|
|
1024
|
+
const templateSourceRoot = resolveTemplateSourceRoot();
|
|
1025
|
+
const sampleDir = path2.join(templateSourceRoot, FRAMEWORK_SAMPLE_MAP.react);
|
|
1026
|
+
const aiCommonSrc = path2.join(sampleDir, ".ai-common");
|
|
1027
|
+
if (!fs2.existsSync(aiCommonSrc)) {
|
|
1028
|
+
throw new Error(`AI common source not found at ${aiCommonSrc}. Ensure the template source is available.`);
|
|
1029
|
+
}
|
|
1030
|
+
return { sampleDir, aiCommonSrc };
|
|
1031
|
+
}
|
|
1032
|
+
var SDK_CONFIG_USER_KEYS = [
|
|
1033
|
+
"serverConfig.infinityRestServerUrl",
|
|
1034
|
+
"serverConfig.appAlias",
|
|
1035
|
+
"authConfig.mashupClientId",
|
|
1036
|
+
"authConfig.mashupUserIdentifier",
|
|
1037
|
+
"authConfig.portalClientId"
|
|
1038
|
+
];
|
|
1039
|
+
function buildSdkConfig(choices) {
|
|
1040
|
+
return {
|
|
1041
|
+
serverConfig: {
|
|
1042
|
+
infinityRestServerUrl: choices.serverUrl,
|
|
1043
|
+
appAlias: choices.appAlias,
|
|
1044
|
+
sdkContentServerUrl: "",
|
|
1045
|
+
appPortal: "",
|
|
1046
|
+
appMashupCaseType: "",
|
|
1047
|
+
excludePortals: [
|
|
1048
|
+
"pxExpress",
|
|
1049
|
+
"Developer",
|
|
1050
|
+
"pxPredictionStudio",
|
|
1051
|
+
"pxAdminStudio",
|
|
1052
|
+
"pyCaseWorker",
|
|
1053
|
+
"pyCaseManager7"
|
|
1054
|
+
]
|
|
1055
|
+
},
|
|
1056
|
+
authConfig: {
|
|
1057
|
+
authService: "pega",
|
|
1058
|
+
mashupClientId: choices.clientId,
|
|
1059
|
+
mashupUserIdentifier: choices.userIdentifier,
|
|
1060
|
+
mashupPassword: "",
|
|
1061
|
+
portalClientId: choices.clientId,
|
|
1062
|
+
portalClientSecret: "",
|
|
1063
|
+
portalGrantType: ""
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
function collectEmbeddedConflicts(targetDir, choices) {
|
|
1068
|
+
const { aiCommonSrc } = resolveEmbeddedSource();
|
|
1069
|
+
const planned = planAiConfigs(aiCommonSrc, targetDir, choices.aiTool, { globalFile: EMBEDDED_GLOBAL_FILE });
|
|
1070
|
+
const conflicts = planned.filter((file) => {
|
|
1071
|
+
if (file.kind !== "json") return isConflict(file.destPath);
|
|
1072
|
+
try {
|
|
1073
|
+
return isConflict(file.destPath, JSON.parse(file.body));
|
|
1074
|
+
} catch {
|
|
1075
|
+
return isConflict(file.destPath);
|
|
1076
|
+
}
|
|
1077
|
+
}).map((file) => file.destPath);
|
|
1078
|
+
const sdkConfigPath = path2.join(resolveStaticDir(targetDir), "sdk-config.json");
|
|
1079
|
+
if (isConflict(sdkConfigPath, buildSdkConfig(choices), SDK_CONFIG_USER_KEYS)) {
|
|
1080
|
+
conflicts.push(sdkConfigPath);
|
|
1081
|
+
}
|
|
1082
|
+
return conflicts.map((filePath) => path2.relative(targetDir, filePath));
|
|
1083
|
+
}
|
|
1084
|
+
async function scaffoldEmbedded(choices, targetDir, onProgress) {
|
|
1085
|
+
const report = (message) => onProgress?.(message);
|
|
1086
|
+
const { aiTool } = choices;
|
|
1087
|
+
const policy = choices.conflictPolicy ?? "merge";
|
|
1088
|
+
report("Locating embedded flow skills\u2026");
|
|
1089
|
+
const { sampleDir, aiCommonSrc } = resolveEmbeddedSource();
|
|
1090
|
+
report(`Generating ${aiTool} configuration\u2026`);
|
|
1091
|
+
const planned = planAiConfigs(aiCommonSrc, targetDir, aiTool, { globalFile: EMBEDDED_GLOBAL_FILE });
|
|
1092
|
+
const counts = applyPlannedFiles(planned, policy);
|
|
1093
|
+
report(
|
|
1094
|
+
`Wrote ${planned.length} file(s): ${counts.created} new, ${counts["block-replaced"]} updated, ${counts.appended} merged, ${counts.overwritten} replaced.`
|
|
1095
|
+
);
|
|
1096
|
+
report("Copying SDK packages\u2026");
|
|
1097
|
+
const tgzFiles = fs2.readdirSync(sampleDir).filter((f) => f.endsWith(".tgz"));
|
|
1098
|
+
for (const tgz of tgzFiles) {
|
|
1099
|
+
const src = path2.join(sampleDir, tgz);
|
|
1100
|
+
const dest = path2.join(targetDir, tgz);
|
|
1101
|
+
fs2.copyFileSync(src, dest);
|
|
1102
|
+
}
|
|
1103
|
+
report("Adding SDK dependencies\u2026");
|
|
1104
|
+
const pkgJsonPath = path2.join(targetDir, "package.json");
|
|
1105
|
+
if (fs2.existsSync(pkgJsonPath)) {
|
|
1106
|
+
const pkgJson = JSON.parse(fs2.readFileSync(pkgJsonPath, "utf-8"));
|
|
1107
|
+
if (!pkgJson.dependencies) pkgJson.dependencies = {};
|
|
1108
|
+
const TGZ_PACKAGE_MAP = {
|
|
1109
|
+
"pega-auth": "@pega/auth",
|
|
1110
|
+
"pega-constellationjs": "@pega/constellationjs",
|
|
1111
|
+
"pega-sdk-react": "@pega/sdk-react",
|
|
1112
|
+
"pega-sdk-types": "@pega/sdk-types"
|
|
1113
|
+
};
|
|
1114
|
+
for (const tgz of tgzFiles) {
|
|
1115
|
+
const match = tgz.match(/^(pega-[\w-]+?)-\d/);
|
|
1116
|
+
if (match) {
|
|
1117
|
+
const pkgName = TGZ_PACKAGE_MAP[match[1]];
|
|
1118
|
+
if (pkgName) {
|
|
1119
|
+
pkgJson.dependencies[pkgName] = `file:${tgz}`;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
fs2.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2) + "\n");
|
|
1124
|
+
}
|
|
1125
|
+
report("Creating SDK configuration\u2026");
|
|
1126
|
+
const staticDir = ensureStaticDir(targetDir);
|
|
1127
|
+
const sdkConfigPath = path2.join(staticDir, "sdk-config.json");
|
|
1128
|
+
writeManagedJson(sdkConfigPath, buildSdkConfig(choices), policy, SDK_CONFIG_USER_KEYS);
|
|
1129
|
+
if (staticDir !== targetDir && fs2.existsSync(path2.join(targetDir, "sdk-config.json"))) {
|
|
1130
|
+
report(`\u26A0\uFE0F A sdk-config.json also exists at the project root. The active one is ${sdkConfigPath}.`);
|
|
1131
|
+
}
|
|
1132
|
+
report("Installing dependencies (this may take a minute)\u2026");
|
|
1133
|
+
let installSucceeded = true;
|
|
1134
|
+
try {
|
|
1135
|
+
await runInstall(targetDir);
|
|
1136
|
+
} catch {
|
|
1137
|
+
installSucceeded = false;
|
|
1138
|
+
report(
|
|
1139
|
+
"\u26A0\uFE0F Dependency installation failed. Run your package manager manually, then copy OAuth callback assets (see below)."
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
if (installSucceeded) {
|
|
1143
|
+
report("Copying OAuth callback assets\u2026");
|
|
1144
|
+
const authOAuthDir = path2.join(targetDir, "node_modules", "@pega", "auth", "lib", "oauth-client");
|
|
1145
|
+
if (fs2.existsSync(authOAuthDir)) {
|
|
1146
|
+
const authHtmlSrc = path2.join(authOAuthDir, "authDone.html");
|
|
1147
|
+
const authJsSrc = path2.join(authOAuthDir, "authDone.js");
|
|
1148
|
+
const lockSvgSrc = path2.join(authOAuthDir, "lock-closed-solid.svg");
|
|
1149
|
+
if (fs2.existsSync(authHtmlSrc)) fs2.copyFileSync(authHtmlSrc, path2.join(staticDir, "auth.html"));
|
|
1150
|
+
if (fs2.existsSync(authJsSrc)) fs2.copyFileSync(authJsSrc, path2.join(staticDir, "authDone.js"));
|
|
1151
|
+
if (fs2.existsSync(lockSvgSrc)) fs2.copyFileSync(lockSvgSrc, path2.join(staticDir, "lock-closed-solid.svg"));
|
|
1152
|
+
} else {
|
|
1153
|
+
report(
|
|
1154
|
+
"\u26A0\uFE0F Auth OAuth assets not found after install. Copy auth.html, authDone.js, and lock-closed-solid.svg manually to the served static directory."
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
report("Done!");
|
|
1159
|
+
}
|
|
1160
|
+
function detectExistingProject(dir) {
|
|
1161
|
+
return fs2.existsSync(path2.join(dir, "package.json"));
|
|
1162
|
+
}
|
|
1163
|
+
function resolveStaticDir(targetDir) {
|
|
1164
|
+
const pkgJsonPath = path2.join(targetDir, "package.json");
|
|
1165
|
+
if (fs2.existsSync(pkgJsonPath)) {
|
|
1166
|
+
const pkgJson = JSON.parse(fs2.readFileSync(pkgJsonPath, "utf-8"));
|
|
1167
|
+
const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies };
|
|
1168
|
+
if (allDeps["next"] || allDeps["vite"] || allDeps["react-scripts"]) {
|
|
1169
|
+
return path2.join(targetDir, "public");
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
return targetDir;
|
|
1173
|
+
}
|
|
1174
|
+
function ensureStaticDir(targetDir) {
|
|
1175
|
+
const staticDir = resolveStaticDir(targetDir);
|
|
1176
|
+
fs2.mkdirSync(staticDir, { recursive: true });
|
|
1177
|
+
return staticDir;
|
|
765
1178
|
}
|
|
766
1179
|
function copyDir(src, dest) {
|
|
767
|
-
|
|
768
|
-
for (const entry of
|
|
1180
|
+
fs2.mkdirSync(dest, { recursive: true });
|
|
1181
|
+
for (const entry of fs2.readdirSync(src, { withFileTypes: true })) {
|
|
769
1182
|
if (SKIP_ENTRIES.has(entry.name)) continue;
|
|
770
|
-
const srcPath =
|
|
771
|
-
const destPath =
|
|
1183
|
+
const srcPath = path2.join(src, entry.name);
|
|
1184
|
+
const destPath = path2.join(dest, entry.name);
|
|
772
1185
|
if (entry.isDirectory()) {
|
|
773
1186
|
copyDir(srcPath, destPath);
|
|
774
1187
|
} else {
|
|
775
|
-
|
|
1188
|
+
fs2.copyFileSync(srcPath, destPath);
|
|
776
1189
|
}
|
|
777
1190
|
}
|
|
778
1191
|
}
|
|
@@ -792,6 +1205,185 @@ async function main() {
|
|
|
792
1205
|
Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
793
1206
|
process.exit(1);
|
|
794
1207
|
}
|
|
1208
|
+
const cwd = process.cwd();
|
|
1209
|
+
const projectMode = detectExistingProject(cwd) ? "embedded" : "new";
|
|
1210
|
+
if (projectMode === "embedded") {
|
|
1211
|
+
const continueEmbedded = await p.confirm({
|
|
1212
|
+
message: "An existing project was detected in this folder (package.json found). Would you like to continue and integrate the embedded flow into it?",
|
|
1213
|
+
initialValue: true
|
|
1214
|
+
});
|
|
1215
|
+
if (p.isCancel(continueEmbedded) || !continueEmbedded) {
|
|
1216
|
+
p.cancel("Operation cancelled.");
|
|
1217
|
+
process.exit(0);
|
|
1218
|
+
}
|
|
1219
|
+
} else {
|
|
1220
|
+
p.log.info(pc.dim("No existing project detected in this folder \u2014 continuing with the new-project flow."));
|
|
1221
|
+
}
|
|
1222
|
+
if (projectMode === "embedded") {
|
|
1223
|
+
p.log.info(pc.dim("Let's set up Pega embedded flow in your existing project."));
|
|
1224
|
+
const aiAssisted = await p.confirm({
|
|
1225
|
+
message: "Would you like AI assistance to set up the embedded flow?",
|
|
1226
|
+
initialValue: true
|
|
1227
|
+
});
|
|
1228
|
+
if (p.isCancel(aiAssisted)) {
|
|
1229
|
+
p.cancel("Operation cancelled.");
|
|
1230
|
+
process.exit(0);
|
|
1231
|
+
}
|
|
1232
|
+
if (!aiAssisted) {
|
|
1233
|
+
p.log.info("Non-AI embedded flow is still under development. Stay tuned!");
|
|
1234
|
+
p.outro(pc.dim("No changes were made."));
|
|
1235
|
+
process.exit(0);
|
|
1236
|
+
}
|
|
1237
|
+
const embeddedAiTool = await p.select({
|
|
1238
|
+
message: "Which AI coding assistant do you use?",
|
|
1239
|
+
options: [
|
|
1240
|
+
{ value: "copilot", label: "GitHub Copilot" },
|
|
1241
|
+
{ value: "cursor", label: "Cursor" },
|
|
1242
|
+
{ value: "claude-code", label: "Claude Code" }
|
|
1243
|
+
]
|
|
1244
|
+
});
|
|
1245
|
+
if (p.isCancel(embeddedAiTool)) {
|
|
1246
|
+
p.cancel("Operation cancelled.");
|
|
1247
|
+
process.exit(0);
|
|
1248
|
+
}
|
|
1249
|
+
p.log.info(pc.dim("\nNow let's connect to your Pega server."));
|
|
1250
|
+
const serverUrl = await p.text({
|
|
1251
|
+
message: "What is your Pega server URL?",
|
|
1252
|
+
placeholder: "https://your-pega-server.com/prweb",
|
|
1253
|
+
validate(value) {
|
|
1254
|
+
if (!value) return "Server URL is required.";
|
|
1255
|
+
if (!value.startsWith("http")) return "Must be a valid URL starting with http:// or https://";
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
if (p.isCancel(serverUrl)) {
|
|
1259
|
+
p.cancel("Operation cancelled.");
|
|
1260
|
+
process.exit(0);
|
|
1261
|
+
}
|
|
1262
|
+
const appAlias = await p.text({
|
|
1263
|
+
message: "What is your Pega application alias?",
|
|
1264
|
+
placeholder: "MyApp",
|
|
1265
|
+
validate(value) {
|
|
1266
|
+
if (!value) return "Application alias is required.";
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
if (p.isCancel(appAlias)) {
|
|
1270
|
+
p.cancel("Operation cancelled.");
|
|
1271
|
+
process.exit(0);
|
|
1272
|
+
}
|
|
1273
|
+
const clientId = await p.text({
|
|
1274
|
+
message: "What is the OAuth Client ID for your app?",
|
|
1275
|
+
placeholder: "Your OAuth 2.0 client identifier",
|
|
1276
|
+
validate(value) {
|
|
1277
|
+
if (!value) return "Client ID is required for authentication.";
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
if (p.isCancel(clientId)) {
|
|
1281
|
+
p.cancel("Operation cancelled.");
|
|
1282
|
+
process.exit(0);
|
|
1283
|
+
}
|
|
1284
|
+
const userIdentifier = await p.text({
|
|
1285
|
+
message: "What is the operator ID for the embedded session?",
|
|
1286
|
+
placeholder: "user@yourapp",
|
|
1287
|
+
validate(value) {
|
|
1288
|
+
if (!value) return "Operator ID is required.";
|
|
1289
|
+
}
|
|
1290
|
+
});
|
|
1291
|
+
if (p.isCancel(userIdentifier)) {
|
|
1292
|
+
p.cancel("Operation cancelled.");
|
|
1293
|
+
process.exit(0);
|
|
1294
|
+
}
|
|
1295
|
+
const embeddedTargetDir = cwd;
|
|
1296
|
+
p.note(
|
|
1297
|
+
[
|
|
1298
|
+
`${pc.bold("Mode")}: Embed Pega flow`,
|
|
1299
|
+
`${pc.bold("Directory")}: ${embeddedTargetDir}`,
|
|
1300
|
+
`${pc.bold("AI Tool")}: ${embeddedAiTool}`,
|
|
1301
|
+
`${pc.bold("Server")}: ${serverUrl}`,
|
|
1302
|
+
`${pc.bold("App Alias")}: ${appAlias}`,
|
|
1303
|
+
`${pc.bold("Client ID")}: ${clientId}`,
|
|
1304
|
+
`${pc.bold("Operator")}: ${userIdentifier}`
|
|
1305
|
+
].join("\n"),
|
|
1306
|
+
"Configuration"
|
|
1307
|
+
);
|
|
1308
|
+
const embeddedConfirmed = await p.confirm({
|
|
1309
|
+
message: "Looks good? Let's set it up.",
|
|
1310
|
+
initialValue: true
|
|
1311
|
+
});
|
|
1312
|
+
if (p.isCancel(embeddedConfirmed) || !embeddedConfirmed) {
|
|
1313
|
+
p.cancel("Operation cancelled.");
|
|
1314
|
+
process.exit(0);
|
|
1315
|
+
}
|
|
1316
|
+
const embeddedChoices = {
|
|
1317
|
+
aiTool: embeddedAiTool,
|
|
1318
|
+
serverUrl,
|
|
1319
|
+
appAlias,
|
|
1320
|
+
clientId,
|
|
1321
|
+
userIdentifier
|
|
1322
|
+
};
|
|
1323
|
+
let conflicts = [];
|
|
1324
|
+
try {
|
|
1325
|
+
conflicts = collectEmbeddedConflicts(embeddedTargetDir, embeddedChoices);
|
|
1326
|
+
} catch (err) {
|
|
1327
|
+
p.log.error(String(err));
|
|
1328
|
+
process.exit(1);
|
|
1329
|
+
}
|
|
1330
|
+
if (conflicts.length > 0) {
|
|
1331
|
+
const MAX_LISTED = 15;
|
|
1332
|
+
const listed = conflicts.slice(0, MAX_LISTED);
|
|
1333
|
+
const remaining = conflicts.length - listed.length;
|
|
1334
|
+
p.note(
|
|
1335
|
+
[...listed, ...remaining > 0 ? [pc.dim(`\u2026and ${remaining} more`)] : []].join("\n"),
|
|
1336
|
+
`Found ${conflicts.length} existing file(s)`
|
|
1337
|
+
);
|
|
1338
|
+
const policyResult = await p.select({
|
|
1339
|
+
message: "These files already exist. How should we handle them?",
|
|
1340
|
+
options: [
|
|
1341
|
+
{
|
|
1342
|
+
value: "merge",
|
|
1343
|
+
label: "Merge",
|
|
1344
|
+
hint: "keep your content and add Pega content in a marked block"
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
value: "override",
|
|
1348
|
+
label: "Override",
|
|
1349
|
+
hint: "replace these files with the Pega versions"
|
|
1350
|
+
}
|
|
1351
|
+
],
|
|
1352
|
+
initialValue: "merge"
|
|
1353
|
+
});
|
|
1354
|
+
if (p.isCancel(policyResult)) {
|
|
1355
|
+
p.cancel("Operation cancelled.");
|
|
1356
|
+
process.exit(0);
|
|
1357
|
+
}
|
|
1358
|
+
embeddedChoices.conflictPolicy = policyResult;
|
|
1359
|
+
}
|
|
1360
|
+
const spinner3 = p.spinner();
|
|
1361
|
+
spinner3.start("Setting up embedded flow\u2026");
|
|
1362
|
+
try {
|
|
1363
|
+
await scaffoldEmbedded(embeddedChoices, embeddedTargetDir, (message) => {
|
|
1364
|
+
spinner3.message(message);
|
|
1365
|
+
});
|
|
1366
|
+
spinner3.stop("Embedded flow ready!");
|
|
1367
|
+
} catch (err) {
|
|
1368
|
+
spinner3.stop("Failed to set up embedded flow.");
|
|
1369
|
+
p.log.error(String(err));
|
|
1370
|
+
process.exit(1);
|
|
1371
|
+
}
|
|
1372
|
+
p.note(
|
|
1373
|
+
[
|
|
1374
|
+
"# Open your AI coding assistant and say:",
|
|
1375
|
+
'"Embed case [YOUR-CASE-TYPE] on click of [your button]"',
|
|
1376
|
+
"",
|
|
1377
|
+
"# The assistant will:",
|
|
1378
|
+
"1. Scan your codebase to understand your design system",
|
|
1379
|
+
"2. Generate Pega components matching your app's style",
|
|
1380
|
+
"3. Wire everything together so the case flow just works"
|
|
1381
|
+
].join("\n"),
|
|
1382
|
+
"Next Steps"
|
|
1383
|
+
);
|
|
1384
|
+
p.outro(pc.green("You're all set! Open your AI assistant and start embedding."));
|
|
1385
|
+
process.exit(0);
|
|
1386
|
+
}
|
|
795
1387
|
const nameResult = await p.text({
|
|
796
1388
|
message: "What is the name of your project?",
|
|
797
1389
|
placeholder: "my-pega-app",
|
|
@@ -848,12 +1440,12 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
848
1440
|
{
|
|
849
1441
|
value: "react",
|
|
850
1442
|
label: "React",
|
|
851
|
-
hint: "Vite + React
|
|
1443
|
+
hint: "Vite + React 19 + @pega/sdk-react"
|
|
852
1444
|
},
|
|
853
1445
|
{
|
|
854
1446
|
value: "angular",
|
|
855
1447
|
label: "Angular",
|
|
856
|
-
hint: "Angular
|
|
1448
|
+
hint: "Angular 21 + @pega/sdk-angular"
|
|
857
1449
|
},
|
|
858
1450
|
{
|
|
859
1451
|
value: "web-components",
|
|
@@ -871,54 +1463,61 @@ Usage: ${pc.cyan("npx @pega/sdk init")}`);
|
|
|
871
1463
|
p.cancel("Operation cancelled.");
|
|
872
1464
|
process.exit(0);
|
|
873
1465
|
}
|
|
874
|
-
|
|
875
|
-
message: "Include starter component implementations? (scaffolds working component files you can customize)",
|
|
876
|
-
initialValue: true
|
|
877
|
-
});
|
|
878
|
-
if (p.isCancel(includeTemplates)) {
|
|
879
|
-
p.cancel("Operation cancelled.");
|
|
880
|
-
process.exit(0);
|
|
881
|
-
}
|
|
1466
|
+
let includeTemplates;
|
|
882
1467
|
let componentCategories = [];
|
|
883
|
-
if (
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
hint: "TextInput, Dropdown, Checkbox, Date, etc."
|
|
891
|
-
},
|
|
892
|
-
{
|
|
893
|
-
value: "templates",
|
|
894
|
-
label: "Templates",
|
|
895
|
-
hint: "OneColumn, TwoColumn, CaseView, DefaultForm, etc."
|
|
896
|
-
},
|
|
897
|
-
{
|
|
898
|
-
value: "widgets",
|
|
899
|
-
label: "Widgets",
|
|
900
|
-
hint: "Attachment, CaseHistory, ToDo, etc."
|
|
901
|
-
},
|
|
902
|
-
{
|
|
903
|
-
value: "infra",
|
|
904
|
-
label: "Infrastructure",
|
|
905
|
-
hint: "NavBar, ActionButtons, Stages, etc."
|
|
906
|
-
},
|
|
907
|
-
{
|
|
908
|
-
value: "designSystemExtension",
|
|
909
|
-
label: "Design System Extensions",
|
|
910
|
-
hint: "AlertBanner, FieldGroup, Pulse, etc."
|
|
911
|
-
}
|
|
912
|
-
],
|
|
913
|
-
required: true
|
|
1468
|
+
if (framework === "react-native") {
|
|
1469
|
+
includeTemplates = true;
|
|
1470
|
+
componentCategories = ["fields", "templates", "infra"];
|
|
1471
|
+
} else {
|
|
1472
|
+
const includeTemplatesResult = await p.confirm({
|
|
1473
|
+
message: "Include starter component implementations? (scaffolds working component files you can customize)",
|
|
1474
|
+
initialValue: true
|
|
914
1475
|
});
|
|
915
|
-
if (p.isCancel(
|
|
1476
|
+
if (p.isCancel(includeTemplatesResult)) {
|
|
916
1477
|
p.cancel("Operation cancelled.");
|
|
917
1478
|
process.exit(0);
|
|
918
1479
|
}
|
|
919
|
-
|
|
1480
|
+
includeTemplates = includeTemplatesResult;
|
|
1481
|
+
if (includeTemplates) {
|
|
1482
|
+
const categories = await p.multiselect({
|
|
1483
|
+
message: "Which component types do you want scaffolded?",
|
|
1484
|
+
options: [
|
|
1485
|
+
{
|
|
1486
|
+
value: "fields",
|
|
1487
|
+
label: "Fields",
|
|
1488
|
+
hint: "TextInput, Dropdown, Checkbox, Date, etc."
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
value: "templates",
|
|
1492
|
+
label: "Templates",
|
|
1493
|
+
hint: "OneColumn, TwoColumn, CaseView, DefaultForm, etc."
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
value: "widgets",
|
|
1497
|
+
label: "Widgets",
|
|
1498
|
+
hint: "Attachment, CaseHistory, ToDo, etc."
|
|
1499
|
+
},
|
|
1500
|
+
{
|
|
1501
|
+
value: "infra",
|
|
1502
|
+
label: "Infrastructure",
|
|
1503
|
+
hint: "NavBar, ActionButtons, Stages, etc."
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
value: "designSystemExtension",
|
|
1507
|
+
label: "Design System Extensions",
|
|
1508
|
+
hint: "AlertBanner, FieldGroup, Pulse, etc."
|
|
1509
|
+
}
|
|
1510
|
+
],
|
|
1511
|
+
required: true
|
|
1512
|
+
});
|
|
1513
|
+
if (p.isCancel(categories)) {
|
|
1514
|
+
p.cancel("Operation cancelled.");
|
|
1515
|
+
process.exit(0);
|
|
1516
|
+
}
|
|
1517
|
+
componentCategories = categories;
|
|
1518
|
+
}
|
|
920
1519
|
}
|
|
921
|
-
const targetDir =
|
|
1520
|
+
const targetDir = path3.resolve(process.cwd(), projectName);
|
|
922
1521
|
p.note(
|
|
923
1522
|
[
|
|
924
1523
|
`${pc.bold("Project")}: ${projectName}`,
|