@drawbridge/drawbridge-utils 0.0.19 → 0.0.20

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/shopify.cjs CHANGED
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var shopify_exports = {};
31
31
  __export(shopify_exports, {
32
32
  getAdminToken: () => getAdminToken,
33
- refreshAdminToken: () => refreshAdminToken
33
+ refreshAdminToken: () => refreshAdminToken,
34
+ resolveConnectionSettings: () => resolveConnectionSettings
34
35
  });
35
36
  module.exports = __toCommonJS(shopify_exports);
36
37
 
@@ -66,6 +67,8 @@ var decrypt = (value) => {
66
67
 
67
68
  // shopify.js
68
69
  var SHOPIFY_ADMIN_API_VERSION = "2025-01";
70
+ var REFRESH_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
71
+ var ACCESS_TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
69
72
  var shopifyOAuthFetch = async (url, body) => {
70
73
  const response = await fetch(url, {
71
74
  method: "POST",
@@ -98,9 +101,37 @@ var pingShop = async ({ adminAccessToken, domain }) => {
98
101
  throw error;
99
102
  }
100
103
  };
104
+ var resolveConnectionSettings = async ({ connection, controller }) => {
105
+ const connectionSettings = (connection == null ? void 0 : connection.settings) ? decrypt(connection.settings) : {};
106
+ if (!(connection == null ? void 0 : connection.credential)) {
107
+ return connectionSettings;
108
+ }
109
+ const credential = await controller.get({
110
+ collection: "credential",
111
+ query: {
112
+ id: connection.credential
113
+ }
114
+ });
115
+ const credentialSettings = (credential == null ? void 0 : credential.settings) ? decrypt(credential.settings) : {};
116
+ return {
117
+ ...credentialSettings,
118
+ ...connectionSettings
119
+ };
120
+ };
101
121
  var refreshAdminToken = async ({ connection, controller }) => {
102
- const settings = decrypt(connection.settings);
103
- const { domain, refreshToken } = settings;
122
+ const credential = await controller.get({
123
+ collection: "credential",
124
+ query: {
125
+ id: connection.credential
126
+ }
127
+ });
128
+ if (!credential) {
129
+ throw new Error("refreshAdminToken: credential not found for connection " + connection.id);
130
+ }
131
+ ;
132
+ const settings = decrypt(credential.settings);
133
+ const { identifier: domain } = credential;
134
+ const { refreshToken } = settings;
104
135
  const data = await shopifyOAuthFetch(
105
136
  `https://${domain}/admin/oauth/access_token`,
106
137
  {
@@ -114,73 +145,48 @@ var refreshAdminToken = async ({ connection, controller }) => {
114
145
  const newRefreshToken = data.refresh_token;
115
146
  const expiresIn = data.expires_in;
116
147
  const tokenExpiresAt = expiresIn ? new Date(Date.now() + expiresIn * 1e3) : null;
148
+ const refreshTokenExpiresAt = new Date(Date.now() + REFRESH_TOKEN_LIFETIME_MS);
117
149
  await pingShop({ adminAccessToken, domain });
118
- const tokenWorkflow = await controller.get({
119
- collection: "workflow",
120
- query: {
121
- connection: connection.id,
122
- organization: connection.organization,
123
- system: true,
124
- title: "Shopify Token Activity"
125
- }
126
- });
127
- await controller.transaction(async (session) => {
128
- const options = { session };
129
- await controller.update({
130
- collection: "connection",
131
- data: {
132
- $set: {
133
- settings: encrypt({
134
- ...settings,
135
- adminAccessToken,
136
- refreshToken: newRefreshToken,
137
- tokenExpiresAt
138
- })
139
- }
140
- },
141
- options,
142
- query: {
143
- id: connection.id
150
+ await controller.update({
151
+ collection: "credential",
152
+ data: {
153
+ $set: {
154
+ settings: encrypt({
155
+ ...settings,
156
+ adminAccessToken,
157
+ refreshToken: newRefreshToken,
158
+ refreshTokenExpiresAt,
159
+ tokenExpiresAt
160
+ })
144
161
  }
145
- });
146
- if (tokenWorkflow) {
147
- await controller.create({
148
- collection: "action",
149
- data: {
150
- completedAt: /* @__PURE__ */ new Date(),
151
- error: null,
152
- errorStatus: null,
153
- organization: connection.organization,
154
- request: null,
155
- response: null,
156
- slug: "action.shopify.token.refresh",
157
- status: "succeeded",
158
- trigger: {
159
- data: {
160
- connection: connection.id
161
- },
162
- event: "shopify.token"
163
- },
164
- usage: null,
165
- workflow: tokenWorkflow.id
166
- },
167
- options
168
- });
162
+ },
163
+ query: {
164
+ id: credential.id
169
165
  }
170
- ;
171
166
  });
172
167
  return adminAccessToken;
173
168
  };
174
169
  var getAdminToken = async ({ connection, controller }) => {
175
- const { adminAccessToken, tokenExpiresAt } = decrypt(connection.settings);
176
- const needsRefresh = tokenExpiresAt && new Date(tokenExpiresAt) < new Date(Date.now() + 5 * 60 * 1e3);
170
+ if (!(connection == null ? void 0 : connection.credential)) {
171
+ return null;
172
+ }
173
+ ;
174
+ const settings = await resolveConnectionSettings({ connection, controller });
175
+ const { adminAccessToken, refreshToken, tokenExpiresAt } = settings;
176
+ if (!refreshToken) {
177
+ return adminAccessToken;
178
+ }
179
+ ;
180
+ const needsRefresh = !tokenExpiresAt || new Date(tokenExpiresAt) < new Date(Date.now() + ACCESS_TOKEN_REFRESH_BUFFER_MS);
177
181
  if (needsRefresh) {
178
182
  return refreshAdminToken({ connection, controller });
179
183
  }
184
+ ;
180
185
  return adminAccessToken;
181
186
  };
182
187
  // Annotate the CommonJS export names for ESM import in node:
183
188
  0 && (module.exports = {
184
189
  getAdminToken,
185
- refreshAdminToken
190
+ refreshAdminToken,
191
+ resolveConnectionSettings
186
192
  });
@@ -2,6 +2,8 @@ import { decrypt, encrypt } from './encrypt.cjs';
2
2
  import 'crypto';
3
3
 
4
4
  const SHOPIFY_ADMIN_API_VERSION = '2025-01';
5
+ const REFRESH_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1000;
6
+ const ACCESS_TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
5
7
 
6
8
  const shopifyOAuthFetch = async ( url, body ) => {
7
9
 
@@ -52,10 +54,49 @@ const pingShop = async ({ adminAccessToken, domain }) => {
52
54
 
53
55
  };
54
56
 
57
+ const resolveConnectionSettings = async ({ connection, controller }) => {
58
+
59
+ const connectionSettings = connection?.settings ? decrypt( connection.settings ) : {};
60
+
61
+ if( ! connection?.credential ){
62
+
63
+ return connectionSettings;
64
+
65
+ }
66
+
67
+ const credential = await controller.get({
68
+ collection : 'credential',
69
+ query : {
70
+ id : connection.credential
71
+ }
72
+ });
73
+
74
+ const credentialSettings = credential?.settings ? decrypt( credential.settings ) : {};
75
+
76
+ return {
77
+ ...credentialSettings,
78
+ ...connectionSettings
79
+ };
80
+
81
+ };
82
+
55
83
  const refreshAdminToken = async ({ connection, controller }) => {
56
84
 
57
- const settings = decrypt( connection.settings );
58
- const { domain, refreshToken } = settings;
85
+ const credential = await controller.get({
86
+ collection : 'credential',
87
+ query : {
88
+ id : connection.credential
89
+ }
90
+ });
91
+
92
+ if( ! credential ){
93
+
94
+ throw new Error( 'refreshAdminToken: credential not found for connection ' + connection.id );
95
+
96
+ }
97
+ const settings = decrypt( credential.settings );
98
+ const { identifier : domain } = credential;
99
+ const { refreshToken } = settings;
59
100
 
60
101
  const data = await shopifyOAuthFetch(
61
102
  `https://${ domain }/admin/oauth/access_token`,
@@ -71,88 +112,57 @@ const refreshAdminToken = async ({ connection, controller }) => {
71
112
  const newRefreshToken = data.refresh_token;
72
113
  const expiresIn = data.expires_in;
73
114
  const tokenExpiresAt = expiresIn ? new Date( Date.now() + ( expiresIn * 1000 ) ) : null;
115
+ const refreshTokenExpiresAt = new Date( Date.now() + REFRESH_TOKEN_LIFETIME_MS );
74
116
 
75
117
  await pingShop({ adminAccessToken, domain });
76
118
 
77
- const tokenWorkflow = await controller.get({
78
- collection : 'workflow',
119
+ await controller.update({
120
+ collection : 'credential',
121
+ data : {
122
+ $set : {
123
+ settings : encrypt({
124
+ ...settings,
125
+ adminAccessToken,
126
+ refreshToken : newRefreshToken,
127
+ refreshTokenExpiresAt,
128
+ tokenExpiresAt
129
+ })
130
+ }
131
+ },
79
132
  query : {
80
- connection : connection.id,
81
- organization : connection.organization,
82
- system : true,
83
- title : 'Shopify Token Activity'
133
+ id : credential.id
84
134
  }
85
135
  });
86
136
 
87
- await controller.transaction( async ( session ) => {
88
-
89
- const options = { session };
90
-
91
- await controller.update({
92
- collection : 'connection',
93
- data : {
94
- $set : {
95
- settings : encrypt({
96
- ...settings,
97
- adminAccessToken,
98
- refreshToken : newRefreshToken,
99
- tokenExpiresAt
100
- })
101
- }
102
- },
103
- options,
104
- query : {
105
- id : connection.id
106
- }
107
- });
108
-
109
- if( tokenWorkflow ){
110
-
111
- await controller.create({
112
- collection : 'action',
113
- data : {
114
- completedAt : new Date(),
115
- error : null,
116
- errorStatus : null,
117
- organization : connection.organization,
118
- request : null,
119
- response : null,
120
- slug : 'action.shopify.token.refresh',
121
- status : 'succeeded',
122
- trigger : {
123
- data : {
124
- connection : connection.id
125
- },
126
- event : 'shopify.token'
127
- },
128
- usage : null,
129
- workflow : tokenWorkflow.id
130
- },
131
- options
132
- });
133
-
134
- }
135
- } );
136
-
137
137
  return adminAccessToken;
138
138
 
139
139
  };
140
140
 
141
141
  const getAdminToken = async ({ connection, controller }) => {
142
142
 
143
- const { adminAccessToken, tokenExpiresAt } = decrypt( connection.settings );
143
+ if( ! connection?.credential ){
144
+
145
+ return null;
146
+
147
+ }
148
+ const settings = await resolveConnectionSettings({ connection, controller });
149
+ const { adminAccessToken, refreshToken, tokenExpiresAt } = settings;
150
+
151
+ if( ! refreshToken ){
152
+
153
+ return adminAccessToken;
144
154
 
145
- const needsRefresh = tokenExpiresAt &&
146
- new Date( tokenExpiresAt ) < new Date( Date.now() + ( 5 * 60 * 1000 ) );
155
+ }
156
+ const needsRefresh = ! tokenExpiresAt ||
157
+ new Date( tokenExpiresAt ) < new Date( Date.now() + ACCESS_TOKEN_REFRESH_BUFFER_MS );
147
158
 
148
159
  if( needsRefresh ){
149
160
 
150
161
  return refreshAdminToken({ connection, controller });
151
162
 
152
163
  }
153
-
154
164
  return adminAccessToken;
155
165
 
156
166
  };
157
167
 
158
- export { getAdminToken, refreshAdminToken };
168
+ export { getAdminToken, refreshAdminToken, resolveConnectionSettings };
package/dist/shopify.d.ts CHANGED
@@ -2,6 +2,8 @@ import { decrypt, encrypt } from './encrypt.js';
2
2
  import 'crypto';
3
3
 
4
4
  const SHOPIFY_ADMIN_API_VERSION = '2025-01';
5
+ const REFRESH_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1000;
6
+ const ACCESS_TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
5
7
 
6
8
  const shopifyOAuthFetch = async ( url, body ) => {
7
9
 
@@ -52,10 +54,49 @@ const pingShop = async ({ adminAccessToken, domain }) => {
52
54
 
53
55
  };
54
56
 
57
+ const resolveConnectionSettings = async ({ connection, controller }) => {
58
+
59
+ const connectionSettings = connection?.settings ? decrypt( connection.settings ) : {};
60
+
61
+ if( ! connection?.credential ){
62
+
63
+ return connectionSettings;
64
+
65
+ }
66
+
67
+ const credential = await controller.get({
68
+ collection : 'credential',
69
+ query : {
70
+ id : connection.credential
71
+ }
72
+ });
73
+
74
+ const credentialSettings = credential?.settings ? decrypt( credential.settings ) : {};
75
+
76
+ return {
77
+ ...credentialSettings,
78
+ ...connectionSettings
79
+ };
80
+
81
+ };
82
+
55
83
  const refreshAdminToken = async ({ connection, controller }) => {
56
84
 
57
- const settings = decrypt( connection.settings );
58
- const { domain, refreshToken } = settings;
85
+ const credential = await controller.get({
86
+ collection : 'credential',
87
+ query : {
88
+ id : connection.credential
89
+ }
90
+ });
91
+
92
+ if( ! credential ){
93
+
94
+ throw new Error( 'refreshAdminToken: credential not found for connection ' + connection.id );
95
+
96
+ }
97
+ const settings = decrypt( credential.settings );
98
+ const { identifier : domain } = credential;
99
+ const { refreshToken } = settings;
59
100
 
60
101
  const data = await shopifyOAuthFetch(
61
102
  `https://${ domain }/admin/oauth/access_token`,
@@ -71,88 +112,57 @@ const refreshAdminToken = async ({ connection, controller }) => {
71
112
  const newRefreshToken = data.refresh_token;
72
113
  const expiresIn = data.expires_in;
73
114
  const tokenExpiresAt = expiresIn ? new Date( Date.now() + ( expiresIn * 1000 ) ) : null;
115
+ const refreshTokenExpiresAt = new Date( Date.now() + REFRESH_TOKEN_LIFETIME_MS );
74
116
 
75
117
  await pingShop({ adminAccessToken, domain });
76
118
 
77
- const tokenWorkflow = await controller.get({
78
- collection : 'workflow',
119
+ await controller.update({
120
+ collection : 'credential',
121
+ data : {
122
+ $set : {
123
+ settings : encrypt({
124
+ ...settings,
125
+ adminAccessToken,
126
+ refreshToken : newRefreshToken,
127
+ refreshTokenExpiresAt,
128
+ tokenExpiresAt
129
+ })
130
+ }
131
+ },
79
132
  query : {
80
- connection : connection.id,
81
- organization : connection.organization,
82
- system : true,
83
- title : 'Shopify Token Activity'
133
+ id : credential.id
84
134
  }
85
135
  });
86
136
 
87
- await controller.transaction( async ( session ) => {
88
-
89
- const options = { session };
90
-
91
- await controller.update({
92
- collection : 'connection',
93
- data : {
94
- $set : {
95
- settings : encrypt({
96
- ...settings,
97
- adminAccessToken,
98
- refreshToken : newRefreshToken,
99
- tokenExpiresAt
100
- })
101
- }
102
- },
103
- options,
104
- query : {
105
- id : connection.id
106
- }
107
- });
108
-
109
- if( tokenWorkflow ){
110
-
111
- await controller.create({
112
- collection : 'action',
113
- data : {
114
- completedAt : new Date(),
115
- error : null,
116
- errorStatus : null,
117
- organization : connection.organization,
118
- request : null,
119
- response : null,
120
- slug : 'action.shopify.token.refresh',
121
- status : 'succeeded',
122
- trigger : {
123
- data : {
124
- connection : connection.id
125
- },
126
- event : 'shopify.token'
127
- },
128
- usage : null,
129
- workflow : tokenWorkflow.id
130
- },
131
- options
132
- });
133
-
134
- }
135
- } );
136
-
137
137
  return adminAccessToken;
138
138
 
139
139
  };
140
140
 
141
141
  const getAdminToken = async ({ connection, controller }) => {
142
142
 
143
- const { adminAccessToken, tokenExpiresAt } = decrypt( connection.settings );
143
+ if( ! connection?.credential ){
144
+
145
+ return null;
146
+
147
+ }
148
+ const settings = await resolveConnectionSettings({ connection, controller });
149
+ const { adminAccessToken, refreshToken, tokenExpiresAt } = settings;
150
+
151
+ if( ! refreshToken ){
152
+
153
+ return adminAccessToken;
144
154
 
145
- const needsRefresh = tokenExpiresAt &&
146
- new Date( tokenExpiresAt ) < new Date( Date.now() + ( 5 * 60 * 1000 ) );
155
+ }
156
+ const needsRefresh = ! tokenExpiresAt ||
157
+ new Date( tokenExpiresAt ) < new Date( Date.now() + ACCESS_TOKEN_REFRESH_BUFFER_MS );
147
158
 
148
159
  if( needsRefresh ){
149
160
 
150
161
  return refreshAdminToken({ connection, controller });
151
162
 
152
163
  }
153
-
154
164
  return adminAccessToken;
155
165
 
156
166
  };
157
167
 
158
- export { getAdminToken, refreshAdminToken };
168
+ export { getAdminToken, refreshAdminToken, resolveConnectionSettings };
package/dist/shopify.js CHANGED
@@ -5,6 +5,8 @@ import {
5
5
 
6
6
  // shopify.js
7
7
  var SHOPIFY_ADMIN_API_VERSION = "2025-01";
8
+ var REFRESH_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
9
+ var ACCESS_TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
8
10
  var shopifyOAuthFetch = async (url, body) => {
9
11
  const response = await fetch(url, {
10
12
  method: "POST",
@@ -37,9 +39,37 @@ var pingShop = async ({ adminAccessToken, domain }) => {
37
39
  throw error;
38
40
  }
39
41
  };
42
+ var resolveConnectionSettings = async ({ connection, controller }) => {
43
+ const connectionSettings = (connection == null ? void 0 : connection.settings) ? decrypt(connection.settings) : {};
44
+ if (!(connection == null ? void 0 : connection.credential)) {
45
+ return connectionSettings;
46
+ }
47
+ const credential = await controller.get({
48
+ collection: "credential",
49
+ query: {
50
+ id: connection.credential
51
+ }
52
+ });
53
+ const credentialSettings = (credential == null ? void 0 : credential.settings) ? decrypt(credential.settings) : {};
54
+ return {
55
+ ...credentialSettings,
56
+ ...connectionSettings
57
+ };
58
+ };
40
59
  var refreshAdminToken = async ({ connection, controller }) => {
41
- const settings = decrypt(connection.settings);
42
- const { domain, refreshToken } = settings;
60
+ const credential = await controller.get({
61
+ collection: "credential",
62
+ query: {
63
+ id: connection.credential
64
+ }
65
+ });
66
+ if (!credential) {
67
+ throw new Error("refreshAdminToken: credential not found for connection " + connection.id);
68
+ }
69
+ ;
70
+ const settings = decrypt(credential.settings);
71
+ const { identifier: domain } = credential;
72
+ const { refreshToken } = settings;
43
73
  const data = await shopifyOAuthFetch(
44
74
  `https://${domain}/admin/oauth/access_token`,
45
75
  {
@@ -53,72 +83,47 @@ var refreshAdminToken = async ({ connection, controller }) => {
53
83
  const newRefreshToken = data.refresh_token;
54
84
  const expiresIn = data.expires_in;
55
85
  const tokenExpiresAt = expiresIn ? new Date(Date.now() + expiresIn * 1e3) : null;
86
+ const refreshTokenExpiresAt = new Date(Date.now() + REFRESH_TOKEN_LIFETIME_MS);
56
87
  await pingShop({ adminAccessToken, domain });
57
- const tokenWorkflow = await controller.get({
58
- collection: "workflow",
59
- query: {
60
- connection: connection.id,
61
- organization: connection.organization,
62
- system: true,
63
- title: "Shopify Token Activity"
64
- }
65
- });
66
- await controller.transaction(async (session) => {
67
- const options = { session };
68
- await controller.update({
69
- collection: "connection",
70
- data: {
71
- $set: {
72
- settings: encrypt({
73
- ...settings,
74
- adminAccessToken,
75
- refreshToken: newRefreshToken,
76
- tokenExpiresAt
77
- })
78
- }
79
- },
80
- options,
81
- query: {
82
- id: connection.id
88
+ await controller.update({
89
+ collection: "credential",
90
+ data: {
91
+ $set: {
92
+ settings: encrypt({
93
+ ...settings,
94
+ adminAccessToken,
95
+ refreshToken: newRefreshToken,
96
+ refreshTokenExpiresAt,
97
+ tokenExpiresAt
98
+ })
83
99
  }
84
- });
85
- if (tokenWorkflow) {
86
- await controller.create({
87
- collection: "action",
88
- data: {
89
- completedAt: /* @__PURE__ */ new Date(),
90
- error: null,
91
- errorStatus: null,
92
- organization: connection.organization,
93
- request: null,
94
- response: null,
95
- slug: "action.shopify.token.refresh",
96
- status: "succeeded",
97
- trigger: {
98
- data: {
99
- connection: connection.id
100
- },
101
- event: "shopify.token"
102
- },
103
- usage: null,
104
- workflow: tokenWorkflow.id
105
- },
106
- options
107
- });
100
+ },
101
+ query: {
102
+ id: credential.id
108
103
  }
109
- ;
110
104
  });
111
105
  return adminAccessToken;
112
106
  };
113
107
  var getAdminToken = async ({ connection, controller }) => {
114
- const { adminAccessToken, tokenExpiresAt } = decrypt(connection.settings);
115
- const needsRefresh = tokenExpiresAt && new Date(tokenExpiresAt) < new Date(Date.now() + 5 * 60 * 1e3);
108
+ if (!(connection == null ? void 0 : connection.credential)) {
109
+ return null;
110
+ }
111
+ ;
112
+ const settings = await resolveConnectionSettings({ connection, controller });
113
+ const { adminAccessToken, refreshToken, tokenExpiresAt } = settings;
114
+ if (!refreshToken) {
115
+ return adminAccessToken;
116
+ }
117
+ ;
118
+ const needsRefresh = !tokenExpiresAt || new Date(tokenExpiresAt) < new Date(Date.now() + ACCESS_TOKEN_REFRESH_BUFFER_MS);
116
119
  if (needsRefresh) {
117
120
  return refreshAdminToken({ connection, controller });
118
121
  }
122
+ ;
119
123
  return adminAccessToken;
120
124
  };
121
125
  export {
122
126
  getAdminToken,
123
- refreshAdminToken
127
+ refreshAdminToken,
128
+ resolveConnectionSettings
124
129
  };
package/package.json CHANGED
@@ -81,5 +81,5 @@
81
81
  "build": "tsup && npm publish"
82
82
  },
83
83
  "types": "dist/index.d.ts",
84
- "version": "0.0.19"
84
+ "version": "0.0.20"
85
85
  }