@uniforge/platform-shopify 0.1.0-alpha.2
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/dist/auth/index.d.cts +246 -0
- package/dist/auth/index.d.ts +246 -0
- package/dist/auth/index.js +623 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +586 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/billing/index.d.cts +58 -0
- package/dist/billing/index.d.ts +58 -0
- package/dist/billing/index.js +226 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/index.mjs +196 -0
- package/dist/billing/index.mjs.map +1 -0
- package/dist/graphql/index.d.cts +17 -0
- package/dist/graphql/index.d.ts +17 -0
- package/dist/graphql/index.js +67 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/index.mjs +40 -0
- package/dist/graphql/index.mjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11 -0
- package/dist/index.mjs.map +1 -0
- package/dist/multi-store/index.d.cts +28 -0
- package/dist/multi-store/index.d.ts +28 -0
- package/dist/multi-store/index.js +181 -0
- package/dist/multi-store/index.js.map +1 -0
- package/dist/multi-store/index.mjs +152 -0
- package/dist/multi-store/index.mjs.map +1 -0
- package/dist/performance/index.d.cts +22 -0
- package/dist/performance/index.d.ts +22 -0
- package/dist/performance/index.js +64 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/index.mjs +35 -0
- package/dist/performance/index.mjs.map +1 -0
- package/dist/platform/index.d.cts +16 -0
- package/dist/platform/index.d.ts +16 -0
- package/dist/platform/index.js +150 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +121 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/rbac/index.d.cts +38 -0
- package/dist/rbac/index.d.ts +38 -0
- package/dist/rbac/index.js +56 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/index.mjs +29 -0
- package/dist/rbac/index.mjs.map +1 -0
- package/dist/security/index.d.cts +26 -0
- package/dist/security/index.d.ts +26 -0
- package/dist/security/index.js +102 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +69 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/webhooks/index.d.cts +36 -0
- package/dist/webhooks/index.d.ts +36 -0
- package/dist/webhooks/index.js +147 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +118 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Role } from '@uniforge/platform-core/rbac';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract user identity from a Shopify online session.
|
|
5
|
+
*
|
|
6
|
+
* Maps Shopify's associatedUser fields to the RBAC SessionUser type.
|
|
7
|
+
* Role mapping: accountOwner → owner, collaborator → collaborator, else → staff.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Shopify user info extracted from a session. */
|
|
11
|
+
interface ShopifyUserInfo {
|
|
12
|
+
userId: number;
|
|
13
|
+
email: string;
|
|
14
|
+
isAccountOwner: boolean;
|
|
15
|
+
suggestedRole: Role;
|
|
16
|
+
firstName: string;
|
|
17
|
+
lastName: string;
|
|
18
|
+
}
|
|
19
|
+
/** Shape of Shopify's onlineAccessInfo from the Session object. */
|
|
20
|
+
interface ShopifyOnlineAccessInfo {
|
|
21
|
+
associatedUser: {
|
|
22
|
+
id: number;
|
|
23
|
+
first_name: string;
|
|
24
|
+
last_name: string;
|
|
25
|
+
email: string;
|
|
26
|
+
account_owner: boolean;
|
|
27
|
+
collaborator: boolean;
|
|
28
|
+
email_verified: boolean;
|
|
29
|
+
locale: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract user info from a Shopify session's online access info.
|
|
34
|
+
* Returns null if the session has no online access info (offline session).
|
|
35
|
+
*/
|
|
36
|
+
declare function extractShopifyUser(onlineAccessInfo: unknown): ShopifyUserInfo | null;
|
|
37
|
+
|
|
38
|
+
export { type ShopifyOnlineAccessInfo, type ShopifyUserInfo, extractShopifyUser };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Role } from '@uniforge/platform-core/rbac';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract user identity from a Shopify online session.
|
|
5
|
+
*
|
|
6
|
+
* Maps Shopify's associatedUser fields to the RBAC SessionUser type.
|
|
7
|
+
* Role mapping: accountOwner → owner, collaborator → collaborator, else → staff.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Shopify user info extracted from a session. */
|
|
11
|
+
interface ShopifyUserInfo {
|
|
12
|
+
userId: number;
|
|
13
|
+
email: string;
|
|
14
|
+
isAccountOwner: boolean;
|
|
15
|
+
suggestedRole: Role;
|
|
16
|
+
firstName: string;
|
|
17
|
+
lastName: string;
|
|
18
|
+
}
|
|
19
|
+
/** Shape of Shopify's onlineAccessInfo from the Session object. */
|
|
20
|
+
interface ShopifyOnlineAccessInfo {
|
|
21
|
+
associatedUser: {
|
|
22
|
+
id: number;
|
|
23
|
+
first_name: string;
|
|
24
|
+
last_name: string;
|
|
25
|
+
email: string;
|
|
26
|
+
account_owner: boolean;
|
|
27
|
+
collaborator: boolean;
|
|
28
|
+
email_verified: boolean;
|
|
29
|
+
locale: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract user info from a Shopify session's online access info.
|
|
34
|
+
* Returns null if the session has no online access info (offline session).
|
|
35
|
+
*/
|
|
36
|
+
declare function extractShopifyUser(onlineAccessInfo: unknown): ShopifyUserInfo | null;
|
|
37
|
+
|
|
38
|
+
export { type ShopifyOnlineAccessInfo, type ShopifyUserInfo, extractShopifyUser };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/rbac/index.ts
|
|
21
|
+
var rbac_exports = {};
|
|
22
|
+
__export(rbac_exports, {
|
|
23
|
+
extractShopifyUser: () => extractShopifyUser
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(rbac_exports);
|
|
26
|
+
|
|
27
|
+
// src/rbac/user-extractor.ts
|
|
28
|
+
function extractShopifyUser(onlineAccessInfo) {
|
|
29
|
+
if (!onlineAccessInfo || typeof onlineAccessInfo !== "object") {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const info = onlineAccessInfo;
|
|
33
|
+
if (!info.associatedUser) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const user = info.associatedUser;
|
|
37
|
+
let suggestedRole = "staff";
|
|
38
|
+
if (user.account_owner) {
|
|
39
|
+
suggestedRole = "owner";
|
|
40
|
+
} else if (user.collaborator) {
|
|
41
|
+
suggestedRole = "collaborator";
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
userId: user.id,
|
|
45
|
+
email: user.email,
|
|
46
|
+
isAccountOwner: user.account_owner,
|
|
47
|
+
suggestedRole,
|
|
48
|
+
firstName: user.first_name,
|
|
49
|
+
lastName: user.last_name
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
53
|
+
0 && (module.exports = {
|
|
54
|
+
extractShopifyUser
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/rbac/index.ts","../../src/rbac/user-extractor.ts"],"sourcesContent":["/**\n * @uniforge/platform-shopify/rbac\n *\n * Shopify-specific RBAC utilities for extracting user identity\n * from Shopify online sessions.\n */\n\nexport { extractShopifyUser } from './user-extractor.js';\nexport type { ShopifyUserInfo, ShopifyOnlineAccessInfo } from './user-extractor.js';\n","/**\n * Extract user identity from a Shopify online session.\n *\n * Maps Shopify's associatedUser fields to the RBAC SessionUser type.\n * Role mapping: accountOwner → owner, collaborator → collaborator, else → staff.\n */\n\nimport type { Role } from '@uniforge/platform-core/rbac';\n\n/** Shopify user info extracted from a session. */\nexport interface ShopifyUserInfo {\n userId: number;\n email: string;\n isAccountOwner: boolean;\n suggestedRole: Role;\n firstName: string;\n lastName: string;\n}\n\n/** Shape of Shopify's onlineAccessInfo from the Session object. */\nexport interface ShopifyOnlineAccessInfo {\n associatedUser: {\n id: number;\n first_name: string;\n last_name: string;\n email: string;\n account_owner: boolean;\n collaborator: boolean;\n email_verified: boolean;\n locale: string;\n };\n}\n\n/**\n * Extract user info from a Shopify session's online access info.\n * Returns null if the session has no online access info (offline session).\n */\nexport function extractShopifyUser(\n onlineAccessInfo: unknown,\n): ShopifyUserInfo | null {\n if (!onlineAccessInfo || typeof onlineAccessInfo !== 'object') {\n return null;\n }\n\n const info = onlineAccessInfo as ShopifyOnlineAccessInfo;\n if (!info.associatedUser) {\n return null;\n }\n\n const user = info.associatedUser;\n\n let suggestedRole: Role = 'staff';\n if (user.account_owner) {\n suggestedRole = 'owner';\n } else if (user.collaborator) {\n suggestedRole = 'collaborator';\n }\n\n return {\n userId: user.id,\n email: user.email,\n isAccountOwner: user.account_owner,\n suggestedRole,\n firstName: user.first_name,\n lastName: user.last_name,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqCO,SAAS,mBACd,kBACwB;AACxB,MAAI,CAAC,oBAAoB,OAAO,qBAAqB,UAAU;AAC7D,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,MAAI,CAAC,KAAK,gBAAgB;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,KAAK;AAElB,MAAI,gBAAsB;AAC1B,MAAI,KAAK,eAAe;AACtB,oBAAgB;AAAA,EAClB,WAAW,KAAK,cAAc;AAC5B,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,gBAAgB,KAAK;AAAA,IACrB;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,EACjB;AACF;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/rbac/user-extractor.ts
|
|
2
|
+
function extractShopifyUser(onlineAccessInfo) {
|
|
3
|
+
if (!onlineAccessInfo || typeof onlineAccessInfo !== "object") {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
const info = onlineAccessInfo;
|
|
7
|
+
if (!info.associatedUser) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const user = info.associatedUser;
|
|
11
|
+
let suggestedRole = "staff";
|
|
12
|
+
if (user.account_owner) {
|
|
13
|
+
suggestedRole = "owner";
|
|
14
|
+
} else if (user.collaborator) {
|
|
15
|
+
suggestedRole = "collaborator";
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
userId: user.id,
|
|
19
|
+
email: user.email,
|
|
20
|
+
isAccountOwner: user.account_owner,
|
|
21
|
+
suggestedRole,
|
|
22
|
+
firstName: user.first_name,
|
|
23
|
+
lastName: user.last_name
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
extractShopifyUser
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/rbac/user-extractor.ts"],"sourcesContent":["/**\n * Extract user identity from a Shopify online session.\n *\n * Maps Shopify's associatedUser fields to the RBAC SessionUser type.\n * Role mapping: accountOwner → owner, collaborator → collaborator, else → staff.\n */\n\nimport type { Role } from '@uniforge/platform-core/rbac';\n\n/** Shopify user info extracted from a session. */\nexport interface ShopifyUserInfo {\n userId: number;\n email: string;\n isAccountOwner: boolean;\n suggestedRole: Role;\n firstName: string;\n lastName: string;\n}\n\n/** Shape of Shopify's onlineAccessInfo from the Session object. */\nexport interface ShopifyOnlineAccessInfo {\n associatedUser: {\n id: number;\n first_name: string;\n last_name: string;\n email: string;\n account_owner: boolean;\n collaborator: boolean;\n email_verified: boolean;\n locale: string;\n };\n}\n\n/**\n * Extract user info from a Shopify session's online access info.\n * Returns null if the session has no online access info (offline session).\n */\nexport function extractShopifyUser(\n onlineAccessInfo: unknown,\n): ShopifyUserInfo | null {\n if (!onlineAccessInfo || typeof onlineAccessInfo !== 'object') {\n return null;\n }\n\n const info = onlineAccessInfo as ShopifyOnlineAccessInfo;\n if (!info.associatedUser) {\n return null;\n }\n\n const user = info.associatedUser;\n\n let suggestedRole: Role = 'staff';\n if (user.account_owner) {\n suggestedRole = 'owner';\n } else if (user.collaborator) {\n suggestedRole = 'collaborator';\n }\n\n return {\n userId: user.id,\n email: user.email,\n isAccountOwner: user.account_owner,\n suggestedRole,\n firstName: user.first_name,\n lastName: user.last_name,\n };\n}\n"],"mappings":";AAqCO,SAAS,mBACd,kBACwB;AACxB,MAAI,CAAC,oBAAoB,OAAO,qBAAqB,UAAU;AAC7D,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,MAAI,CAAC,KAAK,gBAAgB;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,KAAK;AAElB,MAAI,gBAAsB;AAC1B,MAAI,KAAK,eAAe;AACtB,oBAAgB;AAAA,EAClB,WAAW,KAAK,cAAc;AAC5B,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,gBAAgB,KAAK;AAAA,IACrB;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,EACjB;AACF;","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SecurityHeadersConfig, CSPDirectives, RateLimitConfig, InputValidationRule } from '@uniforge/platform-core/security';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shopify-specific security defaults.
|
|
5
|
+
*
|
|
6
|
+
* Provides pre-configured security headers, CSP directives, and rate limit
|
|
7
|
+
* settings tuned for Shopify embedded apps.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const SHOPIFY_SECURITY_HEADERS: SecurityHeadersConfig;
|
|
11
|
+
declare const SHOPIFY_CSP_DIRECTIVES: CSPDirectives;
|
|
12
|
+
declare const SHOPIFY_RATE_LIMIT: RateLimitConfig;
|
|
13
|
+
declare const SHOPIFY_GRAPHQL_RATE_LIMIT: RateLimitConfig;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Shopify-specific input validation rules.
|
|
17
|
+
*
|
|
18
|
+
* Pre-defined validation rules for common Shopify fields such as
|
|
19
|
+
* shop domains, API keys, and webhook payloads.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
declare const SHOP_DOMAIN_RULE: InputValidationRule;
|
|
23
|
+
declare const SHOPIFY_API_KEY_RULE: InputValidationRule;
|
|
24
|
+
declare const SHOPIFY_WEBHOOK_VALIDATION_RULES: InputValidationRule[];
|
|
25
|
+
|
|
26
|
+
export { SHOPIFY_API_KEY_RULE, SHOPIFY_CSP_DIRECTIVES, SHOPIFY_GRAPHQL_RATE_LIMIT, SHOPIFY_RATE_LIMIT, SHOPIFY_SECURITY_HEADERS, SHOPIFY_WEBHOOK_VALIDATION_RULES, SHOP_DOMAIN_RULE };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SecurityHeadersConfig, CSPDirectives, RateLimitConfig, InputValidationRule } from '@uniforge/platform-core/security';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shopify-specific security defaults.
|
|
5
|
+
*
|
|
6
|
+
* Provides pre-configured security headers, CSP directives, and rate limit
|
|
7
|
+
* settings tuned for Shopify embedded apps.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const SHOPIFY_SECURITY_HEADERS: SecurityHeadersConfig;
|
|
11
|
+
declare const SHOPIFY_CSP_DIRECTIVES: CSPDirectives;
|
|
12
|
+
declare const SHOPIFY_RATE_LIMIT: RateLimitConfig;
|
|
13
|
+
declare const SHOPIFY_GRAPHQL_RATE_LIMIT: RateLimitConfig;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Shopify-specific input validation rules.
|
|
17
|
+
*
|
|
18
|
+
* Pre-defined validation rules for common Shopify fields such as
|
|
19
|
+
* shop domains, API keys, and webhook payloads.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
declare const SHOP_DOMAIN_RULE: InputValidationRule;
|
|
23
|
+
declare const SHOPIFY_API_KEY_RULE: InputValidationRule;
|
|
24
|
+
declare const SHOPIFY_WEBHOOK_VALIDATION_RULES: InputValidationRule[];
|
|
25
|
+
|
|
26
|
+
export { SHOPIFY_API_KEY_RULE, SHOPIFY_CSP_DIRECTIVES, SHOPIFY_GRAPHQL_RATE_LIMIT, SHOPIFY_RATE_LIMIT, SHOPIFY_SECURITY_HEADERS, SHOPIFY_WEBHOOK_VALIDATION_RULES, SHOP_DOMAIN_RULE };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/security/index.ts
|
|
21
|
+
var security_exports = {};
|
|
22
|
+
__export(security_exports, {
|
|
23
|
+
SHOPIFY_API_KEY_RULE: () => SHOPIFY_API_KEY_RULE,
|
|
24
|
+
SHOPIFY_CSP_DIRECTIVES: () => SHOPIFY_CSP_DIRECTIVES,
|
|
25
|
+
SHOPIFY_GRAPHQL_RATE_LIMIT: () => SHOPIFY_GRAPHQL_RATE_LIMIT,
|
|
26
|
+
SHOPIFY_RATE_LIMIT: () => SHOPIFY_RATE_LIMIT,
|
|
27
|
+
SHOPIFY_SECURITY_HEADERS: () => SHOPIFY_SECURITY_HEADERS,
|
|
28
|
+
SHOPIFY_WEBHOOK_VALIDATION_RULES: () => SHOPIFY_WEBHOOK_VALIDATION_RULES,
|
|
29
|
+
SHOP_DOMAIN_RULE: () => SHOP_DOMAIN_RULE
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(security_exports);
|
|
32
|
+
|
|
33
|
+
// src/security/shopify-security-config.ts
|
|
34
|
+
var SHOPIFY_SECURITY_HEADERS = {
|
|
35
|
+
hsts: true,
|
|
36
|
+
hstsMaxAge: 63072e3,
|
|
37
|
+
// 2 years
|
|
38
|
+
hstsIncludeSubDomains: true,
|
|
39
|
+
noSniff: true,
|
|
40
|
+
frameOptions: "DENY",
|
|
41
|
+
xssProtection: true,
|
|
42
|
+
referrerPolicy: "strict-origin-when-cross-origin"
|
|
43
|
+
};
|
|
44
|
+
var SHOPIFY_CSP_DIRECTIVES = {
|
|
45
|
+
defaultSrc: ["'self'"],
|
|
46
|
+
scriptSrc: ["'self'", "https://cdn.shopify.com"],
|
|
47
|
+
styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.shopify.com"],
|
|
48
|
+
imgSrc: ["'self'", "https:", "data:"],
|
|
49
|
+
connectSrc: ["'self'", "https://*.shopify.com", "https://*.myshopify.com"],
|
|
50
|
+
fontSrc: ["'self'", "https://cdn.shopify.com"],
|
|
51
|
+
frameSrc: ["'self'", "https://*.myshopify.com"],
|
|
52
|
+
frameAncestors: ["https://admin.shopify.com", "https://*.myshopify.com"]
|
|
53
|
+
};
|
|
54
|
+
var SHOPIFY_RATE_LIMIT = {
|
|
55
|
+
windowMs: 6e4,
|
|
56
|
+
// 1 minute
|
|
57
|
+
maxRequests: 40,
|
|
58
|
+
// Shopify's REST API limit
|
|
59
|
+
keyPrefix: "shopify:"
|
|
60
|
+
};
|
|
61
|
+
var SHOPIFY_GRAPHQL_RATE_LIMIT = {
|
|
62
|
+
windowMs: 1e3,
|
|
63
|
+
// 1 second
|
|
64
|
+
maxRequests: 2,
|
|
65
|
+
// conservative for leaky bucket
|
|
66
|
+
keyPrefix: "shopify:graphql:"
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/security/shopify-input-rules.ts
|
|
70
|
+
var SHOP_DOMAIN_RULE = {
|
|
71
|
+
field: "shopDomain",
|
|
72
|
+
type: "shopDomain",
|
|
73
|
+
required: true,
|
|
74
|
+
message: "Must be a valid .myshopify.com domain"
|
|
75
|
+
};
|
|
76
|
+
var SHOPIFY_API_KEY_RULE = {
|
|
77
|
+
field: "apiKey",
|
|
78
|
+
type: "apiKey",
|
|
79
|
+
required: true,
|
|
80
|
+
message: "Must be a valid Shopify API key"
|
|
81
|
+
};
|
|
82
|
+
var SHOPIFY_WEBHOOK_VALIDATION_RULES = [
|
|
83
|
+
SHOP_DOMAIN_RULE,
|
|
84
|
+
{
|
|
85
|
+
field: "topic",
|
|
86
|
+
type: "string",
|
|
87
|
+
required: true,
|
|
88
|
+
maxLength: 100,
|
|
89
|
+
message: "Webhook topic is required"
|
|
90
|
+
}
|
|
91
|
+
];
|
|
92
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
93
|
+
0 && (module.exports = {
|
|
94
|
+
SHOPIFY_API_KEY_RULE,
|
|
95
|
+
SHOPIFY_CSP_DIRECTIVES,
|
|
96
|
+
SHOPIFY_GRAPHQL_RATE_LIMIT,
|
|
97
|
+
SHOPIFY_RATE_LIMIT,
|
|
98
|
+
SHOPIFY_SECURITY_HEADERS,
|
|
99
|
+
SHOPIFY_WEBHOOK_VALIDATION_RULES,
|
|
100
|
+
SHOP_DOMAIN_RULE
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/security/index.ts","../../src/security/shopify-security-config.ts","../../src/security/shopify-input-rules.ts"],"sourcesContent":["/**\n * @uniforge/platform-shopify/security\n *\n * Shopify-specific security defaults — pre-configured headers,\n * CSP directives, rate limits, and input validation rules.\n */\n\nexport {\n SHOPIFY_SECURITY_HEADERS,\n SHOPIFY_CSP_DIRECTIVES,\n SHOPIFY_RATE_LIMIT,\n SHOPIFY_GRAPHQL_RATE_LIMIT,\n} from './shopify-security-config.js';\n\nexport {\n SHOP_DOMAIN_RULE,\n SHOPIFY_API_KEY_RULE,\n SHOPIFY_WEBHOOK_VALIDATION_RULES,\n} from './shopify-input-rules.js';\n","/**\n * Shopify-specific security defaults.\n *\n * Provides pre-configured security headers, CSP directives, and rate limit\n * settings tuned for Shopify embedded apps.\n */\n\nimport type {\n SecurityHeadersConfig,\n CSPDirectives,\n RateLimitConfig,\n} from '@uniforge/platform-core/security';\n\nexport const SHOPIFY_SECURITY_HEADERS: SecurityHeadersConfig = {\n hsts: true,\n hstsMaxAge: 63072000, // 2 years\n hstsIncludeSubDomains: true,\n noSniff: true,\n frameOptions: 'DENY',\n xssProtection: true,\n referrerPolicy: 'strict-origin-when-cross-origin',\n};\n\nexport const SHOPIFY_CSP_DIRECTIVES: CSPDirectives = {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\", 'https://cdn.shopify.com'],\n styleSrc: [\"'self'\", \"'unsafe-inline'\", 'https://cdn.shopify.com'],\n imgSrc: [\"'self'\", 'https:', 'data:'],\n connectSrc: [\"'self'\", 'https://*.shopify.com', 'https://*.myshopify.com'],\n fontSrc: [\"'self'\", 'https://cdn.shopify.com'],\n frameSrc: [\"'self'\", 'https://*.myshopify.com'],\n frameAncestors: ['https://admin.shopify.com', 'https://*.myshopify.com'],\n};\n\nexport const SHOPIFY_RATE_LIMIT: RateLimitConfig = {\n windowMs: 60000, // 1 minute\n maxRequests: 40, // Shopify's REST API limit\n keyPrefix: 'shopify:',\n};\n\nexport const SHOPIFY_GRAPHQL_RATE_LIMIT: RateLimitConfig = {\n windowMs: 1000, // 1 second\n maxRequests: 2, // conservative for leaky bucket\n keyPrefix: 'shopify:graphql:',\n};\n","/**\n * Shopify-specific input validation rules.\n *\n * Pre-defined validation rules for common Shopify fields such as\n * shop domains, API keys, and webhook payloads.\n */\n\nimport type { InputValidationRule } from '@uniforge/platform-core/security';\n\nexport const SHOP_DOMAIN_RULE: InputValidationRule = {\n field: 'shopDomain',\n type: 'shopDomain',\n required: true,\n message: 'Must be a valid .myshopify.com domain',\n};\n\nexport const SHOPIFY_API_KEY_RULE: InputValidationRule = {\n field: 'apiKey',\n type: 'apiKey',\n required: true,\n message: 'Must be a valid Shopify API key',\n};\n\nexport const SHOPIFY_WEBHOOK_VALIDATION_RULES: InputValidationRule[] = [\n SHOP_DOMAIN_RULE,\n {\n field: 'topic',\n type: 'string',\n required: true,\n maxLength: 100,\n message: 'Webhook topic is required',\n },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaO,IAAM,2BAAkD;AAAA,EAC7D,MAAM;AAAA,EACN,YAAY;AAAA;AAAA,EACZ,uBAAuB;AAAA,EACvB,SAAS;AAAA,EACT,cAAc;AAAA,EACd,eAAe;AAAA,EACf,gBAAgB;AAClB;AAEO,IAAM,yBAAwC;AAAA,EACnD,YAAY,CAAC,QAAQ;AAAA,EACrB,WAAW,CAAC,UAAU,yBAAyB;AAAA,EAC/C,UAAU,CAAC,UAAU,mBAAmB,yBAAyB;AAAA,EACjE,QAAQ,CAAC,UAAU,UAAU,OAAO;AAAA,EACpC,YAAY,CAAC,UAAU,yBAAyB,yBAAyB;AAAA,EACzE,SAAS,CAAC,UAAU,yBAAyB;AAAA,EAC7C,UAAU,CAAC,UAAU,yBAAyB;AAAA,EAC9C,gBAAgB,CAAC,6BAA6B,yBAAyB;AACzE;AAEO,IAAM,qBAAsC;AAAA,EACjD,UAAU;AAAA;AAAA,EACV,aAAa;AAAA;AAAA,EACb,WAAW;AACb;AAEO,IAAM,6BAA8C;AAAA,EACzD,UAAU;AAAA;AAAA,EACV,aAAa;AAAA;AAAA,EACb,WAAW;AACb;;;ACnCO,IAAM,mBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AACX;AAEO,IAAM,uBAA4C;AAAA,EACvD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AACX;AAEO,IAAM,mCAA0D;AAAA,EACrE;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW;AAAA,IACX,SAAS;AAAA,EACX;AACF;","names":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// src/security/shopify-security-config.ts
|
|
2
|
+
var SHOPIFY_SECURITY_HEADERS = {
|
|
3
|
+
hsts: true,
|
|
4
|
+
hstsMaxAge: 63072e3,
|
|
5
|
+
// 2 years
|
|
6
|
+
hstsIncludeSubDomains: true,
|
|
7
|
+
noSniff: true,
|
|
8
|
+
frameOptions: "DENY",
|
|
9
|
+
xssProtection: true,
|
|
10
|
+
referrerPolicy: "strict-origin-when-cross-origin"
|
|
11
|
+
};
|
|
12
|
+
var SHOPIFY_CSP_DIRECTIVES = {
|
|
13
|
+
defaultSrc: ["'self'"],
|
|
14
|
+
scriptSrc: ["'self'", "https://cdn.shopify.com"],
|
|
15
|
+
styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.shopify.com"],
|
|
16
|
+
imgSrc: ["'self'", "https:", "data:"],
|
|
17
|
+
connectSrc: ["'self'", "https://*.shopify.com", "https://*.myshopify.com"],
|
|
18
|
+
fontSrc: ["'self'", "https://cdn.shopify.com"],
|
|
19
|
+
frameSrc: ["'self'", "https://*.myshopify.com"],
|
|
20
|
+
frameAncestors: ["https://admin.shopify.com", "https://*.myshopify.com"]
|
|
21
|
+
};
|
|
22
|
+
var SHOPIFY_RATE_LIMIT = {
|
|
23
|
+
windowMs: 6e4,
|
|
24
|
+
// 1 minute
|
|
25
|
+
maxRequests: 40,
|
|
26
|
+
// Shopify's REST API limit
|
|
27
|
+
keyPrefix: "shopify:"
|
|
28
|
+
};
|
|
29
|
+
var SHOPIFY_GRAPHQL_RATE_LIMIT = {
|
|
30
|
+
windowMs: 1e3,
|
|
31
|
+
// 1 second
|
|
32
|
+
maxRequests: 2,
|
|
33
|
+
// conservative for leaky bucket
|
|
34
|
+
keyPrefix: "shopify:graphql:"
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/security/shopify-input-rules.ts
|
|
38
|
+
var SHOP_DOMAIN_RULE = {
|
|
39
|
+
field: "shopDomain",
|
|
40
|
+
type: "shopDomain",
|
|
41
|
+
required: true,
|
|
42
|
+
message: "Must be a valid .myshopify.com domain"
|
|
43
|
+
};
|
|
44
|
+
var SHOPIFY_API_KEY_RULE = {
|
|
45
|
+
field: "apiKey",
|
|
46
|
+
type: "apiKey",
|
|
47
|
+
required: true,
|
|
48
|
+
message: "Must be a valid Shopify API key"
|
|
49
|
+
};
|
|
50
|
+
var SHOPIFY_WEBHOOK_VALIDATION_RULES = [
|
|
51
|
+
SHOP_DOMAIN_RULE,
|
|
52
|
+
{
|
|
53
|
+
field: "topic",
|
|
54
|
+
type: "string",
|
|
55
|
+
required: true,
|
|
56
|
+
maxLength: 100,
|
|
57
|
+
message: "Webhook topic is required"
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
export {
|
|
61
|
+
SHOPIFY_API_KEY_RULE,
|
|
62
|
+
SHOPIFY_CSP_DIRECTIVES,
|
|
63
|
+
SHOPIFY_GRAPHQL_RATE_LIMIT,
|
|
64
|
+
SHOPIFY_RATE_LIMIT,
|
|
65
|
+
SHOPIFY_SECURITY_HEADERS,
|
|
66
|
+
SHOPIFY_WEBHOOK_VALIDATION_RULES,
|
|
67
|
+
SHOP_DOMAIN_RULE
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/security/shopify-security-config.ts","../../src/security/shopify-input-rules.ts"],"sourcesContent":["/**\n * Shopify-specific security defaults.\n *\n * Provides pre-configured security headers, CSP directives, and rate limit\n * settings tuned for Shopify embedded apps.\n */\n\nimport type {\n SecurityHeadersConfig,\n CSPDirectives,\n RateLimitConfig,\n} from '@uniforge/platform-core/security';\n\nexport const SHOPIFY_SECURITY_HEADERS: SecurityHeadersConfig = {\n hsts: true,\n hstsMaxAge: 63072000, // 2 years\n hstsIncludeSubDomains: true,\n noSniff: true,\n frameOptions: 'DENY',\n xssProtection: true,\n referrerPolicy: 'strict-origin-when-cross-origin',\n};\n\nexport const SHOPIFY_CSP_DIRECTIVES: CSPDirectives = {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\", 'https://cdn.shopify.com'],\n styleSrc: [\"'self'\", \"'unsafe-inline'\", 'https://cdn.shopify.com'],\n imgSrc: [\"'self'\", 'https:', 'data:'],\n connectSrc: [\"'self'\", 'https://*.shopify.com', 'https://*.myshopify.com'],\n fontSrc: [\"'self'\", 'https://cdn.shopify.com'],\n frameSrc: [\"'self'\", 'https://*.myshopify.com'],\n frameAncestors: ['https://admin.shopify.com', 'https://*.myshopify.com'],\n};\n\nexport const SHOPIFY_RATE_LIMIT: RateLimitConfig = {\n windowMs: 60000, // 1 minute\n maxRequests: 40, // Shopify's REST API limit\n keyPrefix: 'shopify:',\n};\n\nexport const SHOPIFY_GRAPHQL_RATE_LIMIT: RateLimitConfig = {\n windowMs: 1000, // 1 second\n maxRequests: 2, // conservative for leaky bucket\n keyPrefix: 'shopify:graphql:',\n};\n","/**\n * Shopify-specific input validation rules.\n *\n * Pre-defined validation rules for common Shopify fields such as\n * shop domains, API keys, and webhook payloads.\n */\n\nimport type { InputValidationRule } from '@uniforge/platform-core/security';\n\nexport const SHOP_DOMAIN_RULE: InputValidationRule = {\n field: 'shopDomain',\n type: 'shopDomain',\n required: true,\n message: 'Must be a valid .myshopify.com domain',\n};\n\nexport const SHOPIFY_API_KEY_RULE: InputValidationRule = {\n field: 'apiKey',\n type: 'apiKey',\n required: true,\n message: 'Must be a valid Shopify API key',\n};\n\nexport const SHOPIFY_WEBHOOK_VALIDATION_RULES: InputValidationRule[] = [\n SHOP_DOMAIN_RULE,\n {\n field: 'topic',\n type: 'string',\n required: true,\n maxLength: 100,\n message: 'Webhook topic is required',\n },\n];\n"],"mappings":";AAaO,IAAM,2BAAkD;AAAA,EAC7D,MAAM;AAAA,EACN,YAAY;AAAA;AAAA,EACZ,uBAAuB;AAAA,EACvB,SAAS;AAAA,EACT,cAAc;AAAA,EACd,eAAe;AAAA,EACf,gBAAgB;AAClB;AAEO,IAAM,yBAAwC;AAAA,EACnD,YAAY,CAAC,QAAQ;AAAA,EACrB,WAAW,CAAC,UAAU,yBAAyB;AAAA,EAC/C,UAAU,CAAC,UAAU,mBAAmB,yBAAyB;AAAA,EACjE,QAAQ,CAAC,UAAU,UAAU,OAAO;AAAA,EACpC,YAAY,CAAC,UAAU,yBAAyB,yBAAyB;AAAA,EACzE,SAAS,CAAC,UAAU,yBAAyB;AAAA,EAC7C,UAAU,CAAC,UAAU,yBAAyB;AAAA,EAC9C,gBAAgB,CAAC,6BAA6B,yBAAyB;AACzE;AAEO,IAAM,qBAAsC;AAAA,EACjD,UAAU;AAAA;AAAA,EACV,aAAa;AAAA;AAAA,EACb,WAAW;AACb;AAEO,IAAM,6BAA8C;AAAA,EACzD,UAAU;AAAA;AAAA,EACV,aAAa;AAAA;AAAA,EACb,WAAW;AACb;;;ACnCO,IAAM,mBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AACX;AAEO,IAAM,uBAA4C;AAAA,EACvD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AACX;AAEO,IAAM,mCAA0D;AAAA,EACrE;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW;AAAA,IACX,SAAS;AAAA,EACX;AACF;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WebhookRegistration } from '@uniforge/platform-core/webhooks';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shopify webhook registration via GraphQL.
|
|
5
|
+
*
|
|
6
|
+
* Uses dependency-injected GraphQL function to register, unregister,
|
|
7
|
+
* and list webhook subscriptions without importing the full Shopify client.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Dependency-injected GraphQL query function. */
|
|
11
|
+
type GraphQLFn = (query: string, variables?: Record<string, unknown>) => Promise<{
|
|
12
|
+
data?: unknown;
|
|
13
|
+
errors?: unknown[];
|
|
14
|
+
}>;
|
|
15
|
+
interface ShopifyWebhookSubscription {
|
|
16
|
+
id: string;
|
|
17
|
+
topic: string;
|
|
18
|
+
endpoint: {
|
|
19
|
+
callbackUrl?: string;
|
|
20
|
+
};
|
|
21
|
+
format: string;
|
|
22
|
+
}
|
|
23
|
+
interface RegisterWebhookResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
webhookSubscriptionId?: string;
|
|
26
|
+
errors?: string[];
|
|
27
|
+
}
|
|
28
|
+
interface UnregisterWebhookResult {
|
|
29
|
+
success: boolean;
|
|
30
|
+
errors?: string[];
|
|
31
|
+
}
|
|
32
|
+
declare function registerShopifyWebhook(graphqlFn: GraphQLFn, registration: WebhookRegistration): Promise<RegisterWebhookResult>;
|
|
33
|
+
declare function unregisterShopifyWebhook(graphqlFn: GraphQLFn, webhookId: string): Promise<UnregisterWebhookResult>;
|
|
34
|
+
declare function listShopifyWebhooks(graphqlFn: GraphQLFn, first?: number): Promise<ShopifyWebhookSubscription[]>;
|
|
35
|
+
|
|
36
|
+
export { type GraphQLFn, type RegisterWebhookResult, type ShopifyWebhookSubscription, type UnregisterWebhookResult, listShopifyWebhooks, registerShopifyWebhook, unregisterShopifyWebhook };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WebhookRegistration } from '@uniforge/platform-core/webhooks';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shopify webhook registration via GraphQL.
|
|
5
|
+
*
|
|
6
|
+
* Uses dependency-injected GraphQL function to register, unregister,
|
|
7
|
+
* and list webhook subscriptions without importing the full Shopify client.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Dependency-injected GraphQL query function. */
|
|
11
|
+
type GraphQLFn = (query: string, variables?: Record<string, unknown>) => Promise<{
|
|
12
|
+
data?: unknown;
|
|
13
|
+
errors?: unknown[];
|
|
14
|
+
}>;
|
|
15
|
+
interface ShopifyWebhookSubscription {
|
|
16
|
+
id: string;
|
|
17
|
+
topic: string;
|
|
18
|
+
endpoint: {
|
|
19
|
+
callbackUrl?: string;
|
|
20
|
+
};
|
|
21
|
+
format: string;
|
|
22
|
+
}
|
|
23
|
+
interface RegisterWebhookResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
webhookSubscriptionId?: string;
|
|
26
|
+
errors?: string[];
|
|
27
|
+
}
|
|
28
|
+
interface UnregisterWebhookResult {
|
|
29
|
+
success: boolean;
|
|
30
|
+
errors?: string[];
|
|
31
|
+
}
|
|
32
|
+
declare function registerShopifyWebhook(graphqlFn: GraphQLFn, registration: WebhookRegistration): Promise<RegisterWebhookResult>;
|
|
33
|
+
declare function unregisterShopifyWebhook(graphqlFn: GraphQLFn, webhookId: string): Promise<UnregisterWebhookResult>;
|
|
34
|
+
declare function listShopifyWebhooks(graphqlFn: GraphQLFn, first?: number): Promise<ShopifyWebhookSubscription[]>;
|
|
35
|
+
|
|
36
|
+
export { type GraphQLFn, type RegisterWebhookResult, type ShopifyWebhookSubscription, type UnregisterWebhookResult, listShopifyWebhooks, registerShopifyWebhook, unregisterShopifyWebhook };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/webhooks/index.ts
|
|
21
|
+
var webhooks_exports = {};
|
|
22
|
+
__export(webhooks_exports, {
|
|
23
|
+
listShopifyWebhooks: () => listShopifyWebhooks,
|
|
24
|
+
registerShopifyWebhook: () => registerShopifyWebhook,
|
|
25
|
+
unregisterShopifyWebhook: () => unregisterShopifyWebhook
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(webhooks_exports);
|
|
28
|
+
|
|
29
|
+
// src/webhooks/registration.ts
|
|
30
|
+
var WEBHOOK_SUBSCRIPTION_CREATE = `
|
|
31
|
+
mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {
|
|
32
|
+
webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {
|
|
33
|
+
webhookSubscription {
|
|
34
|
+
id
|
|
35
|
+
}
|
|
36
|
+
userErrors {
|
|
37
|
+
field
|
|
38
|
+
message
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
var WEBHOOK_SUBSCRIPTION_DELETE = `
|
|
44
|
+
mutation webhookSubscriptionDelete($id: ID!) {
|
|
45
|
+
webhookSubscriptionDelete(id: $id) {
|
|
46
|
+
deletedWebhookSubscriptionId
|
|
47
|
+
userErrors {
|
|
48
|
+
field
|
|
49
|
+
message
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
var WEBHOOK_SUBSCRIPTIONS_QUERY = `
|
|
55
|
+
query webhookSubscriptions($first: Int!) {
|
|
56
|
+
webhookSubscriptions(first: $first) {
|
|
57
|
+
edges {
|
|
58
|
+
node {
|
|
59
|
+
id
|
|
60
|
+
topic
|
|
61
|
+
endpoint {
|
|
62
|
+
... on WebhookHttpEndpoint {
|
|
63
|
+
callbackUrl
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
format
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
async function registerShopifyWebhook(graphqlFn, registration) {
|
|
73
|
+
const response = await graphqlFn(WEBHOOK_SUBSCRIPTION_CREATE, {
|
|
74
|
+
topic: registration.topic,
|
|
75
|
+
webhookSubscription: {
|
|
76
|
+
callbackUrl: registration.address,
|
|
77
|
+
format: (registration.format ?? "json").toUpperCase()
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
if (response.errors && response.errors.length > 0) {
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
errors: response.errors.map((e) => String(e))
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const data = response.data;
|
|
87
|
+
const result = data.webhookSubscriptionCreate;
|
|
88
|
+
if (result.userErrors.length > 0) {
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
errors: result.userErrors.map((e) => e.message)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const registerResult = { success: true };
|
|
95
|
+
const subscriptionId = result.webhookSubscription?.id;
|
|
96
|
+
if (subscriptionId) {
|
|
97
|
+
registerResult.webhookSubscriptionId = subscriptionId;
|
|
98
|
+
}
|
|
99
|
+
return registerResult;
|
|
100
|
+
}
|
|
101
|
+
async function unregisterShopifyWebhook(graphqlFn, webhookId) {
|
|
102
|
+
const response = await graphqlFn(WEBHOOK_SUBSCRIPTION_DELETE, {
|
|
103
|
+
id: webhookId
|
|
104
|
+
});
|
|
105
|
+
if (response.errors && response.errors.length > 0) {
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
errors: response.errors.map((e) => String(e))
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const data = response.data;
|
|
112
|
+
const result = data.webhookSubscriptionDelete;
|
|
113
|
+
if (result.userErrors.length > 0) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
errors: result.userErrors.map((e) => e.message)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return { success: true };
|
|
120
|
+
}
|
|
121
|
+
async function listShopifyWebhooks(graphqlFn, first = 50) {
|
|
122
|
+
const response = await graphqlFn(WEBHOOK_SUBSCRIPTIONS_QUERY, { first });
|
|
123
|
+
if (response.errors && response.errors.length > 0) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const data = response.data;
|
|
127
|
+
return data.webhookSubscriptions.edges.map((edge) => {
|
|
128
|
+
const sub = {
|
|
129
|
+
id: edge.node.id,
|
|
130
|
+
topic: edge.node.topic,
|
|
131
|
+
endpoint: {},
|
|
132
|
+
format: edge.node.format
|
|
133
|
+
};
|
|
134
|
+
const callbackUrl = edge.node.endpoint.callbackUrl;
|
|
135
|
+
if (callbackUrl) {
|
|
136
|
+
sub.endpoint.callbackUrl = callbackUrl;
|
|
137
|
+
}
|
|
138
|
+
return sub;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
listShopifyWebhooks,
|
|
144
|
+
registerShopifyWebhook,
|
|
145
|
+
unregisterShopifyWebhook
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/webhooks/index.ts","../../src/webhooks/registration.ts"],"sourcesContent":["/**\n * @uniforge/platform-shopify - Webhooks\n *\n * Shopify-specific webhook registration via GraphQL mutations.\n */\n\nexport {\n registerShopifyWebhook,\n unregisterShopifyWebhook,\n listShopifyWebhooks,\n} from './registration';\n\nexport type {\n GraphQLFn,\n ShopifyWebhookSubscription,\n RegisterWebhookResult,\n UnregisterWebhookResult,\n} from './registration';\n","/**\n * Shopify webhook registration via GraphQL.\n *\n * Uses dependency-injected GraphQL function to register, unregister,\n * and list webhook subscriptions without importing the full Shopify client.\n */\n\nimport type { WebhookRegistration } from '@uniforge/platform-core/webhooks';\n\n/** Dependency-injected GraphQL query function. */\nexport type GraphQLFn = (\n query: string,\n variables?: Record<string, unknown>,\n) => Promise<{ data?: unknown; errors?: unknown[] }>;\n\nexport interface ShopifyWebhookSubscription {\n id: string;\n topic: string;\n endpoint: {\n callbackUrl?: string;\n };\n format: string;\n}\n\nexport interface RegisterWebhookResult {\n success: boolean;\n webhookSubscriptionId?: string;\n errors?: string[];\n}\n\nexport interface UnregisterWebhookResult {\n success: boolean;\n errors?: string[];\n}\n\nconst WEBHOOK_SUBSCRIPTION_CREATE = `\n mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {\n webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {\n webhookSubscription {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n`;\n\nconst WEBHOOK_SUBSCRIPTION_DELETE = `\n mutation webhookSubscriptionDelete($id: ID!) {\n webhookSubscriptionDelete(id: $id) {\n deletedWebhookSubscriptionId\n userErrors {\n field\n message\n }\n }\n }\n`;\n\nconst WEBHOOK_SUBSCRIPTIONS_QUERY = `\n query webhookSubscriptions($first: Int!) {\n webhookSubscriptions(first: $first) {\n edges {\n node {\n id\n topic\n endpoint {\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n format\n }\n }\n }\n }\n`;\n\nexport async function registerShopifyWebhook(\n graphqlFn: GraphQLFn,\n registration: WebhookRegistration,\n): Promise<RegisterWebhookResult> {\n const response = await graphqlFn(WEBHOOK_SUBSCRIPTION_CREATE, {\n topic: registration.topic,\n webhookSubscription: {\n callbackUrl: registration.address,\n format: (registration.format ?? 'json').toUpperCase(),\n },\n });\n\n if (response.errors && response.errors.length > 0) {\n return {\n success: false,\n errors: response.errors.map((e) => String(e)),\n };\n }\n\n const data = response.data as {\n webhookSubscriptionCreate: {\n webhookSubscription: { id: string } | null;\n userErrors: Array<{ field: string[]; message: string }>;\n };\n };\n\n const result = data.webhookSubscriptionCreate;\n if (result.userErrors.length > 0) {\n return {\n success: false,\n errors: result.userErrors.map((e) => e.message),\n };\n }\n\n const registerResult: RegisterWebhookResult = { success: true };\n const subscriptionId = result.webhookSubscription?.id;\n if (subscriptionId) {\n registerResult.webhookSubscriptionId = subscriptionId;\n }\n return registerResult;\n}\n\nexport async function unregisterShopifyWebhook(\n graphqlFn: GraphQLFn,\n webhookId: string,\n): Promise<UnregisterWebhookResult> {\n const response = await graphqlFn(WEBHOOK_SUBSCRIPTION_DELETE, {\n id: webhookId,\n });\n\n if (response.errors && response.errors.length > 0) {\n return {\n success: false,\n errors: response.errors.map((e) => String(e)),\n };\n }\n\n const data = response.data as {\n webhookSubscriptionDelete: {\n deletedWebhookSubscriptionId: string | null;\n userErrors: Array<{ field: string[]; message: string }>;\n };\n };\n\n const result = data.webhookSubscriptionDelete;\n if (result.userErrors.length > 0) {\n return {\n success: false,\n errors: result.userErrors.map((e) => e.message),\n };\n }\n\n return { success: true };\n}\n\nexport async function listShopifyWebhooks(\n graphqlFn: GraphQLFn,\n first = 50,\n): Promise<ShopifyWebhookSubscription[]> {\n const response = await graphqlFn(WEBHOOK_SUBSCRIPTIONS_QUERY, { first });\n\n if (response.errors && response.errors.length > 0) {\n return [];\n }\n\n const data = response.data as {\n webhookSubscriptions: {\n edges: Array<{\n node: {\n id: string;\n topic: string;\n endpoint: { callbackUrl?: string };\n format: string;\n };\n }>;\n };\n };\n\n return data.webhookSubscriptions.edges.map((edge) => {\n const sub: ShopifyWebhookSubscription = {\n id: edge.node.id,\n topic: edge.node.topic,\n endpoint: {},\n format: edge.node.format,\n };\n const callbackUrl = edge.node.endpoint.callbackUrl;\n if (callbackUrl) {\n sub.endpoint.callbackUrl = callbackUrl;\n }\n return sub;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmCA,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcpC,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYpC,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBpC,eAAsB,uBACpB,WACA,cACgC;AAChC,QAAM,WAAW,MAAM,UAAU,6BAA6B;AAAA,IAC5D,OAAO,aAAa;AAAA,IACpB,qBAAqB;AAAA,MACnB,aAAa,aAAa;AAAA,MAC1B,SAAS,aAAa,UAAU,QAAQ,YAAY;AAAA,IACtD;AAAA,EACF,CAAC;AAED,MAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,SAAS,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,OAAO,SAAS;AAOtB,QAAM,SAAS,KAAK;AACpB,MAAI,OAAO,WAAW,SAAS,GAAG;AAChC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,IAChD;AAAA,EACF;AAEA,QAAM,iBAAwC,EAAE,SAAS,KAAK;AAC9D,QAAM,iBAAiB,OAAO,qBAAqB;AACnD,MAAI,gBAAgB;AAClB,mBAAe,wBAAwB;AAAA,EACzC;AACA,SAAO;AACT;AAEA,eAAsB,yBACpB,WACA,WACkC;AAClC,QAAM,WAAW,MAAM,UAAU,6BAA6B;AAAA,IAC5D,IAAI;AAAA,EACN,CAAC;AAED,MAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,SAAS,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,OAAO,SAAS;AAOtB,QAAM,SAAS,KAAK;AACpB,MAAI,OAAO,WAAW,SAAS,GAAG;AAChC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,IAChD;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,KAAK;AACzB;AAEA,eAAsB,oBACpB,WACA,QAAQ,IAC+B;AACvC,QAAM,WAAW,MAAM,UAAU,6BAA6B,EAAE,MAAM,CAAC;AAEvE,MAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,OAAO,SAAS;AAatB,SAAO,KAAK,qBAAqB,MAAM,IAAI,CAAC,SAAS;AACnD,UAAM,MAAkC;AAAA,MACtC,IAAI,KAAK,KAAK;AAAA,MACd,OAAO,KAAK,KAAK;AAAA,MACjB,UAAU,CAAC;AAAA,MACX,QAAQ,KAAK,KAAK;AAAA,IACpB;AACA,UAAM,cAAc,KAAK,KAAK,SAAS;AACvC,QAAI,aAAa;AACf,UAAI,SAAS,cAAc;AAAA,IAC7B;AACA,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|