@equinor/fusion-framework-cli 11.0.0-next.4 → 11.0.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/bin/build/bin.js +7 -7
  3. package/bin/build/cli.js +432 -207
  4. package/bin/build/{portal-pack-tYUpOtku.js → portal-config-publish-CqqdoblS.js} +248 -35
  5. package/dist/esm/bin/app-dev.js +17 -7
  6. package/dist/esm/bin/app-dev.js.map +1 -1
  7. package/dist/esm/bin/helpers/resolve-portal-config.js +46 -0
  8. package/dist/esm/bin/helpers/resolve-portal-config.js.map +1 -0
  9. package/dist/esm/bin/index.js +2 -0
  10. package/dist/esm/bin/index.js.map +1 -1
  11. package/dist/esm/bin/portal-config-publish.js +74 -0
  12. package/dist/esm/bin/portal-config-publish.js.map +1 -0
  13. package/dist/esm/bin/portal-config.js +48 -0
  14. package/dist/esm/bin/portal-config.js.map +1 -0
  15. package/dist/esm/bin/portal-dev.js +13 -21
  16. package/dist/esm/bin/portal-dev.js.map +1 -1
  17. package/dist/esm/bin/utils/create-dev-server.js +3 -5
  18. package/dist/esm/bin/utils/create-dev-server.js.map +1 -1
  19. package/dist/esm/cli/commands/app/alias.js +4 -4
  20. package/dist/esm/cli/commands/app/alias.js.map +1 -1
  21. package/dist/esm/cli/commands/app/build.js +10 -3
  22. package/dist/esm/cli/commands/app/build.js.map +1 -1
  23. package/dist/esm/cli/commands/app/check.js +15 -5
  24. package/dist/esm/cli/commands/app/check.js.map +1 -1
  25. package/dist/esm/cli/commands/app/config.js +20 -8
  26. package/dist/esm/cli/commands/app/config.js.map +1 -1
  27. package/dist/esm/cli/commands/app/dev.js +10 -4
  28. package/dist/esm/cli/commands/app/dev.js.map +1 -1
  29. package/dist/esm/cli/commands/app/index.js +18 -1
  30. package/dist/esm/cli/commands/app/index.js.map +1 -1
  31. package/dist/esm/cli/commands/app/manifest.js +12 -3
  32. package/dist/esm/cli/commands/app/manifest.js.map +1 -1
  33. package/dist/esm/cli/commands/app/pack.js +16 -9
  34. package/dist/esm/cli/commands/app/pack.js.map +1 -1
  35. package/dist/esm/cli/commands/app/publish.js +15 -4
  36. package/dist/esm/cli/commands/app/publish.js.map +1 -1
  37. package/dist/esm/cli/commands/app/tag.js +16 -4
  38. package/dist/esm/cli/commands/app/tag.js.map +1 -1
  39. package/dist/esm/cli/commands/app/upload.js +13 -8
  40. package/dist/esm/cli/commands/app/upload.js.map +1 -1
  41. package/dist/esm/cli/commands/auth/index.js +13 -1
  42. package/dist/esm/cli/commands/auth/index.js.map +1 -1
  43. package/dist/esm/cli/commands/auth/login.js +11 -7
  44. package/dist/esm/cli/commands/auth/login.js.map +1 -1
  45. package/dist/esm/cli/commands/auth/logout.js +10 -7
  46. package/dist/esm/cli/commands/auth/logout.js.map +1 -1
  47. package/dist/esm/cli/commands/auth/token.js +13 -9
  48. package/dist/esm/cli/commands/auth/token.js.map +1 -1
  49. package/dist/esm/cli/commands/disco/resolve.js +13 -16
  50. package/dist/esm/cli/commands/disco/resolve.js.map +1 -1
  51. package/dist/esm/cli/commands/portal/build.js +12 -7
  52. package/dist/esm/cli/commands/portal/build.js.map +1 -1
  53. package/dist/esm/cli/commands/portal/config.js +101 -0
  54. package/dist/esm/cli/commands/portal/config.js.map +1 -0
  55. package/dist/esm/cli/commands/portal/dev.js +9 -6
  56. package/dist/esm/cli/commands/portal/dev.js.map +1 -1
  57. package/dist/esm/cli/commands/portal/index.js +3 -1
  58. package/dist/esm/cli/commands/portal/index.js.map +1 -1
  59. package/dist/esm/cli/commands/portal/manifest.js +11 -8
  60. package/dist/esm/cli/commands/portal/manifest.js.map +1 -1
  61. package/dist/esm/cli/commands/portal/pack.js +13 -8
  62. package/dist/esm/cli/commands/portal/pack.js.map +1 -1
  63. package/dist/esm/cli/commands/portal/publish.js +11 -8
  64. package/dist/esm/cli/commands/portal/publish.js.map +1 -1
  65. package/dist/esm/cli/commands/portal/schema.js +10 -8
  66. package/dist/esm/cli/commands/portal/schema.js.map +1 -1
  67. package/dist/esm/cli/commands/portal/tag.js +12 -8
  68. package/dist/esm/cli/commands/portal/tag.js.map +1 -1
  69. package/dist/esm/cli/commands/portal/upload.js +8 -7
  70. package/dist/esm/cli/commands/portal/upload.js.map +1 -1
  71. package/dist/esm/lib/portal/create-portal-manifest.js +5 -5
  72. package/dist/esm/lib/portal/create-portal-manifest.js.map +1 -1
  73. package/dist/esm/lib/portal/index.js +2 -0
  74. package/dist/esm/lib/portal/index.js.map +1 -1
  75. package/dist/esm/lib/portal/load-portal-config.js +49 -0
  76. package/dist/esm/lib/portal/load-portal-config.js.map +1 -0
  77. package/dist/esm/lib/portal/load-portal-manifest.js +1 -1
  78. package/dist/esm/lib/portal/load-portal-manifest.js.map +1 -1
  79. package/dist/esm/lib/portal/portal-config.js +23 -0
  80. package/dist/esm/lib/portal/portal-config.js.map +1 -0
  81. package/dist/esm/lib/portal/portal-manifest.schema.js +1 -1
  82. package/dist/esm/lib/portal/portal-manifest.schema.js.map +1 -1
  83. package/dist/esm/version.js +1 -1
  84. package/dist/tsconfig.tsbuildinfo +1 -1
  85. package/dist/types/bin/helpers/resolve-portal-config.d.ts +18 -0
  86. package/dist/types/bin/index.d.ts +2 -0
  87. package/dist/types/bin/portal-config-publish.d.ts +26 -0
  88. package/dist/types/bin/portal-config.d.ts +46 -0
  89. package/dist/types/bin/utils/create-dev-server.d.ts +3 -3
  90. package/dist/types/cli/commands/app/config.d.ts +3 -3
  91. package/dist/types/cli/commands/app/pack.d.ts +1 -1
  92. package/dist/types/cli/commands/auth/logout.d.ts +0 -4
  93. package/dist/types/cli/commands/auth/token.d.ts +0 -5
  94. package/dist/types/cli/commands/disco/resolve.d.ts +0 -7
  95. package/dist/types/cli/commands/portal/config.d.ts +32 -0
  96. package/dist/types/lib/portal/index.d.ts +2 -0
  97. package/dist/types/lib/portal/load-portal-config.d.ts +83 -0
  98. package/dist/types/lib/portal/load-portal-manifest.d.ts +3 -3
  99. package/dist/types/lib/portal/portal-config.d.ts +69 -0
  100. package/dist/types/lib/portal/portal-manifest.schema.d.ts +1 -1
  101. package/dist/types/version.d.ts +1 -1
  102. package/package.json +10 -9
@@ -1,11 +1,5 @@
1
1
  import { loadConfigFromFile, mergeConfig, build } from 'vite';
2
2
  import chalk from 'chalk';
3
- import { PublicClientApplication, CryptoProvider } from '@azure/msal-node';
4
- import openBrowser from 'open';
5
- import { createServer } from 'node:http';
6
- import URL$2, { fileURLToPath } from 'node:url';
7
- import z$2, { z as z$1 } from 'zod';
8
- import isContinuousIntegration from 'is-ci';
9
3
  import { importConfig, FileNotFoundError } from '@equinor/fusion-imports';
10
4
  import mergeWith from 'lodash.mergewith';
11
5
  import { createDevServer as createDevServer$1, processServices } from '@equinor/fusion-framework-dev-server';
@@ -13,10 +7,16 @@ import { statSync, accessSync, constants as constants$1, existsSync, mkdirSync,
13
7
  import { stat, mkdir } from 'node:fs/promises';
14
8
  import { relative, resolve, dirname, basename, extname } from 'node:path';
15
9
  import { readPackageUp } from 'read-package-up';
10
+ import URL$2, { fileURLToPath } from 'node:url';
16
11
  import assert from 'node:assert';
17
12
  import { execSync } from 'node:child_process';
13
+ import z$2, { z as z$1 } from 'zod';
18
14
  import AdmZip from 'adm-zip';
19
15
  import prettyBytes from 'pretty-bytes';
16
+ import { PublicClientApplication, CryptoProvider } from '@azure/msal-node';
17
+ import openBrowser from 'open';
18
+ import { createServer } from 'node:http';
19
+ import isContinuousIntegration from 'is-ci';
20
20
  import ora from 'ora';
21
21
 
22
22
  /**
@@ -290,12 +290,10 @@ const applyAppRouting = (base, manifest, config) => {
290
290
  throw new Error('App manifest does not contain build information');
291
291
  }
292
292
  base.api.routes ??= [];
293
- console.warn('\n\n:::', 'Adding app routing for', appKey, 'version', build.version, 'tag', build.tag, ':::\n\n');
294
293
  // add rewrite to local fs
295
294
  base.api.routes.push({
296
295
  match: `/apps/bundles/apps/${appKey}@${build.version}/*path`,
297
296
  middleware: async (req, res, next) => {
298
- console.warn('\n\n\n--', req.params, '--\n\n\n');
299
297
  const location = req.params?.path;
300
298
  if (Array.isArray(location) === false) {
301
299
  next();
@@ -340,8 +338,9 @@ const applyAppRouting = (base, manifest, config) => {
340
338
  */
341
339
  const applyPortalRouting = (base, manifest, config) => {
342
340
  base.api.routes ??= [];
341
+ // @todo - might add correct tag handling later
343
342
  base.api.routes.push({
344
- match: `/portals/portals/${manifest.id}{@:tag}`,
343
+ match: `/portals/portals/${manifest.name}{@:tag}`,
345
344
  middleware: async (_req, res) => {
346
345
  res.writeHead(200, {
347
346
  'content-type': 'application/json',
@@ -350,7 +349,7 @@ const applyPortalRouting = (base, manifest, config) => {
350
349
  },
351
350
  });
352
351
  base.api.routes.push({
353
- match: `/portals/portals/${manifest.id}{@:tag}/config`,
352
+ match: `/portals/portals/${manifest.name}{@:tag}/config`,
354
353
  middleware: async (_req, res) => {
355
354
  res.writeHead(200, {
356
355
  'content-type': 'application/json',
@@ -386,7 +385,6 @@ const createDevServerConfig = (options) => {
386
385
  };
387
386
  },
388
387
  },
389
- server: options.server,
390
388
  };
391
389
  if (options.app) {
392
390
  applyAppRouting(config, options.app.manifest, options.app.config);
@@ -1463,6 +1461,10 @@ class ServerSentEventResponseError extends HttpResponseError {
1463
1461
  }
1464
1462
  }
1465
1463
 
1464
+ function getDefaultExportFromCjs (x) {
1465
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1466
+ }
1467
+
1466
1468
  var re = {exports: {}};
1467
1469
 
1468
1470
  var constants;
@@ -1819,11 +1821,11 @@ function requireIdentifiers () {
1819
1821
  return identifiers;
1820
1822
  }
1821
1823
 
1822
- var semver$1;
1824
+ var semver$2;
1823
1825
  var hasRequiredSemver$1;
1824
1826
 
1825
1827
  function requireSemver$1 () {
1826
- if (hasRequiredSemver$1) return semver$1;
1828
+ if (hasRequiredSemver$1) return semver$2;
1827
1829
  hasRequiredSemver$1 = 1;
1828
1830
 
1829
1831
  const debug = requireDebug();
@@ -2142,8 +2144,8 @@ function requireSemver$1 () {
2142
2144
  }
2143
2145
  }
2144
2146
 
2145
- semver$1 = SemVer;
2146
- return semver$1;
2147
+ semver$2 = SemVer;
2148
+ return semver$2;
2147
2149
  }
2148
2150
 
2149
2151
  var parse_1;
@@ -4063,11 +4065,11 @@ function requireSubset () {
4063
4065
  return subset_1;
4064
4066
  }
4065
4067
 
4066
- var semver;
4068
+ var semver$1;
4067
4069
  var hasRequiredSemver;
4068
4070
 
4069
4071
  function requireSemver () {
4070
- if (hasRequiredSemver) return semver;
4072
+ if (hasRequiredSemver) return semver$1;
4071
4073
  hasRequiredSemver = 1;
4072
4074
 
4073
4075
  // just pre-load all the stuff that index.js lazily exports
@@ -4112,7 +4114,7 @@ function requireSemver () {
4112
4114
  const intersects = requireIntersects();
4113
4115
  const simplifyRange = requireSimplify();
4114
4116
  const subset = requireSubset();
4115
- semver = {
4117
+ semver$1 = {
4116
4118
  parse,
4117
4119
  valid,
4118
4120
  clean,
@@ -4159,18 +4161,19 @@ function requireSemver () {
4159
4161
  compareIdentifiers: identifiers.compareIdentifiers,
4160
4162
  rcompareIdentifiers: identifiers.rcompareIdentifiers,
4161
4163
  };
4162
- return semver;
4164
+ return semver$1;
4163
4165
  }
4164
4166
 
4165
4167
  var semverExports = requireSemver();
4168
+ var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
4166
4169
 
4167
4170
  /**
4168
4171
  * Extension of {@link SemVer} to expose `satisfies`
4169
4172
  * @see {@link [SemVer](https://www.npmjs.com/package/semver)}
4170
4173
  */
4171
- class SemanticVersion extends semverExports.SemVer {
4174
+ class SemanticVersion extends semver.SemVer {
4172
4175
  satisfies(arg) {
4173
- return semverExports.satisfies(this, arg);
4176
+ return semver.satisfies(this, arg);
4174
4177
  }
4175
4178
  }
4176
4179
 
@@ -11529,11 +11532,14 @@ const startAppDevServer = async (options) => {
11529
11532
  // Resolve the application config using the environment and config path
11530
11533
  const appConfig = await resolveAppConfig(env, { log, config: options?.config });
11531
11534
  // Attempt to resolve the portal entry point if the portal is local
11532
- let portalEntryPoint;
11535
+ let templateEntry;
11536
+ let templateFilePath;
11533
11537
  const portalFilePath = fileURLToPath(import.meta.resolve(portalId));
11534
11538
  if (fileExistsSync(portalFilePath)) {
11535
11539
  // If the portal file exists locally, set the entry point for the dev server
11536
- portalEntryPoint = `/@fs${portalFilePath}`;
11540
+ templateEntry = portalFilePath;
11541
+ // Resolve the directory of the portal file for potential asset paths
11542
+ templateFilePath = await readPackageUp({ cwd: portalFilePath }).then((x) => x ? dirname(x?.path) : undefined);
11537
11543
  }
11538
11544
  else {
11539
11545
  // Otherwise, log that the portal is external and skip entry point resolution
@@ -11548,13 +11554,14 @@ const startAppDevServer = async (options) => {
11548
11554
  },
11549
11555
  },
11550
11556
  // If a local portal entry point is found, add it to the config
11551
- ...(portalEntryPoint
11557
+ ...(templateEntry
11552
11558
  ? {
11553
11559
  portal: {
11554
11560
  manifest: {
11555
- id: portalId,
11561
+ name: portalId,
11556
11562
  build: {
11557
- entrypoint: portalEntryPoint,
11563
+ templateEntry,
11564
+ assetPath: '/@fs',
11558
11565
  },
11559
11566
  },
11560
11567
  // @todo - replace with real portal config when available
@@ -11566,9 +11573,13 @@ const startAppDevServer = async (options) => {
11566
11573
  manifest: appManifest,
11567
11574
  config: appConfig,
11568
11575
  },
11576
+ }, {
11569
11577
  server: {
11570
- port: options?.port || 3000, // Default to port 3000 if not specified
11571
- host: 'localhost', // Use localhost for local development
11578
+ port: options?.port || 3000,
11579
+ host: 'localhost',
11580
+ fs: {
11581
+ allow: templateFilePath ? [pkg.root, templateFilePath] : [pkg.root],
11582
+ },
11572
11583
  },
11573
11584
  });
11574
11585
  await devServer.listen();
@@ -11721,7 +11732,7 @@ const PortalManifestSchema = z$1.object({
11721
11732
  * @template T - The type of the portal manifest, extending Partial<PortalManifest>. Defaults to PortalManifest.
11722
11733
  * @param env - The runtime environment containing configuration such as the root directory and environment name.
11723
11734
  * @param options - Optional settings for loading the manifest.
11724
- * @returns A promise that resolves to a `LoadAppManifestResult<T>` containing the loaded manifest, the file path, and the file extension.
11735
+ * @returns A promise that resolves to a `LoadPortalManifestResult<T>` containing the loaded manifest, the file path, and the file extension.
11725
11736
  *
11726
11737
  * This function is the main entry point for loading portal manifest files. It supports merging with a base manifest, custom file name suggestions, and extension filtering.
11727
11738
  *
@@ -11811,13 +11822,13 @@ const createPortalManifestFromPackage = (env, packageJson) => {
11811
11822
  assert(packageJson.name, 'expected [name] in packageJson');
11812
11823
  assert(packageJson.version, 'expected [version] in packageJson');
11813
11824
  // Determine the entry point for the portal based on environment (prod/dev)
11814
- const entryPoint = resolvePortalEntryPoint(env, packageJson);
11815
- // Extract appKey from package name by removing the scope and leading @
11816
- // Example: '@scope/app-name' -> 'app-name'
11825
+ const templateEntry = resolvePortalEntryPoint(env, packageJson);
11826
+ // Extract portal id from package name by removing the scope and leading @
11827
+ // Example: '@scope/portal-name' -> 'portal-name'
11817
11828
  const name = packageJson.name.replace(/^@|\w.*\//gm, '');
11818
11829
  const version = packageJson.version;
11819
11830
  // Only set assetPath when not building for production (used for dev/preview)
11820
- const assetPath = env.command === 'build' ? undefined : `bundles/portals/${name}/${version}`;
11831
+ const assetPath = env.command === 'build' ? undefined : '/@fs';
11821
11832
  // Attempt to resolve GitHub repo from package, fallback to local git remote
11822
11833
  const githubRepo = resolveRepoFromPackage(packageJson) ?? resolveGitRemoteUrl();
11823
11834
  // Construct the portal manifest object with all required fields
@@ -11826,7 +11837,7 @@ const createPortalManifestFromPackage = (env, packageJson) => {
11826
11837
  displayName: packageJson.name,
11827
11838
  description: packageJson.description || '',
11828
11839
  build: {
11829
- templateEntry: entryPoint,
11840
+ templateEntry,
11830
11841
  schemaEntry: 'portal.schema.json',
11831
11842
  assetPath,
11832
11843
  githubRepo,
@@ -11893,6 +11904,53 @@ const loadPortalSchema = async (env, options) => {
11893
11904
  };
11894
11905
  };
11895
11906
 
11907
+ /**
11908
+ * Loads and resolves the portal configuration from a file or function export.
11909
+ *
11910
+ * This function uses a script resolver to handle dynamic imports. If the imported module's default export
11911
+ * is a function, it will be invoked with the base configuration and runtime environment. The result
11912
+ * is validated against the provided schema (or a permissive passthrough schema by default).
11913
+ *
11914
+ * @param env - The runtime environment containing the root directory and other environment-specific settings.
11915
+ * @param options - Optional parameters for configuring the import process.
11916
+ * @returns A promise that resolves to the imported and validated portal configuration.
11917
+ *
11918
+ * @remarks
11919
+ * - Supports both static and dynamic config authoring patterns for portals.
11920
+ * - Ensures all configs are validated against the schema for type safety.
11921
+ * - Designed for maintainability and RAG-based documentation extraction.
11922
+ *
11923
+ * @example
11924
+ * ```ts
11925
+ * const config = await loadPortalConfig(env, { file: 'custom-portal.config.ts' });
11926
+ * ```
11927
+ */
11928
+ const loadPortalConfig = (env, options) => {
11929
+ // Suggest config filenames based on environment, fallback to default
11930
+ const suggestions = options?.file ?? [`portal.config.${env.environment}`, 'portal.config'];
11931
+ return importConfig(suggestions, {
11932
+ baseDir: env.root, // Set the base directory for config resolution
11933
+ extensions: options?.extensions, // Allow custom file extensions
11934
+ script: {
11935
+ // Custom resolver for the imported config module
11936
+ resolve: async (module) => {
11937
+ // Use provided schema or a permissive passthrough schema by default
11938
+ const schema = options?.schema ?? z$2.object({}).passthrough();
11939
+ const base = options?.base ?? {}; // Use provided base or default
11940
+ // If the module's default export is a function, invoke it with the base config and environment
11941
+ // and validate the result against the schema
11942
+ if (typeof module.default === 'function') {
11943
+ const result = (await module.default(base, env)) ?? base;
11944
+ return schema.parse(result ?? base); // Validate and return
11945
+ }
11946
+ // If the module's default export is not a function, treat it as a configuration object
11947
+ // and validate it against the schema
11948
+ return schema.parse(module.default ?? base); // Validate and return
11949
+ },
11950
+ },
11951
+ });
11952
+ };
11953
+
11896
11954
  /**
11897
11955
  * Resolves the portal manifest for a given runtime environment and package.
11898
11956
  *
@@ -12070,4 +12128,159 @@ const bundlePortal = async (options) => {
12070
12128
  };
12071
12129
  };
12072
12130
 
12073
- export { FusionEnv as F, HttpJsonResponseError as H, NoAccountsError as N, Spinner as S, bundleApp as a, buildApplication as b, buildPortal as c, bundlePortal as d, pack as e, resolveProjectPackage as f, generateApplicationConfig as g, resolveAppManifest as h, initializeFramework as i, formatPath as j, loadAppManifest as k, loadPortalManifest as l, fileExistsSync as m, createDevServer as n, loadPortalSchema as o, publishAppConfig as p, resolveDefaultEnv as r, startAppDevServer as s, writeFile as w };
12131
+ /**
12132
+ * Resolves the portal configuration based on the provided runtime environment and options.
12133
+ * Handles logging, error reporting, and fallback to built-in config if no local config is found.
12134
+ *
12135
+ * @param env - The runtime environment containing the command and mode information.
12136
+ * @param options - Optional parameters:
12137
+ * - config: Path to a specific configuration file.
12138
+ * - log: Logger utility for progress and status messages.
12139
+ * @returns A promise resolving to the loaded portal configuration.
12140
+ * @throws If the portal configuration cannot be resolved.
12141
+ */
12142
+ const resolvePortalConfig = async (env, options) => {
12143
+ const { log } = options;
12144
+ try {
12145
+ // Start logging the config creation process
12146
+ log?.start('create portal configuration');
12147
+ log?.info(`generating config with ${chalk.red.dim(env.command)} command in ${chalk.green.dim(env.mode)} mode`);
12148
+ // Attempt to load the portal config (from file if specified)
12149
+ const result = await loadPortalConfig(env, { file: options?.config });
12150
+ // Log success and show the config file path
12151
+ log?.succeed('⚙️ generated config from ', formatPath(result.path, { relative: true }));
12152
+ return result.config;
12153
+ }
12154
+ catch (err) {
12155
+ // Handle missing config file error
12156
+ if (err instanceof FileNotFoundError) {
12157
+ if (options.config) {
12158
+ // Warn if a specific config file was requested but not found
12159
+ log?.warn(`failed to load config file ${formatPath(options.config)}, please check the path.`);
12160
+ }
12161
+ else {
12162
+ // Fallback to built-in config if no local config is present
12163
+ log?.succeed(chalk.dim('⚙️ no local portal config applied, using built-in'));
12164
+ return {};
12165
+ }
12166
+ }
12167
+ // Log failure and debug information for other errors
12168
+ log?.fail('failed to resolve portal config');
12169
+ log?.debug(err);
12170
+ throw err;
12171
+ }
12172
+ };
12173
+
12174
+ /**
12175
+ * Generates the portal configuration object for the current project.
12176
+ *
12177
+ * This function resolves the portal package, sets up the runtime environment, resolves the portal config,
12178
+ * and optionally writes the config to a file if an output path is provided. Logging is supported for
12179
+ * debugging and progress tracking.
12180
+ *
12181
+ * @param options - Optional settings for logger, environment overrides, config path, and output file.
12182
+ * @returns An object containing the generated config and the resolved package info.
12183
+ * @throws If writing the config to file fails.
12184
+ * @public
12185
+ */
12186
+ const generatePortalConfig = async (options) => {
12187
+ const { log } = options ?? {};
12188
+ // Resolve the portal's package.json for root and metadata
12189
+ const pkg = await resolveProjectPackage(log);
12190
+ // Setup the runtime environment for config resolution
12191
+ const env = {
12192
+ command: 'build',
12193
+ mode: process.env.NODE_ENV ?? 'production',
12194
+ root: pkg.root,
12195
+ ...options?.env, // Allow overrides from options
12196
+ };
12197
+ // Resolve the portal config using the environment and config path
12198
+ const config = await resolvePortalConfig(env, { log, config: options?.config });
12199
+ log?.debug('config:', config);
12200
+ // If an output path is provided, write the config to file
12201
+ if (options?.output) {
12202
+ log?.start('writing config to file');
12203
+ try {
12204
+ // Write the config as pretty-printed JSON
12205
+ await writeFile(options.output, JSON.stringify(config, null, 2));
12206
+ log?.succeed('config written successfully', formatPath(options.output, { relative: true }));
12207
+ }
12208
+ catch (error) {
12209
+ // Log and rethrow errors encountered during file write
12210
+ log?.fail('failed to write config');
12211
+ throw error;
12212
+ }
12213
+ }
12214
+ // Return the generated config and resolved package info for further use
12215
+ return { config, pkg };
12216
+ };
12217
+
12218
+ /**
12219
+ * Publishes the portal configuration to the portal store for a specific build version.
12220
+ *
12221
+ * This function generates the portal config, loads the manifest, initializes the Fusion Framework,
12222
+ * and sends the config to the portal service. Handles and logs errors for common failure scenarios.
12223
+ *
12224
+ * @param options - Options for config, manifest, environment, authentication, and logging.
12225
+ * @returns A promise that resolves when publishing is complete.
12226
+ * @throws If the build version is missing or publishing fails.
12227
+ * @public
12228
+ */
12229
+ const publishPortalConfig = async (options) => {
12230
+ const { log, portal } = options;
12231
+ // Generate the portal config using provided options and environment
12232
+ const { config: portalConfig } = await generatePortalConfig({
12233
+ log,
12234
+ config: options.config,
12235
+ env: { environment: options.environment },
12236
+ });
12237
+ log?.start('Initializing Fusion Framework...');
12238
+ // Initialize the Fusion Framework with the provided environment and authentication
12239
+ const framework = await initializeFramework({
12240
+ env: options.environment,
12241
+ auth: options.auth,
12242
+ });
12243
+ log?.succeed('Initialized Fusion Framework');
12244
+ // Create a client for the 'portals' service
12245
+ const portalClient = await framework.serviceDiscovery.createClient('portals');
12246
+ // Subscribe to outgoing requests for logging and debugging
12247
+ portalClient.request$.subscribe((request) => {
12248
+ log?.debug('Request:', request);
12249
+ log?.info('🌎', 'Executing request to:', formatPath(request.uri));
12250
+ });
12251
+ log?.start('Publishing portal config');
12252
+ log?.info('Using environment:', chalk.redBright(options.environment));
12253
+ try {
12254
+ // Send a PUT request to publish the portal config for the specific build version
12255
+ const response = await portalClient.json(`/portals/${portal.name}@${portal.version}/config`, {
12256
+ method: 'PUT',
12257
+ body: portalConfig,
12258
+ });
12259
+ log?.debug('Response:', response);
12260
+ log?.succeed('Published portal config');
12261
+ }
12262
+ catch (error) {
12263
+ // Handle known HTTP errors with specific log messages
12264
+ if (error instanceof HttpJsonResponseError) {
12265
+ switch (error.response.status) {
12266
+ case 410:
12267
+ log?.fail('🤬', `Portal ${portal.name} is deleted from portals-service. Please check the portal key and try again.`);
12268
+ break;
12269
+ case 404:
12270
+ log?.fail('🤬', `Portal ${portal.name} not found. Please check the portal key and try again.`);
12271
+ break;
12272
+ case 403:
12273
+ case 401:
12274
+ log?.fail('🤬', 'You are not authorized to publish portal config. Please check your permissions.');
12275
+ break;
12276
+ default:
12277
+ log?.fail('🤬', 'Failed to publish portal config.', `Status code: ${error.response.status}`, `Message: ${error.response.statusText}`);
12278
+ break;
12279
+ }
12280
+ }
12281
+ // Rethrow error for upstream handling
12282
+ throw error;
12283
+ }
12284
+ };
12285
+
12286
+ export { FusionEnv as F, HttpJsonResponseError as H, NoAccountsError as N, Spinner as S, bundleApp as a, buildApplication as b, buildPortal as c, bundlePortal as d, generatePortalConfig as e, publishPortalConfig as f, generateApplicationConfig as g, pack as h, resolveProjectPackage as i, resolveAppManifest as j, initializeFramework as k, loadPortalManifest as l, formatPath as m, loadAppManifest as n, fileExistsSync as o, publishAppConfig as p, resolvePortalManifest as q, resolveDefaultEnv as r, startAppDevServer as s, resolvePortalConfig as t, createDevServer as u, getDefaultExportFromCjs as v, loadPortalSchema as w, writeFile as x };
@@ -4,6 +4,8 @@ import { resolveAppConfig } from './helpers/resolve-app-config.js';
4
4
  import { resolveProjectPackage } from './helpers/resolve-project-package.js';
5
5
  import { resolveAppManifest } from './helpers/resolve-app-manifest.js';
6
6
  import { createDevServer } from './utils/create-dev-server.js';
7
+ import { readPackageUp } from 'read-package-up';
8
+ import { dirname } from 'node:path';
7
9
  /**
8
10
  * Starts the application development server for local development.
9
11
  *
@@ -37,11 +39,14 @@ export const startAppDevServer = async (options) => {
37
39
  // Resolve the application config using the environment and config path
38
40
  const appConfig = await resolveAppConfig(env, { log, config: options?.config });
39
41
  // Attempt to resolve the portal entry point if the portal is local
40
- let portalEntryPoint;
42
+ let templateEntry;
43
+ let templateFilePath;
41
44
  const portalFilePath = fileURLToPath(import.meta.resolve(portalId));
42
45
  if (fileExistsSync(portalFilePath)) {
43
46
  // If the portal file exists locally, set the entry point for the dev server
44
- portalEntryPoint = `/@fs${portalFilePath}`;
47
+ templateEntry = portalFilePath;
48
+ // Resolve the directory of the portal file for potential asset paths
49
+ templateFilePath = await readPackageUp({ cwd: portalFilePath }).then((x) => x ? dirname(x?.path) : undefined);
45
50
  }
46
51
  else {
47
52
  // Otherwise, log that the portal is external and skip entry point resolution
@@ -56,13 +61,14 @@ export const startAppDevServer = async (options) => {
56
61
  },
57
62
  },
58
63
  // If a local portal entry point is found, add it to the config
59
- ...(portalEntryPoint
64
+ ...(templateEntry
60
65
  ? {
61
66
  portal: {
62
67
  manifest: {
63
- id: portalId,
68
+ name: portalId,
64
69
  build: {
65
- entrypoint: portalEntryPoint,
70
+ templateEntry,
71
+ assetPath: '/@fs',
66
72
  },
67
73
  },
68
74
  // @todo - replace with real portal config when available
@@ -74,9 +80,13 @@ export const startAppDevServer = async (options) => {
74
80
  manifest: appManifest,
75
81
  config: appConfig,
76
82
  },
83
+ }, {
77
84
  server: {
78
- port: options?.port || 3000, // Default to port 3000 if not specified
79
- host: 'localhost', // Use localhost for local development
85
+ port: options?.port || 3000,
86
+ host: 'localhost',
87
+ fs: {
88
+ allow: templateFilePath ? [pkg.root, templateFilePath] : [pkg.root],
89
+ },
80
90
  },
81
91
  });
82
92
  await devServer.listen();
@@ -1 +1 @@
1
- {"version":3,"file":"app-dev.js","sourceRoot":"","sources":["../../../src/bin/app-dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app-dev.js","sourceRoot":"","sources":["../../../src/bin/app-dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { FileNotFoundError } from '@equinor/fusion-imports';
2
+ import { chalk, formatPath } from '../utils/format.js';
3
+ import { loadPortalConfig } from '../../lib/portal';
4
+ /**
5
+ * Resolves the portal configuration based on the provided runtime environment and options.
6
+ * Handles logging, error reporting, and fallback to built-in config if no local config is found.
7
+ *
8
+ * @param env - The runtime environment containing the command and mode information.
9
+ * @param options - Optional parameters:
10
+ * - config: Path to a specific configuration file.
11
+ * - log: Logger utility for progress and status messages.
12
+ * @returns A promise resolving to the loaded portal configuration.
13
+ * @throws If the portal configuration cannot be resolved.
14
+ */
15
+ export const resolvePortalConfig = async (env, options) => {
16
+ const { log } = options;
17
+ try {
18
+ // Start logging the config creation process
19
+ log?.start('create portal configuration');
20
+ log?.info(`generating config with ${chalk.red.dim(env.command)} command in ${chalk.green.dim(env.mode)} mode`);
21
+ // Attempt to load the portal config (from file if specified)
22
+ const result = await loadPortalConfig(env, { file: options?.config });
23
+ // Log success and show the config file path
24
+ log?.succeed('⚙️ generated config from ', formatPath(result.path, { relative: true }));
25
+ return result.config;
26
+ }
27
+ catch (err) {
28
+ // Handle missing config file error
29
+ if (err instanceof FileNotFoundError) {
30
+ if (options.config) {
31
+ // Warn if a specific config file was requested but not found
32
+ log?.warn(`failed to load config file ${formatPath(options.config)}, please check the path.`);
33
+ }
34
+ else {
35
+ // Fallback to built-in config if no local config is present
36
+ log?.succeed(chalk.dim('⚙️ no local portal config applied, using built-in'));
37
+ return {};
38
+ }
39
+ }
40
+ // Log failure and debug information for other errors
41
+ log?.fail('failed to resolve portal config');
42
+ log?.debug(err);
43
+ throw err;
44
+ }
45
+ };
46
+ //# sourceMappingURL=resolve-portal-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-portal-config.js","sourceRoot":"","sources":["../../../../src/bin/helpers/resolve-portal-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAK5D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAqB,MAAM,kBAAkB,CAAC;AAEvE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,GAAe,EACf,OAAwD,EAC5C,EAAE;IACd,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,IAAI,CAAC;QACH,4CAA4C;QAC5C,GAAG,EAAE,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC1C,GAAG,EAAE,IAAI,CACP,0BAA0B,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CACpG,CAAC;QACF,6DAA6D;QAC7D,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAI,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACzE,4CAA4C;QAC5C,GAAG,EAAE,OAAO,CAAC,2BAA2B,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,mCAAmC;QACnC,IAAI,GAAG,YAAY,iBAAiB,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,6DAA6D;gBAC7D,GAAG,EAAE,IAAI,CACP,8BAA8B,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CACnF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,4DAA4D;gBAC5D,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;gBAC7E,OAAO,EAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,qDAAqD;QACrD,GAAG,EAAE,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC7C,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -6,5 +6,7 @@ export { startAppDevServer } from './app-dev.js';
6
6
  export { buildPortal } from './portal-build.js';
7
7
  export { bundlePortal } from './portal-pack.js';
8
8
  export { loadPortalManifest } from './portal-manifest.js';
9
+ export { generatePortalConfig } from './portal-config.js';
10
+ export { publishPortalConfig } from './portal-config-publish.js';
9
11
  export { pack } from './pack.js';
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { HttpJsonResponseError } from '@equinor/fusion-framework-module-http/errors';
2
+ import { initializeFramework, } from '../lib/framework.node.js';
3
+ import { formatPath, chalk } from './utils';
4
+ import { generatePortalConfig } from './portal-config.js';
5
+ /**
6
+ * Publishes the portal configuration to the portal store for a specific build version.
7
+ *
8
+ * This function generates the portal config, loads the manifest, initializes the Fusion Framework,
9
+ * and sends the config to the portal service. Handles and logs errors for common failure scenarios.
10
+ *
11
+ * @param options - Options for config, manifest, environment, authentication, and logging.
12
+ * @returns A promise that resolves when publishing is complete.
13
+ * @throws If the build version is missing or publishing fails.
14
+ * @public
15
+ */
16
+ export const publishPortalConfig = async (options) => {
17
+ const { log, portal } = options;
18
+ // Generate the portal config using provided options and environment
19
+ const { config: portalConfig } = await generatePortalConfig({
20
+ log,
21
+ config: options.config,
22
+ env: { environment: options.environment },
23
+ });
24
+ log?.start('Initializing Fusion Framework...');
25
+ // Initialize the Fusion Framework with the provided environment and authentication
26
+ const framework = await initializeFramework({
27
+ env: options.environment,
28
+ auth: options.auth,
29
+ });
30
+ log?.succeed('Initialized Fusion Framework');
31
+ // Create a client for the 'portals' service
32
+ const portalClient = await framework.serviceDiscovery.createClient('portals');
33
+ // Subscribe to outgoing requests for logging and debugging
34
+ portalClient.request$.subscribe((request) => {
35
+ log?.debug('Request:', request);
36
+ log?.info('🌎', 'Executing request to:', formatPath(request.uri));
37
+ });
38
+ log?.start('Publishing portal config');
39
+ log?.info('Using environment:', chalk.redBright(options.environment));
40
+ try {
41
+ // Send a PUT request to publish the portal config for the specific build version
42
+ const response = await portalClient.json(`/portals/${portal.name}@${portal.version}/config`, {
43
+ method: 'PUT',
44
+ body: portalConfig,
45
+ });
46
+ log?.debug('Response:', response);
47
+ log?.succeed('Published portal config');
48
+ }
49
+ catch (error) {
50
+ // Handle known HTTP errors with specific log messages
51
+ if (error instanceof HttpJsonResponseError) {
52
+ switch (error.response.status) {
53
+ case 410:
54
+ log?.fail('🤬', `Portal ${portal.name} is deleted from portals-service. Please check the portal key and try again.`);
55
+ break;
56
+ case 404:
57
+ log?.fail('🤬', `Portal ${portal.name} not found. Please check the portal key and try again.`);
58
+ break;
59
+ case 403:
60
+ case 401:
61
+ log?.fail('🤬', 'You are not authorized to publish portal config. Please check your permissions.');
62
+ break;
63
+ default:
64
+ log?.fail('🤬', 'Failed to publish portal config.', `Status code: ${error.response.status}`, `Message: ${error.response.statusText}`);
65
+ break;
66
+ }
67
+ }
68
+ // Rethrow error for upstream handling
69
+ throw error;
70
+ }
71
+ };
72
+ // Export as default for compatibility with import patterns
73
+ export default publishPortalConfig;
74
+ //# sourceMappingURL=portal-config-publish.js.map