@lukoweb/apitogo 0.2.64 → 0.2.65

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/dist/cli/cli.js CHANGED
@@ -8519,10 +8519,13 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
8519
8519
  }
8520
8520
  ] : []
8521
8521
  ];
8522
+ const logo = portal?.logo ? siteLogo(portal) : void 0;
8522
8523
  return {
8524
+ // The browser tab's icon is the project's logo; without one, the portal's own icon (API-134).
8525
+ ...logo ? { metadata: { favicon: logo.src.light } } : {},
8523
8526
  site: {
8524
8527
  title: portal?.name ?? resolved.project.name,
8525
- ...portal?.logo ? { logo: siteLogo(portal) } : {},
8528
+ ...logo ? { logo } : {},
8526
8529
  ...plan2.preview ? { banner: { message: PREVIEW_BANNER_MESSAGE, color: "caution" } } : {}
8527
8530
  },
8528
8531
  modules: {
@@ -11430,7 +11433,7 @@ import {
11430
11433
  // package.json
11431
11434
  var package_default = {
11432
11435
  name: "@lukoweb/apitogo",
11433
- version: "0.2.64",
11436
+ version: "0.2.65",
11434
11437
  type: "module",
11435
11438
  sideEffects: [
11436
11439
  "**/*.css",
@@ -23190,6 +23193,9 @@ function waitForJobStepLabel(kind, moduleType) {
23190
23193
  return "Job";
23191
23194
  }
23192
23195
  }
23196
+ function deletionFinished(error) {
23197
+ return error instanceof ProjectGoneError || error instanceof PlatformApiError && error.status === 404;
23198
+ }
23193
23199
  function projectDeletionNotFoundResult(last, jobId) {
23194
23200
  return last ?? {
23195
23201
  status: "Completed",
@@ -23251,7 +23257,7 @@ function pollProvisionJob(poll, options) {
23251
23257
  stepLabel: options.stepLabel,
23252
23258
  progress: options.progress?.child(options.stepLabel),
23253
23259
  onPollError: options.kind === "projectDeletion" ? (error, last) => {
23254
- if (error instanceof PlatformApiError && error.status === 404) {
23260
+ if (deletionFinished(error)) {
23255
23261
  return {
23256
23262
  status: "succeeded",
23257
23263
  value: projectDeletionNotFoundResult(last, options.jobId),
@@ -3,6 +3,7 @@ import { type ApitogoConfig } from "../config.js";
3
3
  import { recentJobMessages, type ProgressReporter } from "../helpers/progress.js";
4
4
  export type WaitForJobKind = "module" | "deployment" | "azureInfrastructure" | "projectDeletion" | "devPortalDeploy" | "devPortalBackendUpdate";
5
5
  export declare function waitForJobStepLabel(kind: WaitForJobKind, moduleType?: string): string;
6
+ export declare function deletionFinished(error: unknown): boolean;
6
7
  export declare function handleActivateModule(client: PlatformApiClient, config: ApitogoConfig, args: {
7
8
  projectId?: string;
8
9
  moduleType: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo",
3
- "version": "0.2.64",
3
+ "version": "0.2.65",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -400,10 +400,13 @@ export function buildSiteConfig(
400
400
  ]
401
401
  : []),
402
402
  ];
403
+ const logo = portal?.logo ? siteLogo(portal) : undefined;
403
404
  return {
405
+ // The browser tab's icon is the project's logo; without one, the portal's own icon (API-134).
406
+ ...(logo ? { metadata: { favicon: logo.src.light } } : {}),
404
407
  site: {
405
408
  title: portal?.name ?? resolved.project.name,
406
- ...(portal?.logo ? { logo: siteLogo(portal) } : {}),
409
+ ...(logo ? { logo } : {}),
407
410
  ...(plan.preview
408
411
  ? { banner: { message: PREVIEW_BANNER_MESSAGE, color: "caution" } }
409
412
  : {}),
@@ -518,9 +521,10 @@ export const PREVIEW_BANNER_MESSAGE =
518
521
  * The header logo as the site takes it: a file of the portal's `public/` folder becomes its address on the site, an https
519
522
  * address stays as it is (API-129). `check` refuses a file outside `public/`.
520
523
  */
521
- function siteLogo(
522
- portal: NonNullable<ResolvedConfigV2["portal"]>,
523
- ): Record<string, unknown> {
524
+ function siteLogo(portal: NonNullable<ResolvedConfigV2["portal"]>): {
525
+ src: { light: string; dark: string };
526
+ alt: string;
527
+ } {
524
528
  const logo = portal.logo as NonNullable<typeof portal.logo>;
525
529
  const publicDir = path.join(portal.dir, "public");
526
530
  const src = (file: string) =>
@@ -1,46 +1,49 @@
1
- import { Helmet } from "@zudoku/react-helmet-async";
2
- import type { PropsWithChildren } from "react";
3
- import { useLocation } from "react-router";
4
- import { joinUrl } from "../util/joinUrl.js";
5
- import { useZudoku } from "./context/ZudokuContext.js";
6
-
7
- export const Meta = ({ children }: PropsWithChildren) => {
8
- const { options } = useZudoku();
9
- const { metadata: meta } = options;
10
- const location = useLocation();
11
-
12
- return (
13
- <>
14
- <Helmet titleTemplate={meta?.title} defaultTitle={meta?.defaultTitle}>
15
- {options.canonicalUrlOrigin && (
16
- <link
17
- rel="canonical"
18
- href={joinUrl(
19
- options.canonicalUrlOrigin,
20
- options.basePath,
21
- location.pathname,
22
- )}
23
- />
24
- )}
25
- {meta?.description && (
26
- <meta name="description" content={meta.description} />
27
- )}
28
- {meta?.favicon && <link rel="icon" href={meta.favicon} />}
29
- {meta?.generator && <meta name="generator" content={meta.generator} />}
30
- {meta?.applicationName && (
31
- <meta name="application-name" content={meta.applicationName} />
32
- )}
33
- {meta?.referrer && <meta name="referrer" content={meta.referrer} />}
34
- {meta?.keywords && meta.keywords.length > 0 && (
35
- <meta name="keywords" content={meta.keywords.join(", ")} />
36
- )}
37
- {meta?.authors?.map((author) => (
38
- <meta key={author} name="author" content={author} />
39
- ))}
40
- {meta?.creator && <meta name="creator" content={meta.creator} />}
41
- {meta?.publisher && <meta name="publisher" content={meta.publisher} />}
42
- </Helmet>
43
- {children}
44
- </>
45
- );
46
- };
1
+ import { Helmet } from "@zudoku/react-helmet-async";
2
+ import type { PropsWithChildren } from "react";
3
+ import { useLocation } from "react-router";
4
+ // A site without its own icon would leave the browser asking for /favicon.ico, a 404 and a console error on every page
5
+ // (API-134). The build publishes this file with a hashed name, so no project has to carry it.
6
+ import defaultFavicon from "../assets/powered-by-icon.png";
7
+ import { joinUrl } from "../util/joinUrl.js";
8
+ import { useZudoku } from "./context/ZudokuContext.js";
9
+
10
+ export const Meta = ({ children }: PropsWithChildren) => {
11
+ const { options } = useZudoku();
12
+ const { metadata: meta } = options;
13
+ const location = useLocation();
14
+
15
+ return (
16
+ <>
17
+ <Helmet titleTemplate={meta?.title} defaultTitle={meta?.defaultTitle}>
18
+ {options.canonicalUrlOrigin && (
19
+ <link
20
+ rel="canonical"
21
+ href={joinUrl(
22
+ options.canonicalUrlOrigin,
23
+ options.basePath,
24
+ location.pathname,
25
+ )}
26
+ />
27
+ )}
28
+ {meta?.description && (
29
+ <meta name="description" content={meta.description} />
30
+ )}
31
+ <link rel="icon" href={meta?.favicon ?? defaultFavicon} />
32
+ {meta?.generator && <meta name="generator" content={meta.generator} />}
33
+ {meta?.applicationName && (
34
+ <meta name="application-name" content={meta.applicationName} />
35
+ )}
36
+ {meta?.referrer && <meta name="referrer" content={meta.referrer} />}
37
+ {meta?.keywords && meta.keywords.length > 0 && (
38
+ <meta name="keywords" content={meta.keywords.join(", ")} />
39
+ )}
40
+ {meta?.authors?.map((author) => (
41
+ <meta key={author} name="author" content={author} />
42
+ ))}
43
+ {meta?.creator && <meta name="creator" content={meta.creator} />}
44
+ {meta?.publisher && <meta name="publisher" content={meta.publisher} />}
45
+ </Helmet>
46
+ {children}
47
+ </>
48
+ );
49
+ };