@teamscala/service-boot 0.23.363 → 0.23.364

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/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "name": "@teamscala/service-boot",
8
8
  "type": "module",
9
- "version": "0.23.363",
9
+ "version": "0.23.364",
10
10
  "sideEffects": false,
11
11
  "imports": {
12
12
  "#service-boot/*": "./src/*",
@@ -6,11 +6,11 @@
6
6
  * Authenticated asset upload — POST /api/transfers/upload. Restores the
7
7
  * handler deleted with @teamscala/server-files (commit ca5643ef); avatar/logo
8
8
  * upload had 404'd on every service since. Writes to S3 via
9
- * @teamscala/object-storage/create/write-ops and returns the STORED-form URL
10
- * (`/api/files/<key>`) the client persists into avatar_url/logo_url — the
11
- * display path rewrites it to the public `/api/assets/<encoded-key>` proxy
12
- * via `toAssetPath` (@teamscala/formatters/asset-url). Self-authenticates
13
- * (getSession) so it mounts BEFORE the auth gate.
9
+ * @teamscala/object-storage/create/write-ops and returns the SERVABLE URL
10
+ * (`/api/assets/<key>`) the client persists into avatar_url/logo_url — the
11
+ * stored value is the servable value (single-logo-pathway), so display code
12
+ * reads the column with no rewriting. Self-authenticates (getSession) so it
13
+ * mounts BEFORE the auth gate.
14
14
  *
15
15
  * Key scheme is USER-scoped (`users/<userId>/<type>/<file>-<ts>.<ext>`) per
16
16
  * the operator ruling: a profile picture belongs to the individual, not any
@@ -104,7 +104,7 @@ export async function attachTransfersUpload(app: Hono): Promise<void> {
104
104
  });
105
105
  }
106
106
 
107
- const storedUrl = `/api/files/${key}`;
107
+ const storedUrl = `/api/assets/${key}`;
108
108
  return c.json({ url: storedUrl, thumbUrl: storedUrl });
109
109
  });
110
110
  }
@@ -5,7 +5,6 @@
5
5
  *
6
6
  * Stamp partner and client brand assets onto a proposal page's pageData, after
7
7
  * it is built.
8
- *
9
8
  * Split from proposal-post-processors.ts (single-purpose-file: two unrelated
10
9
  * export groups). Both helpers here are synchronous, take an already-resolved
11
10
  * loader-graph org, and only map a logo/colour onto pageData — no network, no
@@ -13,7 +12,6 @@
13
12
  * async ORPC lookup, which is the distinction that was invisible while they sat
14
13
  * together.
15
14
  */
16
- import { toAssetPath } from "@teamscala/formatters/asset-url";
17
15
 
18
16
  /**
19
17
  * Stash a proposal's connected partner logo/colour on `pageData` from the
@@ -37,7 +35,7 @@ export function applyPartnerBrand(
37
35
  | null,
38
36
  ): void {
39
37
  if (!partnerOrg) return;
40
- if (partnerOrg.logo_url) pageData.partnerLogo = toAssetPath(partnerOrg.logo_url);
38
+ if (partnerOrg.logo_url) pageData.partnerLogo = partnerOrg.logo_url;
41
39
  if (partnerOrg.brand_primary_color)
42
40
  pageData.partnerBrandColor = partnerOrg.brand_primary_color;
43
41
  }
@@ -56,5 +54,5 @@ export function applyClientLogo(
56
54
  | null,
57
55
  ): void {
58
56
  if (!clientOrg?.logo_url) return;
59
- pageData.clientLogo = toAssetPath(clientOrg.logo_url);
57
+ pageData.clientLogo = clientOrg.logo_url;
60
58
  }
@@ -38,7 +38,7 @@ describe("buildResourceNotFoundResponse", () => {
38
38
  const bytes = new Uint8Array([137, 80, 78, 71]);
39
39
  const requested: string[] = [];
40
40
  const logo = await inlineLogoAsDataUri(
41
- "/api/files/c503629a/logos/cropped.png",
41
+ "/api/assets/c503629a/logos/cropped.png",
42
42
  async () => ({
43
43
  file(key) {
44
44
  requested.push(key);
@@ -55,7 +55,7 @@ describe("buildResourceNotFoundResponse", () => {
55
55
 
56
56
  it("passes the resolved logo to the waking page instead of its placeholder", async () => {
57
57
  const logo = await inlineLogoAsDataUri(
58
- "/api/files/c503629a/logos/cropped.png",
58
+ "/api/assets/c503629a/logos/cropped.png",
59
59
  async () => ({
60
60
  file() {
61
61
  return {
@@ -33,7 +33,6 @@ import { createCache } from "@teamscala/cache/create-cache";
33
33
  import { createNotifyListener, getDirectDatabaseUrl } from "@teamscala/db/notify-listener/index";
34
34
  import { getServerClient } from "@teamscala/orpc/server-client-registry";
35
35
  import { loadRegistryConfig } from "@teamscala/db/registry/load-config";
36
- import { toAssetPath } from "@teamscala/formatters/asset-url";
37
36
  import { getAppLogger } from "@teamscala/logger/app-loggers";
38
37
  import { brandLogoImgTag } from "@teamscala/os/brand/brand-logo-img-tag";
39
38
  import { ServiceInstallConfigSchema } from "./load-service-install-row.ts";
@@ -134,10 +133,10 @@ const ASSETS_PREFIX = "/api/assets/";
134
133
 
135
134
  /**
136
135
  * Inline a stored logo value as a `data:<mime>;base64,…` URI by fetching its
137
- * bytes from S3 (the same store `/api/assets/` proxies to). Mirrors the asset
138
- * proxy's key extraction: `toAssetPath` normalises every stored form (bare
139
- * key, `/api/files/`, tigris URL) to `/api/assets/<key>`, and the proxy
140
- * decodes that path segment to the S3 key. Skew-tolerant: any miss → null.
136
+ * bytes from S3 (the same store `/api/assets/` proxies to). The stored value
137
+ * IS the servable form — `/api/assets/<key>` — so the bucket key is the path
138
+ * segment after that prefix (single-logo-pathway). Skew-tolerant: any miss →
139
+ * null.
141
140
  */
142
141
  type LogoStorage = {
143
142
  file(key: string): {
@@ -151,9 +150,8 @@ export async function inlineLogoAsDataUri(
151
150
  getStorage: () => Promise<LogoStorage | null> = getClient as unknown as () => Promise<LogoStorage | null>,
152
151
  ): Promise<string | null> {
153
152
  try {
154
- const assetPath = toAssetPath(stored);
155
- if (!assetPath.startsWith(ASSETS_PREFIX)) return null;
156
- const key = decodeURIComponent(assetPath.slice(ASSETS_PREFIX.length));
153
+ if (!stored.startsWith(ASSETS_PREFIX)) return null;
154
+ const key = decodeURIComponent(stored.slice(ASSETS_PREFIX.length));
157
155
  const s3 = await getStorage();
158
156
  if (!s3) return null;
159
157
  const file = s3.file(key);