@designcrowd/fe-shared-lib 1.8.4-edge-fallback-4 → 1.8.5-edge-fallback-5

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/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 20
package/CLAUDE.md CHANGED
@@ -123,7 +123,15 @@ npm link @designcrowd/fe-shared-lib # in consumer project
123
123
 
124
124
  ## Publishing (UAT)
125
125
 
126
- To test experimental versions without publishing to production:
127
- 1. Update `package.json` version to `[current]-[description]`
128
- 2. Run `docker build . --build-arg NPM_TOKEN=$NPM_TOKEN`
129
- 3. Update consumer package reference to the new version
126
+ Use `scripts/publish-uat.sh <suffix>` to publish a UAT build for testing in a consumer (e.g. BrandCrowd.Net). The script handles the version bump, bundle-translation, secret scanning of the tarball, and the commit. Examples:
127
+
128
+ ```bash
129
+ ./scripts/publish-uat.sh edge-fallback-0
130
+ ./scripts/publish-uat.sh edge-fallback-1 # next iteration
131
+ ```
132
+
133
+ It refuses to run on `master`/`main`, refuses if the version is already published, aborts on dangerous filenames or token-shaped strings inside the tarball, and only commits the bump after the registry confirms upload.
134
+
135
+ The npm publish token is read from `~/.config/designcrowd/npm-publish-token` (mode 600). Override with `NPM_PUBLISH_TOKEN_FILE` if it lives elsewhere. The token file is **not** stored anywhere in the repo.
136
+
137
+ The legacy `docker build . --build-arg NPM_TOKEN=...` flow still works but is brittle — prefer the script.
package/README.md CHANGED
@@ -29,19 +29,27 @@ To edit the design system locally whilst being using in a consumer you need to r
29
29
 
30
30
  ### Testing in a UAT
31
31
 
32
- If you want to have an experimental version of your change, like have it in a uat env without publishing it to prod:
32
+ If you want to have an experimental version of your change in a UAT env without publishing to prod, run the publish script with a suffix:
33
33
 
34
- 1. Update package.json with `"version": "[current]-[short description of your work]"`
35
- 2. Run npm i
36
- 3. run `docker build . --build-arg NPM_TOKEN=$NPM_TOKEN` in the project directory (make sure you have $NPM_TOKEN properly set in your local env)
37
- 4. Update package reference in the consumer to the version you have just built
34
+ ```bash
35
+ ./scripts/publish-uat.sh edge-fallback-0 # first iteration
36
+ ./scripts/publish-uat.sh edge-fallback-1 # next iteration
37
+ ```
38
+
39
+ The script bumps `package.json` to `<base>-<suffix>`, runs `bundle-translation`, scans the tarball for secrets and dangerous filenames, publishes via a temp `.npmrc`, and commits the version bump only after the registry confirms upload. It refuses to run on `master`/`main` and refuses already-published versions.
40
+
41
+ The npm publish token is read from `~/.config/designcrowd/npm-publish-token` (mode 600). Override with `NPM_PUBLISH_TOKEN_FILE` if it lives elsewhere. The token is never written into the repo.
42
+
43
+ Once published, update the consumer's package reference to the version you just built.
44
+
45
+ The legacy `docker build . --build-arg NPM_TOKEN=$NPM_TOKEN` flow still works but is brittle — prefer the script.
38
46
 
39
47
  ### If you are making changes to components used into the BrandPage Tab in BC.NET
40
48
 
41
49
  1. Get latest app.maker source code.
42
50
  2. Update its reference to `@designcrowd/fe-shared-lib` with the one you just built
43
51
  3. Bump its version (app.maker version)
44
- 4. Run `npm run docker:publish:bp`
52
+ 4. From app.maker, run `npm run docker:publish:bp` (this script lives in app.maker, not in this repo)
45
53
  5. IN BC.Net Update reference of `@designcrowd/library.brand-page` to use the version you just set in the app.maker
46
54
 
47
55
  <a id="storybook"></a>
@@ -100,4 +108,9 @@ New configuration styles can be added to the `themes/base.js` file which will be
100
108
  New themes can be added by creating a new xx.js file in the themes folder. Once the new theme has been configured, it will need to be made exportable in the `index.js` file.
101
109
 
102
110
  ## Versioning
103
- Ensure to bump the version number in `package.json` followed by running `npm i` before each commit. And then run `npm run docker:publish` to publish the version to NPM.
111
+
112
+ Two flows depending on what you're publishing:
113
+
114
+ - **Test / UAT versions** (suffixed, e.g. `1.8.4-edge-fallback-0`) — use `./scripts/publish-uat.sh <suffix>`. The script bumps `package.json`, runs `bundle-translation`, scans the tarball for secrets and dangerous filenames, publishes via a temp `.npmrc`, and only commits the bump after the registry confirms upload. See [Testing in a UAT](#testing-uat).
115
+
116
+ - **Final releases to NPM** (no suffix, e.g. `1.8.4`) — bump the version in `package.json`, run `npm i`, then `npm run docker:publish`. This is the legacy docker flow; it does **not** run the secret scan that the UAT script does, so review the tarball contents before pushing. (Folding final releases into the script is a planned follow-up.)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designcrowd/fe-shared-lib",
3
- "version": "1.8.4-edge-fallback-4",
3
+ "version": "1.8.5-edge-fallback-5",
4
4
  "scripts": {
5
5
  "start": "run-p storybook watch:translation",
6
6
  "build": "npm run build:css --production",
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # publish-uat.sh — publish a UAT-suffixed version of @designcrowd/fe-shared-lib
4
+ #
5
+ # Usage: ./scripts/publish-uat.sh <suffix>
6
+ # Example: ./scripts/publish-uat.sh edge-fallback-2
7
+ #
8
+ # Reads the npm publish token from $NPM_PUBLISH_TOKEN_FILE
9
+ # (default ~/.config/designcrowd/npm-publish-token, mode 600).
10
+ # The token is never written into the repo.
11
+ #
12
+ # Workflow:
13
+ # 1. Validate branch (refuse master) and suffix.
14
+ # 2. Compute new version = <base>-<suffix>, refuse if already published.
15
+ # 3. Bump package.json, run bundle-translation.
16
+ # 4. npm pack — produces a tarball.
17
+ # 5. Secret scan: dangerous filenames + token-shaped strings + the
18
+ # literal token bytes from the token file (if it leaked into the
19
+ # tree somehow, this catches it).
20
+ # 6. npm publish <tarball> via a temp .npmrc in /tmp (mode 600,
21
+ # removed on exit).
22
+ # 7. git add + commit the version bump.
23
+ #
24
+ # Anything in steps 4-6 that fails leaves the working tree dirty so you
25
+ # can investigate. The commit only lands after the registry confirms
26
+ # the upload.
27
+
28
+ set -euo pipefail
29
+
30
+ PKG="@designcrowd/fe-shared-lib"
31
+ TOKEN_FILE="${NPM_PUBLISH_TOKEN_FILE:-$HOME/.config/designcrowd/npm-publish-token}"
32
+
33
+ abort() { echo "ABORT: $*" >&2; exit 1; }
34
+
35
+ # --- args ---
36
+ SUFFIX="${1:-}"
37
+ [[ -z "$SUFFIX" ]] && abort "usage: $0 <suffix> e.g. $0 edge-fallback-2"
38
+ # Semver pre-release identifiers are [0-9A-Za-z-], dot-separated. Reject underscores etc.
39
+ # so we fail before npm rejects the version mid-flight with a dirty tree.
40
+ [[ "$SUFFIX" =~ ^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*$ ]] || abort "suffix must match semver pre-release: alphanumerics/hyphens, optionally dot-separated"
41
+
42
+ # --- repo state ---
43
+ cd "$(git rev-parse --show-toplevel)"
44
+ BRANCH=$(git symbolic-ref --short HEAD)
45
+ [[ "$BRANCH" == "master" || "$BRANCH" == "main" ]] && abort "refusing to publish from $BRANCH"
46
+
47
+ # --- preconditions: files we'll commit must be clean, so unrelated edits don't get swept into the version-bump commit ---
48
+ [[ -z "$(git status --porcelain -- package.json)" ]] || abort "package.json has uncommitted changes; commit or stash before publishing"
49
+ if [[ -d src/bundles ]] && [[ -n "$(git status --porcelain -- src/bundles)" ]]; then
50
+ abort "src/bundles has uncommitted changes; commit or stash before publishing"
51
+ fi
52
+
53
+ # --- token ---
54
+ [[ -f "$TOKEN_FILE" ]] || abort "no token at $TOKEN_FILE (set NPM_PUBLISH_TOKEN_FILE to override)"
55
+ TOKEN=$(tr -d '[:space:]' < "$TOKEN_FILE")
56
+ [[ -n "$TOKEN" ]] || abort "token file is empty: $TOKEN_FILE"
57
+
58
+ # --- toolchain version check ---
59
+ NODE_V=$(node -v)
60
+ NPM_V=$(npm -v)
61
+ echo "==> node $NODE_V, npm $NPM_V"
62
+ if [[ -f .nvmrc ]]; then
63
+ WANT=$(tr -d '[:space:]v' < .nvmrc)
64
+ WANT_MAJOR="${WANT%%.*}"
65
+ HAVE_MAJOR=$(echo "${NODE_V#v}" | cut -d. -f1)
66
+ if [[ "$WANT_MAJOR" != "$HAVE_MAJOR" ]]; then
67
+ echo "WARNING: .nvmrc wants Node $WANT (major $WANT_MAJOR), you're on $NODE_V. Consider 'nvm use'." >&2
68
+ fi
69
+ fi
70
+
71
+ # --- compute version ---
72
+ BASE=$(node -p "require('./package.json').version.replace(/-.*/, '')")
73
+ NEW="$BASE-$SUFFIX"
74
+
75
+ if npm view "$PKG@$NEW" version >/dev/null 2>&1; then
76
+ abort "$PKG@$NEW already published — pick a new suffix"
77
+ fi
78
+
79
+ echo "==> publishing $PKG@$NEW from branch $BRANCH"
80
+
81
+ # --- bump + bundle ---
82
+ node -e "const fs=require('fs');const p=require('./package.json');p.version='$NEW';fs.writeFileSync('./package.json', JSON.stringify(p, null, 2)+'\n');"
83
+ echo "==> running bundle-translation"
84
+ npm run --silent bundle-translation >/dev/null
85
+
86
+ # --- cleanup trap: registered before any artifacts so a failed mktemp/pack still tidies up ---
87
+ SCAN_DIR=""; TMP_NPMRC=""; TARBALL=""
88
+ cleanup() {
89
+ [[ -n "$SCAN_DIR" ]] && rm -rf "$SCAN_DIR"
90
+ [[ -n "$TMP_NPMRC" ]] && rm -f "$TMP_NPMRC"
91
+ [[ -n "$TARBALL" ]] && rm -f "$TARBALL"
92
+ return 0
93
+ }
94
+ trap cleanup EXIT
95
+
96
+ SCAN_DIR=$(mktemp -d)
97
+ TMP_NPMRC=$(mktemp /tmp/fe-shared-lib-publish.XXXXXX.npmrc)
98
+ chmod 600 "$TMP_NPMRC"
99
+
100
+ # --- pack ---
101
+ echo "==> packing"
102
+ TARBALL=$(npm pack --silent)
103
+ [[ -f "$TARBALL" ]] || abort "npm pack did not produce a tarball"
104
+
105
+ # --- secret scan: filenames ---
106
+ echo "==> scanning $TARBALL"
107
+ DANGEROUS_PATHS='(^|/)(\.env(\..+)?|\.npmrc|\.npm-publish-token|id_rsa.*|id_ed25519.*|.*\.pem|.*\.key|.*[._-]token([._-].*)?|.*[._-]secret([._-].*)?|.*[._-]credentials?([._-].*)?)$|(^|/)\.(aws|ssh|gnupg)/'
108
+ if BAD=$(tar tzf "$TARBALL" | grep -E -i "$DANGEROUS_PATHS" || true); [[ -n "$BAD" ]]; then
109
+ echo "$BAD" >&2
110
+ abort "dangerous filenames in tarball"
111
+ fi
112
+
113
+ # --- secret scan: contents ---
114
+ tar xzf "$TARBALL" -C "$SCAN_DIR"
115
+
116
+ # Token-shaped patterns. Length floors (e.g. {30,}) keep documentation placeholders
117
+ # like 'npm_TOKEN' or '${NPM_TOKEN}' from tripping the check.
118
+ SECRET_PATTERNS='(npm_[A-Za-z0-9]{30,}|AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|sk_live_[A-Za-z0-9]{20,}|-----BEGIN [A-Z ]*PRIVATE KEY-----)'
119
+ if HITS=$(grep -REn -I -E "$SECRET_PATTERNS" "$SCAN_DIR" 2>/dev/null || true); [[ -n "$HITS" ]]; then
120
+ echo "$HITS" >&2
121
+ abort "secret-shaped string in tarball"
122
+ fi
123
+
124
+ # Belt-and-braces: the token's own bytes. If our publish token ever
125
+ # lands in a tracked file by accident, this catches it regardless of
126
+ # pattern-matching. Pass the token via stdin (-f -) so it doesn't appear
127
+ # in the process arglist (visible to other users via `ps`).
128
+ if printf '%s' "$TOKEN" | grep -RFqf - "$SCAN_DIR" 2>/dev/null; then
129
+ abort "publish token bytes appear in tarball — DO NOT publish"
130
+ fi
131
+
132
+ FILES=$(tar tzf "$TARBALL" | wc -l | tr -d ' ')
133
+ SIZE=$(du -h "$TARBALL" | cut -f1)
134
+ echo "==> scan clean. $FILES files, $SIZE"
135
+
136
+ # --- publish ---
137
+ printf '//registry.npmjs.org/:_authToken=%s\n' "$TOKEN" > "$TMP_NPMRC"
138
+ echo "==> publishing"
139
+ npm publish "$TARBALL" --userconfig "$TMP_NPMRC"
140
+
141
+ # --- commit bump ---
142
+ git add -- package.json
143
+ [[ -d src/bundles ]] && git add -- src/bundles
144
+ git commit -m "bump version to $NEW" >/dev/null
145
+ echo
146
+ echo "Published $PKG@$NEW (commit $(git rev-parse --short HEAD))"
147
+ echo
148
+ echo "Install in BrandCrowd.Net:"
149
+ echo " npm i $PKG@$NEW"
@@ -1,21 +1,21 @@
1
1
  <template>
2
2
  <div class="sparkle-loader" role="status" :aria-label="alt">
3
3
  <svg :width="size" :height="size" viewBox="-100 -100 200 200" xmlns="http://www.w3.org/2000/svg">
4
- <g id="bottom-star">
4
+ <g class="bottom-star">
5
5
  <path
6
6
  d="M39.286883,33.960772c-6.044693,2.417601-7.991402,4.376919-10.393442,10.460772C26.491402,38.337691,24.544694,36.378373,18.5,33.960772C24.544694,31.543171,26.491402,29.583852,28.893441,23.5c2.402041,6.083852,4.348749,8.043171,10.393442,10.460772Z"
7
7
  transform="matrix(1 0 0 1 -5 -6)"
8
8
  fill="#8b5cf6"
9
9
  ></path>
10
10
  </g>
11
- <g id="top-star">
11
+ <g class="top-star">
12
12
  <path
13
13
  d="M39.056802,33.844967c-5.977787,2.390837-7.902948,4.328466-10.278401,10.344967C26.402949,38.173434,24.477787,36.235805,18.5,33.844967C24.477787,31.454131,26.402949,29.516502,28.778401,23.5c2.375453,6.016502,4.300614,7.954131,10.278401,10.344967Z"
14
14
  transform="matrix(1 0 0 1 -5 -61)"
15
15
  fill="#8b5cf6"
16
16
  ></path>
17
17
  </g>
18
- <g id="primary">
18
+ <g class="primary">
19
19
  <path
20
20
  d="M65.653886,47.229432c-13.71205,5.484135-18.128049,9.928695-23.576943,23.729431C36.62805,57.158127,32.212051,52.713567,18.5,47.229432C32.212051,41.745296,36.62805,37.300736,42.076943,23.5c5.448894,13.800736,9.864893,18.245296,23.576943,23.729432Z"
21
21
  transform="matrix(1.595951 0.008736 -0.00868 1.585695 -77.344676 -75.246035)"
@@ -26,14 +26,14 @@
26
26
  <path
27
27
  d="M 0 -90
28
28
  A 90 90 0 0 1 85 -30"
29
- stroke="url(#sparkle-grad-2)"
29
+ :stroke="`url(#${gradientId})`"
30
30
  stroke-width="16"
31
31
  stroke-linecap="round"
32
32
  fill="transparent"
33
33
  ></path>
34
34
  </g>
35
35
  <defs>
36
- <linearGradient id="sparkle-grad-2" x1="0" y1="-90" x2="85" y2="-30" gradientUnits="userSpaceOnUse">
36
+ <linearGradient :id="gradientId" x1="0" y1="-90" x2="85" y2="-30" gradientUnits="userSpaceOnUse">
37
37
  <stop stop-color="#E3E3E3" stop-opacity="0"></stop>
38
38
  <stop offset="0.33" stop-color="#E3E3E3" stop-opacity="0.3"></stop>
39
39
  <stop offset="0.66" stop-color="#8b5cf6" stop-opacity="0.5"></stop>
@@ -45,6 +45,8 @@
45
45
  </template>
46
46
 
47
47
  <script setup lang="ts">
48
+ import { useId } from 'vue';
49
+
48
50
  interface Props {
49
51
  size?: number;
50
52
  alt?: string;
@@ -54,6 +56,8 @@ withDefaults(defineProps<Props>(), {
54
56
  size: 96,
55
57
  alt: 'loading',
56
58
  });
59
+
60
+ const gradientId = useId();
57
61
  </script>
58
62
 
59
63
  <style scoped>
@@ -70,7 +74,7 @@ withDefaults(defineProps<Props>(), {
70
74
  }
71
75
  }
72
76
 
73
- #primary {
77
+ .primary {
74
78
  animation: ai-loader-primary 2000ms infinite ease-in-out;
75
79
  }
76
80
 
@@ -86,11 +90,11 @@ withDefaults(defineProps<Props>(), {
86
90
  }
87
91
  }
88
92
 
89
- #top-star {
93
+ .top-star {
90
94
  animation: ai-loader-secondary-top 2000ms infinite ease-in-out;
91
95
  }
92
96
 
93
- #bottom-star {
97
+ .bottom-star {
94
98
  animation: ai-loader-secondary-bottom 2000ms infinite ease-in-out;
95
99
  }
96
100