@uipkge/nuxt 0.1.1 → 0.1.4

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/README.md CHANGED
@@ -14,20 +14,18 @@ Nuxt module for [i18now](https://i18now.com) — loads translations from the i18
14
14
  ## Installation
15
15
 
16
16
  ```bash
17
- npm install @uipkge/nuxt
17
+ npm install @uipkge/nuxt @nuxtjs/i18n
18
18
  # or
19
- pnpm add @uipkge/nuxt
19
+ pnpm add @uipkge/nuxt @nuxtjs/i18n
20
20
  ```
21
21
 
22
- `@nuxtjs/i18n` is a dependency and will be installed automatically.
23
-
24
22
  ## Setup
25
23
 
26
24
  Add the module to `nuxt.config.ts`:
27
25
 
28
26
  ```ts
29
27
  export default defineNuxtConfig({
30
- modules: ['@uipkge/nuxt'],
28
+ modules: ['@nuxtjs/i18n', '@uipkge/nuxt'],
31
29
 
32
30
  i18now: {
33
31
  projectId: process.env.I18NOW_PROJECT_ID ?? '',
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.1.1",
7
+ "version": "0.1.4",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -6,11 +6,6 @@ const module$1 = defineNuxtModule({
6
6
  configKey: "i18now",
7
7
  compatibility: { nuxt: ">=3.0.0" }
8
8
  },
9
- // Auto-install @nuxtjs/i18n when the user hasn't added it themselves.
10
- // It ships as a dependency of @uipkge/nuxt so no separate install is needed.
11
- moduleDependencies: {
12
- "@nuxtjs/i18n": { version: "^9.0.0 || ^10.0.0" }
13
- },
14
9
  defaults: {
15
10
  host: "https://i18now.com",
16
11
  cdnUrl: "https://cdn.i18now.com",
@@ -49,6 +44,7 @@ const module$1 = defineNuxtModule({
49
44
  src: resolver.resolve("./runtime/plugin"),
50
45
  mode: "server"
51
46
  });
47
+ nuxt.options.build.transpile.push("@uipkge/core");
52
48
  if (nuxt.options.dev) {
53
49
  addServerHandler({
54
50
  route: "/api/_i18now/sync",
@@ -1,15 +1,17 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
- const MAX_TRACKED = 2e3;
3
- const MAX_RETRIES = 3;
2
+ import { createI18nowSyncer } from "@uipkge/core";
4
3
  export default defineNuxtPlugin(async (nuxtApp) => {
5
4
  const { projectId, cdnUrl, environment, syncIn, locale: configLocale } = useRuntimeConfig().public.i18now;
6
- if (!syncIn.includes(import.meta.dev ? "development" : "production")) return;
5
+ if (!syncIn.includes(process.env.NODE_ENV ?? "production")) return;
7
6
  if (!projectId) {
8
7
  console.warn("[i18now] projectId is not set \u2014 key sync disabled.");
9
8
  return;
10
9
  }
11
10
  const i18nGlobal = nuxtApp.$i18n ?? nuxtApp.vueApp.config.globalProperties.$i18n;
12
- const existingKeys = /* @__PURE__ */ new Set();
11
+ const syncer = createI18nowSyncer({
12
+ endpoint: "/api/_i18now/sync",
13
+ debug: import.meta.dev
14
+ });
13
15
  const locale = i18nGlobal?.locale?.value ?? i18nGlobal?.locale ?? configLocale;
14
16
  async function loadLocale(targetLocale) {
15
17
  try {
@@ -17,8 +19,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
17
19
  const res = await fetch(url, { signal: AbortSignal.timeout(8e3) });
18
20
  if (res.ok) {
19
21
  const data = await res.json();
20
- existingKeys.clear();
21
- for (const key of Object.keys(data)) existingKeys.add(key);
22
+ syncer.setExistingKeys(Object.keys(data));
22
23
  i18nGlobal?.setLocaleMessage(targetLocale, data);
23
24
  } else if (import.meta.dev) {
24
25
  console.warn(
@@ -32,59 +33,12 @@ export default defineNuxtPlugin(async (nuxtApp) => {
32
33
  }
33
34
  }
34
35
  await loadLocale(locale);
35
- const synced = /* @__PURE__ */ new Set();
36
- const retries = /* @__PURE__ */ new Map();
37
- const pending = /* @__PURE__ */ new Map();
38
- let flushTimer = null;
39
- function flush() {
40
- flushTimer = null;
41
- if (pending.size === 0) return;
42
- const keys = Array.from(pending.entries()).map(([key, value]) => ({ key, value }));
43
- pending.clear();
44
- fetch("/api/_i18now/sync", {
45
- method: "POST",
46
- headers: { "Content-Type": "application/json" },
47
- body: JSON.stringify({ keys })
48
- }).then((res) => {
49
- if (!res.ok) {
50
- if (import.meta.dev) {
51
- res.json().then((data) => console.warn(`[i18now] Sync failed (${res.status}):`, data?.statusMessage ?? data)).catch(() => console.warn(`[i18now] Sync failed with status ${res.status}`));
52
- }
53
- throw Object.assign(new Error(`${res.status}`), { status: res.status });
54
- }
55
- }).catch((err) => {
56
- const status = err.status ?? 0;
57
- const retryable = status === 0 || status >= 500;
58
- for (const { key } of keys) {
59
- if (!retryable) {
60
- retries.delete(key);
61
- continue;
62
- }
63
- const attempts = (retries.get(key) ?? 0) + 1;
64
- if (attempts < MAX_RETRIES) {
65
- retries.set(key, attempts);
66
- synced.delete(key);
67
- } else {
68
- retries.delete(key);
69
- if (import.meta.dev) {
70
- console.warn(`[i18now] Sync failed after ${MAX_RETRIES} attempts for key "${key}". Giving up.`);
71
- }
72
- }
73
- }
74
- });
75
- }
76
- function syncKey(key, value) {
77
- if (synced.has(key) || synced.size >= MAX_TRACKED) return;
78
- synced.add(key);
79
- pending.set(key, value);
80
- if (!flushTimer) flushTimer = setTimeout(flush, 0);
81
- }
82
36
  const originalGlobalT = nuxtApp.vueApp.config.globalProperties.$t;
83
37
  if (originalGlobalT) {
84
38
  nuxtApp.vueApp.config.globalProperties.$t = function(key, defaultValue, ...rest) {
85
39
  const result = originalGlobalT.call(this, key, defaultValue, ...rest);
86
- if (!existingKeys.has(key) && typeof defaultValue === "string") {
87
- syncKey(key, defaultValue);
40
+ if (!syncer.existingKeys.has(key) && typeof defaultValue === "string") {
41
+ syncer.syncKey(key, defaultValue);
88
42
  }
89
43
  return result;
90
44
  };
@@ -94,7 +48,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
94
48
  });
95
49
  return {
96
50
  provide: {
97
- i18nowSync: { syncKey, existingKeys }
51
+ i18nowSync: { syncKey: syncer.syncKey, existingKeys: syncer.existingKeys }
98
52
  }
99
53
  };
100
54
  });
@@ -1,6 +1,7 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
2
  export default defineNuxtPlugin(async (nuxtApp) => {
3
3
  const { projectId, cdnUrl, environment, locale: configLocale } = useRuntimeConfig().public.i18now;
4
+ if (!projectId) return;
4
5
  const i18n = nuxtApp.$i18n ?? nuxtApp.vueApp.config.globalProperties.$i18n;
5
6
  async function loadLocale(locale) {
6
7
  try {
@@ -1,11 +1,16 @@
1
1
  import { defineNuxtPlugin } from "#app";
2
2
  export default defineNuxtPlugin((nuxtApp) => {
3
- const provides = nuxtApp.vueApp._context?.provides ?? {};
4
- const i18nSym = Object.getOwnPropertySymbols(provides).find((s) => s.toString() === "Symbol(vue-i18n)");
5
- const i18nInstance = i18nSym ? provides[i18nSym] : void 0;
6
- const global = i18nInstance?.global;
7
- if (global) {
8
- global.missingWarn = false;
9
- global.fallbackWarn = false;
3
+ const directGlobal = nuxtApp.$i18n?.global;
4
+ let symbolGlobal;
5
+ if (!directGlobal) {
6
+ const provides = nuxtApp.vueApp._context?.provides ?? {};
7
+ const i18nSym = Object.getOwnPropertySymbols(provides).find((s) => s.toString() === "Symbol(vue-i18n)");
8
+ const i18nInstance = i18nSym ? provides[i18nSym] : void 0;
9
+ symbolGlobal = i18nInstance?.global;
10
+ }
11
+ const globalComposer = directGlobal ?? symbolGlobal;
12
+ if (globalComposer) {
13
+ globalComposer.missingWarn = false;
14
+ globalComposer.fallbackWarn = false;
10
15
  }
11
16
  });
@@ -2,7 +2,7 @@ import { createError, defineEventHandler, readBody } from "h3";
2
2
  export default defineEventHandler(async (event) => {
3
3
  const config = useRuntimeConfig(event);
4
4
  const publicConfig = config.public?.i18now;
5
- const env = import.meta.dev ? "development" : "production";
5
+ const env = process.env.NODE_ENV ?? "production";
6
6
  if (!publicConfig?.syncIn?.includes(env)) {
7
7
  throw createError({ statusCode: 403, statusMessage: "Key sync is disabled in this environment" });
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipkge/nuxt",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -12,32 +12,35 @@
12
12
  "files": [
13
13
  "dist"
14
14
  ],
15
- "scripts": {
16
- "build": "nuxt-module-build build",
17
- "dev": "nuxt-module-build prepare",
18
- "dev:playground": "nuxi dev playground",
19
- "prepack": "nuxt-module-build build",
20
- "test": "vitest run",
21
- "test:watch": "vitest",
22
- "test:coverage": "vitest run --coverage"
23
- },
24
15
  "dependencies": {
25
16
  "@nuxt/kit": "^3.0.0",
26
- "@nuxtjs/i18n": "^9.0.0 || ^10.0.0"
17
+ "@uipkge/core": "0.1.1"
27
18
  },
28
19
  "peerDependencies": {
29
- "vue-i18n": "^9.0.0 || ^10.0.0 || ^11.0.0"
20
+ "vue-i18n": "^9.0.0 || ^10.0.0 || ^11.0.0",
21
+ "@nuxtjs/i18n": "^9.0.0 || ^10.0.0"
30
22
  },
31
23
  "peerDependenciesMeta": {
32
24
  "vue-i18n": {
25
+ "optional": false
26
+ },
27
+ "@nuxtjs/i18n": {
33
28
  "optional": true
34
29
  }
35
30
  },
36
31
  "devDependencies": {
37
32
  "@nuxt/module-builder": "^1.0.0",
38
- "@uipkge/nuxt": "file:uipkge-nuxt-0.1.0.tgz",
39
33
  "happy-dom": "^17.0.0",
40
34
  "nuxt": "^3.0.0",
41
35
  "vitest": "^4.0.0"
36
+ },
37
+ "scripts": {
38
+ "build": "nuxt-module-build build",
39
+ "dev": "nuxt-module-build prepare",
40
+ "dev:playground": "nuxi dev playground",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest",
43
+ "test:coverage": "vitest run --coverage",
44
+ "release": "vitest run && nuxt-module-build build && pnpm publish --access public --no-git-checks"
42
45
  }
43
- }
46
+ }