@ipgeotrace/vue 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/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # @ipgeotrace/vue
2
+
3
+ Vue 3 bindings for [IPGeoTrace](https://ipgeotrace.com). Resolve the visitor's location **once** and
4
+ share it across your app with a composable. Built on [`@ipgeotrace/browser`](../browser) — it uses a
5
+ publishable key, so it's safe in the client.
6
+
7
+ Sign up and grab your publishable key at [ipgeotrace.com](https://ipgeotrace.com).
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm add @ipgeotrace/vue vue
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Install the plugin once. It calls `me()` a single time and shares the result app-wide.
18
+
19
+ ```ts
20
+ import { createApp } from 'vue';
21
+ import { ipgeotrace } from '@ipgeotrace/vue';
22
+ import App from './App.vue';
23
+
24
+ createApp(App)
25
+ .use(ipgeotrace, { publishableKey: 'pk_live_...' })
26
+ .mount('#app');
27
+ ```
28
+
29
+ Then read it in any component with `useVisitorGeo()`:
30
+
31
+ ```vue
32
+ <script setup lang="ts">
33
+ import { computed } from 'vue';
34
+ import { useVisitorGeo } from '@ipgeotrace/vue';
35
+
36
+ const { data, loading, error } = useVisitorGeo();
37
+ const currency = computed(() => data.value?.country?.currency ?? 'USD');
38
+ </script>
39
+
40
+ <template>
41
+ <p v-if="loading">Locating…</p>
42
+ <p v-else-if="error">Couldn't detect your location.</p>
43
+ <p v-else>Prices in {{ currency }}</p>
44
+ </template>
45
+ ```
46
+
47
+ ## What the composable gives you
48
+
49
+ All reactive — `data`, `error`, and `loading` are `Ref`s:
50
+
51
+ - `data` — the `GeoResponse`, or `undefined` until it resolves.
52
+ - `error` — a `GeoError` if the lookup failed (`rate_limited`, `network_error`, …).
53
+ - `loading` — `true` while the request is in flight.
54
+ - `refresh()` — run `me()` again. Useful after you know the network changed (e.g. the user toggled a
55
+ VPN), since the result is never cached — every call reflects the visitor's location right now.
56
+
57
+ ## Options
58
+
59
+ Pass browser-client options, defer the first call, or bring your own client:
60
+
61
+ ```ts
62
+ // defer the initial lookup until you call refresh()
63
+ app.use(ipgeotrace, { publishableKey: 'pk_live_...', immediate: false });
64
+
65
+ // pass through browser-client options
66
+ app.use(ipgeotrace, { publishableKey: 'pk_live_...', options: { timeoutMs: 3_000 } });
67
+
68
+ // or share a pre-built client
69
+ import { createBrowserClient } from '@ipgeotrace/browser';
70
+ const client = createBrowserClient({ publishableKey: 'pk_live_...' });
71
+ app.use(ipgeotrace, { client });
72
+ ```
73
+
74
+ See the [`@ipgeotrace/browser` README](../browser) for the underlying `me()` client and publishable
75
+ keys.
package/dist/index.cjs ADDED
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var browser = require('@ipgeotrace/browser');
4
+ var vue = require('vue');
5
+
6
+ // src/plugin.ts
7
+
8
+ // src/context.ts
9
+ var VISITOR_GEO = /* @__PURE__ */ Symbol("ipgeotrace:visitor-geo");
10
+
11
+ // src/plugin.ts
12
+ var ipgeotrace = {
13
+ install(app, options) {
14
+ const opts = options ?? {};
15
+ const client = resolveClient(opts);
16
+ app.provide(VISITOR_GEO, createVisitorGeo(client, opts.immediate ?? true));
17
+ }
18
+ };
19
+ function createVisitorGeo(client, immediate) {
20
+ const data = vue.ref(void 0);
21
+ const error = vue.ref(void 0);
22
+ const loading = vue.ref(false);
23
+ async function refresh(signal) {
24
+ loading.value = true;
25
+ try {
26
+ const result = await client.me(signal);
27
+ if (result.ok) {
28
+ data.value = result.value;
29
+ error.value = void 0;
30
+ } else {
31
+ error.value = result.error;
32
+ }
33
+ } finally {
34
+ loading.value = false;
35
+ }
36
+ }
37
+ if (immediate) void refresh();
38
+ return { data, error, loading, refresh: () => refresh() };
39
+ }
40
+ function resolveClient(options) {
41
+ if (options.client) return options.client;
42
+ if (!options.publishableKey) {
43
+ throw new Error("IPGeoTrace: pass either a client or a publishableKey to app.use(ipgeotrace, \u2026).");
44
+ }
45
+ return browser.createBrowserClient({ publishableKey: options.publishableKey, ...options.options });
46
+ }
47
+ function useVisitorGeo() {
48
+ const state = vue.inject(VISITOR_GEO);
49
+ if (!state) {
50
+ throw new Error("IPGeoTrace: install the plugin with app.use(ipgeotrace, { publishableKey }) before calling useVisitorGeo().");
51
+ }
52
+ return state;
53
+ }
54
+
55
+ exports.VISITOR_GEO = VISITOR_GEO;
56
+ exports.ipgeotrace = ipgeotrace;
57
+ exports.useVisitorGeo = useVisitorGeo;
58
+ //# sourceMappingURL=index.cjs.map
59
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/plugin.ts","../src/use-visitor-geo.ts"],"names":["ref","createBrowserClient","inject"],"mappings":";;;;;;;;AAUO,IAAM,WAAA,0BAA+C,wBAAwB;;;ACO7E,IAAM,UAAA,GAAa;AAAA,EACxB,OAAA,CAAQ,KAAU,OAAA,EAAyC;AACzD,IAAA,MAAM,IAAA,GAAO,WAAW,EAAC;AACzB,IAAA,MAAM,MAAA,GAAS,cAAc,IAAI,CAAA;AACjC,IAAA,GAAA,CAAI,QAAQ,WAAA,EAAa,gBAAA,CAAiB,QAAQ,IAAA,CAAK,SAAA,IAAa,IAAI,CAAC,CAAA;AAAA,EAC3E;AACF;AAEA,SAAS,gBAAA,CAAiB,QAAuB,SAAA,EAAgC;AAC/E,EAAA,MAAM,IAAA,GAAOA,QAA6B,MAAS,CAAA;AACnD,EAAA,MAAM,KAAA,GAAQA,QAA0B,MAAS,CAAA;AACjD,EAAA,MAAM,OAAA,GAAUA,QAAa,KAAK,CAAA;AAElC,EAAA,eAAe,QAAQ,MAAA,EAAqC;AAC1D,IAAA,OAAA,CAAQ,KAAA,GAAQ,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,EAAA,CAAG,MAAM,CAAA;AACrC,MAAA,IAAI,OAAO,EAAA,EAAI;AACb,QAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AACpB,QAAA,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAA;AAAA,MAChB,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,QAAQ,MAAA,CAAO,KAAA;AAAA,MACvB;AAAA,IACF,CAAA,SAAE;AACA,MAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,IAAI,SAAA,OAAgB,OAAA,EAAQ;AAE5B,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,SAAS,OAAA,EAAS,MAAM,SAAQ,EAAE;AAC1D;AAEA,SAAS,cAAc,OAAA,EAAiD;AACtE,EAAA,IAAI,OAAA,CAAQ,MAAA,EAAQ,OAAO,OAAA,CAAQ,MAAA;AACnC,EAAA,IAAI,CAAC,QAAQ,cAAA,EAAgB;AAC3B,IAAA,MAAM,IAAI,MAAM,sFAAiF,CAAA;AAAA,EACnG;AACA,EAAA,OAAOC,2BAAA,CAAoB,EAAE,cAAA,EAAgB,OAAA,CAAQ,gBAAgB,GAAG,OAAA,CAAQ,SAAS,CAAA;AAC3F;ACrDO,SAAS,aAAA,GAA4B;AAC1C,EAAA,MAAM,KAAA,GAAQC,WAAO,WAAW,CAAA;AAChC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,6GAA6G,CAAA;AAAA,EAC/H;AACA,EAAA,OAAO,KAAA;AACT","file":"index.cjs","sourcesContent":["import type { GeoError, GeoResponse } from '@ipgeotrace/browser';\nimport type { InjectionKey, Ref } from 'vue';\n\nexport interface VisitorGeo {\n data: Ref<GeoResponse | undefined>;\n error: Ref<GeoError | undefined>;\n loading: Ref<boolean>;\n refresh: () => Promise<void>;\n}\n\nexport const VISITOR_GEO: InjectionKey<VisitorGeo> = Symbol('ipgeotrace:visitor-geo');\n","import {\n createBrowserClient,\n type BrowserClient,\n type BrowserClientOptions,\n type GeoError,\n type GeoResponse,\n} from '@ipgeotrace/browser';\nimport { ref, type App } from 'vue';\nimport { VISITOR_GEO, type VisitorGeo } from './context.js';\n\nexport interface IpGeoTracePluginOptions {\n publishableKey?: string;\n options?: Omit<BrowserClientOptions, 'publishableKey'>;\n client?: BrowserClient;\n immediate?: boolean;\n}\n\nexport const ipgeotrace = {\n install(app: App, options?: IpGeoTracePluginOptions): void {\n const opts = options ?? {};\n const client = resolveClient(opts);\n app.provide(VISITOR_GEO, createVisitorGeo(client, opts.immediate ?? true));\n },\n};\n\nfunction createVisitorGeo(client: BrowserClient, immediate: boolean): VisitorGeo {\n const data = ref<GeoResponse | undefined>(undefined);\n const error = ref<GeoError | undefined>(undefined);\n const loading = ref<boolean>(false);\n\n async function refresh(signal?: AbortSignal): Promise<void> {\n loading.value = true;\n try {\n const result = await client.me(signal);\n if (result.ok) {\n data.value = result.value;\n error.value = undefined;\n } else {\n error.value = result.error;\n }\n } finally {\n loading.value = false;\n }\n }\n\n if (immediate) void refresh();\n\n return { data, error, loading, refresh: () => refresh() };\n}\n\nfunction resolveClient(options: IpGeoTracePluginOptions): BrowserClient {\n if (options.client) return options.client;\n if (!options.publishableKey) {\n throw new Error('IPGeoTrace: pass either a client or a publishableKey to app.use(ipgeotrace, …).');\n }\n return createBrowserClient({ publishableKey: options.publishableKey, ...options.options });\n}\n","import { inject } from 'vue';\nimport { VISITOR_GEO, type VisitorGeo } from './context.js';\n\nexport function useVisitorGeo(): VisitorGeo {\n const state = inject(VISITOR_GEO);\n if (!state) {\n throw new Error('IPGeoTrace: install the plugin with app.use(ipgeotrace, { publishableKey }) before calling useVisitorGeo().');\n }\n return state;\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { BrowserClientOptions, BrowserClient, GeoResponse, GeoError } from '@ipgeotrace/browser';
2
+ export { GeoError, GeoResponse } from '@ipgeotrace/browser';
3
+ import { App, InjectionKey, Ref } from 'vue';
4
+
5
+ interface IpGeoTracePluginOptions {
6
+ publishableKey?: string;
7
+ options?: Omit<BrowserClientOptions, 'publishableKey'>;
8
+ client?: BrowserClient;
9
+ immediate?: boolean;
10
+ }
11
+ declare const ipgeotrace: {
12
+ install(app: App, options?: IpGeoTracePluginOptions): void;
13
+ };
14
+
15
+ interface VisitorGeo {
16
+ data: Ref<GeoResponse | undefined>;
17
+ error: Ref<GeoError | undefined>;
18
+ loading: Ref<boolean>;
19
+ refresh: () => Promise<void>;
20
+ }
21
+ declare const VISITOR_GEO: InjectionKey<VisitorGeo>;
22
+
23
+ declare function useVisitorGeo(): VisitorGeo;
24
+
25
+ export { type IpGeoTracePluginOptions, VISITOR_GEO, type VisitorGeo, ipgeotrace, useVisitorGeo };
@@ -0,0 +1,25 @@
1
+ import { BrowserClientOptions, BrowserClient, GeoResponse, GeoError } from '@ipgeotrace/browser';
2
+ export { GeoError, GeoResponse } from '@ipgeotrace/browser';
3
+ import { App, InjectionKey, Ref } from 'vue';
4
+
5
+ interface IpGeoTracePluginOptions {
6
+ publishableKey?: string;
7
+ options?: Omit<BrowserClientOptions, 'publishableKey'>;
8
+ client?: BrowserClient;
9
+ immediate?: boolean;
10
+ }
11
+ declare const ipgeotrace: {
12
+ install(app: App, options?: IpGeoTracePluginOptions): void;
13
+ };
14
+
15
+ interface VisitorGeo {
16
+ data: Ref<GeoResponse | undefined>;
17
+ error: Ref<GeoError | undefined>;
18
+ loading: Ref<boolean>;
19
+ refresh: () => Promise<void>;
20
+ }
21
+ declare const VISITOR_GEO: InjectionKey<VisitorGeo>;
22
+
23
+ declare function useVisitorGeo(): VisitorGeo;
24
+
25
+ export { type IpGeoTracePluginOptions, VISITOR_GEO, type VisitorGeo, ipgeotrace, useVisitorGeo };
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ import { createBrowserClient } from '@ipgeotrace/browser';
2
+ import { ref, inject } from 'vue';
3
+
4
+ // src/plugin.ts
5
+
6
+ // src/context.ts
7
+ var VISITOR_GEO = /* @__PURE__ */ Symbol("ipgeotrace:visitor-geo");
8
+
9
+ // src/plugin.ts
10
+ var ipgeotrace = {
11
+ install(app, options) {
12
+ const opts = options ?? {};
13
+ const client = resolveClient(opts);
14
+ app.provide(VISITOR_GEO, createVisitorGeo(client, opts.immediate ?? true));
15
+ }
16
+ };
17
+ function createVisitorGeo(client, immediate) {
18
+ const data = ref(void 0);
19
+ const error = ref(void 0);
20
+ const loading = ref(false);
21
+ async function refresh(signal) {
22
+ loading.value = true;
23
+ try {
24
+ const result = await client.me(signal);
25
+ if (result.ok) {
26
+ data.value = result.value;
27
+ error.value = void 0;
28
+ } else {
29
+ error.value = result.error;
30
+ }
31
+ } finally {
32
+ loading.value = false;
33
+ }
34
+ }
35
+ if (immediate) void refresh();
36
+ return { data, error, loading, refresh: () => refresh() };
37
+ }
38
+ function resolveClient(options) {
39
+ if (options.client) return options.client;
40
+ if (!options.publishableKey) {
41
+ throw new Error("IPGeoTrace: pass either a client or a publishableKey to app.use(ipgeotrace, \u2026).");
42
+ }
43
+ return createBrowserClient({ publishableKey: options.publishableKey, ...options.options });
44
+ }
45
+ function useVisitorGeo() {
46
+ const state = inject(VISITOR_GEO);
47
+ if (!state) {
48
+ throw new Error("IPGeoTrace: install the plugin with app.use(ipgeotrace, { publishableKey }) before calling useVisitorGeo().");
49
+ }
50
+ return state;
51
+ }
52
+
53
+ export { VISITOR_GEO, ipgeotrace, useVisitorGeo };
54
+ //# sourceMappingURL=index.js.map
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts","../src/plugin.ts","../src/use-visitor-geo.ts"],"names":[],"mappings":";;;;;;AAUO,IAAM,WAAA,0BAA+C,wBAAwB;;;ACO7E,IAAM,UAAA,GAAa;AAAA,EACxB,OAAA,CAAQ,KAAU,OAAA,EAAyC;AACzD,IAAA,MAAM,IAAA,GAAO,WAAW,EAAC;AACzB,IAAA,MAAM,MAAA,GAAS,cAAc,IAAI,CAAA;AACjC,IAAA,GAAA,CAAI,QAAQ,WAAA,EAAa,gBAAA,CAAiB,QAAQ,IAAA,CAAK,SAAA,IAAa,IAAI,CAAC,CAAA;AAAA,EAC3E;AACF;AAEA,SAAS,gBAAA,CAAiB,QAAuB,SAAA,EAAgC;AAC/E,EAAA,MAAM,IAAA,GAAO,IAA6B,MAAS,CAAA;AACnD,EAAA,MAAM,KAAA,GAAQ,IAA0B,MAAS,CAAA;AACjD,EAAA,MAAM,OAAA,GAAU,IAAa,KAAK,CAAA;AAElC,EAAA,eAAe,QAAQ,MAAA,EAAqC;AAC1D,IAAA,OAAA,CAAQ,KAAA,GAAQ,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,EAAA,CAAG,MAAM,CAAA;AACrC,MAAA,IAAI,OAAO,EAAA,EAAI;AACb,QAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AACpB,QAAA,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAA;AAAA,MAChB,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,QAAQ,MAAA,CAAO,KAAA;AAAA,MACvB;AAAA,IACF,CAAA,SAAE;AACA,MAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,IAAI,SAAA,OAAgB,OAAA,EAAQ;AAE5B,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,SAAS,OAAA,EAAS,MAAM,SAAQ,EAAE;AAC1D;AAEA,SAAS,cAAc,OAAA,EAAiD;AACtE,EAAA,IAAI,OAAA,CAAQ,MAAA,EAAQ,OAAO,OAAA,CAAQ,MAAA;AACnC,EAAA,IAAI,CAAC,QAAQ,cAAA,EAAgB;AAC3B,IAAA,MAAM,IAAI,MAAM,sFAAiF,CAAA;AAAA,EACnG;AACA,EAAA,OAAO,mBAAA,CAAoB,EAAE,cAAA,EAAgB,OAAA,CAAQ,gBAAgB,GAAG,OAAA,CAAQ,SAAS,CAAA;AAC3F;ACrDO,SAAS,aAAA,GAA4B;AAC1C,EAAA,MAAM,KAAA,GAAQ,OAAO,WAAW,CAAA;AAChC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,6GAA6G,CAAA;AAAA,EAC/H;AACA,EAAA,OAAO,KAAA;AACT","file":"index.js","sourcesContent":["import type { GeoError, GeoResponse } from '@ipgeotrace/browser';\nimport type { InjectionKey, Ref } from 'vue';\n\nexport interface VisitorGeo {\n data: Ref<GeoResponse | undefined>;\n error: Ref<GeoError | undefined>;\n loading: Ref<boolean>;\n refresh: () => Promise<void>;\n}\n\nexport const VISITOR_GEO: InjectionKey<VisitorGeo> = Symbol('ipgeotrace:visitor-geo');\n","import {\n createBrowserClient,\n type BrowserClient,\n type BrowserClientOptions,\n type GeoError,\n type GeoResponse,\n} from '@ipgeotrace/browser';\nimport { ref, type App } from 'vue';\nimport { VISITOR_GEO, type VisitorGeo } from './context.js';\n\nexport interface IpGeoTracePluginOptions {\n publishableKey?: string;\n options?: Omit<BrowserClientOptions, 'publishableKey'>;\n client?: BrowserClient;\n immediate?: boolean;\n}\n\nexport const ipgeotrace = {\n install(app: App, options?: IpGeoTracePluginOptions): void {\n const opts = options ?? {};\n const client = resolveClient(opts);\n app.provide(VISITOR_GEO, createVisitorGeo(client, opts.immediate ?? true));\n },\n};\n\nfunction createVisitorGeo(client: BrowserClient, immediate: boolean): VisitorGeo {\n const data = ref<GeoResponse | undefined>(undefined);\n const error = ref<GeoError | undefined>(undefined);\n const loading = ref<boolean>(false);\n\n async function refresh(signal?: AbortSignal): Promise<void> {\n loading.value = true;\n try {\n const result = await client.me(signal);\n if (result.ok) {\n data.value = result.value;\n error.value = undefined;\n } else {\n error.value = result.error;\n }\n } finally {\n loading.value = false;\n }\n }\n\n if (immediate) void refresh();\n\n return { data, error, loading, refresh: () => refresh() };\n}\n\nfunction resolveClient(options: IpGeoTracePluginOptions): BrowserClient {\n if (options.client) return options.client;\n if (!options.publishableKey) {\n throw new Error('IPGeoTrace: pass either a client or a publishableKey to app.use(ipgeotrace, …).');\n }\n return createBrowserClient({ publishableKey: options.publishableKey, ...options.options });\n}\n","import { inject } from 'vue';\nimport { VISITOR_GEO, type VisitorGeo } from './context.js';\n\nexport function useVisitorGeo(): VisitorGeo {\n const state = inject(VISITOR_GEO);\n if (!state) {\n throw new Error('IPGeoTrace: install the plugin with app.use(ipgeotrace, { publishableKey }) before calling useVisitorGeo().');\n }\n return state;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@ipgeotrace/vue",
3
+ "version": "0.1.0",
4
+ "description": "Vue 3 bindings for IPGeoTrace. Resolve the visitor's location once and share it across your app with useVisitorGeo().",
5
+ "keywords": [
6
+ "ipgeotrace",
7
+ "geolocation",
8
+ "geoip",
9
+ "vue",
10
+ "composable",
11
+ "typescript"
12
+ ],
13
+ "license": "MIT",
14
+ "homepage": "https://ipgeotrace.com",
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "sideEffects": false,
30
+ "engines": {
31
+ "node": ">=18.17"
32
+ },
33
+ "dependencies": {
34
+ "@ipgeotrace/browser": "0.1.0"
35
+ },
36
+ "peerDependencies": {
37
+ "vue": "^3.3.0"
38
+ },
39
+ "devDependencies": {
40
+ "vue": "^3.5.0",
41
+ "tsup": "^8.3.5",
42
+ "typescript": "^5.6.3"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "typecheck": "tsc --noEmit",
48
+ "clean": "rm -rf dist"
49
+ }
50
+ }