@trackunit/iris-app 1.12.9 → 1.12.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +2 -2
  3. package/src/executors/submit/executor.js.map +1 -0
  4. package/src/executors/unpublish/executor.js.map +1 -0
  5. package/src/executors/utils/authentication.js.map +1 -0
  6. package/src/executors/utils/irisAppServerSettings.js.map +1 -0
  7. package/src/executors/utils/src/index.js.map +1 -0
  8. package/src/generators/ai-agent-sync/README.md +5 -2
  9. package/src/generators/ai-agent-sync/generator.d.ts +1 -1
  10. package/src/generators/ai-agent-sync/generator.js +29 -4
  11. package/src/generators/ai-agent-sync/generator.js.map +1 -0
  12. package/src/generators/create/generator.js.map +1 -0
  13. package/src/generators/extend/dependencies.js.map +1 -0
  14. package/src/generators/extend/generator.js.map +1 -0
  15. package/src/generators/preset/files/.agents/skills/browser-testing/SKILL.md +193 -0
  16. package/src/generators/preset/files/.agents/skills/create-app/SKILL.md +191 -0
  17. package/src/generators/preset/files/.agents/skills/customfields/SKILL.md +239 -0
  18. package/src/generators/preset/files/.agents/skills/graphql/SKILL.md +147 -0
  19. package/src/generators/preset/files/.agents/skills/graphql-timeseries/SKILL.md +193 -0
  20. package/src/generators/preset/files/.agents/skills/irisx-app-sdk/SKILL.md +116 -0
  21. package/src/generators/preset/files/.agents/skills/react-core-hooks/SKILL.md +215 -0
  22. package/src/generators/preset/files/.agents/skills/tables-and-sorting/SKILL.md +122 -0
  23. package/src/generators/preset/files/.agents/skills/widget-extensions/SKILL.md +245 -0
  24. package/src/generators/preset/files/.cursor/mcp.json +4 -0
  25. package/src/generators/preset/generator.js.map +1 -0
  26. package/src/generators/preset/root-files/AGENTS.md +43 -0
  27. package/src/generators/preset/root-files/CLAUDE.md +17 -0
  28. package/src/index.js.map +1 -0
  29. package/src/utils/ast/astUtils.js.map +1 -0
  30. package/src/utils/fileUpdater.js.map +1 -0
  31. package/src/generators/preset/files/.cursor/commands/create-app.md +0 -226
  32. package/src/generators/preset/files/.cursor/rules/browser-irisx-development.mdc +0 -246
  33. package/src/generators/preset/files/.cursor/rules/graphql-timeseries.md +0 -260
  34. package/src/generators/preset/files/.cursor/rules/irisx-app-sdk-customfields.md +0 -305
  35. package/src/generators/preset/files/.cursor/rules/irisx-app-sdk-graphql.md +0 -30
  36. package/src/generators/preset/files/.cursor/rules/irisx-app-sdk.mdc +0 -82
  37. package/src/generators/preset/files/.cursor/rules/react-core-hooks.md +0 -155
  38. package/src/generators/preset/files/.cursor/rules/rules-index.mdc +0 -10
  39. package/src/generators/preset/files/.cursor/rules/structured-development.mdc +0 -86
  40. package/src/generators/preset/files/.cursor/rules/tables-and-sorting.mdc +0 -126
  41. package/src/generators/preset/files/.cursor/rules/widget-extensions.md +0 -323
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 1.12.11 (2026-03-06)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated iris-app-build-utilities to 1.12.64
6
+ - Updated iris-app-api to 1.14.58
7
+
8
+ ## 1.12.10 (2026-03-06)
9
+
10
+ ### 🩹 Fixes
11
+
12
+ - address PR review - chrome-devtools MCP, useWidgetConfig consistency ([de581c854a5](https://github.com/Trackunit/manager/commit/de581c854a5))
13
+ - clean up old .cursor/rules and .cursor/commands files during ai-agent-sync ([e7abc4294ab](https://github.com/Trackunit/manager/commit/e7abc4294ab))
14
+
15
+ ### ❤️ Thank You
16
+
17
+ - Cursor Agent @cursoragent
18
+ - Kasper Laursen @ghost-of-kla-trackunit
19
+
1
20
  ## 1.12.9 (2026-03-06)
2
21
 
3
22
  ### 🧱 Updated Dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app",
3
- "version": "1.12.9",
3
+ "version": "1.12.11",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "main": "src/index.js",
6
6
  "generators": "./generators.json",
@@ -26,7 +26,7 @@
26
26
  "@npmcli/arborist": "^9.1.9",
27
27
  "win-ca": "^3.5.1",
28
28
  "@trackunit/shared-utils": "1.13.55",
29
- "@trackunit/iris-app-api": "1.14.57",
29
+ "@trackunit/iris-app-api": "1.14.58",
30
30
  "tslib": "^2.6.2",
31
31
  "@clack/prompts": "^1.0.0",
32
32
  "@npm/types": "^1.0.2"
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/submit/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport { PackageJson } from \"@npm/types\";\nimport { Arborist } from \"@npmcli/arborist\";\nimport { checkPackageVersion } from \"@trackunit/iris-app-build-utilities\";\nimport * as libpub from \"libnpmpublish\";\nimport * as pacote from \"pacote\";\nimport readline from \"readline\";\nimport { inject } from \"win-ca\";\nimport { getAccessToken } from \"../utils/authentication\";\nimport { getSettings, Settings } from \"../utils/irisAppServerSettings\";\nimport { SubmitExecutorSchema } from \"./schema\";\n\n// Inject Windows trusted certificates to support Zscalar and other traffic inspection systems.\ninject(\"+\");\n\ntype SubmitError = Error & { statusCode?: number; code?: string; headers?: { [key: string]: string } };\n\nclass NpmConflictError extends Error {}\nclass NpmGeneralError extends Error {}\nclass ApproveError extends Error {}\n\nfunction sleep(time: number) {\n return new Promise(resolve => setTimeout(resolve, time));\n}\n\n/**\n * Submit the package to the npm registry.\n *\n * @param {SubmitExecutorSchema} options The options provided to the executor.\n * @returns {Promise<{ success: boolean }>} The result of the submit.\n */\nexport default async function runExecutor(options: SubmitExecutorSchema) {\n await checkPackageVersion(true);\n const settings = getSettings();\n const linkToTerms = \"https://trackunit.com/terms-conditions-marketplace/\";\n\n try {\n if (options.devTermsAndConditions?.toLowerCase() !== \"accept\" && !settings.devTermsAccept) {\n // Ask user if they accept dev terms and conditions.\n const userInput = await promptUserForInput(\n `Do you accept the developer terms and conditions? \\n(${linkToTerms}) \\n\\n 📝 Type 'accept' to proceed: `\n );\n if (userInput.toLowerCase() !== \"accept\") {\n throw new Error(`You must accept the developer terms and conditions (${linkToTerms}) to continue.`);\n }\n }\n const tokenData = await getAccessToken(settings.env);\n\n if (\"access_token\" in tokenData) {\n console.log(\"🥳 Successfully authenticated.\");\n\n const manifest = (await pacote.manifest(options.inputPath)) as PackageJson;\n const tarData = await pacote.tarball(options.inputPath, { Arborist });\n\n return await doUploadAppWithRetry(tokenData.access_token, manifest, tarData, settings, 10);\n } else if (\"error\" in tokenData) {\n if (tokenData.error === \"expired_token\") {\n throw new Error(\"⌛️ Authentication attempt expired\");\n } else {\n throw new Error(`Error occurred: ${tokenData.error} ${tokenData.error_description}`);\n }\n } else {\n throw new Error(\"Unknown error occurred\");\n }\n } catch (e) {\n console.error(\"❌ \", e);\n return { success: false };\n }\n}\n\nasync function doUploadAppWithRetry(\n accessToken: string,\n manifest: PackageJson,\n tarData: Buffer & pacote.FetchResult,\n settings: Settings,\n retryCount: number\n): Promise<{ success: boolean }> {\n try {\n return await doUploadApp(accessToken, manifest, tarData, settings);\n } catch (e) {\n if (e instanceof NpmConflictError) {\n console.error(\"❌ Unable to ship app package. Cannot submit over existing version.\");\n return { success: false };\n } else {\n if (retryCount > 1) {\n console.error(\"⚠️ Unable to ship app package. Got error from Iris App SDK repository. Retrying submit...\", e);\n await sleep(30000);\n return await doUploadAppWithRetry(accessToken, manifest, tarData, settings, retryCount - 1);\n } else {\n console.error(\"❌ Unable to ship app package. Got error from Iris App SDK repository.\", e);\n return { success: false };\n }\n }\n }\n}\n\nasync function doUploadApp(\n accessToken: string,\n manifest: PackageJson,\n tarData: Buffer & pacote.FetchResult,\n settings: Settings\n): Promise<{ success: boolean }> {\n const npmFetchOptions: { registry?: string } & Record<string, string | boolean> = {};\n npmFetchOptions.registry = settings.repoUrl.toString();\n const repoHostAndPort = settings.repoUrl.hostname + (settings.repoUrl.port ? \":\" + settings.repoUrl.port : \"\");\n npmFetchOptions[`//${repoHostAndPort}${settings.repoUrl.pathname}:_authToken`] = accessToken;\n npmFetchOptions[`//${repoHostAndPort}${settings.repoUrl.pathname}/repo/:always-auth`] = true;\n\n console.log(\"🚢 Shipping the app package...\");\n const submitResult = await libpub.publish(manifest, tarData, npmFetchOptions).catch((err: SubmitError) => {\n if (err.statusCode === 409 || err.code === \"E409\" || err.code === \"EPUBLISHCONFLICT\") {\n return {\n ok: false,\n publishConflict: true,\n };\n } else {\n return {\n ok: false,\n headers: new Headers(err.headers),\n statusText: `Error`,\n text: () => Promise.resolve(`${err.name} ${err.message}`),\n };\n }\n });\n\n const warningsText = submitResult.headers?.get(\"TU-IRIS-APP-WARNINGS\");\n if (warningsText) {\n console.log(\"⚠️ \" + decodeURI(warningsText));\n }\n\n if (submitResult.ok) {\n console.log(`🚀 Uploaded the app package version ${manifest.version}`);\n\n return await doApproveAppWithRetry(accessToken, manifest, settings, 3);\n } else if (\"publishConflict\" in submitResult) {\n if (process.env.SKIP_EXISTING === \"true\") {\n console.log(`⏩ Skipped submitting ${manifest.version} because the version is already submitted`);\n return await doApproveAppWithRetry(accessToken, manifest, settings, 3);\n } else {\n throw new NpmConflictError();\n }\n } else {\n throw new NpmGeneralError(\n submitResult.statusText +\n \" \" +\n (await submitResult.text()) +\n \". Trace ID: \" +\n submitResult.headers.get(\"trace-id\")\n );\n }\n}\n\nasync function promptUserForInput(query: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise(resolve => {\n rl.question(query, (input: string) => {\n rl.close();\n resolve(input);\n });\n });\n}\n\nasync function doApproveAppWithRetry(\n token: string,\n manifest: PackageJson,\n settings: Settings,\n retryCount: number\n): Promise<{ success: boolean }> {\n try {\n return await doApproveApp(token, manifest, settings);\n } catch (e) {\n if (e instanceof ApproveError) {\n if (retryCount > 1) {\n console.error(\n \"⚠️ Unable to approve app package. Got approve error from Iris App SDK repository. Retrying approve...\",\n e\n );\n await sleep(30000);\n return await doApproveAppWithRetry(token, manifest, settings, retryCount - 1);\n } else {\n console.error(\"❌ Unable to approve app package. Got approve error from Iris App SDK repository.\", e);\n return { success: false };\n }\n } else {\n console.error(\"❌ Unable to approve app package. Got error from Iris App SDK repository.\", e);\n return { success: false };\n }\n }\n}\n\nasync function doApproveApp(token: string, manifest: PackageJson, settings: Settings) {\n if (process.env.TU_APPROVE === \"true\") {\n console.log(`🖋️ Approving the app...`);\n const approveResult = await fetch(new URL(`${manifest.name}@${manifest.version}`, settings.approvalUrl), {\n method: \"PUT\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (approveResult.ok) {\n console.log(`✅ Approved version ${manifest.version} of ${manifest.name}.`);\n return { success: true };\n } else {\n throw new ApproveError(\n `${approveResult.statusText}, ${await approveResult.text()}, Trace ID: ${approveResult.headers.get(\"trace-id\")}`\n );\n }\n } else {\n return { success: true };\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/unpublish/executor.ts"],"names":[],"mappings":";;AAcA,8BAkDC;;AA9DD,uDAAiC;AACjC,kBAAgB;AAChB,4DAAyD;AACzD,0EAA6D;AAG7D;;;;;GAKG;AACY,KAAK,UAAU,WAAW,CAAC,OAAgC;IACxE,MAAM,QAAQ,GAAG,IAAA,mCAAW,GAAE,CAAC;IAE/B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,IAAA,+BAAc,EAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAErD,IAAI,cAAc,IAAI,SAAS,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAE9C,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAgB,CAAC;YAC3E,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;gBAC5E,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,SAAS,CAAC,YAAY,EAAE;iBAClD;aACF,CAAC,CAAC;YACH,IAAI,eAAe,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,QAAQ,eAAe,CAAC,MAAM,EAAE,CAAC;oBAC/B,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,6DAA6D,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CACvG,CAAC;oBACJ,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,wDAAwD,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAClG,CAAC;oBACJ,KAAK,GAAG;wBACN,MAAM,IAAI,KAAK,CACb,iEAAiE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAC3G,CAAC;oBACJ;wBACE,MAAM,IAAI,KAAK,CAAC,GAAG,eAAe,CAAC,UAAU,eAAe,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBAC3G,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;YAChC,IAAI,SAAS,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC","sourcesContent":["/* eslint-disable no-console */\nimport { PackageJson } from \"nx/src/utils/package-json\";\nimport * as pacote from \"pacote\";\nimport \"win-ca\";\nimport { getAccessToken } from \"../utils/authentication\";\nimport { getSettings } from \"../utils/irisAppServerSettings\";\nimport { UnpublishExecutorSchema } from \"./schema\";\n\n/**\n * Unpublish an app from the Trackunit Marketplace.\n *\n * @param {UnpublishExecutorSchema} options options provided to the executor.\n * @returns {Promise<{ success: boolean }>} The result of the unpublish.\n */\nexport default async function runExecutor(options: UnpublishExecutorSchema) {\n const settings = getSettings();\n\n try {\n const tokenData = await getAccessToken(settings.env);\n\n if (\"access_token\" in tokenData) {\n console.log(\"🥳 Successfully authenticated.\");\n\n const manifest = (await pacote.manifest(options.inputPath)) as PackageJson;\n const unpublishResult = await fetch(new URL(manifest.name, settings.repoUrl), {\n method: \"DELETE\",\n headers: {\n Authorization: `Bearer ${tokenData.access_token}`,\n },\n });\n if (unpublishResult.status !== 200) {\n switch (unpublishResult.status) {\n case 401:\n throw new Error(\n `Unpublishing failed due to invalid credentials, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n case 403:\n throw new Error(\n `You are not allowed to unpublish this app, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n case 404:\n throw new Error(\n `The app you are trying to unpublish does not exist, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`\n );\n default:\n throw new Error(`${unpublishResult.statusText}, Trace ID: ${unpublishResult.headers.get(\"trace-id\")}`);\n }\n }\n\n console.log(\"🥳 Successfully unpublished app.\");\n return { success: true };\n } else if (\"error\" in tokenData) {\n if (tokenData.error === \"expired_token\") {\n throw new Error(\"⌛️ Authentication attempt expired\");\n } else {\n throw new Error(`Error occurred: ${tokenData.error} ${tokenData.error_description}`);\n }\n } else {\n throw new Error(\"Unknown error occurred\");\n }\n } catch (e) {\n console.error(\"❌ \", e);\n return { success: false };\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authentication.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/authentication.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport openBrowser from \"open\";\n\nexport interface AuthSettings {\n env: string;\n publicAuthorizationServerBaseUrl: string;\n internalAuthorizationServerBaseUrl: string;\n clientId: string;\n}\n\ninterface OktaError {\n error: string;\n error_description: string;\n}\n\ninterface AuthorizeDataSuccess {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n}\n\ntype AuthorizeData = AuthorizeDataSuccess | OktaError;\n\nexport interface TokenDataSuccess {\n token_type: string;\n expires_in: number;\n access_token: string;\n scope: string;\n id_token: string;\n}\n\ntype TokenData = OktaError | TokenDataSuccess;\n\n/**\n * Authenticate and get access token\n *\n * @param {AuthSettings} env Settings used for authentication\n * @returns {*} {Promise<TokenData>}\n */\nexport async function getAccessToken(env: string): Promise<TokenData> {\n const settings = getAuthSettings(env);\n const clientId = process.env[`TU_CLIENT_ID_${settings.env}`];\n const clientSecret = process.env[`TU_CLIENT_SECRET_${settings.env}`];\n // use token provided as environment variable if available\n if (process.env.TU_TOKEN) {\n return {\n token_type: \"Bearer\",\n id_token: process.env.TU_TOKEN,\n access_token: process.env.TU_TOKEN,\n expires_in: 0,\n scope: \"unknown\",\n };\n // use client id and secret provided as environment variables to fetch a token directly\n // This is used for CI/CD pipelines\n } else if (clientId !== undefined) {\n if (clientId.trim() === \"\") {\n throw new Error(`Missing environment value: TU_CLIENT_ID_${settings.env}`);\n }\n if (clientSecret === undefined || clientSecret.trim() === \"\") {\n throw new Error(`Missing environment value: TU_CLIENT_SECRET_${settings.env}`);\n }\n\n const tokenParams = new URLSearchParams();\n tokenParams.append(\"client_id\", clientId);\n tokenParams.append(\"client_secret\", clientSecret);\n tokenParams.append(\"grant_type\", \"client_credentials\");\n tokenParams.append(\"scope\", \"core.iris.app.publish_for_all_accounts\");\n const tokenResponse = await fetch(`${settings.internalAuthorizationServerBaseUrl}/v1/token`, {\n method: \"POST\",\n body: tokenParams,\n });\n return (await tokenResponse.json()) as TokenData;\n // ask the user to authenticated using a browser\n // and fetch a token using the device code flow\n } else {\n const authorizeParams = new URLSearchParams();\n authorizeParams.append(\"client_id\", settings.clientId);\n authorizeParams.append(\"scope\", \"openid profile fms assume\");\n const authorizeResponse = await fetch(`${settings.publicAuthorizationServerBaseUrl}/v1/device/authorize`, {\n method: \"POST\",\n body: authorizeParams,\n });\n const authorizeData = (await authorizeResponse.json()) as AuthorizeData;\n\n if (\"error\" in authorizeData) {\n throw new Error(`Error occurred: ${authorizeData.error} ${authorizeData.error_description}`);\n } else if (!authorizeData.verification_uri_complete) {\n throw new Error(`Missing verification URI: ${JSON.stringify(authorizeData)}`);\n }\n\n console.log(\n `🔐 Attempting to automatically open the Trackunit authentication page in your default browser...\\n If the browser does not open or you wish to use a different device to authorize this request, open the following URL:\\n\\n ${authorizeData.verification_uri_complete}`\n );\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await ((openBrowser as any).default ? (openBrowser as any).default : openBrowser)(\n authorizeData.verification_uri_complete\n );\n } catch (error) {\n // safe to ignore, since we ask the user to open the URL manually above.\n }\n\n console.log(\"\\n⏳ Waiting for authentication in the browser...\");\n let tokenData: TokenData | null = null;\n do {\n await sleep(authorizeData.interval * 1000);\n if (tokenData && \"error\" in tokenData && tokenData.error === \"slow_down\") {\n await sleep(10000);\n }\n const tokenParams = new URLSearchParams();\n tokenParams.append(\"client_id\", settings.clientId);\n tokenParams.append(\"grant_type\", \"urn:ietf:params:oauth:grant-type:device_code\");\n tokenParams.append(\"device_code\", authorizeData.device_code);\n const tokenResponse = await fetch(`${settings.publicAuthorizationServerBaseUrl}/v1/token`, {\n method: \"POST\",\n body: tokenParams,\n });\n tokenData = (await tokenResponse.json()) as TokenData;\n } while (\n !(\"id_token\" in tokenData) &&\n !(\"error\" in tokenData && tokenData.error !== \"authorization_pending\" && tokenData.error !== \"slow_down\")\n );\n return tokenData;\n }\n}\n\n/**\n *\n */\nfunction getAuthSettings(env: string): AuthSettings {\n switch (env) {\n case \"PROD\":\n return {\n clientId: \"0oamfeklvodROR2ul357\",\n publicAuthorizationServerBaseUrl: \"https://identity.iris.trackunit.com/oauth2/aus2u3jix1dWU7fwt356\",\n internalAuthorizationServerBaseUrl: \"https://identity.iris.trackunit.com/oauth2/aushbxvmpdlWrMnO6357\",\n env,\n };\n case \"STAGE\":\n return {\n clientId: \"0oa1q2vmx21NcFLOs0h8\",\n publicAuthorizationServerBaseUrl: \"https://identity.stage.iris.trackunit.com/oauth2/aus1owd7wny5YVsU00h8\",\n internalAuthorizationServerBaseUrl: \"https://identity.stage.iris.trackunit.com/oauth2/aus1o484n9xEHT7G50h8\",\n env,\n };\n case \"DEV\":\n return {\n clientId: \"0oamebigau4RkaqZ6357\",\n publicAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/ausj7eh9zeiFhLk4m357\",\n internalAuthorizationServerBaseUrl: \"https://identity.dev.iris.trackunit.com/oauth2/aush09l7x4mDGKxLu357\",\n env,\n };\n default:\n throw new Error(`Unknown environment: ${env}`);\n }\n}\n\nfunction sleep(time: number) {\n return new Promise(resolve => setTimeout(resolve, time));\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"irisAppServerSettings.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/irisAppServerSettings.ts"],"names":[],"mappings":";;AAUA,kCAWC;AAdD;;GAEG;AACH,SAAgB,WAAW;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,MAAM,CAAC;IACxD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,WAAW,EAAE,KAAK,QAAQ,CAAC;IAE3F,OAAO;QACL,WAAW,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC;QACzC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QAClC,GAAG;QACH,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;IACjC,QAAQ,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,6BAA6B,CAAC,CAAC;QACxE,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,mCAAmC,CAAC,CAAC;QAC9E,KAAK,KAAK;YACR,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,iCAAiC,CAAC,CAAC;QAC5E;YACE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAA","sourcesContent":["export type Settings = {\n approvalUrl: URL;\n repoUrl: URL;\n env: string;\n devTermsAccept: boolean;\n};\n\n/**\n * Provides the settings for the Iris App server based on the environment.\n */\nexport function getSettings(): Settings {\n const env = process.env.TU_ENV?.toUpperCase() ?? \"PROD\";\n const baseUrl = getBaseUrl(env);\n const devTermsAccept = process.env.TU_DEV_TERMS_AND_CONDITIONS?.toLowerCase() === \"accept\";\n\n return {\n approvalUrl: new URL(\"approve/\", baseUrl),\n repoUrl: new URL(\"repo/\", baseUrl),\n env,\n devTermsAccept,\n };\n}\n\n/**\n * Provides the base URL for the Iris App server based on the environment.\n *\n * @param {string} env The environment to get the base URL for.\n * @returns {URL} The base URL for the Iris App server.\n */\nconst getBaseUrl = (env: string) => {\n switch (env.toUpperCase()) {\n case \"PROD\":\n return new URL(process.env.BASE_URL ?? \"https://iris.trackunit.app/\");\n case \"STAGE\":\n return new URL(process.env.BASE_URL ?? \"https://stage.iris.trackunit.app/\");\n case \"DEV\":\n return new URL(process.env.BASE_URL ?? \"https://dev.iris.trackunit.app/\");\n default:\n throw new Error(`Unknown environment: ${env}`);\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/iris-app-sdk/iris-app/src/executors/utils/src/index.js"],"names":[],"mappings":";AAAA,wFAAwF","sourcesContent":["// Empty ts file for webpack to be happy - we generate module federated js files instead\n"]}
@@ -1,6 +1,6 @@
1
1
  # AI Agent Sync Generator
2
2
 
3
- Syncs Cursor rules and AI agent configuration files to the latest version. Ensures the SDK is at the latest version before applying updates.
3
+ Syncs agent skills, AGENTS.md, CLAUDE.md, and AI agent configuration files to the latest version. Ensures the SDK is at the latest version before applying updates.
4
4
 
5
5
  ## Usage
6
6
 
@@ -10,7 +10,10 @@ nx g @trackunit/iris-app:ai-agent-sync
10
10
 
11
11
  ## What it syncs
12
12
 
13
- - `.cursor/skills/` - Cursor AI skills for the IrisX App SDK
13
+ - `.agents/skills/` - AI agent skills for the IrisX App SDK (editor-agnostic)
14
+ - `.cursor/mcp.json` - Cursor-specific MCP configuration
15
+ - `AGENTS.md` - Workspace-level agent instructions (always applied)
16
+ - `CLAUDE.md` - Claude-specific configuration (references AGENTS.md)
14
17
 
15
18
  ## Flow
16
19
 
@@ -1,7 +1,7 @@
1
1
  import { Tree } from "@nx/devkit";
2
2
  import { AiAgentSyncGeneratorSchema } from "./schema";
3
3
  /**
4
- * Syncs Cursor rules and AI agent configuration files.
4
+ * Syncs Cursor skills, AGENTS.md, CLAUDE.md, and AI agent configuration files.
5
5
  * Requires the SDK to be at the latest version before running.
6
6
  */
7
7
  export declare function aiAgentSyncGenerator(tree: Tree, options: AiAgentSyncGeneratorSchema): Promise<void>;
@@ -50,7 +50,7 @@ function ensureUpdateScript(tree) {
50
50
  });
51
51
  }
52
52
  /**
53
- * Syncs Cursor rules and AI agent configuration files.
53
+ * Syncs Cursor skills, AGENTS.md, CLAUDE.md, and AI agent configuration files.
54
54
  * Requires the SDK to be at the latest version before running.
55
55
  */
56
56
  async function aiAgentSyncGenerator(tree, options) {
@@ -74,9 +74,34 @@ async function aiAgentSyncGenerator(tree, options) {
74
74
  `Then run this generator again.`);
75
75
  }
76
76
  }
77
- // Copy Cursor rules and AI agent configuration
78
- const templatePath = path.join(__dirname, "../preset/files/.cursor");
79
- (0, devkit_1.generateFiles)(tree, templatePath, ".cursor", {});
77
+ // Clean up old .cursor/rules and .cursor/commands files that were managed by previous versions
78
+ const oldManagedFiles = [
79
+ ".cursor/rules/irisx-app-sdk.mdc",
80
+ ".cursor/rules/rules-index.mdc",
81
+ ".cursor/rules/structured-development.mdc",
82
+ ".cursor/rules/browser-irisx-development.mdc",
83
+ ".cursor/rules/graphql-timeseries.md",
84
+ ".cursor/rules/irisx-app-sdk-customfields.md",
85
+ ".cursor/rules/irisx-app-sdk-graphql.md",
86
+ ".cursor/rules/react-core-hooks.md",
87
+ ".cursor/rules/tables-and-sorting.mdc",
88
+ ".cursor/rules/widget-extensions.md",
89
+ ".cursor/commands/create-app.md",
90
+ ];
91
+ for (const file of oldManagedFiles) {
92
+ if (tree.exists(file)) {
93
+ tree.delete(file);
94
+ }
95
+ }
96
+ // Copy Cursor-specific configuration (mcp.json)
97
+ const cursorTemplatePath = path.join(__dirname, "../preset/files/.cursor");
98
+ (0, devkit_1.generateFiles)(tree, cursorTemplatePath, ".cursor", {});
99
+ // Copy agent skills (editor-agnostic)
100
+ const agentsTemplatePath = path.join(__dirname, "../preset/files/.agents");
101
+ (0, devkit_1.generateFiles)(tree, agentsTemplatePath, ".agents", {});
102
+ // Copy AGENTS.md and CLAUDE.md to workspace root
103
+ const rootTemplatePath = path.join(__dirname, "../preset/root-files");
104
+ (0, devkit_1.generateFiles)(tree, rootTemplatePath, ".", {});
80
105
  await (0, devkit_1.formatFiles)(tree);
81
106
  }
82
107
  exports.default = aiAgentSyncGenerator;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/ai-agent-sync/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { Tree, formatFiles, generateFiles, updateJson } from \"@nx/devkit\";\nimport { detectPackageManager, getPackageManagerCommand } from \"nx/src/devkit-exports\";\nimport * as pacote from \"pacote\";\nimport * as path from \"path\";\nimport * as semver from \"semver\";\nimport { AiAgentSyncGeneratorSchema } from \"./schema\";\n\nconst IRIS_APP_PACKAGE = \"@trackunit/iris-app\";\nconst UPDATE_SCRIPT_NAME = \"update:trackunit\";\nconst UPDATE_SCRIPT_CMD = 'npx npm-check-updates \"/@trackunit/\" -u';\n\ntype PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n};\n\nfunction getStringValue(obj: unknown, key: string): string | undefined {\n if (typeof obj === \"object\" && obj !== null && key in obj) {\n const value = (obj as Record<string, unknown>)[key];\n return typeof value === \"string\" ? value : undefined;\n }\n return undefined;\n}\n\n/**\n * Gets the installed version of @trackunit/iris-app from workspace package.json\n */\nfunction getInstalledSdkVersion(tree: Tree): string | undefined {\n const pkgJson: unknown = JSON.parse(tree.read(\"package.json\", \"utf-8\") ?? \"{}\");\n if (typeof pkgJson !== \"object\" || pkgJson === null) {\n return undefined;\n }\n const pkg = pkgJson as Record<string, unknown>;\n return getStringValue(pkg.dependencies, IRIS_APP_PACKAGE) ?? getStringValue(pkg.devDependencies, IRIS_APP_PACKAGE);\n}\n\n/**\n * Fetches the latest version of @trackunit/iris-app from npm\n */\nasync function getLatestSdkVersion(): Promise<string> {\n const manifest = await pacote.manifest(IRIS_APP_PACKAGE);\n return manifest.version;\n}\n\n/**\n * Ensures the update:trackunit script exists in package.json\n */\nfunction ensureUpdateScript(tree: Tree): void {\n updateJson<PackageJson, PackageJson>(tree, \"package.json\", pkgJson => {\n if (!pkgJson.scripts) {\n pkgJson.scripts = {};\n }\n if (!pkgJson.scripts[UPDATE_SCRIPT_NAME]) {\n pkgJson.scripts[UPDATE_SCRIPT_NAME] = UPDATE_SCRIPT_CMD;\n }\n return pkgJson;\n });\n}\n\n/**\n * Syncs Cursor skills, AGENTS.md, CLAUDE.md, and AI agent configuration files.\n * Requires the SDK to be at the latest version before running.\n */\nexport async function aiAgentSyncGenerator(tree: Tree, options: AiAgentSyncGeneratorSchema): Promise<void> {\n // Always ensure the update script exists\n ensureUpdateScript(tree);\n\n // Check SDK version unless skipped\n if (!options.skipVersionCheck) {\n const installedVersion = getInstalledSdkVersion(tree);\n const latestVersion = await getLatestSdkVersion();\n\n if (!installedVersion) {\n throw new Error(`${IRIS_APP_PACKAGE} not found in package.json. Is this an Iris App SDK workspace?`);\n }\n\n const installed = semver.minVersion(installedVersion);\n if (!installed || semver.lt(installed, latestVersion)) {\n const pm = detectPackageManager();\n const pmCmd = getPackageManagerCommand(pm);\n\n throw new Error(\n `${IRIS_APP_PACKAGE} is outdated (installed: ${installedVersion}, latest: ${latestVersion}).\\n\\n` +\n `Run the following commands first:\\n` +\n ` ${pmCmd.run(UPDATE_SCRIPT_NAME)}\\n` +\n ` ${pmCmd.install}\\n\\n` +\n `Then run this generator again.`\n );\n }\n }\n\n // Clean up old .cursor/rules and .cursor/commands files that were managed by previous versions\n const oldManagedFiles = [\n \".cursor/rules/irisx-app-sdk.mdc\",\n \".cursor/rules/rules-index.mdc\",\n \".cursor/rules/structured-development.mdc\",\n \".cursor/rules/browser-irisx-development.mdc\",\n \".cursor/rules/graphql-timeseries.md\",\n \".cursor/rules/irisx-app-sdk-customfields.md\",\n \".cursor/rules/irisx-app-sdk-graphql.md\",\n \".cursor/rules/react-core-hooks.md\",\n \".cursor/rules/tables-and-sorting.mdc\",\n \".cursor/rules/widget-extensions.md\",\n \".cursor/commands/create-app.md\",\n ];\n for (const file of oldManagedFiles) {\n if (tree.exists(file)) {\n tree.delete(file);\n }\n }\n\n // Copy Cursor-specific configuration (mcp.json)\n const cursorTemplatePath = path.join(__dirname, \"../preset/files/.cursor\");\n generateFiles(tree, cursorTemplatePath, \".cursor\", {});\n\n // Copy agent skills (editor-agnostic)\n const agentsTemplatePath = path.join(__dirname, \"../preset/files/.agents\");\n generateFiles(tree, agentsTemplatePath, \".agents\", {});\n\n // Copy AGENTS.md and CLAUDE.md to workspace root\n const rootTemplatePath = path.join(__dirname, \"../preset/root-files\");\n generateFiles(tree, rootTemplatePath, \".\", {});\n\n await formatFiles(tree);\n}\n\nexport default aiAgentSyncGenerator;\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/create/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addDependenciesToPackageJson,\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n installPackagesTask,\n names,\n offsetFromRoot,\n readJsonFile,\n Tree,\n updateJson,\n} from \"@nx/devkit\";\nimport { getNpmScope } from \"@nx/js/src/utils/package-json/get-npm-scope\";\nimport { PackageJson as PackageJsonBase } from \"nx/src/utils/package-json\";\nimport * as pacote from \"pacote\";\nimport * as path from \"path\";\nimport { IrisAppGeneratorSchema } from \"./schema\";\n\ntype PackageJson = PackageJsonBase & {\n engines?: Record<string, string>;\n};\n\ninterface NormalizedSchema extends IrisAppGeneratorSchema {\n projectName: string;\n projectRoot: string;\n projectDirectory: string;\n toNxRoot: string;\n npmScope: string;\n}\n\nfunction normalizeOptions(tree: Tree, options: IrisAppGeneratorSchema): NormalizedSchema {\n const name = names(options.name).fileName;\n const projectDirectory = options.directory ? path.join(options.directory, name) : name;\n const toNxRoot = `../../${projectDirectory.indexOf(\"/\") !== -1 ? \"../\" : \"\"}`;\n const projectName = name.replace(new RegExp(\"/\", \"g\"), \"_\");\n const npmScope = getNpmScope(tree);\n if (!npmScope) {\n throw new Error(\"Could not find npm scope in package.json\");\n }\n const projectRoot = `${getWorkspaceLayout(tree).appsDir}/${projectDirectory}`;\n return {\n ...options,\n projectName,\n projectRoot,\n projectDirectory,\n toNxRoot,\n npmScope,\n };\n}\n\nfunction addFiles(tree: Tree, options: NormalizedSchema, packageJson: PackageJson | null) {\n const nodeVersion = packageJson?.engines?.node ?? \">=20.x\";\n const templateOptions = {\n ...options,\n ...names(options.name),\n offsetFromRoot: offsetFromRoot(options.projectRoot),\n template: \"\",\n nodeVersion,\n };\n generateFiles(tree, path.join(__dirname, \"files\"), options.projectRoot, templateOptions);\n}\n\nconst getManifest = (packageName: string) => {\n return pacote.manifest(\n packageName,\n process.env.TU_NPM_REGISTRY ? { registry: process.env.TU_NPM_REGISTRY } : undefined\n );\n};\n\n/**\n * Iris App Generator.\n * This generator will create a new iris app, you can call this from your own generator.\n *\n * @param tree the nx tree\n * @param options the generator options\n * @returns { Promise<void> } void\n */\nexport const IrisAppGenerator = async function (tree: Tree, options: IrisAppGeneratorSchema) {\n const normalizedOptions = normalizeOptions(tree, options);\n const packageJsonFromNpm = await getManifest(\"@trackunit/iris-app\");\n\n const packageJsonLocally: PackageJson = readJsonFile(path.join(__dirname, \"..\", \"..\", \"..\", \"package.json\"));\n\n if (options.updatePackageJson) {\n if (packageJsonFromNpm.version !== packageJsonLocally.version) {\n // eslint-disable-next-line no-console\n console.warn(\n `⚠️ This version of the iris-app package does not match the version of the iris-app package from NPM JS. Please update using: npm i @trackunit/iris-app@${packageJsonFromNpm.version}`\n );\n }\n\n const reactComponentsPackageJsonFromNpm = getManifest(\"@trackunit/react-components\");\n const reactCoreContextsPackageJsonFromNpm = getManifest(\"@trackunit/react-core-contexts\");\n const cssCorePackageJsonFromNpm = getManifest(\"@trackunit/css-core\");\n\n const tuDependencies = {\n \"@trackunit/react-components\": (await reactComponentsPackageJsonFromNpm).version,\n \"@trackunit/react-core-contexts\": (await reactCoreContextsPackageJsonFromNpm).version,\n \"@trackunit/css-core\": (await cssCorePackageJsonFromNpm).version,\n };\n\n const irisAppSdkVitePackageJsonFromNpm = getManifest(\"@trackunit/iris-app-sdk-vite\");\n const reactCoreContextsTestPackageJsonFromNpm = getManifest(\"@trackunit/react-core-contexts-test\");\n const reactTestSetupPackageJsonFromNpm = getManifest(\"@trackunit/react-test-setup\");\n\n const tuDevDependencies = {\n \"@trackunit/iris-app-sdk-vite\": (await irisAppSdkVitePackageJsonFromNpm).version,\n \"@trackunit/react-core-contexts-test\": (await reactCoreContextsTestPackageJsonFromNpm).version,\n \"@trackunit/react-test-setup\": (await reactTestSetupPackageJsonFromNpm).version,\n };\n\n addDependenciesToPackageJson(\n tree,\n {\n ...tuDependencies,\n tslib: \"2.4.0\",\n react: \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n \"single-spa-react\": \"5.1.4\",\n },\n {\n ...tuDevDependencies,\n nx: \"22.4.4\",\n \"@nx/react\": \"22.4.4\",\n \"@nx/workspace\": \"22.4.4\",\n \"@nx/devkit\": \"22.4.4\",\n \"@nx/eslint-plugin\": \"22.4.4\",\n \"@types/react\": \"19.0.8\",\n eslint: \"9.33.0\",\n \"eslint-plugin-react-hooks\": \"7.0.1\",\n \"eslint-plugin-react\": \"7.37.5\",\n \"eslint-plugin-import\": \"2.32.0\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"typescript-eslint\": \"8.54.0\",\n typescript: \"5.9.3\",\n }\n );\n\n updateJson(tree, \"package.json\", packageJson => {\n packageJson.overrides = {\n react: \"19.0.0\", // to avoid resolution warnings when running npm install\n \"react-dom\": \"19.0.0\", // fix resolution warnings and test\n \"zod-validation-error\": \"4.0.2\",\n };\n return packageJson;\n });\n }\n addProjectConfiguration(tree, normalizedOptions.projectName, {\n root: normalizedOptions.projectRoot,\n projectType: \"application\",\n sourceRoot: `${normalizedOptions.projectRoot}/src`,\n targets: {\n build: {\n executor: \"@trackunit/iris-app-sdk-vite:build\",\n options: {\n viteConfig: `${normalizedOptions.projectRoot}/vite.config.ts`,\n outputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n outputs: [\"{options.outputPath}\"],\n },\n serve: {\n executor: \"@trackunit/iris-app-sdk-vite:serve\",\n options: {\n viteConfig: `${normalizedOptions.projectRoot}/vite.config.ts`,\n },\n outputs: [\"{options.outputPath}\"],\n },\n submitApp: {\n executor: \"@trackunit/iris-app:submit\",\n dependsOn: [\"build\"],\n options: {\n inputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n outputs: [\"{workspaceRoot}/dist/\" + normalizedOptions.projectRoot],\n },\n unpublishApp: {\n executor: \"@trackunit/iris-app:unpublish\",\n options: {\n inputPath: `dist/${normalizedOptions.projectRoot}`,\n },\n dependsOn: [\n {\n target: \"build\",\n },\n ],\n outputs: [\"{workspaceRoot}/dist/\" + normalizedOptions.projectRoot],\n },\n },\n });\n addFiles(tree, normalizedOptions, packageJsonLocally);\n // enforcing engine versions specified in package.json\n tree.write(\".npmrc\", \"engine-strict=true\");\n\n await formatFiles(tree);\n return () => {\n installPackagesTask(tree, true);\n\n // eslint-disable-next-line no-console\n console.log(\n \"🥳 Successfully created an Iris App - review the iris-app-manifest.ts and start adding app extensions!\"\n );\n };\n};\n\nexport default IrisAppGenerator;\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/extend/dependencies.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,eAAe,GAAG;IAC7B,YAAY,EAAE,QAAQ;IACtB,kBAAkB,EAAE,OAAO;CAC5B,CAAC;AAEW,QAAA,gBAAgB,GAAG;IAC9B,UAAU,EAAE,QAAQ;IACpB,wBAAwB,EAAE,QAAQ;IAClC,sBAAsB,EAAE,SAAS;IACjC,IAAI,EAAE,QAAQ;IACd,wBAAwB,EAAE,QAAQ;IAClC,qBAAqB,EAAE,QAAQ;IAC/B,iBAAiB,EAAE,QAAQ;IAC3B,SAAS,EAAE,QAAQ;CACpB,CAAC","sourcesContent":["/*\n * Use this file to maintain the version of single-spa and related dependencies.\n * Versions in here should be in sync with the versions in manager package.json.\n * If the test fails, update this file to reflect the version in manager package.json file.\n */\n\nexport const spaDependencies = {\n \"single-spa\": \"^5.9.5\",\n \"single-spa-react\": \"5.1.4\",\n};\n\nexport const testDependencies = {\n \"@nx/jest\": \"22.4.4\",\n \"@testing-library/react\": \"16.2.0\",\n \"@testing-library/dom\": \"^10.4.0\",\n jest: \"30.0.5\",\n \"jest-environment-jsdom\": \"30.0.5\",\n \"jest-transform-stub\": \"^2.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"ts-jest\": \"29.4.6\",\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../libs/iris-app-sdk/iris-app/src/generators/extend/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addDependenciesToPackageJson,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n installPackagesTask,\n joinPathFragments,\n names,\n offsetFromRoot,\n Tree,\n updateJson,\n} from \"@nx/devkit\";\nimport { Linter } from \"@nx/eslint\";\nimport { getRootTsConfigPathInTree } from \"@nx/js\";\nimport { getNpmScope } from \"@nx/js/src/utils/package-json/get-npm-scope\";\nimport { libraryGenerator } from \"@nx/react\";\nimport { Schema } from \"@nx/react/src/generators/library/schema\";\nimport { nonUiExtensionTypes, serverSideExtensionTypes } from \"@trackunit/iris-app-api\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { camelCase } from \"string-ts\";\nimport { Project, SyntaxKind, VariableDeclaration } from \"ts-morph\";\nimport { addRequireStatement, addSpreadAssignment } from \"../../utils/ast/astUtils\";\nimport { spaDependencies, testDependencies } from \"./dependencies\";\nimport { IrisAppExtensionGeneratorSchema } from \"./schema\";\n\ninterface NormalizedSchema extends IrisAppExtensionGeneratorSchema {\n projectName: string;\n projectRoot: string;\n projectDirectory: string;\n projectCamelcase: string;\n importPath: string;\n sourceRoot: string;\n dependencyDefinitionFile: string;\n}\n\nfunction normalizeOptions(tree: Tree, options: IrisAppExtensionGeneratorSchema): NormalizedSchema {\n const name = names(options.name).fileName;\n const projectDirectory = options.directory ? `${names(options.directory).fileName}/${name}` : name;\n const projectName = projectDirectory.replace(new RegExp(\"/\", \"g\"), \"-\");\n const projectCamelcase = camelCase(projectName);\n const wsLayout = getWorkspaceLayout(tree);\n const projectRoot = `${wsLayout.libsDir}/${projectDirectory}`;\n const sourceRoot = `${wsLayout.libsDir}/${projectDirectory}/src`;\n const dependencyDefinitionFile = `${wsLayout.libsDir}/${projectDirectory}/package.json`;\n\n const npmScope = getNpmScope(tree);\n if (!npmScope) {\n throw new Error(\"Could not find npm scope in package.json\");\n }\n const importPath = `@${npmScope}/${projectName}`;\n\n return {\n ...options,\n projectName,\n projectRoot,\n projectDirectory,\n projectCamelcase,\n importPath,\n sourceRoot,\n dependencyDefinitionFile,\n };\n}\n\n/**\n * Ensures that jest.preset.js exists and includes the required @trackunit/react-test-setup preset.\n * If the file doesn't exist, creates it. If it exists but doesn't include the preset, updates it.\n */\nexport function ensureJestPresetConfiguration(tree: Tree, templateOptions?: object): void {\n const jestPresetPath = \"jest.preset.js\";\n\n if (!tree.exists(jestPresetPath)) {\n // File doesn't exist, generate it using the template\n generateFiles(tree, path.join(__dirname, \"files\", \"preset\"), \"/\", templateOptions || {});\n return;\n }\n\n // File exists, use AST utilities for reliable manipulation\n let currentContent = tree.read(jestPresetPath, \"utf-8\");\n if (!currentContent) {\n throw new Error(`Could not read ${jestPresetPath}`);\n }\n\n // Extract variable name from existing import if it exists\n let presetVariableName = \"irisPreset\"; // default name\n const existingImportMatch = currentContent.match(\n /const\\s+(\\w+)\\s*=\\s*require\\([\"']@trackunit\\/react-test-setup\\/preset[\"']\\)/\n );\n if (existingImportMatch && existingImportMatch[1]) {\n presetVariableName = existingImportMatch[1];\n }\n\n // Add the require statement if it doesn't exist\n currentContent = addRequireStatement(currentContent, presetVariableName, \"@trackunit/react-test-setup/preset\");\n\n // Add the spread assignment to the module.exports object\n currentContent = addSpreadAssignment(currentContent, presetVariableName);\n\n // Write the updated content back to the tree\n tree.write(jestPresetPath, currentContent);\n}\n\n/**\n * Iris App Extension Generator.\n *\n * @param tree the nx tree\n * @param options the generator options\n * @returns { Promise<void> } void\n */\nexport const IrisAppExtensionGenerator = async function (tree: Tree, options: IrisAppExtensionGeneratorSchema) {\n const adjustedOptions = await updateAppName(tree, options);\n\n const normalizedOptions = normalizeOptions(tree, adjustedOptions);\n\n const templateOptions = {\n ...normalizedOptions,\n ...names(normalizedOptions.name),\n offsetFromRoot: offsetFromRoot(normalizedOptions.projectRoot),\n template: \"\",\n };\n const irisAppExtensionType = normalizedOptions.type;\n\n if (!tree.exists(`${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}`)) {\n throw new Error(\n `The app does not exist: ${getWorkspaceLayout(tree).appsDir}/${\n normalizedOptions.app\n } make sure you enter the right app name`\n );\n }\n\n const manifestPath = `${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}/iris-app-manifest.ts`;\n if (!tree.exists(manifestPath)) {\n throw new Error(\n `The app does not have an iris-app-manifest.ts: ${manifestPath} make sure you enter the right app name, which has an iris-app-manifest.ts`\n );\n }\n\n if (normalizedOptions.updatePackageJson) {\n addDependenciesToPackageJson(\n tree,\n {},\n {\n ...spaDependencies,\n ...testDependencies,\n }\n );\n }\n\n const schema: Schema = {\n name: normalizedOptions.projectName,\n style: \"none\",\n skipFormat: false,\n strict: true,\n unitTestRunner: \"jest\",\n linter: Linter.EsLint,\n routing: false,\n directory: normalizedOptions.projectRoot,\n skipTsConfig: false,\n skipPackageJson: true,\n };\n\n await libraryGenerator(tree, schema);\n\n generateFiles(\n tree,\n path.join(__dirname, \"files\", irisAppExtensionType),\n normalizedOptions.projectRoot,\n templateOptions\n );\n\n if (!nonUiExtensionTypes.includes(irisAppExtensionType)) {\n generateFiles(tree, path.join(__dirname, \"files\", \"react-app\"), normalizedOptions.projectRoot, templateOptions);\n if (normalizedOptions.extendJestPreset) {\n ensureJestPresetConfiguration(tree, templateOptions);\n }\n }\n\n const rootTsConfigPath = getRootTsConfigPathInTree(tree);\n if (!rootTsConfigPath) {\n throw new Error(\"Could not find root tsconfig.json\");\n }\n updateJson(tree, rootTsConfigPath, tsConfigBase => {\n // For server side extension types, we need to add deno types to the tsconfig and make Typescript accept Deno import syntax\n if (serverSideExtensionTypes.includes(irisAppExtensionType)) {\n tsConfigBase.compilerOptions = {\n ...tsConfigBase.compilerOptions,\n types: [\"node\"],\n esModuleInterop: true,\n };\n }\n\n tsConfigBase.compilerOptions.paths[normalizedOptions.importPath] = [\n path.join(normalizedOptions.projectRoot, \"extension-manifest.ts\"),\n ];\n return tsConfigBase;\n });\n\n // Add working serve target to the project.json for DENO extensions\n if (serverSideExtensionTypes.includes(irisAppExtensionType)) {\n updateJson(tree, joinPathFragments(normalizedOptions.projectRoot, \"project.json\"), projectJson => {\n projectJson.targets.serve = {\n executor: \"@nx/js:node\",\n options: {\n buildTarget: `${normalizedOptions.projectName}:build:development`,\n inspect: true,\n },\n configurations: {\n breakOnStart: {\n inspect: \"inspect-brk\",\n },\n },\n };\n projectJson.targets.build = {\n executor: \"@nx/esbuild:esbuild\",\n outputs: [\"{options.outputPath}\"],\n defaultConfiguration: \"production\",\n options: {\n platform: \"node\",\n outputPath: `dist/${normalizedOptions.projectRoot}`,\n format: [\"cjs\"],\n bundle: true,\n thirdParty: true,\n external: [],\n main: `${normalizedOptions.sourceRoot}/index.ts`,\n tsConfig: `libs/${normalizedOptions.projectDirectory}/tsconfig.lib.json`,\n esbuildOptions: {\n sourcemap: true,\n outExtension: {\n \".js\": \".js\",\n },\n },\n },\n configurations: {\n development: {\n main: `${normalizedOptions.sourceRoot}/local-serve.ts`,\n },\n production: {\n esbuildOptions: {\n sourcemap: false,\n outExtension: {\n \".js\": \".js\",\n },\n },\n },\n },\n };\n return projectJson;\n });\n }\n\n //TODO: Change the following to update the manifest in the virtual Tree - not on the file system.\n const project = new Project({\n tsConfigFilePath: `${getWorkspaceLayout(tree).appsDir}/${normalizedOptions.app}/tsconfig.app.json`,\n });\n\n const manifest = project.getSourceFileOrThrow(manifestPath);\n\n manifest.addImportDeclaration({\n moduleSpecifier: normalizedOptions.importPath,\n defaultImport: normalizedOptions.projectCamelcase,\n });\n\n // Get the default export symbol from the manifest\n const defaultExportSymbol = manifest.getDefaultExportSymbolOrThrow();\n\n // Get the aliased symbol if the default export is an alias\n const aliasedSymbol = defaultExportSymbol.getAliasedSymbol() || defaultExportSymbol;\n\n // Get the declaration of the aliased symbol\n const declaration = aliasedSymbol.getDeclarations()[0];\n\n if (!VariableDeclaration.isVariableDeclaration(declaration)) {\n throw new Error(\"Expected variable declaration\");\n }\n const irisAppManifestObject = declaration.getInitializer()?.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);\n\n if (!irisAppManifestObject) {\n throw new Error(`irisAppManifest not exported from the file: ${manifestPath}`);\n }\n // Find the extensions property within the irisAppManifest object\n const extensionsProperty = irisAppManifestObject.getPropertyOrThrow(\"extensions\");\n\n if (extensionsProperty.getKind() === SyntaxKind.PropertyAssignment) {\n const extensionsArray = extensionsProperty.getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression);\n extensionsArray.addElement(`${normalizedOptions.projectCamelcase}`);\n }\n\n await manifest.save();\n\n if (!serverSideExtensionTypes.includes(irisAppExtensionType)) {\n tree.delete(joinPathFragments(normalizedOptions.projectRoot, \"src\", \"index.ts\"));\n }\n\n updateJson(tree, joinPathFragments(normalizedOptions.projectRoot, \"tsconfig.spec.json\"), tsConfigSpec => {\n // extension-manifest.ts is a build time file, so we only need to include it in the spec file for type/lint checking\n tsConfigSpec.include = [...tsConfigSpec.include, \"**/jest.setup.ts*\", \"extension-manifest.ts\"];\n return tsConfigSpec;\n });\n\n await formatFiles(tree);\n installPackagesTask(tree, true);\n return () => {\n // eslint-disable-next-line no-console\n console.log(\"🥳 Successfully created an app extensions and it is already added to the Iris App!\");\n };\n};\nconst updateAppName = async (tree: Tree, options: IrisAppExtensionGeneratorSchema) => {\n if (!options.app) {\n const folders = fs\n .readdirSync(getWorkspaceLayout(tree).appsDir, { withFileTypes: true })\n .filter(item => item.isDirectory());\n\n const tileApps: Array<string> = [];\n\n folders.forEach(folder => {\n const irisAppManifest = fs\n .readdirSync(`${getWorkspaceLayout(tree).appsDir}/${folder.name}`, { withFileTypes: true })\n .find(item => item.name === \"iris-app-manifest.ts\");\n\n if (irisAppManifest) {\n tileApps.push(folder.name);\n } else {\n const subFolders = fs\n .readdirSync(path.join(getWorkspaceLayout(tree).appsDir, folder.name), { withFileTypes: true })\n .filter(item => item.isDirectory());\n subFolders.forEach(subFolder => {\n const subDirIrisAppManifest = fs\n .readdirSync(`${getWorkspaceLayout(tree).appsDir}/${folder.name}/${subFolder.name}`, {\n withFileTypes: true,\n })\n .find(item => item.name === \"iris-app-manifest.ts\");\n\n if (subDirIrisAppManifest) {\n tileApps.push(path.join(folder.name, subFolder.name));\n }\n });\n }\n });\n\n if (tileApps.length === 1) {\n options.app = tileApps[0] || \"<Missing iris app name>\";\n } else if (tileApps.length === 0) {\n throw new Error(\"Please add an iris-app using: nx g @trackunit/iris-app:create \");\n } else {\n // Dynamic import to avoid loading ESM module at test time when not needed\n const { autocomplete, isCancel, cancel } = await import(\"@clack/prompts\");\n\n const selectedApp = await autocomplete({\n message: \"Select the iris app that this extension should belong to (type to filter):\",\n options: tileApps.map(item => ({ value: item, label: item })),\n maxItems: 15,\n });\n\n if (isCancel(selectedApp)) {\n cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n options.app = selectedApp;\n }\n }\n return options;\n};\n\nexport default IrisAppExtensionGenerator;\n"]}
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: browser-testing
3
+ description: Use when testing IrisX Apps in browser, extension not appearing, dev mode toggle issues, or verifying code changes in Trackunit Manager.
4
+ ---
5
+
6
+ # Browser Testing for IrisX Apps
7
+
8
+ ## Overview
9
+
10
+ IrisX Apps run inside Trackunit Manager, not on localhost. Test at `https://new.manager.trackunit.com/goto/iris-app-dev` with "Use Local Apps" enabled.
11
+
12
+ ## Chrome DevTools MCP Required
13
+
14
+ **IrisX Apps render inside iFrames.** Standard browser automation tools cannot interact with iFrame content. You **MUST** use Chrome DevTools MCP for browser testing.
15
+
16
+ ### Check Chrome DevTools MCP Availability
17
+
18
+ Before browser testing, verify the MCP is available:
19
+
20
+ 1. Check if `chrome-devtools` MCP server is enabled in Cursor settings
21
+ 2. Try listing pages: use the `list_pages` tool from `user-chrome-devtools` server
22
+ 3. If tools are not available, the MCP needs to be configured
23
+
24
+ ### Setup Chrome DevTools MCP
25
+
26
+ If Chrome DevTools MCP is not available:
27
+
28
+ 1. **Install the MCP server** - Guide the user to install `chrome-devtools-mcp`
29
+ 2. **Configure in Cursor** - Add the server to `.cursor/mcp.json`:
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "chrome-devtools": {
34
+ "command": "npx",
35
+ "args": ["-y", "chrome-devtools-mcp@latest"]
36
+ }
37
+ }
38
+ }
39
+ ```
40
+ 3. **Restart Cursor** to load the new MCP server
41
+ 4. **Launch Chrome with debugging** - Chrome must be started with remote debugging enabled (the MCP handles this)
42
+
43
+ ### Why Chrome DevTools?
44
+
45
+ | Standard Browser Tools | Chrome DevTools MCP |
46
+ |------------------------|---------------------|
47
+ | Cannot access iFrame content | Full iFrame support via CDP |
48
+ | Limited to top-level DOM | Access nested contexts |
49
+ | Screenshots miss iFrame content | Captures complete page |
50
+ | Cannot interact with extensions | Full extension interaction |
51
+
52
+ ## When to Use
53
+
54
+ - Testing extension after code changes
55
+ - Extension not appearing or showing blank
56
+ - Enabling local development mode
57
+ - Debugging GraphQL/API errors in browser
58
+ - Verifying UI renders correctly
59
+
60
+ **Not for:** Unit tests, linting, or type checking (use NX commands).
61
+
62
+ ## Quick Reference
63
+
64
+ ### Setup Steps
65
+
66
+ 1. Navigate to `https://new.manager.trackunit.com/goto/iris-app-dev`
67
+ 2. Wait for user login (2-4 minutes)
68
+ 3. Enable "Use Local Apps" toggle (main content area, not sidebar)
69
+ 4. Navigate to extension based on type
70
+
71
+ ### Navigate to Extension
72
+
73
+ Based on extension type:
74
+
75
+ | Extension Type | Navigation |
76
+ |----------------|------------|
77
+ | `FLEET_EXTENSION` | Main menu → App name |
78
+ | `ASSET_HOME_EXTENSION` | Assets → Open any asset → Extension tab |
79
+ | `SITE_HOME_EXTENSION` | Sites → Open any site → Extension tab |
80
+ | `WIDGET_EXTENSION` | Dashboard → Add Widget → Find widget |
81
+
82
+ ## Testing After Code Changes
83
+
84
+ ### Reload Strategy
85
+
86
+ After making code changes:
87
+
88
+ **1. Check Lints First (Zero Tolerance):**
89
+ ```
90
+ - Run read_lints on modified files
91
+ - Fix ALL errors before testing in browser
92
+ - Do not proceed with any TypeScript or linter errors
93
+ ```
94
+
95
+ **2. Reload Browser:**
96
+
97
+ The dev server hot-reloads, but sometimes a full page refresh is needed:
98
+
99
+ | Option | When to Use | How |
100
+ |--------|-------------|-----|
101
+ | Wait for Hot Reload | First attempt | Wait 2-3 seconds |
102
+ | Soft Refresh | Changes don't appear | `Command+R` (Mac) or `Ctrl+R` (Windows) |
103
+ | Hard Refresh | Soft refresh fails | `Command+Shift+R` (Mac) or `Ctrl+Shift+R` (Windows) |
104
+
105
+ **3. Manifest Changes Require Re-Serve:**
106
+
107
+ If you modified `iris-app-manifest.ts` (scopes, CSP headers, metadata):
108
+ - Browser reload is NOT enough
109
+ - Stop the dev server (`Ctrl+C`)
110
+ - Re-run: `npx nx run [app-name]:serve`
111
+ - Wait for server to restart
112
+ - Then reload browser
113
+
114
+ ### Verification Checklist
115
+
116
+ After each reload:
117
+
118
+ 1. Take browser snapshot
119
+ 2. Look for extension content
120
+ 3. Check if blank/empty → may need hard refresh
121
+ 4. Verify expected UI elements are present
122
+ 5. Check console for errors
123
+ 6. Check network requests for GraphQL/API issues
124
+
125
+ ## Troubleshooting
126
+
127
+ ### Extension Shows Blank After Changes
128
+
129
+ 1. Try hard refresh (`Command+Shift+R`)
130
+ 2. Check browser console for errors
131
+ 3. Check if dev server is still running
132
+ 4. Verify file saved correctly
133
+ 5. Check for TypeScript compilation errors
134
+ 6. Navigate away and back to extension
135
+
136
+ ### "Use Local Apps" Toggle Not Found
137
+
138
+ 1. Verify user is logged in
139
+ 2. Navigate directly to `https://new.manager.trackunit.com/goto/iris-app-dev`
140
+ 3. Wait for page to fully load (redirects to Developer Settings)
141
+ 4. Take snapshot to see what's visible
142
+ 5. Toggle is in the main content area, not the sidebar
143
+
144
+ ### Extension Not Appearing
145
+
146
+ 1. Verify dev server is running
147
+ 2. Check manifest has correct extension type
148
+ 3. If changed `iris-app-manifest.ts` → re-serve the app
149
+ 4. Hard refresh browser
150
+ 5. Disable and re-enable "Use Local Apps"
151
+ 6. Check browser console for loading errors
152
+
153
+ ### GraphQL/API Errors
154
+
155
+ 1. Use browser network tab to find GraphQL requests
156
+ 2. Inspect response body for "errors" array (GraphQL returns 200 even with errors)
157
+ 3. Common fixes:
158
+ - Missing scopes → Add to `iris-app-manifest.ts` scopes array
159
+ - CSP violations → Add domain to `cspHeader` in manifest
160
+ - Auth issues → Deploy app to enable new scopes
161
+
162
+ ## Workflow Checklist
163
+
164
+ ### After Every Code Change:
165
+
166
+ 1. ✅ Check lints (zero tolerance)
167
+ 2. ✅ Fix all errors
168
+ 3. ✅ Wait 2-3 seconds for hot reload
169
+ 4. ✅ Refresh browser if needed
170
+ 5. ✅ Take snapshot
171
+ 6. ✅ Verify changes visible
172
+ 7. ✅ Check console for errors
173
+ 8. ✅ Check network tab if using APIs
174
+
175
+ ### Before Moving to Next Feature:
176
+
177
+ 1. ✅ Current feature fully working in browser
178
+ 2. ✅ Zero linter/TypeScript errors
179
+ 3. ✅ Zero browser console errors
180
+ 4. ✅ All network requests successful
181
+ 5. ✅ Screenshot of working feature
182
+
183
+ ## Common Mistakes
184
+
185
+ | Mistake | Fix |
186
+ |---------|-----|
187
+ | Using default browser automation | Extensions render in iFrames; use Chrome DevTools MCP |
188
+ | Testing on localhost | Use `https://new.manager.trackunit.com/goto/iris-app-dev` |
189
+ | Skipping lint check before browser | Always run `read_lints` first |
190
+ | Not enabling "Use Local Apps" | Toggle is in main content area, not sidebar |
191
+ | Changed manifest without re-serve | Stop dev server and restart |
192
+ | Moving to next feature before verifying | Confirm current feature works in browser first |
193
+ | Chrome DevTools MCP not configured | Help user install and configure the MCP server |