@huloglobal/vendure-plugin-geo-block 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/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@huloglobal/vendure-plugin-geo-block` are documented
4
+ here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] — Unreleased
8
+
9
+ ### Added
10
+ - `GeoBlockPlugin` registering five Channel customFields per channel
11
+ (enable toggle, region presets, allowed countries, blocked countries,
12
+ UK region sub-filter).
13
+ - Public `/geo-block/site-config` endpoint serving a flat resolved
14
+ allow-list per channel.
15
+ - Admin endpoints `/geo-block/admin/channels` and `/geo-block/admin/save`.
16
+ - Dedicated admin UI page with mode picker, region preset cards, chip
17
+ pickers, live preview of the resolved allow-list.
18
+ - `resolveAllowedCountries` exported as a pure helper.
19
+ - Licence verification via `@huloglobal/vendure-licence-sdk` with revocation
20
+ polling.
package/LICENSE ADDED
@@ -0,0 +1,34 @@
1
+ HULO Global Limited — Commercial Plugin Licence
2
+
3
+ Copyright (c) 2026 HULO Global Limited. All rights reserved.
4
+
5
+ This software is licensed, not sold, and is made available only to users
6
+ who hold a valid, active subscription or perpetual licence purchased
7
+ from HULO Global Limited.
8
+
9
+ Permitted use:
10
+
11
+ 1. The software may be installed and run on a single Vendure
12
+ instance per active subscription (or per perpetual licence). Each
13
+ licence is bound to one or more hostnames named at purchase time.
14
+
15
+ 2. The source code is published only so that customers may audit it
16
+ for security review. Modification of the source for production use
17
+ is permitted, but redistribution of the modified source or of any
18
+ derivative work — in whole or in part — is not permitted.
19
+
20
+ Prohibited use:
21
+
22
+ - Use without a valid, active licence key, except for non-production
23
+ evaluation under the plugin's "unlicensed mode" (which writes basic
24
+ delivery rows but disables the open/click endpoints).
25
+ - Use of the package to circumvent the licence verification routine,
26
+ or to extract or replace the embedded RSA public key.
27
+ - Resale, sublicensing, or distribution of the package outside of an
28
+ application that itself holds a valid HULO Vendure plugin licence.
29
+
30
+ No warranty. To the maximum extent permitted by law, HULO Global Limited
31
+ disclaims all warranties and all liability arising from use of this
32
+ software.
33
+
34
+ For commercial licensing enquiries: sales@eliteenterprisesoftware.com
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @huloglobal/vendure-plugin-geo-block
2
+
3
+ Per-channel storefront geo-restriction for Vendure. Allow / block traffic
4
+ by country, by curated region preset (EU, EEA, British Isles, all of
5
+ Europe, North America, Oceania, Worldwide-with-denylist), and by UK
6
+ subdivision (England / Wales / Scotland / Northern Ireland).
7
+
8
+ Maintained by Wayne Garrison.
9
+
10
+ ## What you get
11
+
12
+ - **Five clean Channel customFields** registered automatically — the
13
+ consumer doesn't have to repeat them in their `vendure-config.ts`.
14
+ - **Public flat endpoint** at `GET /geo-block/site-config` returning the
15
+ resolved allow-list as JSON, intended to be polled (and cached) by
16
+ the storefront. Identifies the channel via the standard
17
+ `vendure-token` header (same one shop-api uses).
18
+ - **Admin endpoints** at `/geo-block/admin/channels` (read) and
19
+ `/geo-block/admin/save` (write) backing the dedicated admin page.
20
+ - **Dedicated admin UI** under EES Plugins nav: mode-picker (allow
21
+ specific places / allow worldwide except blocked), preset cards
22
+ (one-click region bundles), chip pickers for extras and blocks, live
23
+ preview of the resolved allow-list, UK-region sub-filter when GB is
24
+ resolved as allowed.
25
+ - **Reusable resolver**: `resolveAllowedCountries({ regions,
26
+ extraAllowed, blocked })` is exported as a pure function for
27
+ downstream code.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ yarn add @huloglobal/vendure-plugin-geo-block
33
+ ```
34
+
35
+ ## Wire up
36
+
37
+ ```ts
38
+ import { GeoBlockPlugin } from '@huloglobal/vendure-plugin-geo-block';
39
+
40
+ export const config: VendureConfig = {
41
+ plugins: [
42
+ GeoBlockPlugin.init({
43
+ publicBaseUrl: 'https://shop.example.com',
44
+ licenceKey: process.env.HULO_LICENCE_KEY,
45
+ }),
46
+ ],
47
+ };
48
+ ```
49
+
50
+ Add the admin UI extension:
51
+
52
+ ```ts
53
+ import { GeoBlockPlugin } from '@huloglobal/vendure-plugin-geo-block';
54
+
55
+ compileUiExtensions({
56
+ outputPath: 'admin-ui',
57
+ extensions: [GeoBlockPlugin.uiExtensions /* + your other extensions */],
58
+ });
59
+ ```
60
+
61
+ ## Storefront integration
62
+
63
+ The plugin only manages **configuration**. Your storefront enforces the
64
+ block by polling the resolved allow-list and comparing it to the
65
+ visitor's resolved country. A Qwik / Next / Nuxt example using
66
+ MaxMind GeoLite2 for the lookup:
67
+
68
+ ```ts
69
+ // Fetch + cache the per-channel config (60s TTL).
70
+ const cfg = await fetch('https://shop.example.com/geo-block/site-config?token=' + channelToken)
71
+ .then(r => r.json());
72
+
73
+ if (cfg.geoBlock.enabled) {
74
+ const visitorCountry = /* run a MaxMind lookup on the visitor IP */;
75
+ const allowed =
76
+ cfg.geoBlock.allowedCountries === null
77
+ || cfg.geoBlock.allowedCountries.includes(visitorCountry);
78
+ if (!allowed || cfg.geoBlock.blockedCountries.includes(visitorCountry)) {
79
+ return new Response('Site temporarily unavailable.', { status: 503 });
80
+ }
81
+ }
82
+ ```
83
+
84
+ ## Behind Cloudflare / nginx / Akamai
85
+
86
+ The geo-block plugin itself doesn't need an IP — it just serves a
87
+ resolved allow-list per channel. The **storefront** does the visitor
88
+ lookup. Two paths to wire it up:
89
+
90
+ ### Path 1: use Cloudflare's resolved country header (zero infrastructure)
91
+
92
+ When the "IP Geolocation → Send country data to origin" toggle is on
93
+ in your Cloudflare dashboard (free plan), every request arrives with
94
+ `CF-IPCountry: GB` already populated. Read it directly in your
95
+ storefront:
96
+
97
+ ```ts
98
+ const country = req.headers['cf-ipcountry'] || null;
99
+ if (cfg.geoBlock.enabled && !cfg.geoBlock.allowedCountries?.includes(country)) {
100
+ return new Response('Site temporarily unavailable.', { status: 503 });
101
+ }
102
+ ```
103
+
104
+ Enable "Send subdivision data" too to also get `CF-Region-Code`
105
+ (`ENG`, `WLS`, `SCT`, `NIR`) for UK subdivision filtering.
106
+
107
+ ### Path 2: self-hosted GeoIP lookup (works behind nginx / any proxy)
108
+
109
+ If you're not on Cloudflare, look the visitor IP up via MaxMind
110
+ GeoLite2-City in the storefront. The free `geolite2-redist` npm
111
+ package mirrors the database without requiring a MaxMind account:
112
+
113
+ ```ts
114
+ import { open } from 'geolite2-redist';
115
+ import { Reader } from '@maxmind/geoip2-node';
116
+
117
+ const reader = await open('GeoLite2-City', p => Reader.open(p));
118
+
119
+ // Real IP from nginx / Caddy. The plugin's proxy-headers helper does
120
+ // the same precedence as the email-tracking plugin's IP extractor:
121
+ // cf-connecting-ip → true-client-ip → x-real-ip → x-forwarded-for[0]
122
+ const ip = req.headers['cf-connecting-ip']
123
+ || req.headers['x-real-ip']
124
+ || (req.headers['x-forwarded-for'] || '').split(',')[0].trim();
125
+
126
+ const r = reader.city(ip);
127
+ const country = r.country?.isoCode || null;
128
+ ```
129
+
130
+ Both paths are documented end-to-end in the plugin's example
131
+ storefront snippets at [the README on GitHub](https://github.com/exceeded/vendure-plugin-geo-block).
132
+
133
+ ## Init options
134
+
135
+ | Option | Type | Required | Description |
136
+ | --- | --- | --- | --- |
137
+ | `publicBaseUrl` | `string` | yes | Public hostname of your Vendure server. Used in licence host-match. |
138
+ | `licenceKey` | `string` | no* | JWT licence key. Without it `enabled` is forced to `false`. |
139
+
140
+ \* Required for production use. Buy at
141
+ `https://elite-software.co.uk/licence/buy/vendure-plugin-geo-block`.
142
+
143
+ ## Licence
144
+
145
+ Commercial — see [LICENSE](./LICENSE). Requires an active subscription
146
+ ($9.95/mo) or a perpetual licence.
@@ -0,0 +1,56 @@
1
+ import { RequestContext, TransactionalConnection } from '@vendure/core';
2
+ import { Request, Response } from 'express';
3
+ interface SiteConfig {
4
+ channelToken: string;
5
+ geoBlock: {
6
+ enabled: boolean;
7
+ /** Resolved flat allow-list of ISO 3166-1 alpha-2 country codes
8
+ * the storefront should let through, or `null` meaning "no
9
+ * country restriction" (WORLDWIDE preset). */
10
+ allowedCountries: string[] | null;
11
+ /** Countries the admin always blocks regardless of region. The
12
+ * resolved `allowedCountries` already has these subtracted —
13
+ * this field is exposed for diagnostics + so the storefront can
14
+ * enforce it even when allowedCountries is `null`. */
15
+ blockedCountries: string[];
16
+ /** UK subdivisions that must additionally match when the visitor
17
+ * resolves to GB. Empty = "any UK region allowed". */
18
+ allowedGbRegions: string[];
19
+ /** The raw region presets the admin selected — exposed for
20
+ * diagnostics (and so the frontend can display the admin's
21
+ * intent in any debug UI). */
22
+ allowedRegions: string[];
23
+ };
24
+ companyData: {
25
+ showCompanyNumber: boolean;
26
+ companyNumber: string;
27
+ };
28
+ }
29
+ /**
30
+ * Public endpoint serving the storefront-facing site config for a given
31
+ * channel. The storefront calls GET /ees/site-config and identifies the
32
+ * channel via the standard `vendure-token` header (the same one shop-api
33
+ * uses), or via ?token=<channelToken> as a fallback for static fetchers.
34
+ *
35
+ * Returned shape is deliberately small + flat so the frontend can cache
36
+ * it in module memory and re-fetch every 60s without much overhead.
37
+ */
38
+ export declare class GeoBlockController {
39
+ private connection;
40
+ constructor(connection: TransactionalConnection);
41
+ getConfig(req: Request): Promise<SiteConfig>;
42
+ /**
43
+ * Admin: list every channel with its current geo-block settings.
44
+ * Used by the dedicated Vendure admin page so the admin can switch
45
+ * between Elite / LicenseDock / any future channel from a single
46
+ * screen.
47
+ */
48
+ listChannels(ctx: RequestContext, res: Response): Promise<Response<any, Record<string, any>> | undefined>;
49
+ /**
50
+ * Admin: save the geo-block settings for one channel. Body shape
51
+ * mirrors what `listChannels` returns (minus the resolved preview).
52
+ */
53
+ saveChannel(ctx: RequestContext, body: any, res: Response): Promise<Response<any, Record<string, any>> | undefined>;
54
+ }
55
+ export {};
56
+ //# sourceMappingURL=geo-block.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo-block.controller.d.ts","sourceRoot":"","sources":["../src/geo-block.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,cAAc,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAgB5C,UAAU,UAAU;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QACN,OAAO,EAAE,OAAO,CAAC;QACjB;;uDAE+C;QAC/C,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAClC;;;+DAGuD;QACvD,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B;+DACuD;QACvD,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B;;uCAE+B;QAC/B,cAAc,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,WAAW,EAAE;QACT,iBAAiB,EAAE,OAAO,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;KACzB,CAAC;CACL;AAcD;;;;;;;;GAQG;AACH,qBACa,kBAAkB;IACf,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,uBAAuB;IAGjD,SAAS,CAAQ,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAqEzD;;;;;OAKG;IAEG,YAAY,CAAQ,GAAG,EAAE,cAAc,EAAS,GAAG,EAAE,QAAQ;IA6CnE;;;OAGG;IAEG,WAAW,CAAQ,GAAG,EAAE,cAAc,EAAU,IAAI,EAAE,GAAG,EAAS,GAAG,EAAE,QAAQ;CA8BxF"}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.GeoBlockController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@vendure/core");
18
+ const geo_regions_1 = require("./geo-regions");
19
+ function requireAdmin(ctx, res, write = false) {
20
+ if (!(ctx === null || ctx === void 0 ? void 0 : ctx.activeUserId)) {
21
+ res.status(401).json({ error: 'Authentication required' });
22
+ return false;
23
+ }
24
+ const needed = write ? [core_1.Permission.UpdateCatalog] : [core_1.Permission.ReadCatalog];
25
+ if (!ctx.userHasPermissions(needed)) {
26
+ res.status(403).json({ error: 'Insufficient permissions' });
27
+ return false;
28
+ }
29
+ return true;
30
+ }
31
+ const DEFAULTS = {
32
+ channelToken: '',
33
+ geoBlock: {
34
+ enabled: false,
35
+ allowedCountries: ['GB'],
36
+ blockedCountries: [],
37
+ allowedGbRegions: ['ENG', 'WLS'],
38
+ allowedRegions: [],
39
+ },
40
+ companyData: { showCompanyNumber: false, companyNumber: '' },
41
+ };
42
+ /**
43
+ * Public endpoint serving the storefront-facing site config for a given
44
+ * channel. The storefront calls GET /ees/site-config and identifies the
45
+ * channel via the standard `vendure-token` header (the same one shop-api
46
+ * uses), or via ?token=<channelToken> as a fallback for static fetchers.
47
+ *
48
+ * Returned shape is deliberately small + flat so the frontend can cache
49
+ * it in module memory and re-fetch every 60s without much overhead.
50
+ */
51
+ let GeoBlockController = class GeoBlockController {
52
+ constructor(connection) {
53
+ this.connection = connection;
54
+ }
55
+ async getConfig(req) {
56
+ const headerToken = req.headers['vendure-token']
57
+ || req.headers['x-vendure-token']
58
+ || req.query.token
59
+ || '';
60
+ const token = headerToken.trim();
61
+ if (!token) {
62
+ return { ...DEFAULTS };
63
+ }
64
+ const rows = await this.connection.rawConnection.query(`SELECT token,
65
+ customFieldsShowcompanynumber AS showCompanyNumber,
66
+ customFieldsBusinesscompanynumber AS companyNumber,
67
+ customFieldsGeoblockenabled AS geoBlockEnabled,
68
+ customFieldsGeoblockallowedregions AS allowedRegions,
69
+ customFieldsGeoblockallowedcountries AS extraAllowed,
70
+ customFieldsGeoblockblockedcountries AS blockedCountries,
71
+ customFieldsGeoblockallowedgbregions AS allowedGbRegions
72
+ FROM channel
73
+ WHERE token = ?
74
+ LIMIT 1`, [token]);
75
+ if (!rows.length) {
76
+ return { ...DEFAULTS, channelToken: token };
77
+ }
78
+ const r = rows[0];
79
+ const parseList = (raw, fallback) => {
80
+ if (Array.isArray(raw))
81
+ return raw.filter(v => typeof v === 'string');
82
+ if (typeof raw !== 'string' || !raw.length)
83
+ return fallback;
84
+ try {
85
+ const parsed = JSON.parse(raw);
86
+ if (Array.isArray(parsed))
87
+ return parsed.filter(v => typeof v === 'string');
88
+ }
89
+ catch { }
90
+ // MariaDB stores list customFields as a JSON-encoded text. Be
91
+ // forgiving of a CSV fallback for older rows.
92
+ return raw.split(',').map(s => s.trim()).filter(Boolean);
93
+ };
94
+ const allowedRegions = parseList(r.allowedRegions, []);
95
+ const extraAllowed = parseList(r.extraAllowed, ['GB']);
96
+ const blockedCountries = parseList(r.blockedCountries, []);
97
+ // Resolve regions + extras − blocked into a single flat allow-list.
98
+ // `allowed === null` means WORLDWIDE — no country filter, only the
99
+ // denylist applies.
100
+ const resolved = (0, geo_regions_1.resolveAllowedCountries)({
101
+ regions: allowedRegions,
102
+ extraAllowed,
103
+ blocked: blockedCountries,
104
+ });
105
+ return {
106
+ channelToken: token,
107
+ geoBlock: {
108
+ enabled: !!Number(r.geoBlockEnabled || 0),
109
+ allowedCountries: resolved.allowed,
110
+ blockedCountries: resolved.blocked,
111
+ allowedGbRegions: parseList(r.allowedGbRegions, ['ENG', 'WLS']),
112
+ allowedRegions,
113
+ },
114
+ companyData: {
115
+ showCompanyNumber: !!Number(r.showCompanyNumber || 0),
116
+ companyNumber: String(r.companyNumber || ''),
117
+ },
118
+ };
119
+ }
120
+ /**
121
+ * Admin: list every channel with its current geo-block settings.
122
+ * Used by the dedicated Vendure admin page so the admin can switch
123
+ * between Elite / LicenseDock / any future channel from a single
124
+ * screen.
125
+ */
126
+ async listChannels(ctx, res) {
127
+ if (!requireAdmin(ctx, res, false))
128
+ return;
129
+ const rows = await this.connection.rawConnection.query(`SELECT id, code, token,
130
+ COALESCE(customFieldsGeoblockenabled, 0) AS geoBlockEnabled,
131
+ customFieldsGeoblockallowedregions AS allowedRegions,
132
+ customFieldsGeoblockallowedcountries AS extraAllowed,
133
+ customFieldsGeoblockblockedcountries AS blockedCountries,
134
+ customFieldsGeoblockallowedgbregions AS allowedGbRegions
135
+ FROM channel
136
+ ORDER BY id`);
137
+ const parseList = (raw, fallback) => {
138
+ if (Array.isArray(raw))
139
+ return raw.filter(v => typeof v === 'string');
140
+ if (typeof raw !== 'string' || !raw.length)
141
+ return fallback;
142
+ try {
143
+ const parsed = JSON.parse(raw);
144
+ if (Array.isArray(parsed))
145
+ return parsed.filter(v => typeof v === 'string');
146
+ }
147
+ catch { }
148
+ return raw.split(',').map(s => s.trim()).filter(Boolean);
149
+ };
150
+ const result = rows.map((r) => {
151
+ const allowedRegions = parseList(r.allowedRegions, []);
152
+ const extraAllowed = parseList(r.extraAllowed, []);
153
+ const blockedCountries = parseList(r.blockedCountries, []);
154
+ const resolved = (0, geo_regions_1.resolveAllowedCountries)({
155
+ regions: allowedRegions,
156
+ extraAllowed,
157
+ blocked: blockedCountries,
158
+ });
159
+ return {
160
+ id: r.id,
161
+ code: r.code,
162
+ token: r.token,
163
+ enabled: !!Number(r.geoBlockEnabled || 0),
164
+ allowedRegions,
165
+ extraAllowed,
166
+ blockedCountries,
167
+ allowedGbRegions: parseList(r.allowedGbRegions, []),
168
+ resolved: { allowedCountries: resolved.allowed, blockedCountries: resolved.blocked },
169
+ };
170
+ });
171
+ return res.json({ channels: result });
172
+ }
173
+ /**
174
+ * Admin: save the geo-block settings for one channel. Body shape
175
+ * mirrors what `listChannels` returns (minus the resolved preview).
176
+ */
177
+ async saveChannel(ctx, body, res) {
178
+ if (!requireAdmin(ctx, res, true))
179
+ return;
180
+ if (!(body === null || body === void 0 ? void 0 : body.token) || typeof body.token !== 'string') {
181
+ return res.status(400).json({ error: 'channel token required' });
182
+ }
183
+ const normList = (v) => {
184
+ if (!Array.isArray(v))
185
+ return '[]';
186
+ const clean = v.filter(x => typeof x === 'string').map(x => x.trim().toUpperCase()).filter(Boolean);
187
+ return JSON.stringify(Array.from(new Set(clean)));
188
+ };
189
+ const enabled = body.enabled ? 1 : 0;
190
+ const regions = normList(body.allowedRegions);
191
+ const extras = normList(body.extraAllowed);
192
+ const blocked = normList(body.blockedCountries);
193
+ const gbRegions = normList(body.allowedGbRegions);
194
+ const updated = await this.connection.rawConnection.query(`UPDATE channel
195
+ SET customFieldsGeoblockenabled = ?,
196
+ customFieldsGeoblockallowedregions = ?,
197
+ customFieldsGeoblockallowedcountries = ?,
198
+ customFieldsGeoblockblockedcountries = ?,
199
+ customFieldsGeoblockallowedgbregions = ?
200
+ WHERE token = ?`, [enabled, regions, extras, blocked, gbRegions, body.token]);
201
+ if (!updated.affectedRows) {
202
+ return res.status(404).json({ error: 'channel not found' });
203
+ }
204
+ return res.json({ ok: true });
205
+ }
206
+ };
207
+ exports.GeoBlockController = GeoBlockController;
208
+ __decorate([
209
+ (0, common_1.Get)('site-config'),
210
+ __param(0, (0, common_1.Req)()),
211
+ __metadata("design:type", Function),
212
+ __metadata("design:paramtypes", [Object]),
213
+ __metadata("design:returntype", Promise)
214
+ ], GeoBlockController.prototype, "getConfig", null);
215
+ __decorate([
216
+ (0, common_1.Get)('admin/channels'),
217
+ __param(0, (0, core_1.Ctx)()),
218
+ __param(1, (0, common_1.Res)()),
219
+ __metadata("design:type", Function),
220
+ __metadata("design:paramtypes", [core_1.RequestContext, Object]),
221
+ __metadata("design:returntype", Promise)
222
+ ], GeoBlockController.prototype, "listChannels", null);
223
+ __decorate([
224
+ (0, common_1.Post)('admin/save'),
225
+ __param(0, (0, core_1.Ctx)()),
226
+ __param(1, (0, common_1.Body)()),
227
+ __param(2, (0, common_1.Res)()),
228
+ __metadata("design:type", Function),
229
+ __metadata("design:paramtypes", [core_1.RequestContext, Object, Object]),
230
+ __metadata("design:returntype", Promise)
231
+ ], GeoBlockController.prototype, "saveChannel", null);
232
+ exports.GeoBlockController = GeoBlockController = __decorate([
233
+ (0, common_1.Controller)('geo-block'),
234
+ __metadata("design:paramtypes", [core_1.TransactionalConnection])
235
+ ], GeoBlockController);
236
+ //# sourceMappingURL=geo-block.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo-block.controller.js","sourceRoot":"","sources":["../src/geo-block.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAuE;AACvE,wCAAyF;AAEzF,+CAAwD;AAExD,SAAS,YAAY,CAAC,GAAmB,EAAE,GAAa,EAAE,KAAK,GAAG,KAAK;IACnE,IAAI,CAAC,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,YAAY,CAAA,EAAE,CAAC;QACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAU,CAAC,WAAW,CAAC,CAAC;IAC7E,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AA6BD,MAAM,QAAQ,GAAe;IACzB,YAAY,EAAE,EAAE;IAChB,QAAQ,EAAE;QACN,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,CAAC,IAAI,CAAC;QACxB,gBAAgB,EAAE,EAAE;QACpB,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAChC,cAAc,EAAE,EAAE;KACrB;IACD,WAAW,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE;CAC/D,CAAC;AAEF;;;;;;;;GAQG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC3B,YAAoB,UAAmC;QAAnC,eAAU,GAAV,UAAU,CAAyB;IAAG,CAAC;IAGrD,AAAN,KAAK,CAAC,SAAS,CAAQ,GAAY;QAC/B,MAAM,WAAW,GAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAY;eACpD,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAY;eACzC,GAAG,CAAC,KAAK,CAAC,KAAgB;eAC3B,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CAClD;;;;;;;;;;qBAUS,EACT,CAAC,KAAK,CAAC,CACV,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,OAAO,EAAE,GAAG,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAChD,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAE,QAAkB,EAAY,EAAE;YACzD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YACtE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM;gBAAE,OAAO,QAAQ,CAAC;YAC5D,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YAChF,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,8DAA8D;YAC9D,8CAA8C;YAC9C,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACvD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAE3D,oEAAoE;QACpE,mEAAmE;QACnE,oBAAoB;QACpB,MAAM,QAAQ,GAAG,IAAA,qCAAuB,EAAC;YACrC,OAAO,EAAE,cAAc;YACvB,YAAY;YACZ,OAAO,EAAE,gBAAgB;SAC5B,CAAC,CAAC;QAEH,OAAO;YACH,YAAY,EAAE,KAAK;YACnB,QAAQ,EAAE;gBACN,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;gBACzC,gBAAgB,EAAE,QAAQ,CAAC,OAAO;gBAClC,gBAAgB,EAAE,QAAQ,CAAC,OAAO;gBAClC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC/D,cAAc;aACjB;YACD,WAAW,EAAE;gBACT,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC;gBACrD,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC;aAC/C;SACJ,CAAC;IACN,CAAC;IAED;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,YAAY,CAAQ,GAAmB,EAAS,GAAa;QAC/D,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC;YAAE,OAAO;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CAClD;;;;;;;yBAOa,CAChB,CAAC;QACF,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAE,QAAkB,EAAY,EAAE;YACzD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YACtE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM;gBAAE,OAAO,QAAQ,CAAC;YAC5D,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YAChF,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YAC/B,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACnD,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,IAAA,qCAAuB,EAAC;gBACrC,OAAO,EAAE,cAAc;gBACvB,YAAY;gBACZ,OAAO,EAAE,gBAAgB;aAC5B,CAAC,CAAC;YACH,OAAO;gBACH,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;gBACzC,cAAc;gBACd,YAAY;gBACZ,gBAAgB;gBAChB,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC;gBACnD,QAAQ,EAAE,EAAE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,EAAE;aACvF,CAAC;QACN,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,WAAW,CAAQ,GAAmB,EAAU,IAAS,EAAS,GAAa;QACjF,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;YAAE,OAAO;QAC1C,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAA,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjD,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,CAAM,EAAU,EAAE;YAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACpG,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CACrD;;;;;;6BAMiB,EACjB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAC7D,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;CACJ,CAAA;AAhKY,gDAAkB;AAIrB;IADL,IAAA,YAAG,EAAC,aAAa,CAAC;IACF,WAAA,IAAA,YAAG,GAAE,CAAA;;;;mDAmErB;AASK;IADL,IAAA,YAAG,EAAC,gBAAgB,CAAC;IACF,WAAA,IAAA,UAAG,GAAE,CAAA;IAAuB,WAAA,IAAA,YAAG,GAAE,CAAA;;qCAAtB,qBAAc;;sDA2C5C;AAOK;IADL,IAAA,aAAI,EAAC,YAAY,CAAC;IACA,WAAA,IAAA,UAAG,GAAE,CAAA;IAAuB,WAAA,IAAA,aAAI,GAAE,CAAA;IAAa,WAAA,IAAA,YAAG,GAAE,CAAA;;qCAAzC,qBAAc;;qDA6B3C;6BA/JQ,kBAAkB;IAD9B,IAAA,mBAAU,EAAC,WAAW,CAAC;qCAEY,8BAAuB;GAD9C,kBAAkB,CAgK9B"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Region presets for the storefront geo-block.
3
+ *
4
+ * Each key is the value stored in the channel customField
5
+ * `geoBlockAllowedRegions`; the array is the ISO 3166-1 alpha-2
6
+ * country list it expands to. The site-config resolver unions the
7
+ * countries from every selected region, adds the admin's "extra
8
+ * allowed countries", then removes anything in the "blocked
9
+ * countries" list — giving a single flat allow-list the storefront
10
+ * checks each visitor against.
11
+ *
12
+ * `WORLDWIDE` is the special "no country filter" preset (still
13
+ * subject to the blocked-countries list, so the admin can ship
14
+ * "everywhere except these few" by picking WORLDWIDE + a denylist).
15
+ */
16
+ export type GeoRegionKey = 'EUROPE' | 'EU' | 'EEA' | 'BRITISH_ISLES' | 'UK_ONLY' | 'NORTH_AMERICA' | 'OCEANIA' | 'WORLDWIDE';
17
+ /**
18
+ * Resolve an admin's geo-block selections into a final country
19
+ * allow-list (or `null` meaning "allow any country").
20
+ *
21
+ * final = (∪ region.expand for r in regions) ∪ extraAllowed − blocked
22
+ *
23
+ * Returns `null` if WORLDWIDE is among the selected regions AND there's
24
+ * no other constraint that would make the resolved set finite — the
25
+ * caller then skips the country check and only applies the denylist.
26
+ */
27
+ export declare function resolveAllowedCountries(input: {
28
+ regions: string[];
29
+ extraAllowed: string[];
30
+ blocked: string[];
31
+ }): {
32
+ allowed: string[] | null;
33
+ blocked: string[];
34
+ };
35
+ //# sourceMappingURL=geo-regions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo-regions.d.ts","sourceRoot":"","sources":["../src/geo-regions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,GAClB,QAAQ,GAAG,IAAI,GAAG,KAAK,GAAG,eAAe,GAAG,SAAS,GACrD,eAAe,GAAG,SAAS,GAAG,WAAW,CAAC;AAgChD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAmBlD"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveAllowedCountries = resolveAllowedCountries;
4
+ const EU_27 = [
5
+ 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE',
6
+ 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT',
7
+ 'RO', 'SK', 'SI', 'ES', 'SE',
8
+ ];
9
+ const EEA_EXTRA = ['IS', 'LI', 'NO']; // EEA non-EU members
10
+ const NON_EU_EUROPE = [
11
+ // The rest of geographic Europe — micro-states, Western Balkans,
12
+ // Eastern Europe. Russia/Belarus included so the admin has a
13
+ // single switch + the freedom to add them to the denylist if
14
+ // they don't want to sell there.
15
+ 'GB', 'CH', 'NO', 'IS', 'LI',
16
+ 'AL', 'AD', 'BA', 'BY', 'FO', 'GI', 'IM', 'JE', 'GG',
17
+ 'MC', 'ME', 'MD', 'MK', 'RS', 'SM', 'UA', 'VA', 'XK', 'RU',
18
+ ];
19
+ const EUROPE = Array.from(new Set([...EU_27, ...NON_EU_EUROPE]));
20
+ const REGION_TO_COUNTRIES = {
21
+ EUROPE,
22
+ EU: EU_27,
23
+ EEA: Array.from(new Set([...EU_27, ...EEA_EXTRA])),
24
+ BRITISH_ISLES: ['GB', 'IE', 'IM', 'JE', 'GG', 'FO'],
25
+ UK_ONLY: ['GB'],
26
+ NORTH_AMERICA: ['US', 'CA', 'MX'],
27
+ OCEANIA: ['AU', 'NZ'],
28
+ WORLDWIDE: null, // null = no country restriction; denylist still applies
29
+ };
30
+ /**
31
+ * Resolve an admin's geo-block selections into a final country
32
+ * allow-list (or `null` meaning "allow any country").
33
+ *
34
+ * final = (∪ region.expand for r in regions) ∪ extraAllowed − blocked
35
+ *
36
+ * Returns `null` if WORLDWIDE is among the selected regions AND there's
37
+ * no other constraint that would make the resolved set finite — the
38
+ * caller then skips the country check and only applies the denylist.
39
+ */
40
+ function resolveAllowedCountries(input) {
41
+ const norm = (s) => s.trim().toUpperCase();
42
+ const regions = (input.regions || []).map(norm);
43
+ const extra = (input.extraAllowed || []).map(norm);
44
+ const blocked = (input.blocked || []).map(norm);
45
+ // Worldwide short-circuits — denylist is the only constraint.
46
+ if (regions.includes('WORLDWIDE')) {
47
+ return { allowed: null, blocked };
48
+ }
49
+ const allowed = new Set();
50
+ for (const r of regions) {
51
+ const countries = REGION_TO_COUNTRIES[r];
52
+ if (countries)
53
+ for (const c of countries)
54
+ allowed.add(c);
55
+ }
56
+ for (const c of extra)
57
+ allowed.add(c);
58
+ for (const c of blocked)
59
+ allowed.delete(c);
60
+ return { allowed: Array.from(allowed).sort(), blocked };
61
+ }
62
+ //# sourceMappingURL=geo-regions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo-regions.js","sourceRoot":"","sources":["../src/geo-regions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `@huloglobal/vendure-plugin-geo-block` — public exports.
3
+ *
4
+ * `GeoBlockPlugin` registers the per-channel custom fields, controllers
5
+ * and admin UI. `resolveAllowedCountries` is also re-exported so
6
+ * downstream plugins / scripts can compute the resolved country
7
+ * allow-list outside the HTTP path.
8
+ */
9
+ export { GeoBlockPlugin, GeoBlockPluginOptions } from './plugin';
10
+ export { resolveAllowedCountries, GeoRegionKey } from './geo-regions';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /**
3
+ * `@huloglobal/vendure-plugin-geo-block` — public exports.
4
+ *
5
+ * `GeoBlockPlugin` registers the per-channel custom fields, controllers
6
+ * and admin UI. `resolveAllowedCountries` is also re-exported so
7
+ * downstream plugins / scripts can compute the resolved country
8
+ * allow-list outside the HTTP path.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.resolveAllowedCountries = exports.GeoBlockPlugin = void 0;
12
+ var plugin_1 = require("./plugin");
13
+ Object.defineProperty(exports, "GeoBlockPlugin", { enumerable: true, get: function () { return plugin_1.GeoBlockPlugin; } });
14
+ var geo_regions_1 = require("./geo-regions");
15
+ Object.defineProperty(exports, "resolveAllowedCountries", { enumerable: true, get: function () { return geo_regions_1.resolveAllowedCountries; } });
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,mCAAiE;AAAxD,wGAAA,cAAc,OAAA;AACvB,6CAAsE;AAA7D,sHAAA,uBAAuB,OAAA"}