@mundogamernetwork/shared-ui 1.2.1 → 1.2.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.
package/locales/de.json CHANGED
@@ -51,7 +51,8 @@
51
51
  "restriction": {
52
52
  "exclusive_official": "Official streamers only",
53
53
  "level_official": "Official",
54
- "level_affiliate": "Affiliate"
54
+ "level_affiliate": "Affiliate",
55
+ "tier_locked": "Exklusiv für den Plan {tier} oder höher"
55
56
  },
56
57
  "status_key": {
57
58
  "see_key": "View key",
package/locales/en.json CHANGED
@@ -51,7 +51,8 @@
51
51
  "restriction": {
52
52
  "exclusive_official": "Official streamers only",
53
53
  "level_official": "Official",
54
- "level_affiliate": "Affiliate"
54
+ "level_affiliate": "Affiliate",
55
+ "tier_locked": "Exclusive to {tier} plan or higher"
55
56
  },
56
57
  "status_key": {
57
58
  "see_key": "View key",
@@ -51,7 +51,8 @@
51
51
  "restriction": {
52
52
  "exclusive_official": "Official streamers only",
53
53
  "level_official": "Official",
54
- "level_affiliate": "Affiliate"
54
+ "level_affiliate": "Affiliate",
55
+ "tier_locked": "Exclusiva para o plano {tier} ou superior"
55
56
  },
56
57
  "status_key": {
57
58
  "see_key": "View key",
package/locales/ro.json CHANGED
@@ -51,7 +51,8 @@
51
51
  "restriction": {
52
52
  "exclusive_official": "Official streamers only",
53
53
  "level_official": "Official",
54
- "level_affiliate": "Affiliate"
54
+ "level_affiliate": "Affiliate",
55
+ "tier_locked": "Exclusiv pentru planul {tier} sau superior"
55
56
  },
56
57
  "status_key": {
57
58
  "see_key": "View key",
package/nuxt.config.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { addComponentsDir, createResolver, defineNuxtModule } from "@nuxt/kit";
1
+ import { createRequire } from "node:module";
2
+ import { dirname } from "node:path";
2
3
 
3
4
  // Nuxt's built-in `components` module resolves cross-layer name collisions by
4
5
  // picking the highest `priority` directory (see `scanComponents` in
@@ -13,33 +14,83 @@ import { addComponentsDir, createResolver, defineNuxtModule } from "@nuxt/kit";
13
14
  // (MgBanners, MgLoginModal, MgAppInstallBanner, Playtest components, etc.) to
14
15
  // silently fail to resolve.
15
16
  //
16
- // Fix: register shared-ui's own component directory explicitly via
17
- // `addComponentsDir`, with an explicit `priority` far above anything
18
- // `layerCount - i` could ever produce (realistic layer counts are single
19
- // digits), so shared-ui always wins regardless of the consuming app's layer
20
- // ordering/count.
17
+ // A second, separate footgun discovered while fixing this: `~/components`
18
+ // (a bare alias string) in *this* config is NOT resolved relative to
19
+ // shared-ui's own directory when loaded as an extended layer Nuxt resolves
20
+ // `~` against the *consuming app's* srcDir (aliases are global, not
21
+ // per-layer), so a plain `"~/components"` entry here silently pointed at
22
+ // community-frontend's own `components/` directory and never scanned
23
+ // shared-ui's components at all. An absolute path is required instead.
24
+ //
25
+ // IMPORTANT: do NOT import anything from `@nuxt/kit` (e.g. `createResolver`,
26
+ // `resolveModule`) at the top of this file, and do NOT reference
27
+ // `import.meta` anywhere in it. Older Nuxt/c12 toolchains (e.g. Nuxt 3.13.x,
28
+ // still used by agency-frontend) load layer `nuxt.config.ts` files through an
29
+ // older jiti (1.x) that evaluates them via `vm.Script` in a non-ESM context.
30
+ // Any `import.meta` reference is a hard SyntaxError there ("Cannot use
31
+ // 'import.meta' outside a module") — and critically, importing *anything*
32
+ // from `@nuxt/kit`'s bundle drags jiti into re-transpiling that whole bundle
33
+ // in the same non-ESM vm context too, which itself uses `import.meta.url` /
34
+ // `import.meta.dev` internally and throws the same error, even though none
35
+ // of @nuxt/kit's own `import.meta` usage has anything to do with the specific
36
+ // export being imported. Only Node.js builtins (`node:module`, `node:path`)
37
+ // are safe to import here — jiti 1.x and 2.x both transpile plain builtin
38
+ // imports into `require()` trivially without walking into this trap.
39
+ //
40
+ // Fix: declare shared-ui's own components dir with an absolute path (resolved
41
+ // via `createRequire` + `require.resolve`, no @nuxt/kit, no import.meta) and
42
+ // an explicit `priority` far above anything `layerCount - i` could ever
43
+ // produce (realistic layer counts are single digits), so shared-ui always
44
+ // wins regardless of the consuming app's layer ordering/count.
45
+ //
46
+ // NOTE: do NOT also call `addComponentsDir` for this same path — Nuxt's
47
+ // `scanComponents` dedups purely by `dir.path` via a `scannedPaths` guard, so
48
+ // a *second* dir entry pointing at an already-scanned path is silently
49
+ // skipped (its files never even get globbed), regardless of priority.
50
+ // Declaring the dir once, correctly, is required.
21
51
  const SHARED_UI_COMPONENT_PRIORITY = 1000;
22
52
 
23
- const registerSharedUiComponents = defineNuxtModule({
24
- meta: {
25
- name: "shared-ui-components",
26
- },
27
- setup() {
28
- // Resolve relative to this file (shared-ui's package root), not the
29
- // consuming app's `srcDir`/`~` alias — this is the standard Nuxt Kit
30
- // pattern (`createResolver(import.meta.url)`) and keeps registration
31
- // correct no matter which app extends this layer.
32
- const resolver = createResolver(import.meta.url);
33
- addComponentsDir({
34
- path: resolver.resolve("./components"),
53
+ const require = createRequire(`${process.cwd()}/`);
54
+ const packageRoot = dirname(require.resolve("@mundogamernetwork/shared-ui/package.json"));
55
+
56
+ export default defineNuxtConfig({
57
+ components: [
58
+ {
59
+ path: `${packageRoot}/components`,
35
60
  pathPrefix: false,
36
61
  priority: SHARED_UI_COMPONENT_PRIORITY,
37
- });
62
+ },
63
+ ],
64
+ // @pinia/nuxt only auto-scans the top-level app's own storesDirs by
65
+ // default — it does NOT pick up an extended layer's stores/ directory on
66
+ // its own. Every consuming app previously had to hand-list these specific
67
+ // files in its own nuxt.config.ts pinia.storesDirs (see tv-frontend/
68
+ // community-frontend/agency-frontend history) — easy to forget for new
69
+ // apps and a real cause of a production 500 (useAnnouncementStore /
70
+ // useAppInstallBannerStore "is not defined") when tv-frontend's list
71
+ // went stale relative to shared-ui.
72
+ //
73
+ // Nuxt/c12 merges extended-layer config via defu, which concatenates
74
+ // arrays, so declaring these here gets picked up by every consumer
75
+ // automatically without they having to list them — consumers can still
76
+ // add their own storesDirs entries and this list just gets appended.
77
+ //
78
+ // Deliberately an explicit file list, NOT "${packageRoot}/stores/**" —
79
+ // shared-ui also ships auth/chat/contact/institutional/index stores that
80
+ // collide by name with consuming apps' own, more full-featured local
81
+ // versions; a full glob would silently override them.
82
+ //
83
+ // Absolute paths (via packageRoot), same reasoning as the components dir
84
+ // above: a relative path here resolves against the *consuming app's*
85
+ // srcDir when this file is loaded as an extended layer, not shared-ui's
86
+ // own directory.
87
+ pinia: {
88
+ storesDirs: [
89
+ `${packageRoot}/stores/announcement.ts`,
90
+ `${packageRoot}/stores/appInstallBanner.ts`,
91
+ `${packageRoot}/stores/promotion.ts`,
92
+ ],
38
93
  },
39
- });
40
-
41
- export default defineNuxtConfig({
42
- modules: [registerSharedUiComponents],
43
94
  css: [
44
95
  "@mundogamernetwork/shared-ui/assets/kit/kit-base.css",
45
96
  "@mundogamernetwork/shared-ui/assets/kit/kit-theme.css",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.2.1",
3
+ "version": "1.2.6",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -361,6 +361,10 @@ const campaignsStore = useCampaignsStore()
361
361
 
362
362
  const currentStep = ref(1)
363
363
  const searchTerm = ref("")
364
+ // Guards against out-of-order responses — e.g. clearing the search box right
365
+ // after typing could let the (slower) filtered response resolve after the
366
+ // (faster) unfiltered one, silently reverting the list to stale results.
367
+ let loadRequestToken = 0
364
368
  const currentSlide = ref(0)
365
369
  const slider = ref<HTMLElement | null>(null)
366
370
  let slideInterval: ReturnType<typeof setInterval> | null = null
@@ -499,6 +503,8 @@ async function loadFeaturedCampaigns() {
499
503
  }
500
504
 
501
505
  async function loadCampaigns(page = 1) {
506
+ const requestToken = ++loadRequestToken
507
+
502
508
  if (page === 1) {
503
509
  loading.value = true
504
510
  cards.value = []
@@ -515,9 +521,18 @@ async function loadCampaigns(page = 1) {
515
521
 
516
522
  if (activeFilter.value !== null) params["filter[type_id]"] = activeFilter.value
517
523
  if (activePlatformFilter.value !== null) params["filter[platform_id]"] = activePlatformFilter.value
524
+ // Server-side search — the campaign list is paginated by id desc, so a
525
+ // campaign not on the first page(s) would never match a client-side-only
526
+ // filter over whatever happens to already be loaded.
527
+ if (searchTerm.value.trim()) params["filter[name]"] = searchTerm.value.trim()
518
528
 
519
529
  try {
520
530
  const response = await campaignsStore.fetchCampaigns(params, mgPlatform)
531
+
532
+ // A newer request already started (e.g. user kept typing/cleared the
533
+ // box) — discard this now-stale response instead of overwriting cards.
534
+ if (requestToken !== loadRequestToken) return
535
+
521
536
  const keysData = response.data || []
522
537
  const pagination = response.meta?.pagination || {}
523
538
 
@@ -564,11 +579,14 @@ async function loadCampaigns(page = 1) {
564
579
  loadError.value = false
565
580
  applyUserRequestStatuses()
566
581
  } catch {
582
+ if (requestToken !== loadRequestToken) return
567
583
  hasMoreItems.value = false
568
584
  if (page === 1) loadError.value = true
569
585
  } finally {
570
- loading.value = false
571
- loadingMore.value = false
586
+ if (requestToken === loadRequestToken) {
587
+ loading.value = false
588
+ loadingMore.value = false
589
+ }
572
590
  }
573
591
  }
574
592
 
@@ -704,6 +722,19 @@ const resetAutoplay = () => {
704
722
  // ------------------------------------------------------------------
705
723
  // Step watcher
706
724
  // ------------------------------------------------------------------
725
+ // Debounced server-side search — re-queries the backend by name instead of
726
+ // only filtering whatever page(s) happen to already be loaded client-side.
727
+ let searchDebounce: ReturnType<typeof setTimeout> | null = null
728
+ watch(searchTerm, () => {
729
+ if (currentStep.value !== 1) return
730
+ if (searchDebounce) clearTimeout(searchDebounce)
731
+ searchDebounce = setTimeout(() => {
732
+ currentPage.value = 1
733
+ hasMoreItems.value = true
734
+ loadCampaigns(1)
735
+ }, 400)
736
+ })
737
+
707
738
  watch(currentStep, (newVal) => {
708
739
  activeFilter.value = null
709
740
  activePlatformFilter.value = null
@@ -234,7 +234,7 @@ export const fetchFeaturedCampaigns = (mgPlatform = "MGTV") => {
234
234
  filter: {
235
235
  is_public: true,
236
236
  status: 1,
237
- is_featured: true,
237
+ featured: true,
238
238
  mg_platform: mgPlatform,
239
239
  },
240
240
  sort: "id",