diff --git a/crates/desktop/artcraft/tauri.conf.json b/crates/desktop/artcraft/tauri.conf.json
index d0030b8763..fc037816e8 100644
--- a/crates/desktop/artcraft/tauri.conf.json
+++ b/crates/desktop/artcraft/tauri.conf.json
@@ -4,10 +4,10 @@
"version": "0.0.1",
"identifier": "ai.artcraft.app",
"build": {
- "frontendDist": "../../../",
- "devUrl": "http://localhost:5741",
- "beforeDevCommand": "nx run editor2d:dev",
- "beforeBuildCommand": "nx run editor2d:build"
+ "frontendDist": "../../../frontend/apps/editor3d/dist",
+ "devUrl": "http://localhost:5173",
+ "beforeDevCommand": "nx run editor3d:dev",
+ "beforeBuildCommand": "nx run editor3d:build"
},
"app": {
"windows": [
diff --git a/frontend/apps/artcraft-website/src/pages/landing2/landing2.tsx b/frontend/apps/artcraft-website/src/pages/landing2/landing2.tsx
index ffcc045fb6..5a5e366de6 100644
--- a/frontend/apps/artcraft-website/src/pages/landing2/landing2.tsx
+++ b/frontend/apps/artcraft-website/src/pages/landing2/landing2.tsx
@@ -67,6 +67,7 @@ const Landing = () => {
muted
autoPlay
loop
+ playsInline
className="w-full aspect-[16/9] object-cover"
>
@@ -113,6 +114,7 @@ const Landing = () => {
autoPlay
muted
loop
+ playsInline
className="aspect-square w-full max-w-none rounded-tl-xl bg-gray-800 ring-1 ring-white/10 object-cover h-full rounded-lg overflow-hidden"
/>
@@ -137,13 +139,13 @@ const Landing = () => {
variants={fadeUpVariants}
>
-
diff --git a/frontend/apps/editor3d/app/src/Classes/GetFrontendEnvironment.ts b/frontend/apps/editor3d/app/src/Classes/GetFrontendEnvironment.ts
deleted file mode 100644
index 230aea3999..0000000000
--- a/frontend/apps/editor3d/app/src/Classes/GetFrontendEnvironment.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Environment } from "~/configs";
-
-export enum FrontendEnvironmentType {
- Dev,
- DevProxy,
- Staging,
- Production,
-}
-
-export class FrontendEnvironment {
- private static instance: FrontendEnvironment;
- private readonly environment: FrontendEnvironmentType;
- private readonly isLocalDev: boolean;
-
- public static getInstance(): FrontendEnvironment {
- if (FrontendEnvironment.instance !== undefined) {
- return FrontendEnvironment.instance;
- }
-
- if (typeof document === "undefined") {
- // TODO(bt,2025-02-10): This is digusting. Vite or whatever
- // doesn't have 'document' defined early in preloading execution.
- // This non-cached codepath is dangerous, because who knows what
- // happens downstream. Fix this ASAP.
- return new FrontendEnvironment(FrontendEnvironmentType.Production, false);
- }
-
- const isLocalDev =
- document.location.host.includes("localhost") ||
- document.location.host.startsWith("dev.") ||
- document.location.host.startsWith("development.");
-
- let environmentType = FrontendEnvironmentType.Production;
-
- if (isLocalDev) {
- environmentType = FrontendEnvironmentType.Dev;
- }
-
- if (document.location.host.includes("dev") &&
- document.location.hostname.includes("proxy")) {
- environmentType = FrontendEnvironmentType.DevProxy;
- }
-
- const instance = new FrontendEnvironment(environmentType, isLocalDev);
- FrontendEnvironment.instance = instance;
- return instance;
- }
-
- public getFrontendEnvironmentType(): FrontendEnvironmentType {
- return this.environment;
- }
-
- public getIsLocalDev(): boolean {
- return this.isLocalDev;
- }
-
- private constructor(environment: FrontendEnvironmentType, isLocalDev: boolean) {
- this.environment = environment;
- this.isLocalDev = isLocalDev;
- }
-}
-
-export function GetFrontendEnvironment() : FrontendEnvironment {
- return FrontendEnvironment.getInstance();
-}
diff --git a/frontend/apps/editor3d/app/src/api/GetCdnOrigin.ts b/frontend/apps/editor3d/app/src/api/GetCdnOrigin.ts
index 80376dd74a..79e16f250c 100644
--- a/frontend/apps/editor3d/app/src/api/GetCdnOrigin.ts
+++ b/frontend/apps/editor3d/app/src/api/GetCdnOrigin.ts
@@ -1,4 +1,4 @@
-import { GetFrontendEnvironment } from "~/Classes/GetFrontendEnvironment";
+// TODO(bt,2025-05-15): Remove this code
/**
* Return the CDN origin (scheme + host + optional port, but no path)
@@ -15,16 +15,9 @@ class CdnHostHelper {
return CdnHostHelper.instance;
}
- const isLocalDev = GetFrontendEnvironment().getIsLocalDev();
-
- let origin;
- if (isLocalDev) {
- //origin = 'https://pub-c8a4a5bdbdb048f286b77bdf9f786ff2.r2.dev';
- origin = 'https://cdn-2.fakeyou.com';
- } else {
- origin = 'https://cdn-2.fakeyou.com';
- }
+ const origin = 'https://cdn-2.fakeyou.com';
const instance = new CdnHostHelper(origin);
+
CdnHostHelper.instance = instance;
return instance;
}
diff --git a/frontend/apps/editor3d/app/src/components/signaled/TopBar/TopBar.tsx b/frontend/apps/editor3d/app/src/components/signaled/TopBar/TopBar.tsx
index 3693beead0..173b0793f8 100644
--- a/frontend/apps/editor3d/app/src/components/signaled/TopBar/TopBar.tsx
+++ b/frontend/apps/editor3d/app/src/components/signaled/TopBar/TopBar.tsx
@@ -19,6 +19,7 @@ import { Signal } from "@preact/signals-react";
import { useSignals } from "@preact/signals-react/runtime";
import { setLogoutStates } from "~/signals/authentication/utilities";
import { EngineContext } from "~/pages/PageEnigma/contexts/EngineContext";
+import { useAppUiContext } from "~/pages/Page2d/contextSignals/appUi";
function isEditorPath(path: string) {
if (path === "/") return true;
diff --git a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene.ts b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene.ts
index 0819cca671..0798ea35a0 100644
--- a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene.ts
+++ b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene.ts
@@ -11,7 +11,9 @@ import { ChromaKeyMaterial } from "./chromakey";
import { TimeLine } from "./timeline";
import { ClipGroup, ClipType } from "~/enums";
import { ClipUI } from "../clips/clip_ui";
+
import { GetFrontendEnvironment } from "~/Classes/GetFrontendEnvironment";
+
import { gridVisibility } from "../signals/engine";
import { InfiniteGridHelper } from "./InfiniteGridHelper";
import { cameras, selectedCameraId } from "../signals/camera";
@@ -379,10 +381,7 @@ class Scene {
cameraConfig.position.z,
);
- // TODO(bt,2025-02-10): Make the local dev assets more configurable or seedable.
- const camera_id = GetFrontendEnvironment().getIsLocalDev()
- ? "m_cxh4asqhapdz10j880755dg4yevshb" // Local development
- : "m_cxh4asqhapdz10j880755dg4yevshb"; // Production
+ const camera_id = "m_cxh4asqhapdz10j880755dg4yevshb";
this.loadGlbWithPlaceholder(
camera_id,
diff --git a/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoAnimationItems.ts b/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoAnimationItems.ts
index 365869f637..39320c31c2 100644
--- a/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoAnimationItems.ts
+++ b/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoAnimationItems.ts
@@ -1,5 +1,4 @@
import { signal } from "@preact/signals-core";
-import { GetFrontendEnvironment } from "~/Classes/GetFrontendEnvironment";
import { AssetType } from "~/enums";
import { MediaItem } from "~/pages/PageEnigma/models";
@@ -26,9 +25,7 @@ export const demoAnimationItems = signal([
},
{
version: 1,
- media_id: GetFrontendEnvironment().getIsLocalDev() ?
- "m_z0wj1rckcsea1sb0ht27m41g2w4zss" : // Local development
- "m_s7d4ems68sb2vqj4pdje1rc15q3ycp", // Production
+ media_id: "m_s7d4ems68sb2vqj4pdje1rc15q3ycp",
type: AssetType.ANIMATION,
length: 100,
name: "Walk",
diff --git a/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoCharacterItems.ts b/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoCharacterItems.ts
index bdcfd8fbae..e1ba2f42b1 100644
--- a/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoCharacterItems.ts
+++ b/frontend/apps/editor3d/app/src/pages/PageEnigma/signals/demoAssets/demoCharacterItems.ts
@@ -1,14 +1,11 @@
import { signal } from "@preact/signals-core";
import { MediaItem } from "~/pages/PageEnigma/models";
import { AssetType } from "~/enums";
-import { GetFrontendEnvironment } from "~/Classes/GetFrontendEnvironment";
export const demoCharacterItems = signal([
{
version: 1,
- media_id: GetFrontendEnvironment().getIsLocalDev() ?
- "m_8dvne30awgsyrb45xvha9f23gtgg8w" : // Local development
- "m_gff67btr810vg3ng9szj85zskztcgy", // Production
+ media_id: "m_gff67btr810vg3ng9szj85zskztcgy",
type: AssetType.CHARACTER,
name: "Story Girl",
thumbnail: "/resources/characters/img13.png",
diff --git a/frontend/apps/editor3d/tsconfig.json b/frontend/apps/editor3d/tsconfig.json
index a5421155f0..b89dbb548a 100644
--- a/frontend/apps/editor3d/tsconfig.json
+++ b/frontend/apps/editor3d/tsconfig.json
@@ -84,6 +84,9 @@
},
{
"path": "../../libs/tauri-utils"
+ },
+ {
+ "path": "../../libs/build-env"
}
]
}
diff --git a/frontend/libs/api/src/lib/GetCdnOrigin.ts b/frontend/libs/api/src/lib/GetCdnOrigin.ts
index 5d604bc745..132c39e58c 100644
--- a/frontend/libs/api/src/lib/GetCdnOrigin.ts
+++ b/frontend/libs/api/src/lib/GetCdnOrigin.ts
@@ -1,45 +1,4 @@
-// import { GetFrontendEnvironment } from "~/Classes/GetFrontendEnvironment";
-
-/**
- * Return the CDN origin (scheme + host + optional port, but no path)
- * See: https://web.dev/articles/url-parts
- *
- * TODO(bt,2025-02-10): Make this easier to configure in development
- */
-// class CdnHostHelper {
-// private static instance: CdnHostHelper;
-// private readonly origin: string;
-
-// public static getInstance(): CdnHostHelper {
-// if (CdnHostHelper.instance !== undefined) {
-// return CdnHostHelper.instance;
-// }
-
-// const isLocalDev = GetFrontendEnvironment().getIsLocalDev();
-
-// let origin;
-// if (isLocalDev) {
-// //origin = 'https://pub-c8a4a5bdbdb048f286b77bdf9f786ff2.r2.dev';
-// origin = "https://cdn-2.fakeyou.com";
-// } else {
-// origin = "https://cdn-2.fakeyou.com";
-// }
-// const instance = new CdnHostHelper(origin);
-// CdnHostHelper.instance = instance;
-// return instance;
-// }
-
-// public getOrigin(): string {
-// return this.origin;
-// }
-
-// private constructor(origin: string) {
-// this.origin = origin;
-// }
-// }
-
-// TODO(bt,2025-02-10): Consolidate all of this logic.
+// TODO(bt,2025-05-15): Remove this code
export function GetCdnOrigin(): string {
- // return CdnHostHelper.getInstance().getOrigin();
return "https://cdn-2.fakeyou.com";
}
diff --git a/frontend/libs/build-env/.babelrc b/frontend/libs/build-env/.babelrc
new file mode 100644
index 0000000000..1ea870ead4
--- /dev/null
+++ b/frontend/libs/build-env/.babelrc
@@ -0,0 +1,12 @@
+{
+ "presets": [
+ [
+ "@nx/react/babel",
+ {
+ "runtime": "automatic",
+ "useBuiltIns": "usage"
+ }
+ ]
+ ],
+ "plugins": []
+}
diff --git a/frontend/libs/build-env/README.md b/frontend/libs/build-env/README.md
new file mode 100644
index 0000000000..9becded76e
--- /dev/null
+++ b/frontend/libs/build-env/README.md
@@ -0,0 +1,7 @@
+# @frontend/build-env
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test @frontend/build-env` to execute the unit tests via [Vitest](https://vitest.dev/).
diff --git a/frontend/libs/build-env/package.json b/frontend/libs/build-env/package.json
new file mode 100644
index 0000000000..8712e95b42
--- /dev/null
+++ b/frontend/libs/build-env/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "@frontend/build-env",
+ "version": "0.0.1",
+ "type": "module",
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ "./package.json": "./package.json",
+ ".": {
+ "development": "./src/index.ts",
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
+ "default": "./dist/index.js"
+ }
+ }
+}
diff --git a/frontend/libs/build-env/src/index.ts b/frontend/libs/build-env/src/index.ts
new file mode 100644
index 0000000000..383df5f16d
--- /dev/null
+++ b/frontend/libs/build-env/src/index.ts
@@ -0,0 +1,3 @@
+
+export * from './lib/BuildEnv';
+export * from './lib/BuildEnvType';
diff --git a/frontend/libs/build-env/src/lib/BuildEnv.ts b/frontend/libs/build-env/src/lib/BuildEnv.ts
new file mode 100644
index 0000000000..983923e3fa
--- /dev/null
+++ b/frontend/libs/build-env/src/lib/BuildEnv.ts
@@ -0,0 +1,30 @@
+import { BuildEnvType, GetBuildEnvType } from "./BuildEnvType";
+
+export class BuildEnv {
+ private static instance: BuildEnv;
+ private readonly envType: BuildEnvType;
+
+ public static getInstance(): BuildEnv {
+ if (BuildEnv.instance !== undefined) {
+ return BuildEnv.instance;
+ }
+
+ const envType = GetBuildEnvType();
+ const instance = new BuildEnv(envType);
+ BuildEnv.instance = instance;
+
+ return instance;
+ }
+
+ public getType(): BuildEnvType {
+ return this.envType;
+ }
+
+ private constructor(envType: BuildEnvType) {
+ this.envType = envType;
+ }
+}
+
+export function GetBuildEnv() : BuildEnv {
+ return BuildEnv.getInstance();
+}
diff --git a/frontend/libs/build-env/src/lib/BuildEnvType.ts b/frontend/libs/build-env/src/lib/BuildEnvType.ts
new file mode 100644
index 0000000000..9ea80ecd06
--- /dev/null
+++ b/frontend/libs/build-env/src/lib/BuildEnvType.ts
@@ -0,0 +1,61 @@
+
+/**
+ * This is cached whenever vite/remix launches or CI/CD bakes in constants.
+ * It's fed from an environment variable.
+ */
+export enum BuildEnvType {
+ Dev,
+ DevProxy,
+ Staging,
+ Production,
+}
+
+// Use CI/CD to replace this value with one of the BuildEnvType values.
+const BUILD_ENV_TYPE = '%BUILD_ENV_TYPE_VALUE%';
+
+// Attempt to read the environment type.
+export function GetBuildEnvType() : BuildEnvType {
+ let maybeEnvType : BuildEnvType | undefined = undefined;
+
+ if (!BUILD_ENV_TYPE.startsWith("%") && !BUILD_ENV_TYPE.endsWith("%")) {
+ maybeEnvType = stringToEnvType(BUILD_ENV_TYPE);
+ if (maybeEnvType !== undefined) {
+ return maybeEnvType;
+ }
+ }
+
+ if (import.meta.env.BUILD_ENV_TYPE !== undefined) {
+ console.log(`Reading environment variable 'BUILD_ENV_TYPE' (= ${import.meta.env.BUILD_ENV_TYPE}) to determine build environment.`)
+ maybeEnvType = stringToEnvType(import.meta.env.BUILD_ENV_TYPE);
+ if (maybeEnvType !== undefined) {
+ return maybeEnvType;
+ }
+ }
+
+ if (import.meta.env.VITE_ENVIRONMENT_TYPE !== undefined) {
+ console.log(`Reading legacy environment variable 'VITE_ENVIRONMENT_TYPE' (= ${import.meta.env.VITE_ENVIRONMENT_TYPE}) to determine build environment.`)
+ maybeEnvType = stringToEnvType(import.meta.env.VITE_ENVIRONMENT_TYPE);
+ if (maybeEnvType !== undefined) {
+ return maybeEnvType;
+ }
+ }
+
+ // Always default to production.
+ return BuildEnvType.Production;
+}
+
+function stringToEnvType(str: string): BuildEnvType | undefined {
+ switch (str.toLocaleLowerCase()) {
+ case "dev":
+ case "development":
+ return BuildEnvType.Dev;
+ case "dev-proxy":
+ case "devproxy":
+ return BuildEnvType.DevProxy;
+ case "stage":
+ case "staging":
+ return BuildEnvType.Staging;
+ default:
+ return undefined;
+ }
+}
diff --git a/frontend/libs/build-env/tsconfig.json b/frontend/libs/build-env/tsconfig.json
new file mode 100644
index 0000000000..8c5fc025ff
--- /dev/null
+++ b/frontend/libs/build-env/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "extends": "../../tsconfig.base.json"
+}
diff --git a/frontend/libs/build-env/tsconfig.lib.json b/frontend/libs/build-env/tsconfig.lib.json
new file mode 100644
index 0000000000..ea31c66850
--- /dev/null
+++ b/frontend/libs/build-env/tsconfig.lib.json
@@ -0,0 +1,45 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "types": [
+ "node",
+ "@nx/react/typings/cssmodule.d.ts",
+ "@nx/react/typings/image.d.ts",
+ "vite/client"
+ ],
+ "rootDir": "src",
+ "jsx": "react-jsx",
+ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
+ },
+ "exclude": [
+ "out-tsc",
+ "dist",
+ "**/*.spec.ts",
+ "**/*.test.ts",
+ "**/*.spec.tsx",
+ "**/*.test.tsx",
+ "**/*.spec.js",
+ "**/*.test.js",
+ "**/*.spec.jsx",
+ "**/*.test.jsx",
+ "vite.config.ts",
+ "vite.config.mts",
+ "vitest.config.ts",
+ "vitest.config.mts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.test.tsx",
+ "src/**/*.spec.tsx",
+ "src/**/*.test.js",
+ "src/**/*.spec.js",
+ "src/**/*.test.jsx",
+ "src/**/*.spec.jsx"
+ ],
+ "include": [
+ "src/**/*.js",
+ "src/**/*.jsx",
+ "src/**/*.ts",
+ "src/**/*.tsx"
+ ]
+}
diff --git a/frontend/libs/build-env/tsconfig.spec.json b/frontend/libs/build-env/tsconfig.spec.json
new file mode 100644
index 0000000000..c1faced82c
--- /dev/null
+++ b/frontend/libs/build-env/tsconfig.spec.json
@@ -0,0 +1,34 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/vitest",
+ "types": [
+ "vitest/globals",
+ "vitest/importMeta",
+ "vite/client",
+ "node",
+ "vitest"
+ ],
+ "jsx": "react-jsx"
+ },
+ "include": [
+ "vite.config.ts",
+ "vite.config.mts",
+ "vitest.config.ts",
+ "vitest.config.mts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.test.tsx",
+ "src/**/*.spec.tsx",
+ "src/**/*.test.js",
+ "src/**/*.spec.js",
+ "src/**/*.test.jsx",
+ "src/**/*.spec.jsx",
+ "src/**/*.d.ts"
+ ],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ }
+ ]
+}
diff --git a/frontend/libs/build-env/vite.config.ts b/frontend/libs/build-env/vite.config.ts
new file mode 100644
index 0000000000..577c9d15f1
--- /dev/null
+++ b/frontend/libs/build-env/vite.config.ts
@@ -0,0 +1,49 @@
+///
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import dts from 'vite-plugin-dts';
+import * as path from 'path';
+
+export default defineConfig(() => ({
+ root: __dirname,
+ cacheDir: '../../node_modules/.vite/libs/build-env',
+ plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
+ // Uncomment this if you are using workers.
+ // worker: {
+ // plugins: [ nxViteTsPaths() ],
+ // },
+ // Configuration for building your library.
+ // See: https://vitejs.dev/guide/build.html#library-mode
+ build: {
+ outDir: './dist',
+ emptyOutDir: true,
+ reportCompressedSize: true,
+ commonjsOptions: {
+ transformMixedEsModules: true,
+ },
+ lib: {
+ // Could also be a dictionary or array of multiple entry points.
+ entry: 'src/index.ts',
+ name: '@frontend/build-env',
+ fileName: 'index',
+ // Change this to the formats you want to support.
+ // Don't forget to update your package.json as well.
+ formats: ['es' as const]
+ },
+ rollupOptions: {
+ // External packages that should not be bundled into your library.
+ external: ['react','react-dom','react/jsx-runtime']
+ },
+ },
+ test: {
+ watch: false,
+ globals: true,
+ environment: 'jsdom',
+ include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+ reporters: ['default'],
+ coverage: {
+ reportsDirectory: './test-output/vitest/coverage',
+ provider: 'v8' as const,
+ }
+ },
+}));
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 6203d8cd54..051e606855 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -2187,6 +2187,10 @@
"@tauri-apps/plugin-upload": "2.2.1"
}
},
+ "libs/build-env": {
+ "name": "@frontend/build-env",
+ "version": "0.0.1"
+ },
"libs/common": {
"name": "@storyteller/common",
"version": "0.0.1"
@@ -5020,6 +5024,10 @@
"resolved": "apps/artcraft-website",
"link": true
},
+ "node_modules/@frontend/build-env": {
+ "resolved": "libs/build-env",
+ "link": true
+ },
"node_modules/@frontend/login": {
"resolved": "libs/login",
"link": true
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index 3c6736b982..ab379e6875 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -89,6 +89,9 @@
},
{
"path": "./libs/components/switch"
+ },
+ {
+ "path": "./libs/build-env"
}
]
}