@jskit-ai/crud-server-generator 0.1.65 → 0.1.67
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/package.descriptor.mjs +9 -9
- package/package.json +7 -7
- package/src/server/subcommands/resourceAst.js +35 -0
- package/templates/src/local-package/server/repository.js +11 -6
- package/templates/src/local-package/server/service.js +2 -3
- package/test/addFieldSubcommand.test.js +50 -0
- package/test/buildTemplateContext.test.js +6 -2
- package/test/crudServerGuards.test.js +83 -0
- package/test/crudService.test.js +38 -5
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/crud-server-generator",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.67",
|
|
5
5
|
kind: "generator",
|
|
6
6
|
description: "CRUD server generator with routes, actions, and persistence scaffolding.",
|
|
7
7
|
options: {
|
|
@@ -152,14 +152,14 @@ export default Object.freeze({
|
|
|
152
152
|
mutations: {
|
|
153
153
|
dependencies: {
|
|
154
154
|
runtime: {
|
|
155
|
-
"@jskit-ai/auth-core": "0.1.
|
|
156
|
-
"@jskit-ai/crud-core": "0.1.
|
|
157
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
158
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
159
|
-
"@jskit-ai/json-rest-api-core": "0.1.
|
|
160
|
-
"@jskit-ai/kernel": "0.1.
|
|
161
|
-
"@jskit-ai/realtime": "0.1.
|
|
162
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
155
|
+
"@jskit-ai/auth-core": "0.1.58",
|
|
156
|
+
"@jskit-ai/crud-core": "0.1.67",
|
|
157
|
+
"@jskit-ai/database-runtime": "0.1.59",
|
|
158
|
+
"@jskit-ai/http-runtime": "0.1.58",
|
|
159
|
+
"@jskit-ai/json-rest-api-core": "0.1.4",
|
|
160
|
+
"@jskit-ai/kernel": "0.1.59",
|
|
161
|
+
"@jskit-ai/realtime": "0.1.58",
|
|
162
|
+
"@jskit-ai/resource-crud-core": "0.1.4",
|
|
163
163
|
"@local/${option:namespace|kebab}": "file:packages/${option:namespace|kebab}"
|
|
164
164
|
},
|
|
165
165
|
dev: {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/crud-server-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@babel/parser": "^7.29.2",
|
|
16
|
-
"@jskit-ai/crud-core": "0.1.
|
|
17
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
18
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
19
|
-
"@jskit-ai/json-rest-api-core": "0.1.
|
|
20
|
-
"@jskit-ai/kernel": "0.1.
|
|
21
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
16
|
+
"@jskit-ai/crud-core": "0.1.67",
|
|
17
|
+
"@jskit-ai/database-runtime": "0.1.59",
|
|
18
|
+
"@jskit-ai/http-runtime": "0.1.58",
|
|
19
|
+
"@jskit-ai/json-rest-api-core": "0.1.4",
|
|
20
|
+
"@jskit-ai/kernel": "0.1.59",
|
|
21
|
+
"@jskit-ai/resource-crud-core": "0.1.4",
|
|
22
22
|
"recast": "^0.23.11"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -31,6 +31,16 @@ const BABEL_REC_AST_PARSER = Object.freeze({
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
const IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
34
|
+
const EXPLICIT_CRUD_SCHEMA_OVERRIDE_KEYS = Object.freeze([
|
|
35
|
+
"body",
|
|
36
|
+
"output",
|
|
37
|
+
"listOutput",
|
|
38
|
+
"listItemOutput",
|
|
39
|
+
"createBody",
|
|
40
|
+
"replaceBody",
|
|
41
|
+
"patchBody",
|
|
42
|
+
"deleteOutput"
|
|
43
|
+
]);
|
|
34
44
|
|
|
35
45
|
function isIdentifierName(value = "") {
|
|
36
46
|
return IDENTIFIER_PATTERN.test(String(value || ""));
|
|
@@ -138,6 +148,7 @@ function requireCrudResourceConfigObject(programNode, context = "crud-server-gen
|
|
|
138
148
|
|
|
139
149
|
function requireResourceSchemaObject(programNode, context = "crud-server-generator scaffold-field") {
|
|
140
150
|
const resourceObject = requireCrudResourceConfigObject(programNode, context);
|
|
151
|
+
assertNoExplicitCrudSchemaOverrides(resourceObject, context);
|
|
141
152
|
const schemaProperty = findObjectPropertyByName(resourceObject, "schema");
|
|
142
153
|
if (!schemaProperty || !n.ObjectExpression.check(schemaProperty.value)) {
|
|
143
154
|
throw new Error(
|
|
@@ -148,6 +159,30 @@ function requireResourceSchemaObject(programNode, context = "crud-server-generat
|
|
|
148
159
|
return schemaProperty.value;
|
|
149
160
|
}
|
|
150
161
|
|
|
162
|
+
function assertNoExplicitCrudSchemaOverrides(resourceObject, context = "crud-server-generator scaffold-field") {
|
|
163
|
+
const crudProperty = findObjectPropertyByName(resourceObject, "crud");
|
|
164
|
+
if (!crudProperty) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!n.ObjectExpression.check(crudProperty.value)) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`${context} cannot patch defineCrudResource({ ..., crud: ... }) unless crud is omitted or authored as an inline object literal without explicit schema overrides.`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const overrideKeys = EXPLICIT_CRUD_SCHEMA_OVERRIDE_KEYS.filter((propertyName) =>
|
|
175
|
+
hasObjectProperty(crudProperty.value, propertyName)
|
|
176
|
+
);
|
|
177
|
+
if (overrideKeys.length === 0) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
throw new Error(
|
|
182
|
+
`${context} cannot patch defineCrudResource({ ..., crud: { ... } }) when explicit crud schema overrides are authored (${overrideKeys.join(", ")}). Update schema and override validators manually.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
151
186
|
function findObjectPropertyByName(objectNode, propertyName = "") {
|
|
152
187
|
const targetName = normalizeText(propertyName);
|
|
153
188
|
if (!targetName || !n.ObjectExpression.check(objectNode)) {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
returnNullWhenJsonRestResourceMissing
|
|
7
7
|
} from "@jskit-ai/json-rest-api-core/server/jsonRestApiHost";
|
|
8
8
|
import { resource } from "../shared/${option:namespace|singular|camel}Resource.js";
|
|
9
|
-
const
|
|
9
|
+
const JSON_REST_SCOPE_NAME = __JSKIT_CRUD_JSONREST_SCOPE_NAME__;
|
|
10
10
|
|
|
11
11
|
function createRepository({ api, knex } = {}) {
|
|
12
12
|
const withTransaction = createWithTransaction(knex);
|
|
@@ -14,7 +14,7 @@ function createRepository({ api, knex } = {}) {
|
|
|
14
14
|
async function queryDocuments(query = {}, options = {}) {
|
|
15
15
|
return api.resources.${option:namespace|camel}.query(
|
|
16
16
|
{
|
|
17
|
-
queryParams: buildJsonRestQueryParams(
|
|
17
|
+
queryParams: buildJsonRestQueryParams(JSON_REST_SCOPE_NAME, query),
|
|
18
18
|
transaction: options?.trx || null,
|
|
19
19
|
simplified: false
|
|
20
20
|
},
|
|
@@ -27,7 +27,7 @@ function createRepository({ api, knex } = {}) {
|
|
|
27
27
|
api.resources.${option:namespace|camel}.get(
|
|
28
28
|
{
|
|
29
29
|
id: recordId,
|
|
30
|
-
queryParams: buildJsonRestQueryParams(
|
|
30
|
+
queryParams: buildJsonRestQueryParams(JSON_REST_SCOPE_NAME, {}, {
|
|
31
31
|
include: options?.include
|
|
32
32
|
}),
|
|
33
33
|
transaction: options?.trx || null,
|
|
@@ -41,7 +41,9 @@ function createRepository({ api, knex } = {}) {
|
|
|
41
41
|
async function createDocument(payload = {}, options = {}) {
|
|
42
42
|
return api.resources.${option:namespace|camel}.post(
|
|
43
43
|
{
|
|
44
|
-
inputRecord: createJsonApiInputRecord(
|
|
44
|
+
inputRecord: createJsonApiInputRecord(JSON_REST_SCOPE_NAME, payload, {
|
|
45
|
+
resource
|
|
46
|
+
}),
|
|
45
47
|
transaction: options?.trx || null,
|
|
46
48
|
simplified: false
|
|
47
49
|
},
|
|
@@ -60,10 +62,13 @@ function createRepository({ api, knex } = {}) {
|
|
|
60
62
|
{
|
|
61
63
|
id: recordId,
|
|
62
64
|
inputRecord: createJsonApiInputRecord(
|
|
63
|
-
|
|
65
|
+
JSON_REST_SCOPE_NAME,
|
|
64
66
|
{
|
|
65
67
|
...sourcePatch,
|
|
66
68
|
updatedAt: new Date()
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
resource
|
|
67
72
|
}
|
|
68
73
|
),
|
|
69
74
|
transaction: options?.trx || null,
|
|
@@ -85,7 +90,7 @@ function createRepository({ api, knex } = {}) {
|
|
|
85
90
|
createJsonRestContext(options?.context || null)
|
|
86
91
|
);
|
|
87
92
|
|
|
88
|
-
return
|
|
93
|
+
return null;
|
|
89
94
|
});
|
|
90
95
|
}
|
|
91
96
|
|
|
@@ -43,11 +43,10 @@ function createService({ ${option:namespace|camel}Repository } = {}) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
async function deleteDocumentById(recordId, options = {}) {
|
|
46
|
-
|
|
46
|
+
return ${option:namespace|camel}Repository.deleteDocumentById(recordId, {
|
|
47
47
|
trx: options?.trx || null,
|
|
48
48
|
context: options?.context || null
|
|
49
|
-
})
|
|
50
|
-
return null;
|
|
49
|
+
});
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
return Object.freeze({
|
|
@@ -78,6 +78,38 @@ const resource = defineCrudResource({
|
|
|
78
78
|
export { resource };
|
|
79
79
|
`;
|
|
80
80
|
|
|
81
|
+
const EXPLICIT_CRUD_OVERRIDE_RESOURCE_SOURCE = `import { createSchema } from "json-rest-schema";
|
|
82
|
+
import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
|
|
83
|
+
|
|
84
|
+
const recordOutputSchema = createSchema({
|
|
85
|
+
id: {
|
|
86
|
+
type: "string",
|
|
87
|
+
required: true
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const resource = defineCrudResource({
|
|
92
|
+
namespace: "contacts",
|
|
93
|
+
tableName: "contacts",
|
|
94
|
+
schema: {
|
|
95
|
+
firstName: {
|
|
96
|
+
type: "string",
|
|
97
|
+
required: true,
|
|
98
|
+
operations: {
|
|
99
|
+
output: { required: true },
|
|
100
|
+
create: { required: true },
|
|
101
|
+
patch: { required: false }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
crud: {
|
|
106
|
+
output: recordOutputSchema
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export { resource };
|
|
111
|
+
`;
|
|
112
|
+
|
|
81
113
|
async function withTempApp(run) {
|
|
82
114
|
const appRoot = await mkdtemp(path.join(tmpdir(), "crud-server-scaffold-field-"));
|
|
83
115
|
try {
|
|
@@ -194,3 +226,21 @@ test("scaffold-field rejects resource modules without an inline schema object li
|
|
|
194
226
|
);
|
|
195
227
|
});
|
|
196
228
|
});
|
|
229
|
+
|
|
230
|
+
test("scaffold-field rejects defineCrudResource modules with explicit crud schema overrides", async () => {
|
|
231
|
+
await withTempApp(async (appRoot) => {
|
|
232
|
+
const resourceFile = "packages/contacts/src/shared/contactResource.js";
|
|
233
|
+
await writeAppFile(appRoot, resourceFile, EXPLICIT_CRUD_OVERRIDE_RESOURCE_SOURCE);
|
|
234
|
+
|
|
235
|
+
await assert.rejects(
|
|
236
|
+
() => runGeneratorSubcommand({
|
|
237
|
+
appRoot,
|
|
238
|
+
subcommand: "scaffold-field",
|
|
239
|
+
args: ["categoryId", resourceFile],
|
|
240
|
+
options: {},
|
|
241
|
+
resolveSnapshot: async () => createSnapshot()
|
|
242
|
+
}),
|
|
243
|
+
/cannot patch defineCrudResource\(\{ \.\.\., crud: \{ \.\.\. \} \}\) when explicit crud schema overrides are authored \(output\)\. Update schema and override validators manually\./
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
@@ -958,6 +958,7 @@ test("crud repository template defines a json-rest-api adapter over the injected
|
|
|
958
958
|
const templatePath = path.resolve(testDirectory, "..", "templates", "src", "local-package", "server", "repository.js");
|
|
959
959
|
const templateSource = await readFile(templatePath, "utf8");
|
|
960
960
|
assert.doesNotMatch(templateSource, /from "@jskit-ai\/http-runtime\/shared";/);
|
|
961
|
+
assert.match(templateSource, /const JSON_REST_SCOPE_NAME = __JSKIT_CRUD_JSONREST_SCOPE_NAME__;/);
|
|
961
962
|
assert.match(templateSource, /returnNullWhenJsonRestResourceMissing/);
|
|
962
963
|
assert.match(templateSource, /return api\.resources\.\$\{option:namespace\|camel\}\.query\(/);
|
|
963
964
|
assert.match(templateSource, /return returnNullWhenJsonRestResourceMissing\(\(\) =>\s+api\.resources\.\$\{option:namespace\|camel\}\.get\(/s);
|
|
@@ -965,8 +966,8 @@ test("crud repository template defines a json-rest-api adapter over the injected
|
|
|
965
966
|
assert.match(templateSource, /return returnNullWhenJsonRestResourceMissing\(\(\) =>\s+api\.resources\.\$\{option:namespace\|camel\}\.patch\(/s);
|
|
966
967
|
assert.match(templateSource, /return returnNullWhenJsonRestResourceMissing\(async \(\) => \{\s+await api\.resources\.\$\{option:namespace\|camel\}\.delete\(/s);
|
|
967
968
|
assert.match(templateSource, /createJsonRestContext\(options\?\.context \|\| null\)/);
|
|
968
|
-
assert.match(templateSource, /buildJsonRestQueryParams\(
|
|
969
|
-
assert.match(templateSource, /createJsonApiInputRecord\(
|
|
969
|
+
assert.match(templateSource, /buildJsonRestQueryParams\(JSON_REST_SCOPE_NAME, query\)/);
|
|
970
|
+
assert.match(templateSource, /createJsonApiInputRecord\(JSON_REST_SCOPE_NAME, payload/);
|
|
970
971
|
assert.doesNotMatch(templateSource, /function toJsonRestContext\(context = null\)/);
|
|
971
972
|
assert.doesNotMatch(templateSource, /function normalizeArrayInput\(value\)/);
|
|
972
973
|
assert.doesNotMatch(templateSource, /function buildJsonRestQueryParams\(query = \{\}/);
|
|
@@ -1039,6 +1040,9 @@ test("crud service template preserves JSON:API output and emits entity ids from
|
|
|
1039
1040
|
assert.match(templateSource, /returnJsonApiDocument\(await \$\{option:namespace\|camel\}Repository\.queryDocuments\(query, \{/);
|
|
1040
1041
|
assert.match(templateSource, /async function patchDocumentById\(recordId, payload = \{\}, options = \{\}\)/);
|
|
1041
1042
|
assert.match(templateSource, /returnJsonApiDocument\(return404IfNotFound\(await \$\{option:namespace\|camel\}Repository\.patchDocumentById\(recordId, payload, \{/);
|
|
1043
|
+
assert.match(templateSource, /async function deleteDocumentById\(recordId, options = \{\}\)/);
|
|
1044
|
+
assert.match(templateSource, /return \$\{option:namespace\|camel\}Repository\.deleteDocumentById\(recordId, \{/);
|
|
1045
|
+
assert.doesNotMatch(templateSource, /return404IfNotFound\(await \$\{option:namespace\|camel\}Repository\.deleteDocumentById/);
|
|
1042
1046
|
assert.match(templateSource, /return Object\.freeze\(\{/);
|
|
1043
1047
|
assert.match(templateSource, /export \{ createService \};/);
|
|
1044
1048
|
});
|
|
@@ -117,6 +117,50 @@ test("template createRepository builds mutable JSON:API input documents for writ
|
|
|
117
117
|
});
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
+
test("template createRepository returns null for successful deletes", async () => {
|
|
121
|
+
const calls = [];
|
|
122
|
+
const api = {
|
|
123
|
+
resources: {
|
|
124
|
+
customers: {
|
|
125
|
+
async delete(params, context) {
|
|
126
|
+
calls.push({ params, context });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const knex = {
|
|
132
|
+
async transaction(work) {
|
|
133
|
+
return work("trx");
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const repository = createRepository({ api, knex });
|
|
138
|
+
const result = await repository.deleteDocumentById("7", {
|
|
139
|
+
trx: "trx-1",
|
|
140
|
+
context: {
|
|
141
|
+
visibilityContext: {
|
|
142
|
+
visibility: "workspace",
|
|
143
|
+
scopeOwnerId: "7"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
assert.equal(result, null);
|
|
149
|
+
assert.deepEqual(calls[0], {
|
|
150
|
+
params: {
|
|
151
|
+
id: "7",
|
|
152
|
+
transaction: "trx-1",
|
|
153
|
+
simplified: false
|
|
154
|
+
},
|
|
155
|
+
context: {
|
|
156
|
+
visibilityContext: {
|
|
157
|
+
visibility: "workspace",
|
|
158
|
+
scopeOwnerId: "7"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
120
164
|
test("template createService turns missing resource records into 404 errors", async () => {
|
|
121
165
|
const service = createService({
|
|
122
166
|
customersRepository: {
|
|
@@ -139,6 +183,45 @@ test("template createService turns missing resource records into 404 errors", as
|
|
|
139
183
|
);
|
|
140
184
|
});
|
|
141
185
|
|
|
186
|
+
test("template createService returns delete results unchanged", async () => {
|
|
187
|
+
const service = createService({
|
|
188
|
+
customersRepository: {
|
|
189
|
+
async deleteDocumentById(recordId, options) {
|
|
190
|
+
return {
|
|
191
|
+
recordId,
|
|
192
|
+
options,
|
|
193
|
+
deleted: true
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
assert.deepEqual(
|
|
200
|
+
await service.deleteDocumentById("7", {
|
|
201
|
+
trx: "trx-1",
|
|
202
|
+
context: {
|
|
203
|
+
visibilityContext: {
|
|
204
|
+
visibility: "workspace",
|
|
205
|
+
scopeOwnerId: "7"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}),
|
|
209
|
+
{
|
|
210
|
+
recordId: "7",
|
|
211
|
+
options: {
|
|
212
|
+
trx: "trx-1",
|
|
213
|
+
context: {
|
|
214
|
+
visibilityContext: {
|
|
215
|
+
visibility: "workspace",
|
|
216
|
+
scopeOwnerId: "7"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
deleted: true
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
142
225
|
test("template createActions requires namespaced CRUD permissions by default", () => {
|
|
143
226
|
const actions = createActions({ surface: "admin" });
|
|
144
227
|
|
package/test/crudService.test.js
CHANGED
|
@@ -30,7 +30,7 @@ test("crudService exposes the explicit JSON:API CRUD service contract", async ()
|
|
|
30
30
|
},
|
|
31
31
|
async deleteDocumentById(recordId, options) {
|
|
32
32
|
calls.push(["deleteDocumentById", recordId, options]);
|
|
33
|
-
return
|
|
33
|
+
return null;
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
@@ -131,9 +131,42 @@ test("crudService throws 404 when a document is missing", async () => {
|
|
|
131
131
|
() => service.patchDocumentById(9, { textField: "Changed" }, {}),
|
|
132
132
|
(error) => error?.status === 404 && error?.message === "Document not found."
|
|
133
133
|
);
|
|
134
|
+
});
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
test("crudService returns delete results unchanged", async () => {
|
|
137
|
+
const service = createService({
|
|
138
|
+
customersRepository: {
|
|
139
|
+
async deleteDocumentById(recordId, options) {
|
|
140
|
+
return {
|
|
141
|
+
recordId,
|
|
142
|
+
options,
|
|
143
|
+
deleted: true
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const result = await service.deleteDocumentById(9, {
|
|
150
|
+
trx: "trx-1",
|
|
151
|
+
context: {
|
|
152
|
+
visibilityContext: {
|
|
153
|
+
visibility: "workspace",
|
|
154
|
+
scopeOwnerId: "7"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
assert.deepEqual(result, {
|
|
160
|
+
recordId: 9,
|
|
161
|
+
options: {
|
|
162
|
+
trx: "trx-1",
|
|
163
|
+
context: {
|
|
164
|
+
visibilityContext: {
|
|
165
|
+
visibility: "workspace",
|
|
166
|
+
scopeOwnerId: "7"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
deleted: true
|
|
171
|
+
});
|
|
139
172
|
});
|