@captiveorigins/payload-plugin-onephylogeny 0.1.0-alpha.3 → 0.1.0-alpha.4
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/README.md +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +9 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,3 +23,5 @@ It refuses, in plain words, a file whose text doesn't match its SHA-256, a file
|
|
|
23
23
|
|
|
24
24
|
`assignWaiting(payload, { evaluate })` is the sweep. It tests each waiting sequence against the panel for its marker and species, using the `evaluate` function you pass (OnePhylogeny's `testSample` in a Node job), and records a result pending review. A sequence with no panel stays waiting, and one the panel's checks refuse is marked `not-assessable`, with the reason. Results reach readers only after a reviewer approves them.
|
|
25
25
|
|
|
26
|
+
On a multi-site host, set `tenantField` if the site field isn't called `tenant`. A result, sample or sequence keeps the site it was made for, so nobody can move it to another site's readers.
|
|
27
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -127,6 +127,11 @@ type OnePhylogenyPluginOptions = {
|
|
|
127
127
|
* sequences. Left out, neither collection is added. Results then relate to these sequences.
|
|
128
128
|
*/
|
|
129
129
|
records?: RecordsOptions;
|
|
130
|
+
/**
|
|
131
|
+
* The host's tenant (site) field on results, if it has one, such as a multi-tenant plugin adds. A result's site is set
|
|
132
|
+
* when it is made and can't change, so a reviewer can't move it to a site whose people would then see it. Default `tenant`.
|
|
133
|
+
*/
|
|
134
|
+
tenantField?: string;
|
|
130
135
|
};
|
|
131
136
|
|
|
132
137
|
/**
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ function recordCollections(o, base) {
|
|
|
33
33
|
const manage = base.manage;
|
|
34
34
|
const read = anyOf(manage, o.readAccess);
|
|
35
35
|
const access = { read, create: manage, update: manage, delete: () => false };
|
|
36
|
+
const tenantField = o.tenantField ?? "tenant";
|
|
36
37
|
const sampleCollection = {
|
|
37
38
|
slug: samples,
|
|
38
39
|
labels: { singular: "Sample", plural: "Samples" },
|
|
@@ -47,7 +48,7 @@ function recordCollections(o, base) {
|
|
|
47
48
|
{ name: "collectedAt", type: "date" },
|
|
48
49
|
{ name: "consent", type: "text", admin: { description: "The keeper's consent, as recorded with the kit or upload." } }
|
|
49
50
|
],
|
|
50
|
-
hooks: { beforeChange: [locked(["subject", "kit", "source"], "A sample's animal, kit and
|
|
51
|
+
hooks: { beforeChange: [locked(["subject", "kit", "source", tenantField], "A sample's animal, kit, source and site can't change. Record a new sample instead.")] }
|
|
51
52
|
};
|
|
52
53
|
const sequenceCollection = {
|
|
53
54
|
slug: sequences,
|
|
@@ -66,14 +67,14 @@ function recordCollections(o, base) {
|
|
|
66
67
|
{ name: "status", type: "select", required: true, defaultValue: "received", index: true, options: ["received", "assigned", "not-assessable"] },
|
|
67
68
|
{ name: "statusReason", type: "text", admin: { description: "Why it couldn't be assessed, in plain words." } }
|
|
68
69
|
],
|
|
69
|
-
hooks: { beforeChange: [locked(["sample", "marker", "file", "sha256", "residues", "recordId", "length"], "A sequence can't be edited. Register the corrected file instead.")] }
|
|
70
|
+
hooks: { beforeChange: [locked(["sample", "marker", "file", "sha256", "residues", "recordId", "length", tenantField], "A sequence can't be edited. Register the corrected file instead.")] }
|
|
70
71
|
};
|
|
71
72
|
const config = {
|
|
72
73
|
samples,
|
|
73
74
|
sequences,
|
|
74
75
|
panels: base.panels,
|
|
75
76
|
assignments: base.assignments,
|
|
76
|
-
tenantField
|
|
77
|
+
tenantField,
|
|
77
78
|
markers: o.markers,
|
|
78
79
|
subject: base.subject,
|
|
79
80
|
hasTaxa: Boolean(base.taxa),
|
|
@@ -269,7 +270,7 @@ var supersedeOthers = (panels) => async ({ doc, previousDoc, req }) => {
|
|
|
269
270
|
for (const other of others.docs) await req.payload.update({ collection: panels, id: other.id, data: { status: "superseded" }, req, overrideAccess: true });
|
|
270
271
|
return doc;
|
|
271
272
|
};
|
|
272
|
-
var assignmentBeforeChange = (panels, againstShown) => async ({ data, originalDoc, operation, req }) => {
|
|
273
|
+
var assignmentBeforeChange = (panels, againstShown, tenantField) => async ({ data, originalDoc, operation, req }) => {
|
|
273
274
|
if (operation === "create") {
|
|
274
275
|
if ((data.reviewStatus ?? "pending") !== "pending") fail2("A new result starts as pending review.");
|
|
275
276
|
const panel = await req.payload.findByID({ collection: panels, id: idOf2(data.panel), depth: 0, req, overrideAccess: true });
|
|
@@ -292,6 +293,7 @@ var assignmentBeforeChange = (panels, againstShown) => async ({ data, originalDo
|
|
|
292
293
|
for (const f of ["result", "panel", "sequence", "subject", "summary", "importRun"]) {
|
|
293
294
|
if (f in data && (f === "result" || f === "summary" ? !same(data[f], originalDoc[f]) : idOf2(data[f]) !== idOf2(originalDoc[f]))) fail2("A result can't be edited. Make a new one instead.");
|
|
294
295
|
}
|
|
296
|
+
if (tenantField in data && idOf2(data[tenantField]) !== idOf2(originalDoc[tenantField])) fail2("A result stays on the site it was made for.");
|
|
295
297
|
for (const f of ["panelStatus", "panelShownAsExploratory"]) {
|
|
296
298
|
if (f in data && !same(data[f], originalDoc[f])) fail2("The panel status a result was made against is set when it is made.");
|
|
297
299
|
}
|
|
@@ -313,7 +315,8 @@ var checkedWhenMade = { validate: (value, options) => options.operation === "upd
|
|
|
313
315
|
var onePhylogeny = (options = {}) => (config) => {
|
|
314
316
|
const panels = options.slugs?.panels ?? "panels";
|
|
315
317
|
const assignments = options.slugs?.assignments ?? "assignments";
|
|
316
|
-
const
|
|
318
|
+
const tenantField = options.tenantField ?? options.records?.tenantField ?? "tenant";
|
|
319
|
+
const records = options.records ? recordCollections({ tenantField, ...options.records }, { panels, assignments, subject: options.relations?.subject, taxa: options.relations?.taxa, files: options.relations?.files, manage: options.manageAccess ?? (() => false), againstShown: options.resultsAgainst === "activeOrShown" }) : void 0;
|
|
317
320
|
const r = { ...options.relations, ...records && !options.relations?.sequence ? { sequence: records.config.sequences } : {} };
|
|
318
321
|
const group = options.group ?? "Genetics";
|
|
319
322
|
const manage = options.manageAccess ?? (() => false);
|
|
@@ -380,7 +383,7 @@ var onePhylogeny = (options = {}) => (config) => {
|
|
|
380
383
|
{ name: "panelStatus", type: "text", admin: { readOnly: true, description: "The panel's status when this result was made." } },
|
|
381
384
|
{ name: "panelShownAsExploratory", type: "checkbox", admin: { readOnly: true } }
|
|
382
385
|
],
|
|
383
|
-
hooks: { beforeChange: [assignmentBeforeChange(panels, againstShown)] }
|
|
386
|
+
hooks: { beforeChange: [assignmentBeforeChange(panels, againstShown, tenantField)] }
|
|
384
387
|
};
|
|
385
388
|
const released = {
|
|
386
389
|
path: "/onephylogeny/released",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@captiveorigins/payload-plugin-onephylogeny",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"description": "OnePhylogeny for Payload: immutable reference panels and released results on your own collections, with server-enforced review, safe endpoints and no coordinates.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"phylogenetics",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=22"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@captiveorigins/onephylogeny-core": "^0.1.0-alpha.
|
|
38
|
+
"@captiveorigins/onephylogeny-core": "^0.1.0-alpha.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"payload": "^3.80.0"
|