@friggframework/core 2.0.0--canary.684.bfb48ef.0 → 2.0.0--canary.683.edb4f0b.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/credential/use-cases/credential-operations-for-user.js +33 -110
- package/credential/use-cases/reauthorize-credential-for-user.js +13 -10
- package/management-api/openapi/components.js +0 -1
- package/management-api/openapi/v2-operations.js +0 -3
- package/management-api/v2/dependencies.js +2 -2
- package/management-api/v2/dto.js +0 -3
- package/management-api/v2/handlers/credentials.js +2 -6
- package/modules/scope-policy.js +0 -15
- package/modules/use-cases/authorize-entity-for-user.js +2 -4
- package/modules/use-cases/multi-step-authorization.js +1 -4
- package/package.json +5 -5
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
const Boom = require('@hapi/boom');
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
describeRecord,
|
|
5
|
-
visibilityClauses,
|
|
6
|
-
matchesListFilters,
|
|
7
|
-
SCOPES,
|
|
8
|
-
} = require('../../modules/entity-scope');
|
|
2
|
+
const { userOwns } = require('../../modules/use-cases/get-entity-module-for-user');
|
|
3
|
+
const { DEFAULT_SCOPE_POLICY } = require('../../modules/scope-policy');
|
|
9
4
|
const { assertCanManage } = require('../../modules/use-cases/manage-access');
|
|
10
5
|
|
|
11
6
|
/**
|
|
12
|
-
* Management API v2 credential operations
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - its `type` and `entityIds` come from the entities that use it that the
|
|
16
|
-
* caller may see, so the same person's account connected in two
|
|
17
|
-
* organizations (one credential, two entities) lists in each organization
|
|
18
|
-
* with that organization's entity only;
|
|
19
|
-
* - who it belongs to is its OWNER (`credential.userId`), never the entities:
|
|
20
|
-
* a credential an individual entity and an organization entity both point at
|
|
21
|
-
* (possible only through legacy data) is described by whoever owns the
|
|
22
|
-
* credential, so the answer cannot change with the order the entities load;
|
|
23
|
-
* - a credential whose entities are all out of sight (another organization's)
|
|
24
|
-
* is a 404, and one with no entities at all (its entity was deleted) is
|
|
25
|
-
* visible to its owner only, as it was before scoping.
|
|
7
|
+
* Management API v2 credential operations. A credential has no module name
|
|
8
|
+
* of its own; its `type` and the entities that use it come from the
|
|
9
|
+
* caller's entities. A missing or foreign credential is a 404.
|
|
26
10
|
*/
|
|
27
11
|
|
|
28
12
|
const credentialIdOf = (entity) => {
|
|
@@ -55,82 +39,31 @@ function withEntityUsage(credentials, entities) {
|
|
|
55
39
|
});
|
|
56
40
|
}
|
|
57
41
|
|
|
58
|
-
/**
|
|
59
|
-
* `{scope, owner, organizationId, access}` of a credential for this caller, or
|
|
60
|
-
* null when its owner is neither the caller nor the active organization. Built
|
|
61
|
-
* by `describeRecord` over the row a connection by this owner has: the
|
|
62
|
-
* organization of a visible entity, else the one a new entity would get.
|
|
63
|
-
*/
|
|
64
|
-
function credentialTenancy(credential, visibleEntities, ctx) {
|
|
65
|
-
const entityOrg = visibleEntities.find(
|
|
66
|
-
(entity) => entity.organizationId !== undefined && entity.organizationId !== null
|
|
67
|
-
)?.organizationId;
|
|
68
|
-
const organizationId =
|
|
69
|
-
entityOrg ?? (ctx.individualAcross === 'all' ? null : ctx.activeOrgId);
|
|
70
|
-
return describeRecord({ userId: credential.userId, organizationId }, ctx, 'entity');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** The entities of `entities` the caller may see, each with its `tenancy`. */
|
|
74
|
-
function visibleOf(entities, ctx) {
|
|
75
|
-
const visible = [];
|
|
76
|
-
for (const entity of entities || []) {
|
|
77
|
-
const tenancy = describeRecord(entity, ctx, 'entity');
|
|
78
|
-
if (tenancy) visible.push({ ...entity, tenancy });
|
|
79
|
-
}
|
|
80
|
-
return visible;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* The caller's credentials with their type, the entities of them they may see
|
|
85
|
-
* and `tenancy`. Credentials with no entity at all are listed too, for the
|
|
86
|
-
* person and the active organization that own them.
|
|
87
|
-
*/
|
|
42
|
+
/** The caller's credentials with their type and entity usage. */
|
|
88
43
|
class ListCredentialsForUser {
|
|
89
|
-
constructor({ credentialRepository, moduleRepository
|
|
44
|
+
constructor({ credentialRepository, moduleRepository }) {
|
|
90
45
|
this.credentialRepository = credentialRepository;
|
|
91
46
|
this.moduleRepository = moduleRepository;
|
|
92
|
-
this.scopePolicy = scopePolicy || createScopePolicy();
|
|
93
47
|
}
|
|
94
48
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.moduleRepository.findEntitiesByOwnership(visibilityClauses(ctx, 'entity')),
|
|
101
|
-
Promise.all(owners.map((id) => this.credentialRepository.findCredentialsByUserId(id))),
|
|
102
|
-
// Every entity of those owners, in any organization: only to tell a credential
|
|
103
|
-
// with no entity at all from one used elsewhere.
|
|
104
|
-
Promise.all(owners.map((id) => this.moduleRepository.findEntitiesByUserId(id))),
|
|
49
|
+
async execute(user) {
|
|
50
|
+
const userId = user.getId();
|
|
51
|
+
const [credentials, entities] = await Promise.all([
|
|
52
|
+
this.credentialRepository.findCredentialsByUserId(userId),
|
|
53
|
+
this.moduleRepository.findEntitiesByUserId(userId),
|
|
105
54
|
]);
|
|
106
|
-
|
|
107
|
-
const usedAnywhere = new Set(owned.flat().map(credentialIdOf).filter(Boolean));
|
|
108
|
-
const listed = [];
|
|
109
|
-
for (const credential of perOwner.flat().filter(Boolean)) {
|
|
110
|
-
const id = String(credential.id);
|
|
111
|
-
const referencing = visible.filter((entity) => credentialIdOf(entity) === id);
|
|
112
|
-
if (referencing.length === 0 && usedAnywhere.has(id)) continue;
|
|
113
|
-
const tenancy = credentialTenancy(credential, referencing, ctx);
|
|
114
|
-
if (!tenancy || !matchesListFilters(tenancy, filters)) continue;
|
|
115
|
-
listed.push({ ...withEntityUsage([credential], referencing)[0], tenancy });
|
|
116
|
-
}
|
|
117
|
-
return listed;
|
|
55
|
+
return withEntityUsage(credentials || [], entities);
|
|
118
56
|
}
|
|
119
57
|
}
|
|
120
58
|
|
|
121
|
-
/** One credential the caller
|
|
59
|
+
/** One credential the caller owns, with its type and entity usage. */
|
|
122
60
|
class GetCredentialForUserV2 {
|
|
123
|
-
constructor({ credentialRepository, moduleRepository
|
|
61
|
+
constructor({ credentialRepository, moduleRepository }) {
|
|
124
62
|
this.credentialRepository = credentialRepository;
|
|
125
63
|
this.moduleRepository = moduleRepository;
|
|
126
|
-
this.scopePolicy = scopePolicy || createScopePolicy();
|
|
127
64
|
}
|
|
128
65
|
|
|
129
66
|
async execute(credentialId, user) {
|
|
130
|
-
const notFound = () =>
|
|
131
|
-
Boom.notFound(`Credential ${credentialId} not found`, {
|
|
132
|
-
code: 'CREDENTIAL_NOT_FOUND',
|
|
133
|
-
});
|
|
134
67
|
let credential = null;
|
|
135
68
|
try {
|
|
136
69
|
credential = await this.credentialRepository.findCredentialById(
|
|
@@ -141,32 +74,26 @@ class GetCredentialForUserV2 {
|
|
|
141
74
|
throw error;
|
|
142
75
|
}
|
|
143
76
|
}
|
|
144
|
-
if (!credential
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return { ...withEntityUsage([credential], visible)[0], tenancy };
|
|
77
|
+
if (!credential || !userOwns(user, credential.userId)) {
|
|
78
|
+
throw Boom.notFound(`Credential ${credentialId} not found`, {
|
|
79
|
+
code: 'CREDENTIAL_NOT_FOUND',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const entities = await this.moduleRepository.findEntitiesByUserId(
|
|
83
|
+
credential.userId
|
|
84
|
+
);
|
|
85
|
+
return withEntityUsage([credential], entities)[0];
|
|
154
86
|
}
|
|
155
87
|
}
|
|
156
88
|
|
|
157
89
|
/**
|
|
158
|
-
* Deletes a credential the caller
|
|
159
|
-
*
|
|
90
|
+
* Deletes a credential the caller owns. The entities that used it stay, with
|
|
91
|
+
* their credential unset, so they show as needing re-authorization rather
|
|
160
92
|
* than disappearing from integrations.
|
|
161
|
-
*
|
|
162
|
-
* Refuses with 409 `CREDENTIAL_SHARED` while an entity the caller cannot see
|
|
163
|
-
* still uses it: one credential row serves the same provider account in every
|
|
164
|
-
* organization, and deleting it from one would break the other. The message
|
|
165
|
-
* says nothing about the other connections (not even how many): remove the
|
|
166
|
-
* entities that use it, and it goes with the last one.
|
|
167
93
|
*/
|
|
168
94
|
class DeleteCredentialForUser {
|
|
169
|
-
constructor({ credentialRepository, moduleRepository, getCredentialForUser }) {
|
|
95
|
+
constructor({ credentialRepository, moduleRepository, getCredentialForUser, scopePolicy }) {
|
|
96
|
+
this.scopePolicy = scopePolicy || DEFAULT_SCOPE_POLICY;
|
|
170
97
|
this.credentialRepository = credentialRepository;
|
|
171
98
|
this.moduleRepository = moduleRepository;
|
|
172
99
|
this.getCredentialForUser = getCredentialForUser;
|
|
@@ -177,15 +104,11 @@ class DeleteCredentialForUser {
|
|
|
177
104
|
credentialId,
|
|
178
105
|
user
|
|
179
106
|
);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`Credential ${credential.id} is still in use by other connections and cannot be deleted from here`,
|
|
186
|
-
{ code: 'CREDENTIAL_SHARED' }
|
|
187
|
-
);
|
|
188
|
-
}
|
|
107
|
+
// A credential an organization owns: the organization's admins only.
|
|
108
|
+
// (null: not the person's or the active organization's, which the
|
|
109
|
+
// owner check above already decided.)
|
|
110
|
+
const access = this.scopePolicy.accessToOwnedBy(user, credential.userId);
|
|
111
|
+
if (access !== null) assertCanManage(access, `credential ${credential.id}`);
|
|
189
112
|
for (const entityId of credential.entityIds) {
|
|
190
113
|
await this.moduleRepository.unsetCredential(entityId);
|
|
191
114
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const Boom = require('@hapi/boom');
|
|
2
|
+
const { DEFAULT_SCOPE_POLICY } = require('../../modules/scope-policy');
|
|
2
3
|
const { assertCanManage } = require('../../modules/use-cases/manage-access');
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -18,9 +19,7 @@ async function credentialEntityType(getCredentialForUser, credentialId, user) {
|
|
|
18
19
|
return {
|
|
19
20
|
entityType: credential.type,
|
|
20
21
|
credentialId: String(credential.id),
|
|
21
|
-
|
|
22
|
-
fixedScope: credential.tenancy?.scope,
|
|
23
|
-
access: credential.tenancy?.access,
|
|
22
|
+
ownerId: credential.userId,
|
|
24
23
|
};
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -32,12 +31,14 @@ class GetCredentialReauthorization {
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
async execute(credentialId, user, { step = 1, sessionId, state } = {}) {
|
|
35
|
-
const {
|
|
36
|
-
|
|
34
|
+
const { ownerId, ...binding } = await credentialEntityType(
|
|
35
|
+
this.getCredentialForUser,
|
|
36
|
+
credentialId,
|
|
37
|
+
user
|
|
38
|
+
);
|
|
37
39
|
return this.getAuthorizationStep.execute({
|
|
38
40
|
user,
|
|
39
|
-
|
|
40
|
-
credentialId: boundCredentialId,
|
|
41
|
+
...binding,
|
|
41
42
|
step,
|
|
42
43
|
sessionId,
|
|
43
44
|
state,
|
|
@@ -47,19 +48,21 @@ class GetCredentialReauthorization {
|
|
|
47
48
|
|
|
48
49
|
/** POST /api/v2/credentials/:credentialId/reauthorize */
|
|
49
50
|
class ReauthorizeCredentialForUser {
|
|
50
|
-
constructor({ getCredentialForUser, submitAuthorizationStep }) {
|
|
51
|
+
constructor({ getCredentialForUser, submitAuthorizationStep, scopePolicy }) {
|
|
52
|
+
this.scopePolicy = scopePolicy || DEFAULT_SCOPE_POLICY;
|
|
51
53
|
this.getCredentialForUser = getCredentialForUser;
|
|
52
54
|
this.submitAuthorizationStep = submitAuthorizationStep;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
async execute(credentialId, user, { data, step = 1, sessionId } = {}) {
|
|
56
|
-
const {
|
|
58
|
+
const { ownerId, ...binding } = await credentialEntityType(
|
|
57
59
|
this.getCredentialForUser,
|
|
58
60
|
credentialId,
|
|
59
61
|
user
|
|
60
62
|
);
|
|
61
63
|
// A credential an organization owns: the organization's admins only.
|
|
62
|
-
|
|
64
|
+
const access = this.scopePolicy.accessToOwnedBy(user, ownerId);
|
|
65
|
+
if (access !== null) assertCanManage(access, `credential ${credentialId}`);
|
|
63
66
|
return this.submitAuthorizationStep.execute({
|
|
64
67
|
user,
|
|
65
68
|
...binding,
|
|
@@ -206,7 +206,6 @@ const SCHEMAS = {
|
|
|
206
206
|
authIsValid: nullable({ type: 'boolean' }),
|
|
207
207
|
entityIds: { type: 'array', items: { type: 'string' } },
|
|
208
208
|
entityCount: { type: 'integer', minimum: 0 },
|
|
209
|
-
...tenancyProperties,
|
|
210
209
|
createdAt: nullable({ type: 'string', format: 'date-time' }),
|
|
211
210
|
updatedAt: nullable({ type: 'string', format: 'date-time' }),
|
|
212
211
|
data: {
|
|
@@ -184,9 +184,6 @@ const V2_OPERATIONS = {
|
|
|
184
184
|
// Credentials
|
|
185
185
|
listCredentials: {
|
|
186
186
|
summary: "List the caller's credentials (masked)",
|
|
187
|
-
description:
|
|
188
|
-
'A credential is listed through the entities that use it that the caller may see, so each organization lists only its own connections; one no entity uses is listed to its owner. Each carries `scope`, `owner`, `organizationId` and `access`, taken from who owns the credential.',
|
|
189
|
-
parameters: listFilters,
|
|
190
187
|
responses: { 200: ok('Credentials', ref('ListCredentialsResponse')), ...errors('Unauthorized') },
|
|
191
188
|
},
|
|
192
189
|
getCredential: {
|
|
@@ -124,7 +124,6 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
|
|
|
124
124
|
const getCredentialForUser = new credentialOps.GetCredentialForUserV2({
|
|
125
125
|
credentialRepository,
|
|
126
126
|
moduleRepository,
|
|
127
|
-
scopePolicy,
|
|
128
127
|
});
|
|
129
128
|
const getAuthorizationRequirements = new GetAuthorizationRequirements({
|
|
130
129
|
moduleDefinitions,
|
|
@@ -247,13 +246,13 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
|
|
|
247
246
|
listCredentialsForUser: new credentialOps.ListCredentialsForUser({
|
|
248
247
|
credentialRepository,
|
|
249
248
|
moduleRepository,
|
|
250
|
-
scopePolicy,
|
|
251
249
|
}),
|
|
252
250
|
getCredentialForUser,
|
|
253
251
|
deleteCredentialForUser: new credentialOps.DeleteCredentialForUser({
|
|
254
252
|
credentialRepository,
|
|
255
253
|
moduleRepository,
|
|
256
254
|
getCredentialForUser,
|
|
255
|
+
scopePolicy,
|
|
257
256
|
}),
|
|
258
257
|
getCredentialReauthorization: new GetCredentialReauthorization({
|
|
259
258
|
getCredentialForUser,
|
|
@@ -262,6 +261,7 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
|
|
|
262
261
|
reauthorizeCredentialForUser: new ReauthorizeCredentialForUser({
|
|
263
262
|
getCredentialForUser,
|
|
264
263
|
submitAuthorizationStep,
|
|
264
|
+
scopePolicy,
|
|
265
265
|
}),
|
|
266
266
|
|
|
267
267
|
// Authorization (multi-step)
|
package/management-api/v2/dto.js
CHANGED
|
@@ -75,8 +75,6 @@ const CREDENTIAL_METADATA = new Set([
|
|
|
75
75
|
'type',
|
|
76
76
|
'entityIds',
|
|
77
77
|
'status',
|
|
78
|
-
// Added by the credential use cases (ADR-056 §3.4); never provider data.
|
|
79
|
-
'tenancy',
|
|
80
78
|
]);
|
|
81
79
|
|
|
82
80
|
/**
|
|
@@ -128,7 +126,6 @@ function maskCredential(credential) {
|
|
|
128
126
|
entityCount: entityIds.length,
|
|
129
127
|
createdAt: toIso(credential.createdAt),
|
|
130
128
|
updatedAt: toIso(credential.updatedAt),
|
|
131
|
-
...tenancyFields(credential.tenancy),
|
|
132
129
|
data,
|
|
133
130
|
};
|
|
134
131
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { maskCredential } = require('../dto');
|
|
2
|
-
const { parseListFilters } = require('../request');
|
|
3
2
|
|
|
4
3
|
/** Management API v2 credential handlers, keyed by operationId. */
|
|
5
4
|
function createCredentialHandlers(useCases) {
|
|
@@ -7,11 +6,8 @@ function createCredentialHandlers(useCases) {
|
|
|
7
6
|
useCases;
|
|
8
7
|
|
|
9
8
|
return {
|
|
10
|
-
async listCredentials(
|
|
11
|
-
const credentials = await listCredentialsForUser.execute(
|
|
12
|
-
user,
|
|
13
|
-
parseListFilters(req.query)
|
|
14
|
-
);
|
|
9
|
+
async listCredentials(_req, res, user) {
|
|
10
|
+
const credentials = await listCredentialsForUser.execute(user);
|
|
15
11
|
res.json({ credentials: credentials.map(maskCredential) });
|
|
16
12
|
},
|
|
17
13
|
|
package/modules/scope-policy.js
CHANGED
|
@@ -69,20 +69,6 @@ function createScopePolicy({ ownership, entityTypeRegistry } = {}) {
|
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
/**
|
|
73
|
-
* The owner and organization for a scope that is already decided: a
|
|
74
|
-
* re-authorization keeps the scope its connection has, whatever the config
|
|
75
|
-
* says now. The admin gate applies as it does on create.
|
|
76
|
-
*/
|
|
77
|
-
const ownershipForScope = ({ scope, user }) => {
|
|
78
|
-
const ctx = contextFor(user);
|
|
79
|
-
return {
|
|
80
|
-
...resolveOwnerForScope(scope, ctx),
|
|
81
|
-
legacyOrgId: ctx.legacyOrgId,
|
|
82
|
-
source: 'fixed',
|
|
83
|
-
};
|
|
84
|
-
};
|
|
85
|
-
|
|
86
72
|
/** Whether `user` may load this stored entity for use (same clauses as the list). */
|
|
87
73
|
const canUseEntity = (user, entity) =>
|
|
88
74
|
describeRecord(entity, contextFor(user), 'entity') !== null;
|
|
@@ -100,7 +86,6 @@ function createScopePolicy({ ownership, entityTypeRegistry } = {}) {
|
|
|
100
86
|
accessContext: contextFor,
|
|
101
87
|
resolveScope: resolveEntityScope,
|
|
102
88
|
resolveOwnership,
|
|
103
|
-
ownershipForScope,
|
|
104
89
|
canUseEntity,
|
|
105
90
|
});
|
|
106
91
|
}
|
|
@@ -19,11 +19,9 @@ class AuthorizeEntityForUser {
|
|
|
19
19
|
* The scope, owner and organization a new entity of `entityType` gets for
|
|
20
20
|
* this caller. Throws a 400/403 when the request cannot have one.
|
|
21
21
|
*
|
|
22
|
-
* @param {{user: Object, entityType: string, scope?: string
|
|
23
|
-
* `fixedScope`: a re-authorization keeps the scope its connection has
|
|
22
|
+
* @param {{user: Object, entityType: string, scope?: string}} params
|
|
24
23
|
*/
|
|
25
|
-
resolveOwnership({ user, entityType, scope
|
|
26
|
-
if (fixedScope) return this.scopePolicy.ownershipForScope({ scope: fixedScope, user });
|
|
24
|
+
resolveOwnership({ user, entityType, scope }) {
|
|
27
25
|
return this.scopePolicy.resolveOwnership({
|
|
28
26
|
entityType,
|
|
29
27
|
requestScope: scope,
|
|
@@ -166,10 +166,8 @@ class SubmitAuthorizationStep {
|
|
|
166
166
|
* @param {Object} params
|
|
167
167
|
* @param {string} [params.scope] - the scope the caller asks for, from the
|
|
168
168
|
* deciding level's allow list (ADR-056 §3.1). Never `global`.
|
|
169
|
-
* @param {string} [params.fixedScope] - re-authorization keeps the scope the
|
|
170
|
-
* credential already has, whatever the config says now.
|
|
171
169
|
*/
|
|
172
|
-
async execute({ user, entityType, data, step = 1, sessionId, credentialId = null, scope
|
|
170
|
+
async execute({ user, entityType, data, step = 1, sessionId, credentialId = null, scope }) {
|
|
173
171
|
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
174
172
|
throw Boom.badRequest('data must be an object', {
|
|
175
173
|
code: 'VALIDATION_ERROR',
|
|
@@ -185,7 +183,6 @@ class SubmitAuthorizationStep {
|
|
|
185
183
|
user,
|
|
186
184
|
entityType,
|
|
187
185
|
scope,
|
|
188
|
-
fixedScope,
|
|
189
186
|
});
|
|
190
187
|
|
|
191
188
|
if (!isMultiStep(definition)) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/core",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.
|
|
4
|
+
"version": "2.0.0--canary.683.edb4f0b.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.588.0",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@friggframework/eslint-config": "2.0.0--canary.
|
|
52
|
-
"@friggframework/prettier-config": "2.0.0--canary.
|
|
53
|
-
"@friggframework/test": "2.0.0--canary.
|
|
51
|
+
"@friggframework/eslint-config": "2.0.0--canary.683.edb4f0b.0",
|
|
52
|
+
"@friggframework/prettier-config": "2.0.0--canary.683.edb4f0b.0",
|
|
53
|
+
"@friggframework/test": "2.0.0--canary.683.edb4f0b.0",
|
|
54
54
|
"@prisma/client": "^6.19.3",
|
|
55
55
|
"@types/lodash": "4.17.15",
|
|
56
56
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"publishConfig": {
|
|
91
91
|
"access": "public"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "edb4f0b45af2a0a70fc5c7dbe3324d9a8e088d70"
|
|
94
94
|
}
|