@uniforge/core 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 +165 -0
- package/dist/auth/index.d.ts +165 -0
- package/dist/auth/index.js +443 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +406 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/billing/index.d.cts +34 -0
- package/dist/billing/index.d.ts +34 -0
- package/dist/billing/index.js +254 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/index.mjs +225 -0
- package/dist/billing/index.mjs.map +1 -0
- package/dist/config/index.d.cts +12 -0
- package/dist/config/index.d.ts +12 -0
- package/dist/config/index.js +186 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +156 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/database/index.d.cts +33 -0
- package/dist/database/index.d.ts +33 -0
- package/dist/database/index.js +127 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/index.mjs +95 -0
- package/dist/database/index.mjs.map +1 -0
- package/dist/graphql/index.d.cts +36 -0
- package/dist/graphql/index.d.ts +36 -0
- package/dist/graphql/index.js +209 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/index.mjs +179 -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 +36 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/index.mjs.map +1 -0
- package/dist/multi-store/index.d.cts +11 -0
- package/dist/multi-store/index.d.ts +11 -0
- package/dist/multi-store/index.js +473 -0
- package/dist/multi-store/index.js.map +1 -0
- package/dist/multi-store/index.mjs +447 -0
- package/dist/multi-store/index.mjs.map +1 -0
- package/dist/multi-tenant/index.d.cts +23 -0
- package/dist/multi-tenant/index.d.ts +23 -0
- package/dist/multi-tenant/index.js +69 -0
- package/dist/multi-tenant/index.js.map +1 -0
- package/dist/multi-tenant/index.mjs +41 -0
- package/dist/multi-tenant/index.mjs.map +1 -0
- package/dist/performance/index.d.cts +34 -0
- package/dist/performance/index.d.ts +34 -0
- package/dist/performance/index.js +319 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/index.mjs +290 -0
- package/dist/performance/index.mjs.map +1 -0
- package/dist/platform/index.d.cts +25 -0
- package/dist/platform/index.d.ts +25 -0
- package/dist/platform/index.js +91 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +62 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/rbac/index.d.cts +24 -0
- package/dist/rbac/index.d.ts +24 -0
- package/dist/rbac/index.js +267 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/index.mjs +236 -0
- package/dist/rbac/index.mjs.map +1 -0
- package/dist/schema-CM7mHj_H.d.cts +53 -0
- package/dist/schema-CM7mHj_H.d.ts +53 -0
- package/dist/security/index.d.cts +47 -0
- package/dist/security/index.d.ts +47 -0
- package/dist/security/index.js +505 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +474 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/session-storage/index.d.cts +70 -0
- package/dist/session-storage/index.d.ts +70 -0
- package/dist/session-storage/index.js +271 -0
- package/dist/session-storage/index.js.map +1 -0
- package/dist/session-storage/index.mjs +242 -0
- package/dist/session-storage/index.mjs.map +1 -0
- package/dist/webhooks/index.d.cts +89 -0
- package/dist/webhooks/index.d.ts +89 -0
- package/dist/webhooks/index.js +380 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/index.mjs +348 -0
- package/dist/webhooks/index.mjs.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,186 @@
|
|
|
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/config/index.ts
|
|
21
|
+
var config_exports = {};
|
|
22
|
+
__export(config_exports, {
|
|
23
|
+
ConfigValidationError: () => ConfigValidationError,
|
|
24
|
+
defaultConfig: () => defaultConfig,
|
|
25
|
+
loadConfig: () => loadConfig,
|
|
26
|
+
validateConfig: () => validateConfig
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(config_exports);
|
|
29
|
+
|
|
30
|
+
// src/config/schema.ts
|
|
31
|
+
var defaultConfig = {
|
|
32
|
+
shopify: {
|
|
33
|
+
apiKey: "",
|
|
34
|
+
apiSecretKey: "",
|
|
35
|
+
scopes: [],
|
|
36
|
+
hostName: "",
|
|
37
|
+
apiVersion: "2024-10",
|
|
38
|
+
isEmbeddedApp: true
|
|
39
|
+
},
|
|
40
|
+
database: {
|
|
41
|
+
url: ""
|
|
42
|
+
},
|
|
43
|
+
redis: {
|
|
44
|
+
url: ""
|
|
45
|
+
},
|
|
46
|
+
features: {
|
|
47
|
+
encryption: false,
|
|
48
|
+
dualSessionStorage: false
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/config/loader.ts
|
|
53
|
+
var import_node_fs = require("fs");
|
|
54
|
+
var import_node_path = require("path");
|
|
55
|
+
var import_node_url = require("url");
|
|
56
|
+
|
|
57
|
+
// src/config/validator.ts
|
|
58
|
+
var ConfigValidationError = class extends Error {
|
|
59
|
+
constructor(errors) {
|
|
60
|
+
super(`Invalid UniForge config:
|
|
61
|
+
- ${errors.join("\n - ")}`);
|
|
62
|
+
this.errors = errors;
|
|
63
|
+
this.name = "ConfigValidationError";
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
function validateConfig(config) {
|
|
67
|
+
const errors = [];
|
|
68
|
+
if (!config || typeof config !== "object") {
|
|
69
|
+
throw new ConfigValidationError(["Config must be an object"]);
|
|
70
|
+
}
|
|
71
|
+
const c = config;
|
|
72
|
+
if (!c.appName || typeof c.appName !== "string") {
|
|
73
|
+
errors.push("appName is required and must be a string");
|
|
74
|
+
}
|
|
75
|
+
if (!c.shopify || typeof c.shopify !== "object") {
|
|
76
|
+
errors.push("shopify configuration is required");
|
|
77
|
+
} else {
|
|
78
|
+
const s = c.shopify;
|
|
79
|
+
if (!s.apiKey || typeof s.apiKey !== "string") {
|
|
80
|
+
errors.push("shopify.apiKey is required and must be a string");
|
|
81
|
+
}
|
|
82
|
+
if (!s.apiSecretKey || typeof s.apiSecretKey !== "string") {
|
|
83
|
+
errors.push("shopify.apiSecretKey is required and must be a string");
|
|
84
|
+
}
|
|
85
|
+
if (!Array.isArray(s.scopes)) {
|
|
86
|
+
errors.push("shopify.scopes must be an array of strings");
|
|
87
|
+
}
|
|
88
|
+
if (!s.hostName || typeof s.hostName !== "string") {
|
|
89
|
+
errors.push("shopify.hostName is required and must be a string");
|
|
90
|
+
}
|
|
91
|
+
if (!s.apiVersion || typeof s.apiVersion !== "string") {
|
|
92
|
+
errors.push("shopify.apiVersion is required and must be a string");
|
|
93
|
+
}
|
|
94
|
+
if (typeof s.isEmbeddedApp !== "boolean") {
|
|
95
|
+
errors.push("shopify.isEmbeddedApp must be a boolean");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!c.database || typeof c.database !== "object") {
|
|
99
|
+
errors.push("database configuration is required");
|
|
100
|
+
} else {
|
|
101
|
+
const d = c.database;
|
|
102
|
+
if (!d.url || typeof d.url !== "string") {
|
|
103
|
+
errors.push("database.url is required and must be a string");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!c.redis || typeof c.redis !== "object") {
|
|
107
|
+
errors.push("redis configuration is required");
|
|
108
|
+
} else {
|
|
109
|
+
const r = c.redis;
|
|
110
|
+
if (!r.url || typeof r.url !== "string") {
|
|
111
|
+
errors.push("redis.url is required and must be a string");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (c.features && typeof c.features === "object") {
|
|
115
|
+
const f = c.features;
|
|
116
|
+
if (f.encryption !== void 0 && typeof f.encryption !== "boolean") {
|
|
117
|
+
errors.push("features.encryption must be a boolean");
|
|
118
|
+
}
|
|
119
|
+
if (f.dualSessionStorage !== void 0 && typeof f.dualSessionStorage !== "boolean") {
|
|
120
|
+
errors.push("features.dualSessionStorage must be a boolean");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (errors.length > 0) {
|
|
124
|
+
throw new ConfigValidationError(errors);
|
|
125
|
+
}
|
|
126
|
+
return config;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/config/loader.ts
|
|
130
|
+
var CONFIG_FILENAME = "uniforge.config.ts";
|
|
131
|
+
function findConfigFile(startDir) {
|
|
132
|
+
let current = (0, import_node_path.resolve)(startDir);
|
|
133
|
+
const root = (0, import_node_path.dirname)(current);
|
|
134
|
+
while (current !== root) {
|
|
135
|
+
const candidate = (0, import_node_path.resolve)(current, CONFIG_FILENAME);
|
|
136
|
+
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
137
|
+
return candidate;
|
|
138
|
+
}
|
|
139
|
+
const parent = (0, import_node_path.dirname)(current);
|
|
140
|
+
if (parent === current) break;
|
|
141
|
+
current = parent;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
function deepMerge(defaults, overrides) {
|
|
146
|
+
const result = { ...defaults };
|
|
147
|
+
for (const key of Object.keys(overrides)) {
|
|
148
|
+
const val = overrides[key];
|
|
149
|
+
if (val && typeof val === "object" && !Array.isArray(val) && result[key] && typeof result[key] === "object" && !Array.isArray(result[key])) {
|
|
150
|
+
result[key] = deepMerge(
|
|
151
|
+
result[key],
|
|
152
|
+
val
|
|
153
|
+
);
|
|
154
|
+
} else {
|
|
155
|
+
result[key] = val;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
async function loadConfig(configPath) {
|
|
161
|
+
const resolvedPath = configPath ? (0, import_node_path.resolve)(configPath) : findConfigFile(process.cwd());
|
|
162
|
+
if (!resolvedPath) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Could not find ${CONFIG_FILENAME}. Run "uniforge init" to create one.`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
if (!(0, import_node_fs.existsSync)(resolvedPath)) {
|
|
168
|
+
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
169
|
+
}
|
|
170
|
+
const fileUrl = (0, import_node_url.pathToFileURL)(resolvedPath).href;
|
|
171
|
+
const mod = await import(fileUrl);
|
|
172
|
+
const userConfig = mod.default ?? mod;
|
|
173
|
+
const merged = deepMerge(
|
|
174
|
+
defaultConfig,
|
|
175
|
+
userConfig
|
|
176
|
+
);
|
|
177
|
+
return validateConfig(merged);
|
|
178
|
+
}
|
|
179
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
180
|
+
0 && (module.exports = {
|
|
181
|
+
ConfigValidationError,
|
|
182
|
+
defaultConfig,
|
|
183
|
+
loadConfig,
|
|
184
|
+
validateConfig
|
|
185
|
+
});
|
|
186
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/config/index.ts","../../src/config/schema.ts","../../src/config/loader.ts","../../src/config/validator.ts"],"sourcesContent":["export type { UniforgeConfig } from './schema.js';\nexport { defaultConfig } from './schema.js';\nexport { loadConfig } from './loader.js';\nexport { validateConfig, ConfigValidationError } from './validator.js';\n","export interface UniforgeConfig {\n appName: string;\n shopify: {\n apiKey: string;\n apiSecretKey: string;\n scopes: string[];\n hostName: string;\n apiVersion: string;\n isEmbeddedApp: boolean;\n };\n database: {\n url: string;\n };\n redis: {\n url: string;\n };\n features: {\n encryption: boolean;\n dualSessionStorage: boolean;\n };\n multiStore?: {\n enabled: boolean;\n defaultAccountType: 'individual' | 'enterprise';\n autoProvisionAccount: boolean;\n basePrice: number;\n includedStores: number;\n };\n billing?: {\n returnUrl: string;\n trialDays?: number;\n };\n platform?: {\n id: string;\n autoRegister: boolean;\n };\n security?: {\n rateLimiting: boolean;\n inputValidation: boolean;\n securityHeaders: boolean;\n csp: boolean;\n auditEnabled: boolean;\n };\n performance?: {\n cacheEnabled: boolean;\n cacheTTL: number;\n cacheMaxEntries: number;\n queryCostTracking: boolean;\n queryBatching: boolean;\n };\n}\n\nexport const defaultConfig: Partial<UniforgeConfig> = {\n shopify: {\n apiKey: '',\n apiSecretKey: '',\n scopes: [],\n hostName: '',\n apiVersion: '2024-10',\n isEmbeddedApp: true,\n },\n database: {\n url: '',\n },\n redis: {\n url: '',\n },\n features: {\n encryption: false,\n dualSessionStorage: false,\n },\n};\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { UniforgeConfig } from './schema.js';\nimport { defaultConfig } from './schema.js';\nimport { validateConfig } from './validator.js';\n\nconst CONFIG_FILENAME = 'uniforge.config.ts';\n\nfunction findConfigFile(startDir: string): string | null {\n let current = resolve(startDir);\n const root = dirname(current);\n\n while (current !== root) {\n const candidate = resolve(current, CONFIG_FILENAME);\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n\n return null;\n}\n\nfunction deepMerge(\n defaults: Record<string, unknown>,\n overrides: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...defaults };\n for (const key of Object.keys(overrides)) {\n const val = overrides[key];\n if (\n val &&\n typeof val === 'object' &&\n !Array.isArray(val) &&\n result[key] &&\n typeof result[key] === 'object' &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(\n result[key] as Record<string, unknown>,\n val as Record<string, unknown>,\n );\n } else {\n result[key] = val;\n }\n }\n return result;\n}\n\nexport async function loadConfig(configPath?: string): Promise<UniforgeConfig> {\n const resolvedPath = configPath\n ? resolve(configPath)\n : findConfigFile(process.cwd());\n\n if (!resolvedPath) {\n throw new Error(\n `Could not find ${CONFIG_FILENAME}. Run \"uniforge init\" to create one.`,\n );\n }\n\n if (!existsSync(resolvedPath)) {\n throw new Error(`Config file not found: ${resolvedPath}`);\n }\n\n const fileUrl = pathToFileURL(resolvedPath).href;\n const mod = await import(fileUrl);\n const userConfig = mod.default ?? mod;\n\n const merged = deepMerge(\n defaultConfig as Record<string, unknown>,\n userConfig as Record<string, unknown>,\n );\n\n return validateConfig(merged);\n}\n","import type { UniforgeConfig } from './schema.js';\n\nexport class ConfigValidationError extends Error {\n constructor(public readonly errors: string[]) {\n super(`Invalid UniForge config:\\n - ${errors.join('\\n - ')}`);\n this.name = 'ConfigValidationError';\n }\n}\n\nexport function validateConfig(config: unknown): UniforgeConfig {\n const errors: string[] = [];\n\n if (!config || typeof config !== 'object') {\n throw new ConfigValidationError(['Config must be an object']);\n }\n\n const c = config as Record<string, unknown>;\n\n if (!c.appName || typeof c.appName !== 'string') {\n errors.push('appName is required and must be a string');\n }\n\n if (!c.shopify || typeof c.shopify !== 'object') {\n errors.push('shopify configuration is required');\n } else {\n const s = c.shopify as Record<string, unknown>;\n if (!s.apiKey || typeof s.apiKey !== 'string') {\n errors.push('shopify.apiKey is required and must be a string');\n }\n if (!s.apiSecretKey || typeof s.apiSecretKey !== 'string') {\n errors.push('shopify.apiSecretKey is required and must be a string');\n }\n if (!Array.isArray(s.scopes)) {\n errors.push('shopify.scopes must be an array of strings');\n }\n if (!s.hostName || typeof s.hostName !== 'string') {\n errors.push('shopify.hostName is required and must be a string');\n }\n if (!s.apiVersion || typeof s.apiVersion !== 'string') {\n errors.push('shopify.apiVersion is required and must be a string');\n }\n if (typeof s.isEmbeddedApp !== 'boolean') {\n errors.push('shopify.isEmbeddedApp must be a boolean');\n }\n }\n\n if (!c.database || typeof c.database !== 'object') {\n errors.push('database configuration is required');\n } else {\n const d = c.database as Record<string, unknown>;\n if (!d.url || typeof d.url !== 'string') {\n errors.push('database.url is required and must be a string');\n }\n }\n\n if (!c.redis || typeof c.redis !== 'object') {\n errors.push('redis configuration is required');\n } else {\n const r = c.redis as Record<string, unknown>;\n if (!r.url || typeof r.url !== 'string') {\n errors.push('redis.url is required and must be a string');\n }\n }\n\n if (c.features && typeof c.features === 'object') {\n const f = c.features as Record<string, unknown>;\n if (f.encryption !== undefined && typeof f.encryption !== 'boolean') {\n errors.push('features.encryption must be a boolean');\n }\n if (f.dualSessionStorage !== undefined && typeof f.dualSessionStorage !== 'boolean') {\n errors.push('features.dualSessionStorage must be a boolean');\n }\n }\n\n if (errors.length > 0) {\n throw new ConfigValidationError(errors);\n }\n\n return config as UniforgeConfig;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// src/config/schema.ts
|
|
2
|
+
var defaultConfig = {
|
|
3
|
+
shopify: {
|
|
4
|
+
apiKey: "",
|
|
5
|
+
apiSecretKey: "",
|
|
6
|
+
scopes: [],
|
|
7
|
+
hostName: "",
|
|
8
|
+
apiVersion: "2024-10",
|
|
9
|
+
isEmbeddedApp: true
|
|
10
|
+
},
|
|
11
|
+
database: {
|
|
12
|
+
url: ""
|
|
13
|
+
},
|
|
14
|
+
redis: {
|
|
15
|
+
url: ""
|
|
16
|
+
},
|
|
17
|
+
features: {
|
|
18
|
+
encryption: false,
|
|
19
|
+
dualSessionStorage: false
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/config/loader.ts
|
|
24
|
+
import { existsSync } from "fs";
|
|
25
|
+
import { resolve, dirname } from "path";
|
|
26
|
+
import { pathToFileURL } from "url";
|
|
27
|
+
|
|
28
|
+
// src/config/validator.ts
|
|
29
|
+
var ConfigValidationError = class extends Error {
|
|
30
|
+
constructor(errors) {
|
|
31
|
+
super(`Invalid UniForge config:
|
|
32
|
+
- ${errors.join("\n - ")}`);
|
|
33
|
+
this.errors = errors;
|
|
34
|
+
this.name = "ConfigValidationError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function validateConfig(config) {
|
|
38
|
+
const errors = [];
|
|
39
|
+
if (!config || typeof config !== "object") {
|
|
40
|
+
throw new ConfigValidationError(["Config must be an object"]);
|
|
41
|
+
}
|
|
42
|
+
const c = config;
|
|
43
|
+
if (!c.appName || typeof c.appName !== "string") {
|
|
44
|
+
errors.push("appName is required and must be a string");
|
|
45
|
+
}
|
|
46
|
+
if (!c.shopify || typeof c.shopify !== "object") {
|
|
47
|
+
errors.push("shopify configuration is required");
|
|
48
|
+
} else {
|
|
49
|
+
const s = c.shopify;
|
|
50
|
+
if (!s.apiKey || typeof s.apiKey !== "string") {
|
|
51
|
+
errors.push("shopify.apiKey is required and must be a string");
|
|
52
|
+
}
|
|
53
|
+
if (!s.apiSecretKey || typeof s.apiSecretKey !== "string") {
|
|
54
|
+
errors.push("shopify.apiSecretKey is required and must be a string");
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(s.scopes)) {
|
|
57
|
+
errors.push("shopify.scopes must be an array of strings");
|
|
58
|
+
}
|
|
59
|
+
if (!s.hostName || typeof s.hostName !== "string") {
|
|
60
|
+
errors.push("shopify.hostName is required and must be a string");
|
|
61
|
+
}
|
|
62
|
+
if (!s.apiVersion || typeof s.apiVersion !== "string") {
|
|
63
|
+
errors.push("shopify.apiVersion is required and must be a string");
|
|
64
|
+
}
|
|
65
|
+
if (typeof s.isEmbeddedApp !== "boolean") {
|
|
66
|
+
errors.push("shopify.isEmbeddedApp must be a boolean");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!c.database || typeof c.database !== "object") {
|
|
70
|
+
errors.push("database configuration is required");
|
|
71
|
+
} else {
|
|
72
|
+
const d = c.database;
|
|
73
|
+
if (!d.url || typeof d.url !== "string") {
|
|
74
|
+
errors.push("database.url is required and must be a string");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!c.redis || typeof c.redis !== "object") {
|
|
78
|
+
errors.push("redis configuration is required");
|
|
79
|
+
} else {
|
|
80
|
+
const r = c.redis;
|
|
81
|
+
if (!r.url || typeof r.url !== "string") {
|
|
82
|
+
errors.push("redis.url is required and must be a string");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (c.features && typeof c.features === "object") {
|
|
86
|
+
const f = c.features;
|
|
87
|
+
if (f.encryption !== void 0 && typeof f.encryption !== "boolean") {
|
|
88
|
+
errors.push("features.encryption must be a boolean");
|
|
89
|
+
}
|
|
90
|
+
if (f.dualSessionStorage !== void 0 && typeof f.dualSessionStorage !== "boolean") {
|
|
91
|
+
errors.push("features.dualSessionStorage must be a boolean");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (errors.length > 0) {
|
|
95
|
+
throw new ConfigValidationError(errors);
|
|
96
|
+
}
|
|
97
|
+
return config;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/config/loader.ts
|
|
101
|
+
var CONFIG_FILENAME = "uniforge.config.ts";
|
|
102
|
+
function findConfigFile(startDir) {
|
|
103
|
+
let current = resolve(startDir);
|
|
104
|
+
const root = dirname(current);
|
|
105
|
+
while (current !== root) {
|
|
106
|
+
const candidate = resolve(current, CONFIG_FILENAME);
|
|
107
|
+
if (existsSync(candidate)) {
|
|
108
|
+
return candidate;
|
|
109
|
+
}
|
|
110
|
+
const parent = dirname(current);
|
|
111
|
+
if (parent === current) break;
|
|
112
|
+
current = parent;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function deepMerge(defaults, overrides) {
|
|
117
|
+
const result = { ...defaults };
|
|
118
|
+
for (const key of Object.keys(overrides)) {
|
|
119
|
+
const val = overrides[key];
|
|
120
|
+
if (val && typeof val === "object" && !Array.isArray(val) && result[key] && typeof result[key] === "object" && !Array.isArray(result[key])) {
|
|
121
|
+
result[key] = deepMerge(
|
|
122
|
+
result[key],
|
|
123
|
+
val
|
|
124
|
+
);
|
|
125
|
+
} else {
|
|
126
|
+
result[key] = val;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
async function loadConfig(configPath) {
|
|
132
|
+
const resolvedPath = configPath ? resolve(configPath) : findConfigFile(process.cwd());
|
|
133
|
+
if (!resolvedPath) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Could not find ${CONFIG_FILENAME}. Run "uniforge init" to create one.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (!existsSync(resolvedPath)) {
|
|
139
|
+
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
140
|
+
}
|
|
141
|
+
const fileUrl = pathToFileURL(resolvedPath).href;
|
|
142
|
+
const mod = await import(fileUrl);
|
|
143
|
+
const userConfig = mod.default ?? mod;
|
|
144
|
+
const merged = deepMerge(
|
|
145
|
+
defaultConfig,
|
|
146
|
+
userConfig
|
|
147
|
+
);
|
|
148
|
+
return validateConfig(merged);
|
|
149
|
+
}
|
|
150
|
+
export {
|
|
151
|
+
ConfigValidationError,
|
|
152
|
+
defaultConfig,
|
|
153
|
+
loadConfig,
|
|
154
|
+
validateConfig
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/config/schema.ts","../../src/config/loader.ts","../../src/config/validator.ts"],"sourcesContent":["export interface UniforgeConfig {\n appName: string;\n shopify: {\n apiKey: string;\n apiSecretKey: string;\n scopes: string[];\n hostName: string;\n apiVersion: string;\n isEmbeddedApp: boolean;\n };\n database: {\n url: string;\n };\n redis: {\n url: string;\n };\n features: {\n encryption: boolean;\n dualSessionStorage: boolean;\n };\n multiStore?: {\n enabled: boolean;\n defaultAccountType: 'individual' | 'enterprise';\n autoProvisionAccount: boolean;\n basePrice: number;\n includedStores: number;\n };\n billing?: {\n returnUrl: string;\n trialDays?: number;\n };\n platform?: {\n id: string;\n autoRegister: boolean;\n };\n security?: {\n rateLimiting: boolean;\n inputValidation: boolean;\n securityHeaders: boolean;\n csp: boolean;\n auditEnabled: boolean;\n };\n performance?: {\n cacheEnabled: boolean;\n cacheTTL: number;\n cacheMaxEntries: number;\n queryCostTracking: boolean;\n queryBatching: boolean;\n };\n}\n\nexport const defaultConfig: Partial<UniforgeConfig> = {\n shopify: {\n apiKey: '',\n apiSecretKey: '',\n scopes: [],\n hostName: '',\n apiVersion: '2024-10',\n isEmbeddedApp: true,\n },\n database: {\n url: '',\n },\n redis: {\n url: '',\n },\n features: {\n encryption: false,\n dualSessionStorage: false,\n },\n};\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { UniforgeConfig } from './schema.js';\nimport { defaultConfig } from './schema.js';\nimport { validateConfig } from './validator.js';\n\nconst CONFIG_FILENAME = 'uniforge.config.ts';\n\nfunction findConfigFile(startDir: string): string | null {\n let current = resolve(startDir);\n const root = dirname(current);\n\n while (current !== root) {\n const candidate = resolve(current, CONFIG_FILENAME);\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n\n return null;\n}\n\nfunction deepMerge(\n defaults: Record<string, unknown>,\n overrides: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...defaults };\n for (const key of Object.keys(overrides)) {\n const val = overrides[key];\n if (\n val &&\n typeof val === 'object' &&\n !Array.isArray(val) &&\n result[key] &&\n typeof result[key] === 'object' &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(\n result[key] as Record<string, unknown>,\n val as Record<string, unknown>,\n );\n } else {\n result[key] = val;\n }\n }\n return result;\n}\n\nexport async function loadConfig(configPath?: string): Promise<UniforgeConfig> {\n const resolvedPath = configPath\n ? resolve(configPath)\n : findConfigFile(process.cwd());\n\n if (!resolvedPath) {\n throw new Error(\n `Could not find ${CONFIG_FILENAME}. Run \"uniforge init\" to create one.`,\n );\n }\n\n if (!existsSync(resolvedPath)) {\n throw new Error(`Config file not found: ${resolvedPath}`);\n }\n\n const fileUrl = pathToFileURL(resolvedPath).href;\n const mod = await import(fileUrl);\n const userConfig = mod.default ?? mod;\n\n const merged = deepMerge(\n defaultConfig as Record<string, unknown>,\n userConfig as Record<string, unknown>,\n );\n\n return validateConfig(merged);\n}\n","import type { UniforgeConfig } from './schema.js';\n\nexport class ConfigValidationError extends Error {\n constructor(public readonly errors: string[]) {\n super(`Invalid UniForge config:\\n - ${errors.join('\\n - ')}`);\n this.name = 'ConfigValidationError';\n }\n}\n\nexport function validateConfig(config: unknown): UniforgeConfig {\n const errors: string[] = [];\n\n if (!config || typeof config !== 'object') {\n throw new ConfigValidationError(['Config must be an object']);\n }\n\n const c = config as Record<string, unknown>;\n\n if (!c.appName || typeof c.appName !== 'string') {\n errors.push('appName is required and must be a string');\n }\n\n if (!c.shopify || typeof c.shopify !== 'object') {\n errors.push('shopify configuration is required');\n } else {\n const s = c.shopify as Record<string, unknown>;\n if (!s.apiKey || typeof s.apiKey !== 'string') {\n errors.push('shopify.apiKey is required and must be a string');\n }\n if (!s.apiSecretKey || typeof s.apiSecretKey !== 'string') {\n errors.push('shopify.apiSecretKey is required and must be a string');\n }\n if (!Array.isArray(s.scopes)) {\n errors.push('shopify.scopes must be an array of strings');\n }\n if (!s.hostName || typeof s.hostName !== 'string') {\n errors.push('shopify.hostName is required and must be a string');\n }\n if (!s.apiVersion || typeof s.apiVersion !== 'string') {\n errors.push('shopify.apiVersion is required and must be a string');\n }\n if (typeof s.isEmbeddedApp !== 'boolean') {\n errors.push('shopify.isEmbeddedApp must be a boolean');\n }\n }\n\n if (!c.database || typeof c.database !== 'object') {\n errors.push('database configuration is required');\n } else {\n const d = c.database as Record<string, unknown>;\n if (!d.url || typeof d.url !== 'string') {\n errors.push('database.url is required and must be a string');\n }\n }\n\n if (!c.redis || typeof c.redis !== 'object') {\n errors.push('redis configuration is required');\n } else {\n const r = c.redis as Record<string, unknown>;\n if (!r.url || typeof r.url !== 'string') {\n errors.push('redis.url is required and must be a string');\n }\n }\n\n if (c.features && typeof c.features === 'object') {\n const f = c.features as Record<string, unknown>;\n if (f.encryption !== undefined && typeof f.encryption !== 'boolean') {\n errors.push('features.encryption must be a boolean');\n }\n if (f.dualSessionStorage !== undefined && typeof f.dualSessionStorage !== 'boolean') {\n errors.push('features.dualSessionStorage must be a boolean');\n }\n }\n\n if (errors.length > 0) {\n throw new ConfigValidationError(errors);\n }\n\n return config as UniforgeConfig;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PrismaClient, Shop as Shop$1, Session as Session$1 } from '@prisma/client';
|
|
2
|
+
import { Shop, Session } from '@uniforge/platform-core/auth';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PrismaClient singleton factory.
|
|
6
|
+
*
|
|
7
|
+
* Provides a single shared PrismaClient instance across the application.
|
|
8
|
+
* Logging verbosity is controlled by NODE_ENV.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Create or return the singleton PrismaClient. */
|
|
12
|
+
declare function createPrismaClient(url?: string): PrismaClient;
|
|
13
|
+
/** Disconnect and discard the singleton PrismaClient. */
|
|
14
|
+
declare function disconnectPrisma(): Promise<void>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converters between platform-core domain types and Prisma record types.
|
|
18
|
+
*
|
|
19
|
+
* The Prisma models use camelCase field names (shopDomain, isOnline, etc.)
|
|
20
|
+
* while platform-core types use slightly different shapes (e.g. session.shop
|
|
21
|
+
* vs record.shopDomain, onlineAccessInfo as object vs JSON).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Convert a platform-core Shop to a Prisma-compatible record. */
|
|
25
|
+
declare function shopToRecord(shop: Shop): Omit<Shop$1, 'id'>;
|
|
26
|
+
/** Convert a Prisma Shop record to a platform-core Shop. */
|
|
27
|
+
declare function recordToShop(record: Shop$1): Shop;
|
|
28
|
+
/** Convert a platform-core Session to a Prisma-compatible create/update input. */
|
|
29
|
+
declare function sessionToRecord(session: Session): Omit<Session$1, 'createdAt' | 'updatedAt'>;
|
|
30
|
+
/** Convert a Prisma Session record to a platform-core Session. */
|
|
31
|
+
declare function recordToSession(record: Session$1): Session;
|
|
32
|
+
|
|
33
|
+
export { createPrismaClient, disconnectPrisma, recordToSession, recordToShop, sessionToRecord, shopToRecord };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PrismaClient, Shop as Shop$1, Session as Session$1 } from '@prisma/client';
|
|
2
|
+
import { Shop, Session } from '@uniforge/platform-core/auth';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PrismaClient singleton factory.
|
|
6
|
+
*
|
|
7
|
+
* Provides a single shared PrismaClient instance across the application.
|
|
8
|
+
* Logging verbosity is controlled by NODE_ENV.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Create or return the singleton PrismaClient. */
|
|
12
|
+
declare function createPrismaClient(url?: string): PrismaClient;
|
|
13
|
+
/** Disconnect and discard the singleton PrismaClient. */
|
|
14
|
+
declare function disconnectPrisma(): Promise<void>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converters between platform-core domain types and Prisma record types.
|
|
18
|
+
*
|
|
19
|
+
* The Prisma models use camelCase field names (shopDomain, isOnline, etc.)
|
|
20
|
+
* while platform-core types use slightly different shapes (e.g. session.shop
|
|
21
|
+
* vs record.shopDomain, onlineAccessInfo as object vs JSON).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Convert a platform-core Shop to a Prisma-compatible record. */
|
|
25
|
+
declare function shopToRecord(shop: Shop): Omit<Shop$1, 'id'>;
|
|
26
|
+
/** Convert a Prisma Shop record to a platform-core Shop. */
|
|
27
|
+
declare function recordToShop(record: Shop$1): Shop;
|
|
28
|
+
/** Convert a platform-core Session to a Prisma-compatible create/update input. */
|
|
29
|
+
declare function sessionToRecord(session: Session): Omit<Session$1, 'createdAt' | 'updatedAt'>;
|
|
30
|
+
/** Convert a Prisma Session record to a platform-core Session. */
|
|
31
|
+
declare function recordToSession(record: Session$1): Session;
|
|
32
|
+
|
|
33
|
+
export { createPrismaClient, disconnectPrisma, recordToSession, recordToShop, sessionToRecord, shopToRecord };
|
|
@@ -0,0 +1,127 @@
|
|
|
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/database/index.ts
|
|
21
|
+
var database_exports = {};
|
|
22
|
+
__export(database_exports, {
|
|
23
|
+
createPrismaClient: () => createPrismaClient,
|
|
24
|
+
disconnectPrisma: () => disconnectPrisma,
|
|
25
|
+
recordToSession: () => recordToSession,
|
|
26
|
+
recordToShop: () => recordToShop,
|
|
27
|
+
sessionToRecord: () => sessionToRecord,
|
|
28
|
+
shopToRecord: () => shopToRecord
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(database_exports);
|
|
31
|
+
|
|
32
|
+
// src/database/client.ts
|
|
33
|
+
var import_client = require("@prisma/client");
|
|
34
|
+
var client = null;
|
|
35
|
+
function createPrismaClient(url) {
|
|
36
|
+
if (client) return client;
|
|
37
|
+
const options = {
|
|
38
|
+
log: process.env.NODE_ENV === "development" ? ["query", "warn", "error"] : ["error"]
|
|
39
|
+
};
|
|
40
|
+
if (url) {
|
|
41
|
+
options.datasourceUrl = url;
|
|
42
|
+
}
|
|
43
|
+
client = new import_client.PrismaClient(options);
|
|
44
|
+
return client;
|
|
45
|
+
}
|
|
46
|
+
function disconnectPrisma() {
|
|
47
|
+
if (!client) return Promise.resolve();
|
|
48
|
+
const c = client;
|
|
49
|
+
client = null;
|
|
50
|
+
return c.$disconnect();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/database/utils.ts
|
|
54
|
+
function shopToRecord(shop) {
|
|
55
|
+
return {
|
|
56
|
+
shopDomain: shop.shopDomain,
|
|
57
|
+
isInstalled: shop.isInstalled,
|
|
58
|
+
installedAt: shop.installedAt,
|
|
59
|
+
uninstalledAt: shop.uninstalledAt,
|
|
60
|
+
scopes: shop.scopes,
|
|
61
|
+
shopifyPlan: shop.shopifyPlan,
|
|
62
|
+
createdAt: shop.createdAt,
|
|
63
|
+
updatedAt: shop.updatedAt
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function recordToShop(record) {
|
|
67
|
+
return {
|
|
68
|
+
shopDomain: record.shopDomain,
|
|
69
|
+
isInstalled: record.isInstalled,
|
|
70
|
+
installedAt: record.installedAt ?? null,
|
|
71
|
+
uninstalledAt: record.uninstalledAt ?? null,
|
|
72
|
+
scopes: record.scopes,
|
|
73
|
+
shopifyPlan: record.shopifyPlan ?? null,
|
|
74
|
+
createdAt: record.createdAt,
|
|
75
|
+
updatedAt: record.updatedAt
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function sessionToRecord(session) {
|
|
79
|
+
const record = {
|
|
80
|
+
id: session.id,
|
|
81
|
+
shopDomain: session.shop,
|
|
82
|
+
state: session.state,
|
|
83
|
+
isOnline: session.isOnline,
|
|
84
|
+
scope: session.scope,
|
|
85
|
+
expires: session.expires,
|
|
86
|
+
accessToken: session.accessToken ?? null,
|
|
87
|
+
refreshToken: session.refreshToken ?? null,
|
|
88
|
+
refreshTokenExpiresAt: session.refreshTokenExpiresAt ?? null,
|
|
89
|
+
onlineAccessInfo: session.onlineAccessInfo ? session.onlineAccessInfo : null
|
|
90
|
+
};
|
|
91
|
+
return record;
|
|
92
|
+
}
|
|
93
|
+
function recordToSession(record) {
|
|
94
|
+
const session = {
|
|
95
|
+
id: record.id,
|
|
96
|
+
shop: record.shopDomain,
|
|
97
|
+
state: record.state,
|
|
98
|
+
isOnline: record.isOnline,
|
|
99
|
+
scope: record.scope,
|
|
100
|
+
expires: record.expires ?? null,
|
|
101
|
+
createdAt: record.createdAt,
|
|
102
|
+
updatedAt: record.updatedAt
|
|
103
|
+
};
|
|
104
|
+
if (record.accessToken) {
|
|
105
|
+
session.accessToken = record.accessToken;
|
|
106
|
+
}
|
|
107
|
+
if (record.refreshToken) {
|
|
108
|
+
session.refreshToken = record.refreshToken;
|
|
109
|
+
}
|
|
110
|
+
if (record.refreshTokenExpiresAt) {
|
|
111
|
+
session.refreshTokenExpiresAt = record.refreshTokenExpiresAt;
|
|
112
|
+
}
|
|
113
|
+
if (record.onlineAccessInfo) {
|
|
114
|
+
session.onlineAccessInfo = record.onlineAccessInfo;
|
|
115
|
+
}
|
|
116
|
+
return session;
|
|
117
|
+
}
|
|
118
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
119
|
+
0 && (module.exports = {
|
|
120
|
+
createPrismaClient,
|
|
121
|
+
disconnectPrisma,
|
|
122
|
+
recordToSession,
|
|
123
|
+
recordToShop,
|
|
124
|
+
sessionToRecord,
|
|
125
|
+
shopToRecord
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/index.ts","../../src/database/client.ts","../../src/database/utils.ts"],"sourcesContent":["/**\n * @uniforge/core - Database\n *\n * PrismaClient singleton and type converters.\n */\n\nexport { createPrismaClient, disconnectPrisma } from './client';\nexport {\n shopToRecord,\n recordToShop,\n sessionToRecord,\n recordToSession,\n} from './utils';\n","/**\n * PrismaClient singleton factory.\n *\n * Provides a single shared PrismaClient instance across the application.\n * Logging verbosity is controlled by NODE_ENV.\n */\n\nimport { PrismaClient } from '@prisma/client';\n\nlet client: PrismaClient | null = null;\n\n/** Create or return the singleton PrismaClient. */\nexport function createPrismaClient(url?: string): PrismaClient {\n if (client) return client;\n\n const options: ConstructorParameters<typeof PrismaClient>[0] = {\n log:\n process.env.NODE_ENV === 'development'\n ? ['query', 'warn', 'error']\n : ['error'],\n };\n if (url) {\n options.datasourceUrl = url;\n }\n\n client = new PrismaClient(options);\n return client;\n}\n\n/** Disconnect and discard the singleton PrismaClient. */\nexport function disconnectPrisma(): Promise<void> {\n if (!client) return Promise.resolve();\n const c = client;\n client = null;\n return c.$disconnect();\n}\n","/**\n * Converters between platform-core domain types and Prisma record types.\n *\n * The Prisma models use camelCase field names (shopDomain, isOnline, etc.)\n * while platform-core types use slightly different shapes (e.g. session.shop\n * vs record.shopDomain, onlineAccessInfo as object vs JSON).\n */\n\nimport type { Session, Shop } from '@uniforge/platform-core/auth';\nimport type {\n Shop as PrismaShop,\n Session as PrismaSession,\n Prisma,\n} from '@prisma/client';\n\n// ---------------------------------------------------------------------------\n// Shop converters\n// ---------------------------------------------------------------------------\n\n/** Convert a platform-core Shop to a Prisma-compatible record. */\nexport function shopToRecord(\n shop: Shop,\n): Omit<PrismaShop, 'id'> {\n return {\n shopDomain: shop.shopDomain,\n isInstalled: shop.isInstalled,\n installedAt: shop.installedAt,\n uninstalledAt: shop.uninstalledAt,\n scopes: shop.scopes,\n shopifyPlan: shop.shopifyPlan,\n createdAt: shop.createdAt,\n updatedAt: shop.updatedAt,\n };\n}\n\n/** Convert a Prisma Shop record to a platform-core Shop. */\nexport function recordToShop(record: PrismaShop): Shop {\n return {\n shopDomain: record.shopDomain,\n isInstalled: record.isInstalled,\n installedAt: record.installedAt ?? null,\n uninstalledAt: record.uninstalledAt ?? null,\n scopes: record.scopes,\n shopifyPlan: record.shopifyPlan ?? null,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Session converters\n// ---------------------------------------------------------------------------\n\n/** Convert a platform-core Session to a Prisma-compatible create/update input. */\nexport function sessionToRecord(\n session: Session,\n): Omit<PrismaSession, 'createdAt' | 'updatedAt'> {\n const record: Omit<PrismaSession, 'createdAt' | 'updatedAt'> = {\n id: session.id,\n shopDomain: session.shop,\n state: session.state,\n isOnline: session.isOnline,\n scope: session.scope,\n expires: session.expires,\n accessToken: session.accessToken ?? null,\n refreshToken: session.refreshToken ?? null,\n refreshTokenExpiresAt: session.refreshTokenExpiresAt ?? null,\n onlineAccessInfo: session.onlineAccessInfo\n ? (session.onlineAccessInfo as unknown as Prisma.JsonValue)\n : null,\n };\n\n return record;\n}\n\n/** Convert a Prisma Session record to a platform-core Session. */\nexport function recordToSession(record: PrismaSession): Session {\n const session: Session = {\n id: record.id,\n shop: record.shopDomain,\n state: record.state,\n isOnline: record.isOnline,\n scope: record.scope,\n expires: record.expires ?? null,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n };\n\n if (record.accessToken) {\n session.accessToken = record.accessToken;\n }\n if (record.refreshToken) {\n session.refreshToken = record.refreshToken;\n }\n if (record.refreshTokenExpiresAt) {\n session.refreshTokenExpiresAt = record.refreshTokenExpiresAt;\n }\n if (record.onlineAccessInfo) {\n session.onlineAccessInfo = record.onlineAccessInfo as unknown as NonNullable<Session['onlineAccessInfo']>;\n }\n\n return session;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,oBAA6B;AAE7B,IAAI,SAA8B;AAG3B,SAAS,mBAAmB,KAA4B;AAC7D,MAAI,OAAQ,QAAO;AAEnB,QAAM,UAAyD;AAAA,IAC7D,KACE,QAAQ,IAAI,aAAa,gBACrB,CAAC,SAAS,QAAQ,OAAO,IACzB,CAAC,OAAO;AAAA,EAChB;AACA,MAAI,KAAK;AACP,YAAQ,gBAAgB;AAAA,EAC1B;AAEA,WAAS,IAAI,2BAAa,OAAO;AACjC,SAAO;AACT;AAGO,SAAS,mBAAkC;AAChD,MAAI,CAAC,OAAQ,QAAO,QAAQ,QAAQ;AACpC,QAAM,IAAI;AACV,WAAS;AACT,SAAO,EAAE,YAAY;AACvB;;;ACfO,SAAS,aACd,MACwB;AACxB,SAAO;AAAA,IACL,YAAY,KAAK;AAAA,IACjB,aAAa,KAAK;AAAA,IAClB,aAAa,KAAK;AAAA,IAClB,eAAe,KAAK;AAAA,IACpB,QAAQ,KAAK;AAAA,IACb,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,EAClB;AACF;AAGO,SAAS,aAAa,QAA0B;AACrD,SAAO;AAAA,IACL,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO,eAAe;AAAA,IACnC,eAAe,OAAO,iBAAiB;AAAA,IACvC,QAAQ,OAAO;AAAA,IACf,aAAa,OAAO,eAAe;AAAA,IACnC,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB;AACF;AAOO,SAAS,gBACd,SACgD;AAChD,QAAM,SAAyD;AAAA,IAC7D,IAAI,QAAQ;AAAA,IACZ,YAAY,QAAQ;AAAA,IACpB,OAAO,QAAQ;AAAA,IACf,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ,eAAe;AAAA,IACpC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,uBAAuB,QAAQ,yBAAyB;AAAA,IACxD,kBAAkB,QAAQ,mBACrB,QAAQ,mBACT;AAAA,EACN;AAEA,SAAO;AACT;AAGO,SAAS,gBAAgB,QAAgC;AAC9D,QAAM,UAAmB;AAAA,IACvB,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,SAAS,OAAO,WAAW;AAAA,IAC3B,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB;AAEA,MAAI,OAAO,aAAa;AACtB,YAAQ,cAAc,OAAO;AAAA,EAC/B;AACA,MAAI,OAAO,cAAc;AACvB,YAAQ,eAAe,OAAO;AAAA,EAChC;AACA,MAAI,OAAO,uBAAuB;AAChC,YAAQ,wBAAwB,OAAO;AAAA,EACzC;AACA,MAAI,OAAO,kBAAkB;AAC3B,YAAQ,mBAAmB,OAAO;AAAA,EACpC;AAEA,SAAO;AACT;","names":[]}
|