@norskvideo/ctl-dev-kit 0.1.0
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/build/Dockerfile.bundle +55 -0
- package/build/build-bundle-image.sh +87 -0
- package/build/common.sh +77 -0
- package/conventions/CLAUDE.core.md +49 -0
- package/local-dev/README.md +45 -0
- package/local-dev/dev-link.sh +35 -0
- package/package.json +11 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Shared copy-only product-backend image for the "bundle" products
|
|
2
|
+
# (probe / funke-pegasus / norsk-commentary / norsk-playout). Single-sourced in
|
|
3
|
+
# @norskvideo/ctl-dev-kit so the four images cannot drift; the per-product facts
|
|
4
|
+
# (tag, container port, optional native addon / assets) come in as build args and
|
|
5
|
+
# staged directories from the shared build-bundle-image.sh driver.
|
|
6
|
+
#
|
|
7
|
+
# Studio is NOT built from this file — it ships a `bun build --compile` binary
|
|
8
|
+
# with a different (STUDIO_ASSET_ROOT) layout; see products/studio/deployment.
|
|
9
|
+
#
|
|
10
|
+
# Copy-only: the backend bundle, frontend, dashboards, components, and the
|
|
11
|
+
# optional native addon + product-template assets are all built/collected on the
|
|
12
|
+
# host by the driver and COPYd in. Nothing is installed or compiled here (the old
|
|
13
|
+
# per-product images ran `bun install` inside an oven/bun:alpine builder and
|
|
14
|
+
# shipped the whole node_modules; the bundle inlines only what it reaches).
|
|
15
|
+
#
|
|
16
|
+
# The base is single-sourced in build/common.sh (PRODUCT_BASE_IMAGE) and passed
|
|
17
|
+
# as BASE_IMAGE, so every product image shares one pinned distroless base (glibc
|
|
18
|
+
# + libgcc/libstdc++, no shell). The runtime bun is imported Docker-natively from
|
|
19
|
+
# the upstream slim image (BUN_IMAGE = oven/bun:<version>-slim): buildkit rejects
|
|
20
|
+
# a variable in `COPY --from=${BUN_IMAGE}`, so it's aliased to a named stage from
|
|
21
|
+
# the global-scope ARG and the binary COPYd out; that stage only donates a
|
|
22
|
+
# prebuilt binary, so the final image stays copy-only.
|
|
23
|
+
#
|
|
24
|
+
# Split-level asset layout (the subtle part): the backend is a single bundled
|
|
25
|
+
# file at backend/dist/index.js, so at runtime import.meta.dir is that bundle's
|
|
26
|
+
# dir for ALL of the collapsed modules. server.ts's `../../frontend/dist` lands
|
|
27
|
+
# beside the app dir, but lib/{components,dashboards,assets}.ts (originally under
|
|
28
|
+
# backend/src/lib, one level deeper) kept `../../../{components/lib,dashboards,
|
|
29
|
+
# assets}`, which resolve ONE level above the app dir. So dashboards +
|
|
30
|
+
# components/lib + assets go at /usr/src while backend/frontend go under
|
|
31
|
+
# /usr/src/app. A flat /usr/src/app layout silently drops them from the generated
|
|
32
|
+
# product-template tars.
|
|
33
|
+
ARG BASE_IMAGE
|
|
34
|
+
ARG BUN_IMAGE
|
|
35
|
+
FROM ${BUN_IMAGE} AS bun
|
|
36
|
+
|
|
37
|
+
FROM ${BASE_IMAGE}
|
|
38
|
+
# The container port docker-runner maps the host port to (probe/funke 4321,
|
|
39
|
+
# commentary/playout 4322). Passed by the driver from the wrapper's PRODUCT_PORT.
|
|
40
|
+
ARG PRODUCT_PORT=4321
|
|
41
|
+
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
|
|
42
|
+
WORKDIR /usr/src/app
|
|
43
|
+
COPY backend/dist ./backend/dist
|
|
44
|
+
# Optional native addon(s), beside the bundle where <product>-identity.ts
|
|
45
|
+
# createRequires them. The driver stages an empty native/ for products that ship
|
|
46
|
+
# no signer (funke/commentary/playout), so this COPY is then a harmless no-op.
|
|
47
|
+
COPY native/ ./backend/dist/
|
|
48
|
+
COPY frontend/dist ./frontend/dist
|
|
49
|
+
COPY dashboards /usr/src/dashboards
|
|
50
|
+
COPY components/lib /usr/src/components/lib
|
|
51
|
+
# Optional product-template assets (funke's slate/black PNGs). Empty otherwise.
|
|
52
|
+
COPY assets /usr/src/assets
|
|
53
|
+
ENV PORT=${PRODUCT_PORT}
|
|
54
|
+
EXPOSE ${PRODUCT_PORT}
|
|
55
|
+
CMD ["/usr/local/bin/bun", "run", "backend/dist/index.js"]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared driver for the copy-only "bundle" product images
|
|
3
|
+
# (probe / funke-pegasus / norsk-commentary / norsk-playout). Single-sourced in
|
|
4
|
+
# @norskvideo/ctl-dev-kit; each product's deployment/build-image.sh is a thin
|
|
5
|
+
# wrapper that sets the per-product facts and sources this file. Studio does NOT
|
|
6
|
+
# use this driver (it ships a --compile binary; see products/studio/deployment).
|
|
7
|
+
#
|
|
8
|
+
# The wrapper MUST set before sourcing:
|
|
9
|
+
# PRODUCT_DIR absolute path to the product workspace (backend/, frontend/,
|
|
10
|
+
# dashboards/, components/, package.json)
|
|
11
|
+
# IMAGE_TAG the image tag to build (the wrapper sets the product default)
|
|
12
|
+
# PRODUCT_PORT the container port docker-runner maps to (probe/funke 4321,
|
|
13
|
+
# commentary/playout 4322)
|
|
14
|
+
# Optional:
|
|
15
|
+
# PRODUCT_BUILD_SCRIPT workspace script that builds the host artifacts
|
|
16
|
+
# (default: build:no-lint)
|
|
17
|
+
# BUN_VERSION override the pinned bun (default from packageManager)
|
|
18
|
+
#
|
|
19
|
+
# Everything else is auto-detected off PRODUCT_DIR, so a product opts in just by
|
|
20
|
+
# having the directory/script — no per-product flag to keep in sync:
|
|
21
|
+
# native/ native addon(s) (probe's signer) -> beside bundle
|
|
22
|
+
# assets/ product-template assets (funke's PNGs)
|
|
23
|
+
# scripts/runtime-images.ts -> emits the norsk-ctl.runtime-images label
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
|
|
26
|
+
: "${PRODUCT_DIR:?build-bundle-image.sh: PRODUCT_DIR must be set by the wrapper}"
|
|
27
|
+
: "${IMAGE_TAG:?build-bundle-image.sh: IMAGE_TAG must be set by the wrapper}"
|
|
28
|
+
: "${PRODUCT_PORT:?build-bundle-image.sh: PRODUCT_PORT must be set by the wrapper}"
|
|
29
|
+
build_script="${PRODUCT_BUILD_SCRIPT:-build:no-lint}"
|
|
30
|
+
|
|
31
|
+
driver_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
32
|
+
# shellcheck source=./common.sh
|
|
33
|
+
source "${driver_dir}/common.sh"
|
|
34
|
+
|
|
35
|
+
# Pin bun once from the product repo's packageManager so downstream helpers don't
|
|
36
|
+
# each re-walk the tree.
|
|
37
|
+
export BUN_VERSION="${BUN_VERSION:-$(product_bun_version "${PRODUCT_DIR}")}"
|
|
38
|
+
|
|
39
|
+
echo "==> building on host (${build_script})"
|
|
40
|
+
bun run --cwd "${PRODUCT_DIR}" "${build_script}"
|
|
41
|
+
|
|
42
|
+
stage="$(mktemp -d)"
|
|
43
|
+
trap 'rm -rf "${stage}"' EXIT
|
|
44
|
+
|
|
45
|
+
echo "==> staging artifacts"
|
|
46
|
+
mkdir -p "${stage}/backend" "${stage}/frontend" "${stage}/components" "${stage}/native" "${stage}/assets"
|
|
47
|
+
cp -R "${PRODUCT_DIR}/backend/dist" "${stage}/backend/dist"
|
|
48
|
+
cp -R "${PRODUCT_DIR}/frontend/dist" "${stage}/frontend/dist"
|
|
49
|
+
cp -R "${PRODUCT_DIR}/dashboards" "${stage}/dashboards"
|
|
50
|
+
cp -R "${PRODUCT_DIR}/components/lib" "${stage}/components/lib"
|
|
51
|
+
|
|
52
|
+
# Native addon(s): staged beside the bundle. Strip the build host's RUNPATH (nix
|
|
53
|
+
# store / repo-local paths) so the shipped .node carries no build-host paths; its
|
|
54
|
+
# NEEDED libs resolve via the base image's default search path. Best-effort:
|
|
55
|
+
# only if patchelf is available.
|
|
56
|
+
if [ -d "${PRODUCT_DIR}/native" ]; then
|
|
57
|
+
find "${PRODUCT_DIR}/native" -maxdepth 1 -name '*.node' -exec cp {} "${stage}/native/" \;
|
|
58
|
+
if command -v patchelf >/dev/null 2>&1; then
|
|
59
|
+
find "${stage}/native" -name '*.node' -exec patchelf --remove-rpath {} \;
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Product-template assets (optional): copy contents into the always-staged dir.
|
|
64
|
+
if [ -d "${PRODUCT_DIR}/assets" ]; then
|
|
65
|
+
cp -R "${PRODUCT_DIR}/assets/." "${stage}/assets/"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Runtime images the default templates launch, stamped on as a label so a
|
|
69
|
+
# golden-image bake can warm them with `docker inspect` + `docker pull` alone —
|
|
70
|
+
# no daemon, no license. Derived from the rendered compose (scripts/runtime-images.ts),
|
|
71
|
+
# never hardcoded. Products without that script simply don't carry the label.
|
|
72
|
+
label_args=()
|
|
73
|
+
if [ -f "${PRODUCT_DIR}/scripts/runtime-images.ts" ]; then
|
|
74
|
+
echo "==> resolving runtime images for the norsk-ctl.runtime-images label"
|
|
75
|
+
runtime_images="$(bun "${PRODUCT_DIR}/scripts/runtime-images.ts")"
|
|
76
|
+
label_args+=(--label "norsk-ctl.runtime-images=${runtime_images}")
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
echo "==> docker build ${IMAGE_TAG}"
|
|
80
|
+
docker build \
|
|
81
|
+
--build-arg BASE_IMAGE="${PRODUCT_BASE_IMAGE}" \
|
|
82
|
+
--build-arg BUN_IMAGE="$(product_bun_slim_image)" \
|
|
83
|
+
--build-arg PRODUCT_PORT="${PRODUCT_PORT}" \
|
|
84
|
+
"${label_args[@]}" \
|
|
85
|
+
-f "${driver_dir}/Dockerfile.bundle" -t "${IMAGE_TAG}" "${stage}"
|
|
86
|
+
|
|
87
|
+
echo "==> built ${IMAGE_TAG}"
|
package/build/common.sh
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Shared deployment constants + helpers for the product container images.
|
|
2
|
+
# Single-sourced in @norskvideo/ctl-dev-kit and sourced by the product build
|
|
3
|
+
# scripts (the bundle driver build-bundle-image.sh, and studio's bespoke
|
|
4
|
+
# build-image.sh). This is the one place the pinned base + bun live, so no two
|
|
5
|
+
# product images can drift.
|
|
6
|
+
#
|
|
7
|
+
# Location-independent: this file makes NO assumption about where in a repo it
|
|
8
|
+
# sits (it used to live at products/deployment/common.sh and derive the repo
|
|
9
|
+
# root from its own path). The same file works vendored/symlinked in the
|
|
10
|
+
# monorepo and installed into a split-out product repo's node_modules — callers
|
|
11
|
+
# pass the product directory in, they don't rely on this file's location.
|
|
12
|
+
#
|
|
13
|
+
# Base choice — gcr.io/distroless/cc-debian12: glibc plus libgcc/libstdc++ (bun
|
|
14
|
+
# and probe's native rust addon link these) and nothing else — no shell, no
|
|
15
|
+
# package manager. studio's compiled binary would fit the smaller
|
|
16
|
+
# distroless/base-debian12, but we take probe's minimum (cc) for every product so
|
|
17
|
+
# a host running several products pulls one shared base layer. Pinned by digest
|
|
18
|
+
# because distroless publishes only moving tags (no immutable version tags). No
|
|
19
|
+
# shell is fine: images run via exec-form CMD and health is checked over HTTP.
|
|
20
|
+
PRODUCT_BASE_IMAGE="gcr.io/distroless/cc-debian12@sha256:7ee09f36862efbdbf70422db263e411c2618409ca46faa555bd5b636155307df"
|
|
21
|
+
|
|
22
|
+
# The pinned bun version. Override with BUN_VERSION; otherwise walk up from the
|
|
23
|
+
# given directory (default: PWD) to the nearest package.json declaring
|
|
24
|
+
# "packageManager": "bun@X" — the workspace root in the monorepo, the repo root
|
|
25
|
+
# in a split-out product. Prints X.
|
|
26
|
+
product_bun_version() {
|
|
27
|
+
if [ -n "${BUN_VERSION:-}" ]; then
|
|
28
|
+
printf '%s' "${BUN_VERSION}"
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
local dir version
|
|
32
|
+
dir="${1:-$PWD}"
|
|
33
|
+
while [ "${dir}" != "/" ]; do
|
|
34
|
+
if [ -f "${dir}/package.json" ]; then
|
|
35
|
+
version="$(sed -n 's/.*"packageManager": *"bun@\([^"]*\)".*/\1/p' "${dir}/package.json")"
|
|
36
|
+
if [ -n "${version}" ]; then
|
|
37
|
+
printf '%s' "${version}"
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
dir="$(dirname "${dir}")"
|
|
42
|
+
done
|
|
43
|
+
echo "could not determine bun version (no packageManager in any ancestor package.json)" >&2
|
|
44
|
+
return 1
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Prints the upstream oven/bun slim image ref for the pinned version. The bundle
|
|
48
|
+
# products import their runtime bun from this image Docker-natively (COPY --from),
|
|
49
|
+
# so they never touch the host cache; only studio's host-side --compile needs the
|
|
50
|
+
# extracted binary below.
|
|
51
|
+
product_bun_slim_image() {
|
|
52
|
+
local version
|
|
53
|
+
version="$(product_bun_version)" || return 1
|
|
54
|
+
printf 'oven/bun:%s-slim' "${version}"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Prints the path to an upstream (glibc, FHS-loader) bun of the pinned version,
|
|
58
|
+
# extracted from oven/bun:<version>-slim and cached. The nix-devshell bun is
|
|
59
|
+
# patched to a /nix/store loader: it won't run in the base image, and baked into
|
|
60
|
+
# a `--compile` binary it makes that binary fail to exec in a stock container.
|
|
61
|
+
# So the bun that ships (bundle products) or does the compile (studio) must be
|
|
62
|
+
# this one. Progress goes to stderr so `$(product_upstream_bun)` captures only
|
|
63
|
+
# the path.
|
|
64
|
+
product_upstream_bun() {
|
|
65
|
+
local version cache_dir bun_path cid
|
|
66
|
+
version="$(product_bun_version)" || return 1
|
|
67
|
+
cache_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/norsk-ctl"
|
|
68
|
+
bun_path="${cache_dir}/bun-${version}"
|
|
69
|
+
if [ ! -x "${bun_path}" ]; then
|
|
70
|
+
echo "==> fetching upstream bun ${version} from oven/bun:${version}-slim" >&2
|
|
71
|
+
mkdir -p "${cache_dir}"
|
|
72
|
+
cid="$(docker create "oven/bun:${version}-slim")"
|
|
73
|
+
docker cp "${cid}:/usr/local/bin/bun" "${bun_path}"
|
|
74
|
+
docker rm "${cid}" >/dev/null
|
|
75
|
+
fi
|
|
76
|
+
printf '%s' "${bun_path}"
|
|
77
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!-- BEGIN ctl-shared-conventions v1 -->
|
|
2
|
+
<!--
|
|
3
|
+
This block is the SHARED conventions core, single-sourced in
|
|
4
|
+
@norskvideo/ctl-dev-kit (conventions/CLAUDE.core.md). It is copied verbatim
|
|
5
|
+
into each product repo's CLAUDE.md between these fenced markers, and a
|
|
6
|
+
drift-check gate (Workstream I) fails CI if a copy diverges from the dev-kit's
|
|
7
|
+
version. Do NOT hand-edit a copy — edit the dev-kit source and re-sync. The
|
|
8
|
+
per-product tail (this product's build, iterate loop, gotchas) lives OUTSIDE
|
|
9
|
+
the markers and is yours to own.
|
|
10
|
+
|
|
11
|
+
It is copied (not `@import`ed) on purpose: CLAUDE.md's value is being read
|
|
12
|
+
verbatim by a human on GitHub with no tooling, and an @import shows a human a
|
|
13
|
+
dead path.
|
|
14
|
+
-->
|
|
15
|
+
|
|
16
|
+
## Conventions (shared across all Norsk ctl product repos — do not edit in place)
|
|
17
|
+
|
|
18
|
+
- **RED -> GREEN -> REFACTOR. No fix before its failing test.** Write the test,
|
|
19
|
+
run it, watch it fail against the old code, THEN write the fix. This applies
|
|
20
|
+
_most_ when the fix feels too obvious to bother — that's precisely when the
|
|
21
|
+
skip happens. If code somehow got written first: stash it, prove the test RED,
|
|
22
|
+
pop, prove GREEN.
|
|
23
|
+
- **No `Co-Authored-By` tags on commits.** Imperative subject. Short body, only
|
|
24
|
+
if the why isn't obvious from the diff. Each commit logically scoped — don't
|
|
25
|
+
dump a phase into one commit.
|
|
26
|
+
- **No emojis** in code, commits, or docs unless explicitly asked.
|
|
27
|
+
- **Minimal comments.** Names explain _what_; comments explain _why_ —
|
|
28
|
+
non-obvious constraints, surprising invariants, workarounds for upstream bugs.
|
|
29
|
+
Don't restate the code.
|
|
30
|
+
- **Result over throws** for predictable failures. `Result<T, E>` + `ok()`/
|
|
31
|
+
`err()`/`tryResult()` from `@norskvideo/ctl-foundation`. Throws are reserved
|
|
32
|
+
for genuine exceptions.
|
|
33
|
+
- **ESLint / biome rules are non-negotiable** — adhere, never ignore. Keep the
|
|
34
|
+
whole project clean (`biome check .` exits 0), not just your own diff.
|
|
35
|
+
- **Test temp dirs that get bind-mounted into a container must come from the
|
|
36
|
+
repo-local temp helper**, never `os.tmpdir()`/`/tmp`. On OrbStack, `/tmp` bind
|
|
37
|
+
mounts don't forward host->guest inotify events, so file watchers never fire —
|
|
38
|
+
a failure that looks exactly like a code bug. Unit tests that don't bind-mount
|
|
39
|
+
may keep using `os.tmpdir()`.
|
|
40
|
+
- **Don't pipe test runs to `tail`** — you lose the failure context. Write output
|
|
41
|
+
to a temp file, then tail _that_ file for the results.
|
|
42
|
+
- **Evolve the ctl<->product contract additively.** An older ctl must launch a
|
|
43
|
+
newer product release: never repurpose or remove a required launch-interface
|
|
44
|
+
field. When a product genuinely cannot launch on an older ctl it declares a
|
|
45
|
+
named capability in its manifest's `requires: [...]`; ctl refuses only if it
|
|
46
|
+
lacks that capability. Reach for a capability as rarely as possible — it is the
|
|
47
|
+
escape hatch, not the default.
|
|
48
|
+
|
|
49
|
+
<!-- END ctl-shared-conventions v1 -->
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Local-dev overrides
|
|
2
|
+
|
|
3
|
+
A product repo consumes ctl and the Norsk runtime as published packages/images.
|
|
4
|
+
To develop a product against **un-published** ctl code or a **locally-built**
|
|
5
|
+
media server, there are two independent override layers. Each is opt-in and
|
|
6
|
+
leaves the default (registry/pinned) path untouched when unset.
|
|
7
|
+
|
|
8
|
+
## 1. The npm layer — local `@norskvideo/ctl-*` checkouts
|
|
9
|
+
|
|
10
|
+
The product depends on `@norskvideo/ctl-{sdk,foundation,product-template-schema,
|
|
11
|
+
oas-to-ts,test-harness,commands,dev-kit}` at a caret range. To point one (or all)
|
|
12
|
+
at a local checkout of the ctl monorepo instead of the registry, use
|
|
13
|
+
`dev-link.sh`:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
# link every @norskvideo/ctl-* dep to a sibling monorepo checkout
|
|
17
|
+
node_modules/@norskvideo/ctl-dev-kit/local-dev/dev-link.sh ../norsk-ctl
|
|
18
|
+
|
|
19
|
+
# undo — restore the registry versions
|
|
20
|
+
node_modules/@norskvideo/ctl-dev-kit/local-dev/dev-link.sh --unlink
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It `bun link`s the packages the monorepo exposes and re-installs; `--unlink`
|
|
24
|
+
drops the overrides and reinstalls from the lockfile. Nothing is committed —
|
|
25
|
+
the links live only in your local `node_modules`.
|
|
26
|
+
|
|
27
|
+
## 2. The image layer — local media / studio image
|
|
28
|
+
|
|
29
|
+
Every product's `shared/src/version.ts` already reads the runtime image tag from
|
|
30
|
+
the environment, so this layer needs no script — just export the hook before you
|
|
31
|
+
launch:
|
|
32
|
+
|
|
33
|
+
- `NORSK_MEDIA_TAG` — override the Norsk media-server image tag.
|
|
34
|
+
- `NORSK_STUDIO_TAG` — override the Norsk Studio image tag.
|
|
35
|
+
|
|
36
|
+
Since Workstream C unified the tag convention, both are **bare tags** across every
|
|
37
|
+
product (no full-ref/bare-tag divergence), so the same exported value means the
|
|
38
|
+
same thing everywhere:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
export NORSK_STUDIO_TAG=my-local-studio:dev
|
|
42
|
+
bun run --cwd . iterate # or the product's launch/iterate entry
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Leave the hooks unset to launch the pinned tags the product declares.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Point a product repo's @norskvideo/ctl-* dependencies at a local checkout of
|
|
3
|
+
# the ctl monorepo (or restore the registry versions). See local-dev/README.md.
|
|
4
|
+
#
|
|
5
|
+
# dev-link.sh <path-to-ctl-monorepo> # link ctl-* packages to that checkout
|
|
6
|
+
# dev-link.sh --unlink # drop the overrides, reinstall pinned
|
|
7
|
+
#
|
|
8
|
+
# Nothing is committed — the links live only in this repo's node_modules.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
PACKAGES=(sdk foundation product-template-schema oas-to-ts test-harness commands dev-kit)
|
|
12
|
+
product_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && git -C . rev-parse --show-toplevel 2>/dev/null || pwd)"
|
|
13
|
+
|
|
14
|
+
if [ "${1:-}" = "--unlink" ]; then
|
|
15
|
+
for pkg in "${PACKAGES[@]}"; do
|
|
16
|
+
bun unlink "@norskvideo/ctl-${pkg}" 2>/dev/null || true
|
|
17
|
+
done
|
|
18
|
+
echo "==> reinstalling pinned versions"
|
|
19
|
+
bun install --cwd "${product_root}"
|
|
20
|
+
echo "==> unlinked; registry versions restored"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
mono="${1:?usage: dev-link.sh <path-to-ctl-monorepo> | --unlink}"
|
|
25
|
+
mono="$(cd "${mono}" && pwd)"
|
|
26
|
+
[ -d "${mono}/packages" ] || { echo "not a ctl monorepo checkout: ${mono}" >&2; exit 1; }
|
|
27
|
+
|
|
28
|
+
for pkg in "${PACKAGES[@]}"; do
|
|
29
|
+
dir="${mono}/packages/${pkg}"
|
|
30
|
+
[ -d "${dir}" ] || { echo " skip @norskvideo/ctl-${pkg} (not in checkout)"; continue; }
|
|
31
|
+
( cd "${dir}" && bun link )
|
|
32
|
+
bun link "@norskvideo/ctl-${pkg}" --cwd "${product_root}"
|
|
33
|
+
echo " linked @norskvideo/ctl-${pkg} -> ${dir}"
|
|
34
|
+
done
|
|
35
|
+
echo "==> linked against ${mono}; run dev-link.sh --unlink to restore"
|