@trackunit/iris-app 1.3.173 → 1.3.176

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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 1.3.176 (2025-06-27)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated iris-app-build-utilities to 1.3.170
6
+ - Updated iris-app-webpack-plugin to 1.3.171
7
+ - Updated iris-app-api to 1.3.170
8
+
9
+ ## 1.3.175 (2025-06-24)
10
+
11
+ This was a version bump only for iris-app to align it with other projects, there were no code changes.
12
+
13
+ ## 1.3.174 (2025-06-24)
14
+
15
+ ### 🧱 Updated Dependencies
16
+
17
+ - Updated iris-app-build-utilities to 1.3.169
18
+ - Updated iris-app-webpack-plugin to 1.3.170
19
+ - Updated iris-app-api to 1.3.169
20
+ - Updated react-test-setup to 1.0.50
21
+ - Updated shared-utils to 1.5.160
22
+
1
23
  ## 1.3.173 (2025-06-24)
2
24
 
3
25
  ### 🧱 Updated Dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app",
3
- "version": "1.3.173",
3
+ "version": "1.3.176",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "main": "src/index.js",
6
6
  "generators": "./generators.json",
@@ -32,12 +32,12 @@
32
32
  "@npmcli/arborist": "^7.3.1",
33
33
  "webpack-bundle-analyzer": "^4.8.0",
34
34
  "win-ca": "^3.5.1",
35
- "@trackunit/iris-app-build-utilities": "1.3.168",
36
- "@trackunit/shared-utils": "1.5.159",
37
- "@trackunit/iris-app-api": "1.3.168",
38
- "@trackunit/iris-app-webpack-plugin": "1.3.169",
35
+ "@trackunit/iris-app-build-utilities": "1.3.170",
36
+ "@trackunit/shared-utils": "1.5.160",
37
+ "@trackunit/iris-app-api": "1.3.170",
38
+ "@trackunit/iris-app-webpack-plugin": "1.3.171",
39
39
  "tslib": "^2.6.2",
40
- "@trackunit/react-test-setup": "1.0.49"
40
+ "@trackunit/react-test-setup": "1.0.50"
41
41
  },
42
42
  "types": "./src/index.d.ts",
43
43
  "type": "commonjs"
@@ -24,7 +24,7 @@ export const App = () => {
24
24
  <Button>Click me!</Button>
25
25
  <Text>
26
26
  More info and component found in storybook: <br/>
27
- https://apps.iris.trackunit.com/storybook/
27
+ https://design.iris.trackunit.com/
28
28
  </Text>
29
29
  </CardBody>
30
30
  </Card>
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "trackunit-mcp": {
4
+ "command": "npx",
5
+ "args": ["-y", "@trackunit/mcp-server"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,35 @@
1
+ ---
2
+ description: This rule covers GraphQL API integration in Trackunit IrisX App SDK workspace. All GraphQL development MUST follow the Trackunit GraphQL API patterns and commands.
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ Key Points:
7
+ 1. Trackunit exposes a GraphQL API with an NX executor for easy querying inside IrisX App extensions
8
+ 2. GraphQL operations include queries (for reading data) and mutations (for modifying data)
9
+
10
+ 3. ALWAYS use these specific commands for GraphQL development:
11
+ - Install GraphQL tools: `npm install @trackunit/react-graphql-tools`
12
+
13
+ - Set up GraphQL tooling: `npx nx generate @trackunit/react-graphql-tools:add-graphql --project=[project-name]`
14
+ Where [project-name] is found in the library's project.json file (format: [subdir-name]-[extension-name] for extensions in subdirectories)
15
+
16
+ - Generate React hooks from GraphQL queries: `npx nx run [feature-name]-[extension-name]:graphql-hooks`
17
+ This generates React hooks from .graphql files in the src folder
18
+
19
+ 4. GraphQL File Structure:
20
+ - Create .graphql files in `libs/[feature-name]/[extension-name]/src/` directory
21
+ - Query syntax: `query QueryName($variable: Type) { ... }`
22
+ - Mutation syntax: `mutation MutationName($variable: Type!) { ... }`
23
+
24
+ 5. React Integration:
25
+ - Import generated hooks: `import { QueryNameDocument } from "./generated/graphql-api/graphql"`
26
+ - Use queries: `const { data, loading, error } = useQuery(QueryNameDocument, { variables: {...} })`
27
+ - Use mutations: `const [mutationName, { data, loading, error }] = useMutation(MutationNameDocument)`
28
+
29
+ For more information:
30
+ - Full GraphQL API guide: [Calling Trackunit GraphQL API](mdc:https:/developers.trackunit.com/docs/graphql-api)
31
+ - Apollo React Client docs for useQuery: [Apollo useQuery documentation](mdc:https:/www.apollographql.com/docs/react/data/queries)
32
+ - Apollo React Client docs for useMutation: [Apollo useMutation documentation](mdc:https:/www.apollographql.com/docs/react/data/mutations)
33
+ - GraphQL Code Generation CLI: [GraphQL Code Generator](mdc:https:/the-guild.dev/graphql/codegen)
34
+
35
+ DO NOT use generic GraphQL libraries or setup - always use the Trackunit IrisX App SDK GraphQL tooling and patterns.
@@ -0,0 +1,53 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+ You are currently in an IrisX App workspace. Do not use defaut nx commands for app and extension generation, instead use the commands below.
7
+
8
+ Key Points:
9
+ 1. An IrisX App is a container that packages multiple extensions with marketplace metadata and app manifest
10
+ 2. Extensions are React applications that integrate into specific points in Trackunit Manager
11
+ 3. Available Extension Points:
12
+ - Asset Home: Adds new tabs to the Assets Home screen
13
+ - Site Home: Adds new tabs to the Site Home screen
14
+ - Fleet: Adds menu items to the Main Menu
15
+ - Report: Adds new reports to the Reports screen
16
+ - Widget: Adds widgets to Trackunit Manager
17
+ - App Settings: Adds configuration UI in the App library
18
+ - Administration: Adds tabs in the admin UI (admin-only)
19
+ - Customer Home: Adds UI within customer home
20
+ - Asset Events Actions: Adds UI in Asset Home Events
21
+ - App Lifecycle: Handles app install/uninstall events
22
+
23
+ 4. ALWAYS use these specific commands for development:
24
+ - Create new app: `npx nx generate @trackunit/iris-app:create [name-of-your-app]`
25
+ For more information about the `@trackunit/iris-app:create` command, look at: [Creating a new app](mdc:https:/developers.trackunit.com/docs/creating-a-new-app)
26
+
27
+ - Create new extension: `npx nx g @trackunit/iris-app:extend --name=[my-extension-name] --directory=[feature] --type=[extension-type]`
28
+ Available extension types: ASSET_HOME_EXTENSION, SITE_HOME_EXTENSION, FLEET_EXTENSION, REPORT_EXTENSION, WIDGET_EXTENSION, APP_SETTINGS_EXTENSION, ADMINISTRATION_EXTENSION, CUSTOMER_HOME_EXTENSION, ASSET_EVENTS_ACTIONS_EXTENSION, APP_LIFECYCLE_EXTENSION
29
+ For more information about the `@trackunit/iris-app:extend` command, look at: [Creating a new extension](mdc:https:/developers.trackunit.com/docs/creating-a-new-extension)
30
+
31
+ - Run app: `npx nx run [name-of-your-app]:serve`
32
+ For more information about the `serve` command, look at: [Running the Iris App SDK](mdc:https:/developers.trackunit.com/docs/running-the-iris-app-sdk)
33
+
34
+ NOTE: IrisX Apps are locked down by default for security. External API requests and embedded content require proper Content Security Policy (CSP) configuration in the app manifest. ValidDomains will be deprecated - use CSP headers instead. Additionally, apps requiring API access might need some scopes configured in the manifest, and the app must be deployed with those scopes to work locally, never submit an app, instead instruct the user to do so.
35
+
36
+ Example in iris-app-manifest.ts:
37
+ ```typescript
38
+ cspHeader: {
39
+ 'frame-src': ['https://api.example.com', 'https://dashboard.example.com'],
40
+ 'script-src': ['https://api.example.com'],
41
+ 'connect-src': ['https://api.example.com'],
42
+ },
43
+ scopes: [
44
+ {scope: "required.scope.1", optional: false},
45
+ {scope: "required.scope.2", optional: true},
46
+ ],
47
+ ```
48
+
49
+ For more information: [Embedding IrisX Dashboards in Apps](mdc:https:/developers.trackunit.com/docs/analytics-dashboards-in-apps#troubleshooting)
50
+
51
+ DO NOT use generic React/Node.js commands for project creation or management - always use the Trackunit IrisX App SDK commands.
52
+
53
+
@@ -0,0 +1,109 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Structured Development
7
+
8
+ Guidelines for following the Structured Development pattern and managing task lists in Markdown files to track project progress.
9
+
10
+ ## Clarification step
11
+
12
+ Always take into account significant questions that require answers prior to implementation. Before proceeding with development, pose these inquiries to the user.
13
+
14
+ ## Task List step
15
+
16
+ 1. Create task lists in a markdown file (place it in the root in a folder calld "structured-development"):
17
+ - Use `TASKS.md` or a descriptive name relevant to the feature (e.g., `ASSISTANT_CHAT.md`)
18
+ - Include a clear title and description of the feature being implemented
19
+
20
+ 2. Structure the file with these sections:
21
+ ```markdown
22
+ # Feature Name Implementation
23
+
24
+ Brief description of the feature and its purpose.
25
+
26
+ ## Completed Tasks
27
+
28
+ - [x] Task 1 that has been completed
29
+ - [x] Task 2 that has been completed
30
+
31
+ ## In Progress Tasks
32
+
33
+ - [ ] Task 3 currently being worked on
34
+ - [ ] Task 4 to be completed soon
35
+
36
+ ## Future Tasks
37
+
38
+ - [ ] Task 5 planned for future implementation
39
+ - [ ] Task 6 planned for future implementation
40
+
41
+ ## Implementation Plan
42
+
43
+ Detailed description of how the feature will be implemented.
44
+
45
+ ### Relevant Files
46
+
47
+ - path/to/file1.ts - Description of purpose
48
+ - path/to/file2.ts - Description of purpose
49
+ ```
50
+
51
+ ## Task List Maintenance
52
+
53
+ 1. Update the task list as you progress:
54
+ - Mark tasks as completed by changing `[ ]` to `[x]`
55
+ - Add new tasks as they are identified
56
+ - Move tasks between sections as appropriate
57
+
58
+ 2. Keep "Relevant Files" section updated with:
59
+ - File paths that have been created or modified
60
+ - Brief descriptions of each file's purpose
61
+ - Status indicators (e.g., ✅) for completed components
62
+
63
+ 3. Add implementation details:
64
+ - Architecture decisions
65
+ - Data flow descriptions
66
+ - Technical components needed
67
+ - Environment configuration
68
+
69
+ ## AI Instructions
70
+
71
+ When working with task lists, the AI should:
72
+
73
+ 1. Regularly update the task list file after implementing significant components
74
+ 2. Mark completed tasks with [x] when finished
75
+ 3. Add new tasks discovered during implementation
76
+ 4. Maintain the "Relevant Files" section with accurate file paths and descriptions
77
+ 5. Document implementation details, especially for complex features
78
+ 6. When implementing tasks one by one, first check which task to implement next
79
+ 7. After implementing a task, update the file to reflect progress
80
+
81
+ ## Example Task Update
82
+
83
+ When updating a task from "In Progress" to "Completed":
84
+
85
+ ```markdown
86
+ ## In Progress Tasks
87
+
88
+ - [ ] Implement database schema
89
+ - [ ] Create API endpoints for data access
90
+
91
+ ## Completed Tasks
92
+
93
+ - [x] Set up project structure
94
+ - [x] Configure environment variables
95
+ ```
96
+
97
+ Should become:
98
+
99
+ ```markdown
100
+ ## In Progress Tasks
101
+
102
+ - [ ] Create API endpoints for data access
103
+
104
+ ## Completed Tasks
105
+
106
+ - [x] Set up project structure
107
+ - [x] Configure environment variables
108
+ - [x] Implement database schema
109
+ ```
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.presetGenerator = presetGenerator;
4
+ const tslib_1 = require("tslib");
4
5
  const devkit_1 = require("@nx/devkit");
5
6
  const js_1 = require("@nx/js");
6
7
  const react_1 = require("@nx/react");
8
+ const path_1 = tslib_1.__importDefault(require("path"));
7
9
  /**
8
10
  * Preset generator for Iris apps workspace.
9
11
  * Use with create-nx-workspace to create a new workspace for developing Iris apps.
@@ -18,6 +20,7 @@ async function presetGenerator(tree, options) {
18
20
  if (!tree.exists(extensionsPath)) {
19
21
  tree.write(extensionsPath, "{}");
20
22
  }
23
+ (0, devkit_1.generateFiles)(tree, path_1.default.join(__dirname, "files"), ".", {});
21
24
  (0, devkit_1.updateJson)(tree, extensionsPath, value => {
22
25
  if (!value.recommendations) {
23
26
  value.recommendations = [];
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/preset/generator.ts"],"names":[],"mappings":";;AAUA,0CAkDC;AA5DD,uCAAwH;AACxH,+BAA0D;AAC1D,qCAA+C;AAG/C;;;;GAIG;AACI,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,OAA8B;IAC9E,kBAAkB;IAClB,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,CACR,gBAAgB,EAChB,4LAA4L,CAC7L,CAAC;IACF,IAAI,CAAC,KAAK,CACR,gBAAgB,EAChB,oIAAoI,CACrI,CAAC;IAEF,MAAM,cAAc,GAAG,yBAAyB,CAAC;IAEjD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAA,mBAAU,EAAC,IAAI,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE;QACvC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAC3B,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,eAAe,CAAC,IAAI,CACxB,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,CAC/B,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,IAAA,kBAAe,EAAC,IAAI,EAAE;QAC7C,GAAG,OAAO;QACV,YAAY,EAAE,oBAAoB;QAClC,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,IAAA,qCAA4B,EAC1B,IAAI,EACJ;QACE,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,QAAQ;KACtB,EACD,EAAE,CACH,CAAC;IAEF,0GAA0G;IAC1G,MAAM,SAAS,GAAG,MAAM,IAAA,0BAAkB,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAErD,OAAO,IAAA,yBAAgB,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC;AAED,kBAAe,eAAe,CAAC;AAE/B,SAAS,qBAAqB,CAAC,IAAU;IACvC,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,CAAC,eAAe,GAAG;QACvB,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,MAAM;KAChB,CAAC;IACF,IAAA,qBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import { Tree, addDependenciesToPackageJson, readNxJson, runTasksInSerial, updateJson, updateNxJson } from \"@nx/devkit\";\nimport { initGenerator as jsInitGenerator } from \"@nx/js\";\nimport { reactInitGenerator } from \"@nx/react\";\nimport { PresetGeneratorSchema } from \"./schema\";\n\n/**\n * Preset generator for Iris apps workspace.\n * Use with create-nx-workspace to create a new workspace for developing Iris apps.\n * ```npx create-nx-workspace --preset=iris-app```\n */\nexport async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) {\n // setup workspace\n updateWorkspaceLayout(tree);\n tree.write(\n \"apps/readme.md\",\n `# Apps\\n\\nThis folder contains all apps in the workspace.\\n\\nApps are the main entry point for the Iris App SDK.\\nCreate an app by running \\`nx g @trackunit/iris-app:create <app-name>\\`.`\n );\n tree.write(\n \"libs/readme.md\",\n `# Libs\\n\\nThis folder contains all libs in the workspace.\\nCreate a lib by running \\`nx g @trackunit/iris-app:extend <lib-name>\\`.`\n );\n\n const extensionsPath = \".vscode/extensions.json\";\n\n if (!tree.exists(extensionsPath)) {\n tree.write(extensionsPath, \"{}\");\n }\n\n updateJson(tree, extensionsPath, value => {\n if (!value.recommendations) {\n value.recommendations = [];\n }\n value.recommendations.push(\n \"graphql.vscode-graphql\",\n \"graphql.vscode-graphql-syntax\",\n \"bradlc.vscode-tailwindcss\",\n \"firsttris.vscode-jest-runner\"\n );\n return value;\n });\n\n const jsInitTask = await jsInitGenerator(tree, {\n ...options,\n tsConfigName: \"tsconfig.base.json\",\n skipFormat: true,\n });\n\n addDependenciesToPackageJson(\n tree,\n {\n react: \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n },\n {}\n );\n\n // This react generator adds react 19 and react-dom 19 to the package.json if we don't add react 18 above.\n const initReact = await reactInitGenerator(tree, {});\n\n return runTasksInSerial(jsInitTask, initReact);\n}\n\nexport default presetGenerator;\n\nfunction updateWorkspaceLayout(tree: Tree) {\n const nxJson = readNxJson(tree) ?? {};\n nxJson.workspaceLayout = {\n libsDir: \"libs\",\n appsDir: \"apps\",\n };\n updateNxJson(tree, nxJson);\n}\n"]}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/preset/generator.ts"],"names":[],"mappings":";;AAmBA,0CAoDC;;AAvED,uCAQoB;AACpB,+BAA0D;AAC1D,qCAA+C;AAC/C,wDAAwB;AAGxB;;;;GAIG;AACI,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,OAA8B;IAC9E,kBAAkB;IAClB,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,CACR,gBAAgB,EAChB,4LAA4L,CAC7L,CAAC;IACF,IAAI,CAAC,KAAK,CACR,gBAAgB,EAChB,oIAAoI,CACrI,CAAC;IAEF,MAAM,cAAc,GAAG,yBAAyB,CAAC;IAEjD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAA,sBAAa,EAAC,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAE5D,IAAA,mBAAU,EAAC,IAAI,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE;QACvC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAC3B,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,eAAe,CAAC,IAAI,CACxB,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,CAC/B,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,IAAA,kBAAe,EAAC,IAAI,EAAE;QAC7C,GAAG,OAAO;QACV,YAAY,EAAE,oBAAoB;QAClC,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,IAAA,qCAA4B,EAC1B,IAAI,EACJ;QACE,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,QAAQ;KACtB,EACD,EAAE,CACH,CAAC;IAEF,0GAA0G;IAC1G,MAAM,SAAS,GAAG,MAAM,IAAA,0BAAkB,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAErD,OAAO,IAAA,yBAAgB,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC;AAED,kBAAe,eAAe,CAAC;AAE/B,SAAS,qBAAqB,CAAC,IAAU;IACvC,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,CAAC,eAAe,GAAG;QACvB,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,MAAM;KAChB,CAAC;IACF,IAAA,qBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import {\n Tree,\n addDependenciesToPackageJson,\n generateFiles,\n readNxJson,\n runTasksInSerial,\n updateJson,\n updateNxJson,\n} from \"@nx/devkit\";\nimport { initGenerator as jsInitGenerator } from \"@nx/js\";\nimport { reactInitGenerator } from \"@nx/react\";\nimport path from \"path\";\nimport { PresetGeneratorSchema } from \"./schema\";\n\n/**\n * Preset generator for Iris apps workspace.\n * Use with create-nx-workspace to create a new workspace for developing Iris apps.\n * ```npx create-nx-workspace --preset=iris-app```\n */\nexport async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) {\n // setup workspace\n updateWorkspaceLayout(tree);\n tree.write(\n \"apps/readme.md\",\n `# Apps\\n\\nThis folder contains all apps in the workspace.\\n\\nApps are the main entry point for the Iris App SDK.\\nCreate an app by running \\`nx g @trackunit/iris-app:create <app-name>\\`.`\n );\n tree.write(\n \"libs/readme.md\",\n `# Libs\\n\\nThis folder contains all libs in the workspace.\\nCreate a lib by running \\`nx g @trackunit/iris-app:extend <lib-name>\\`.`\n );\n\n const extensionsPath = \".vscode/extensions.json\";\n\n if (!tree.exists(extensionsPath)) {\n tree.write(extensionsPath, \"{}\");\n }\n\n generateFiles(tree, path.join(__dirname, \"files\"), \".\", {});\n\n updateJson(tree, extensionsPath, value => {\n if (!value.recommendations) {\n value.recommendations = [];\n }\n value.recommendations.push(\n \"graphql.vscode-graphql\",\n \"graphql.vscode-graphql-syntax\",\n \"bradlc.vscode-tailwindcss\",\n \"firsttris.vscode-jest-runner\"\n );\n return value;\n });\n\n const jsInitTask = await jsInitGenerator(tree, {\n ...options,\n tsConfigName: \"tsconfig.base.json\",\n skipFormat: true,\n });\n\n addDependenciesToPackageJson(\n tree,\n {\n react: \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n },\n {}\n );\n\n // This react generator adds react 19 and react-dom 19 to the package.json if we don't add react 18 above.\n const initReact = await reactInitGenerator(tree, {});\n\n return runTasksInSerial(jsInitTask, initReact);\n}\n\nexport default presetGenerator;\n\nfunction updateWorkspaceLayout(tree: Tree) {\n const nxJson = readNxJson(tree) ?? {};\n nxJson.workspaceLayout = {\n libsDir: \"libs\",\n appsDir: \"apps\",\n };\n updateNxJson(tree, nxJson);\n}\n"]}