@trackunit/iris-app 2.3.2 → 2.3.3

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,13 @@
1
+ ## 2.3.3 (2026-08-04)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated iris-app-build-utilities to 2.2.3
6
+ - Updated iris-app-api to 2.2.3
7
+ - Updated react-vite-test-setup to 0.0.89
8
+ - Updated react-graphql-tools to 1.14.90
9
+ - Updated shared-utils to 1.15.91
10
+
1
11
  ## 2.3.2 (2026-08-03)
2
12
 
3
13
  ### 🧱 Updated Dependencies
package/README.md CHANGED
@@ -11,6 +11,24 @@ For more info and a full guide on Iris App SDK Development, please visit our [De
11
11
 
12
12
  Run through the easy getting started guide here: [Getting Started](https://developers.trackunit.com/docs/getting-started)
13
13
 
14
+ ## Serverside GraphQL scaffolding
15
+
16
+ Typed access to the Trackunit public GraphQL API is optional for serverside API extensions:
17
+
18
+ ```bash
19
+ npx nx generate @trackunit/iris-app:extend \
20
+ --type=SERVERSIDE_API_EXTENSION \
21
+ --graphql
22
+ ```
23
+
24
+ The option is off by default. It reuses the standard `graphql-hooks` target, configures React-free code generation against the public schema, and adds a named typed asset query example. Regenerate documents after editing `.graphql` files:
25
+
26
+ ```bash
27
+ npx nx run <project>:graphql-hooks
28
+ ```
29
+
30
+ Local requests must include a user bearer token. Set `SDK_ENVIRONMENT=DEV` or `STAGE` in the extension's `.env` to target a non-production public API; unset defaults to production.
31
+
14
32
  ## Testing Local Changes
15
33
 
16
34
  To test changes to the SDK generators locally, you can verify them in a full, temporary workspace environment.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "main": "src/index.js",
6
6
  "generators": "./generators.json",
@@ -23,8 +23,10 @@
23
23
  "@nx/react": "23.1.0",
24
24
  "@npmcli/arborist": "^9.1.9",
25
25
  "win-ca": "^3.5.1",
26
- "@trackunit/shared-utils": "1.15.90",
27
- "@trackunit/iris-app-api": "2.2.2",
26
+ "@trackunit/iris-app-build-utilities": "2.2.3",
27
+ "@trackunit/react-graphql-tools": "1.14.90",
28
+ "@trackunit/shared-utils": "1.15.91",
29
+ "@trackunit/iris-app-api": "2.2.3",
28
30
  "tslib": "^2.6.2",
29
31
  "@clack/prompts": "^1.0.0",
30
32
  "@npm/types": "^1.0.2",
@@ -4,8 +4,8 @@ exports.IrisAppGenerator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const internal_1 = require("@nx/js/internal");
7
- const pacote = tslib_1.__importStar(require("pacote"));
8
7
  const path = tslib_1.__importStar(require("path"));
8
+ const get_package_manifest_1 = require("../utils/get-package-manifest");
9
9
  function normalizeOptions(tree, options) {
10
10
  const name = (0, devkit_1.names)(options.name).fileName;
11
11
  const projectDirectory = options.directory ? path.join(options.directory, name) : name;
@@ -36,9 +36,6 @@ function addFiles(tree, options, packageJson) {
36
36
  };
37
37
  (0, devkit_1.generateFiles)(tree, path.join(__dirname, "files"), options.projectRoot, templateOptions);
38
38
  }
39
- const getManifest = (packageName) => {
40
- return pacote.manifest(packageName, process.env.TU_NPM_REGISTRY ? { registry: process.env.TU_NPM_REGISTRY } : undefined);
41
- };
42
39
  /**
43
40
  * Iris App Generator.
44
41
  * This generator will create a new iris app, you can call this from your own generator.
@@ -49,24 +46,24 @@ const getManifest = (packageName) => {
49
46
  */
50
47
  const IrisAppGenerator = async function (tree, options) {
51
48
  const normalizedOptions = normalizeOptions(tree, options);
52
- const packageJsonFromNpm = await getManifest("@trackunit/iris-app");
49
+ const packageJsonFromNpm = await (0, get_package_manifest_1.getPackageManifest)("@trackunit/iris-app");
53
50
  const packageJsonLocally = (0, devkit_1.readJsonFile)(path.join(__dirname, "..", "..", "..", "package.json"));
54
51
  if (options.updatePackageJson) {
55
52
  if (packageJsonFromNpm.version !== packageJsonLocally.version) {
56
53
  // eslint-disable-next-line no-console
57
54
  console.warn(`⚠️ 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}`);
58
55
  }
59
- const reactComponentsPackageJsonFromNpm = getManifest("@trackunit/react-components");
60
- const reactCoreContextsPackageJsonFromNpm = getManifest("@trackunit/react-core-contexts");
61
- const cssCorePackageJsonFromNpm = getManifest("@trackunit/css-core");
56
+ const reactComponentsPackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/react-components");
57
+ const reactCoreContextsPackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/react-core-contexts");
58
+ const cssCorePackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/css-core");
62
59
  const tuDependencies = {
63
60
  "@trackunit/react-components": (await reactComponentsPackageJsonFromNpm).version,
64
61
  "@trackunit/react-core-contexts": (await reactCoreContextsPackageJsonFromNpm).version,
65
62
  "@trackunit/css-core": (await cssCorePackageJsonFromNpm).version,
66
63
  };
67
- const irisAppSdkVitePackageJsonFromNpm = getManifest("@trackunit/iris-app-sdk-vite");
68
- const reactCoreContextsTestPackageJsonFromNpm = getManifest("@trackunit/react-core-contexts-test");
69
- const reactTestSetupPackageJsonFromNpm = getManifest("@trackunit/react-test-setup");
64
+ const irisAppSdkVitePackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/iris-app-sdk-vite");
65
+ const reactCoreContextsTestPackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/react-core-contexts-test");
66
+ const reactTestSetupPackageJsonFromNpm = (0, get_package_manifest_1.getPackageManifest)("@trackunit/react-test-setup");
70
67
  const tuDevDependencies = {
71
68
  "@trackunit/iris-app-sdk-vite": (await irisAppSdkVitePackageJsonFromNpm).version,
72
69
  "@trackunit/react-core-contexts-test": (await reactCoreContextsTestPackageJsonFromNpm).version,
@@ -0,0 +1,6 @@
1
+ query <%= className %>AssetById($id: ID!) {
2
+ asset(id: $id) {
3
+ id
4
+ name
5
+ }
6
+ }
@@ -0,0 +1,31 @@
1
+ import { createTrackunitGraphqlClient, getUserToken } from "@trackunit/serverside-utils";
2
+ import { Hono } from "hono";
3
+ import { <%= className %>AssetByIdDocument } from "./generated/graphql-api/graphql";
4
+
5
+ const app = new Hono();
6
+
7
+ app.get("/health", c => {
8
+ return c.json({
9
+ status: "ok",
10
+ timestamp: new Date().toISOString(),
11
+ service: "<%= projectName %>",
12
+ });
13
+ });
14
+
15
+ app.get("/assets/:id", async c => {
16
+ const token = getUserToken({ context: c });
17
+ if (!token) {
18
+ return c.json({ error: "Unauthorized" }, 401);
19
+ }
20
+
21
+ const client = createTrackunitGraphqlClient({ context: c });
22
+ const data = await client.request({
23
+ document: <%= className %>AssetByIdDocument,
24
+ variables: { id: c.req.param("id") },
25
+ signal: c.req.raw.signal,
26
+ });
27
+
28
+ return c.json(data);
29
+ });
30
+
31
+ export default app.fetch;
@@ -1,5 +1,15 @@
1
1
  import { Tree } from "@nx/devkit";
2
2
  import { IrisAppExtensionGeneratorSchema } from "./schema";
3
+ type ServersideGraphqlOptions = {
4
+ readonly projectName: string;
5
+ readonly projectRoot: string;
6
+ readonly className: string;
7
+ readonly serversideUtilsVersion: string;
8
+ };
9
+ /**
10
+ * Adds public-schema codegen and a typed Hono example to a generated serverside extension.
11
+ */
12
+ export declare const addServersideGraphql: (tree: Tree, options: ServersideGraphqlOptions) => Promise<void>;
3
13
  /**
4
14
  * Ensures that jest.preset.js exists and includes the required @trackunit/react-test-setup preset.
5
15
  * If the file doesn't exist, creates it. If it exists but doesn't include the preset, updates it.
@@ -13,3 +23,4 @@ export declare function ensureJestPresetConfiguration(tree: Tree, templateOption
13
23
  * @returns { Promise<void> } void
14
24
  */
15
25
  export declare const IrisAppExtensionGenerator: (tree: Tree, options: IrisAppExtensionGeneratorSchema) => Promise<() => void>;
26
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IrisAppExtensionGenerator = void 0;
3
+ exports.IrisAppExtensionGenerator = exports.addServersideGraphql = void 0;
4
4
  exports.ensureJestPresetConfiguration = ensureJestPresetConfiguration;
5
5
  const tslib_1 = require("tslib");
6
6
  const devkit_1 = require("@nx/devkit");
@@ -9,12 +9,53 @@ const js_1 = require("@nx/js");
9
9
  const internal_1 = require("@nx/js/internal");
10
10
  const react_1 = require("@nx/react");
11
11
  const iris_app_api_1 = require("@trackunit/iris-app-api");
12
+ const react_graphql_tools_1 = require("@trackunit/react-graphql-tools");
12
13
  const fs = tslib_1.__importStar(require("fs"));
13
14
  const path = tslib_1.__importStar(require("path"));
14
15
  const string_ts_1 = require("string-ts");
15
16
  const ts_morph_1 = require("ts-morph");
16
17
  const astUtils_1 = require("../../utils/ast/astUtils");
18
+ const get_package_manifest_1 = require("../utils/get-package-manifest");
17
19
  const dependencies_1 = require("./dependencies");
20
+ const addGraphqlDependency = (target) => {
21
+ if (!target) {
22
+ return;
23
+ }
24
+ const dependsOn = target.dependsOn ?? [];
25
+ if (!dependsOn.includes("graphql-hooks")) {
26
+ target.dependsOn = [...dependsOn, "graphql-hooks"];
27
+ }
28
+ };
29
+ /**
30
+ * Adds public-schema codegen and a typed Hono example to a generated serverside extension.
31
+ */
32
+ const addServersideGraphql = async (tree, options) => {
33
+ await (0, react_graphql_tools_1.addGraphqlGenerator)(tree, {
34
+ project: options.projectName,
35
+ schemaSource: "public",
36
+ generateMocks: false,
37
+ });
38
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, "files", "SERVERSIDE_API_EXTENSION_GRAPHQL"), options.projectRoot, {
39
+ ...options,
40
+ template: "",
41
+ });
42
+ (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, "project.json"), projectJson => {
43
+ addGraphqlDependency(projectJson.targets.build);
44
+ addGraphqlDependency(projectJson.targets.test);
45
+ addGraphqlDependency(projectJson.targets.serve);
46
+ addGraphqlDependency(projectJson.targets["tsc-validate"]);
47
+ return projectJson;
48
+ });
49
+ (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, "package.json"), packageJson => {
50
+ packageJson.dependencies = {
51
+ ...packageJson.dependencies,
52
+ "@trackunit/serverside-utils": options.serversideUtilsVersion,
53
+ };
54
+ return packageJson;
55
+ });
56
+ };
57
+ exports.addServersideGraphql = addServersideGraphql;
58
+ const getPackageVersion = async (packageName) => (await (0, get_package_manifest_1.getPackageManifest)(packageName)).version;
18
59
  function normalizeOptions(tree, options) {
19
60
  const name = (0, devkit_1.names)(options.name).fileName;
20
61
  const projectDirectory = options.directory ? `${(0, devkit_1.names)(options.directory).fileName}/${name}` : name;
@@ -86,6 +127,9 @@ const IrisAppExtensionGenerator = async function (tree, options) {
86
127
  template: "",
87
128
  };
88
129
  const irisAppExtensionType = normalizedOptions.type;
130
+ if (normalizedOptions.graphql && irisAppExtensionType !== "SERVERSIDE_API_EXTENSION") {
131
+ throw new Error("GraphQL setup is only supported for SERVERSIDE_API_EXTENSION");
132
+ }
89
133
  if (!tree.exists(`${(0, devkit_1.getWorkspaceLayout)(tree).appsDir}/${normalizedOptions.app}`)) {
90
134
  throw new Error(`The app does not exist: ${(0, devkit_1.getWorkspaceLayout)(tree).appsDir}/${normalizedOptions.app} make sure you enter the right app name`);
91
135
  }
@@ -193,6 +237,14 @@ const IrisAppExtensionGenerator = async function (tree, options) {
193
237
  return projectJson;
194
238
  });
195
239
  }
240
+ if (normalizedOptions.graphql) {
241
+ await (0, exports.addServersideGraphql)(tree, {
242
+ projectName: normalizedOptions.projectName,
243
+ projectRoot: normalizedOptions.projectRoot,
244
+ className: (0, devkit_1.names)(normalizedOptions.name).className,
245
+ serversideUtilsVersion: await getPackageVersion("@trackunit/serverside-utils"),
246
+ });
247
+ }
196
248
  //TODO: Change the following to update the manifest in the virtual Tree - not on the file system.
197
249
  const project = new ts_morph_1.Project({
198
250
  tsConfigFilePath: `${(0, devkit_1.getWorkspaceLayout)(tree).appsDir}/${normalizedOptions.app}/tsconfig.app.json`,
@@ -16,4 +16,5 @@ export interface IrisAppExtensionGeneratorSchema {
16
16
  | "LIFECYCLE_EXTENSION"
17
17
  | "SERVERSIDE_API_EXTENSION";
18
18
  extendJestPreset?: boolean;
19
+ graphql?: boolean;
19
20
  }
@@ -64,6 +64,11 @@
64
64
  "type": "boolean",
65
65
  "description": "If the root jest.preset.js should be extended with the Iris app preset",
66
66
  "default": true
67
+ },
68
+ "graphql": {
69
+ "type": "boolean",
70
+ "description": "Add typed Trackunit public GraphQL support (SERVERSIDE_API_EXTENSION only)",
71
+ "default": false
67
72
  }
68
73
  },
69
74
  "required": ["name", "directory", "type"]
@@ -0,0 +1,5 @@
1
+ import * as pacote from "pacote";
2
+ /**
3
+ * Keeps Trackunit registry overrides consistent across package-consuming generators.
4
+ */
5
+ export declare const getPackageManifest: (packageName: string) => Promise<pacote.AbbreviatedManifest & pacote.ManifestResult>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPackageManifest = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const pacote = tslib_1.__importStar(require("pacote"));
6
+ /**
7
+ * Keeps Trackunit registry overrides consistent across package-consuming generators.
8
+ */
9
+ const getPackageManifest = (packageName) => pacote.manifest(packageName, process.env.TU_NPM_REGISTRY ? { registry: process.env.TU_NPM_REGISTRY } : undefined);
10
+ exports.getPackageManifest = getPackageManifest;
11
+ //# sourceMappingURL=get-package-manifest.js.map