@choiceapps/communityservices-sdk 0.6.0 → 0.8.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/CHANGELOG.md +17 -0
- package/browser/enrollment-workflow.d.mts +29 -5
- package/browser/enrollment-workflow.mjs +88 -34
- package/browser/entry-correction.mjs +13 -11
- package/browser/entry-row-registration.mjs +63 -0
- package/browser/household-enrollment-discovery.mjs +49 -0
- package/browser/index.d.mts +7 -2
- package/browser/index.mjs +1 -1
- package/browser/playwright-session.mjs +24 -8
- package/browser/workflow-error-codes.mjs +198 -0
- package/dist/cjs/mobile-preflight.d.ts +19 -0
- package/dist/cjs/mobile-preflight.d.ts.map +1 -0
- package/dist/cjs/mobile-preflight.js +75 -0
- package/dist/cjs/mobile-preflight.js.map +1 -0
- package/dist/cjs/picklist-labels.d.ts +22 -0
- package/dist/cjs/picklist-labels.d.ts.map +1 -0
- package/dist/cjs/picklist-labels.js +35 -0
- package/dist/cjs/picklist-labels.js.map +1 -0
- package/dist/cjs/v2.d.ts +4 -0
- package/dist/cjs/v2.d.ts.map +1 -1
- package/dist/cjs/v2.js +5 -0
- package/dist/cjs/v2.js.map +1 -1
- package/dist/cjs/v3.d.ts +4 -0
- package/dist/cjs/v3.d.ts.map +1 -1
- package/dist/cjs/v3.js +5 -0
- package/dist/cjs/v3.js.map +1 -1
- package/dist/cjs/write-labels.d.ts +13 -0
- package/dist/cjs/write-labels.d.ts.map +1 -0
- package/dist/cjs/write-labels.js +68 -0
- package/dist/cjs/write-labels.js.map +1 -0
- package/dist/esm/mobile-preflight.d.ts +19 -0
- package/dist/esm/mobile-preflight.d.ts.map +1 -0
- package/dist/esm/mobile-preflight.js +70 -0
- package/dist/esm/mobile-preflight.js.map +1 -0
- package/dist/esm/picklist-labels.d.ts +22 -0
- package/dist/esm/picklist-labels.d.ts.map +1 -0
- package/dist/esm/picklist-labels.js +32 -0
- package/dist/esm/picklist-labels.js.map +1 -0
- package/dist/esm/v2.d.ts +4 -0
- package/dist/esm/v2.d.ts.map +1 -1
- package/dist/esm/v2.js +3 -0
- package/dist/esm/v2.js.map +1 -1
- package/dist/esm/v3.d.ts +4 -0
- package/dist/esm/v3.d.ts.map +1 -1
- package/dist/esm/v3.js +3 -0
- package/dist/esm/v3.js.map +1 -1
- package/dist/esm/write-labels.d.ts +13 -0
- package/dist/esm/write-labels.d.ts.map +1 -0
- package/dist/esm/write-labels.js +65 -0
- package/dist/esm/write-labels.js.map +1 -0
- package/docs/assessments.md +50 -1
- package/docs/capabilities.md +19 -0
- package/docs/enrollments.md +41 -5
- package/docs/reference.md +3 -2
- package/docs/troubleshooting.md +17 -0
- package/docs/vendor-issues/lookup-write-labels.md +13 -0
- package/examples/README.md +3 -0
- package/examples/catalog-write-labels.mts +15 -0
- package/examples/checked-assessment-writes.mts +14 -0
- package/examples/enrollment-discovery-and-correction.mts +19 -0
- package/package.json +1 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCatalogWriteLabelResolver = createCatalogWriteLabelResolver;
|
|
4
|
+
const metadata_js_1 = require("./metadata.js");
|
|
5
|
+
const errors_js_1 = require("./errors.js");
|
|
6
|
+
/** Exact catalog names joined by identity, without reading any stored answer.
|
|
7
|
+
* Only choices present in the supplied assessment definition can resolve. */
|
|
8
|
+
function createCatalogWriteLabelResolver(definition, catalog) {
|
|
9
|
+
const fail = () => { throw new errors_js_1.ValidationError('incomplete or mismatched picklist label catalog'); };
|
|
10
|
+
if (catalog?.source !== 'gwt-rpc' || catalog.tenant !== definition.tenant || !Number.isSafeInteger(catalog.clientId) || catalog.clientId <= 0 || !Array.isArray(catalog.values) || catalog.count !== catalog.values.length)
|
|
11
|
+
fail();
|
|
12
|
+
const rows = new Map();
|
|
13
|
+
for (const row of catalog.values) {
|
|
14
|
+
if (!row || !Number.isSafeInteger(row.optionId) || row.optionId <= 0 || !Number.isSafeInteger(row.picklistId) || row.picklistId <= 0 || row.code !== null && typeof row.code !== 'string' || typeof row.name !== 'string' || !row.name.trim() || rows.has(row.optionId))
|
|
15
|
+
fail();
|
|
16
|
+
rows.set(row.optionId, { ...row });
|
|
17
|
+
}
|
|
18
|
+
const signature = (q, o) => JSON.stringify([q.questionId, q.fieldName, q.questionType, o.id, o.picklistId, o.code, o.picklistCode, o.name, o.hudVisibility]);
|
|
19
|
+
const labels = new Map();
|
|
20
|
+
for (const { question } of (0, metadata_js_1.flattenQuestions)(definition.questions)) {
|
|
21
|
+
if (question.questionType !== 'lookup')
|
|
22
|
+
continue;
|
|
23
|
+
for (const option of question.options) {
|
|
24
|
+
const row = rows.get(option.id);
|
|
25
|
+
if (!row || row.picklistId !== option.picklistId || row.code !== option.code) {
|
|
26
|
+
fail();
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
labels.set(signature(question, option), row.name);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const resolver = (question, option) => labels.get(signature(question, option));
|
|
33
|
+
return Object.freeze(Object.assign(resolver, { tenant: definition.tenant }));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=picklist-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picklist-labels.js","sourceRoot":"","sources":["../../src/picklist-labels.ts"],"names":[],"mappings":"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","sourcesContent":["import type {AssessmentDefinition,PicklistOption,QuestionDefinition} from './metadata.js';\nimport {flattenQuestions} from './metadata.js';\nimport type {EncodingOptions} from './encoding.js';\nimport {ValidationError} from './errors.js';\n\nexport interface PicklistCatalogOption {optionId:number;picklistId:number;code:string|null;name:string;}\nexport interface PicklistCatalogSnapshot {source:'gwt-rpc';tenant:string;clientId:number;count:number;values:PicklistCatalogOption[];}\nexport type CatalogWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {readonly tenant:string};\n\n/** Exact catalog names joined by identity, without reading any stored answer.\n * Only choices present in the supplied assessment definition can resolve. */\nexport function createCatalogWriteLabelResolver(definition:AssessmentDefinition,catalog:PicklistCatalogSnapshot):CatalogWriteLabelResolver{\n const fail=()=>{throw new ValidationError('incomplete or mismatched picklist label catalog');};\n if(catalog?.source!=='gwt-rpc'||catalog.tenant!==definition.tenant||!Number.isSafeInteger(catalog.clientId)||catalog.clientId<=0||!Array.isArray(catalog.values)||catalog.count!==catalog.values.length)fail();\n const rows=new Map<number,PicklistCatalogOption>();\n for(const row of catalog.values){\n if(!row||!Number.isSafeInteger(row.optionId)||row.optionId<=0||!Number.isSafeInteger(row.picklistId)||row.picklistId<=0||row.code!==null&&typeof row.code!=='string'||typeof row.name!=='string'||!row.name.trim()||rows.has(row.optionId))fail();\n rows.set(row.optionId,{...row});\n }\n const signature=(q:QuestionDefinition,o:PicklistOption)=>JSON.stringify([q.questionId,q.fieldName,q.questionType,o.id,o.picklistId,o.code,o.picklistCode,o.name,o.hudVisibility]);\n const labels=new Map<string,string>();\n for(const {question}of flattenQuestions(definition.questions)){\n if(question.questionType!=='lookup')continue;\n for(const option of question.options){\n const row=rows.get(option.id);\n if(!row||row.picklistId!==option.picklistId||row.code!==option.code){fail();continue;}\n labels.set(signature(question,option),row.name);\n }\n }\n const resolver=(question:QuestionDefinition,option:PicklistOption)=>labels.get(signature(question,option));\n return Object.freeze(Object.assign(resolver,{tenant:definition.tenant}));\n}\n"]}
|
package/dist/cjs/v2.d.ts
CHANGED
|
@@ -10,4 +10,8 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
17
|
//# sourceMappingURL=v2.d.ts.map
|
package/dist/cjs/v2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAC,qBAAqB,EAAC,uBAAuB,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/cjs/v2.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createCatalogWriteLabelResolver = void 0;
|
|
17
18
|
__exportStar(require("./generated/v2.js"), exports);
|
|
18
19
|
__exportStar(require("./generated/v2-models.js"), exports);
|
|
19
20
|
__exportStar(require("./runtime.js"), exports);
|
|
@@ -26,4 +27,8 @@ __exportStar(require("./subassessments.js"), exports);
|
|
|
26
27
|
__exportStar(require("./enrollment-verifications.js"), exports);
|
|
27
28
|
__exportStar(require("./gwt-enrollments.js"), exports);
|
|
28
29
|
__exportStar(require("./program-discovery.js"), exports);
|
|
30
|
+
__exportStar(require("./mobile-preflight.js"), exports);
|
|
31
|
+
__exportStar(require("./write-labels.js"), exports);
|
|
32
|
+
var picklist_labels_js_1 = require("./picklist-labels.js");
|
|
33
|
+
Object.defineProperty(exports, "createCatalogWriteLabelResolver", { enumerable: true, get: function () { return picklist_labels_js_1.createCatalogWriteLabelResolver; } });
|
|
29
34
|
//# sourceMappingURL=v2.js.map
|
package/dist/cjs/v2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,2DAAyC;AACzC,+CAA6B;AAC7B,gDAA8B;AAC9B,8CAA4B;AAC5B,gDAA8B;AAC9B,oDAAkC;AAClC,4CAA0B;AAC1B,sDAAoC;AACpC,gEAA8C;AAE9C,uDAAqC;AACrC,yDAAuC;AACvC,wDAAsC;AACtC,oDAAkC;AAElC,2DAAqE;AAA7D,qIAAA,+BAA+B,OAAA","sourcesContent":["export * from \"./generated/v2.js\";\nexport * from \"./generated/v2-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\nexport * from \"./mobile-preflight.js\";\nexport * from \"./write-labels.js\";\n\nexport {createCatalogWriteLabelResolver} from './picklist-labels.js';\nexport type {PicklistCatalogOption,PicklistCatalogSnapshot,CatalogWriteLabelResolver} from './picklist-labels.js';\n"]}
|
package/dist/cjs/v3.d.ts
CHANGED
|
@@ -10,4 +10,8 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
17
|
//# sourceMappingURL=v3.d.ts.map
|
package/dist/cjs/v3.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAC,qBAAqB,EAAC,uBAAuB,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/cjs/v3.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createCatalogWriteLabelResolver = void 0;
|
|
17
18
|
__exportStar(require("./generated/v3.js"), exports);
|
|
18
19
|
__exportStar(require("./generated/v3-models.js"), exports);
|
|
19
20
|
__exportStar(require("./runtime.js"), exports);
|
|
@@ -26,4 +27,8 @@ __exportStar(require("./subassessments.js"), exports);
|
|
|
26
27
|
__exportStar(require("./enrollment-verifications.js"), exports);
|
|
27
28
|
__exportStar(require("./gwt-enrollments.js"), exports);
|
|
28
29
|
__exportStar(require("./program-discovery.js"), exports);
|
|
30
|
+
__exportStar(require("./mobile-preflight.js"), exports);
|
|
31
|
+
__exportStar(require("./write-labels.js"), exports);
|
|
32
|
+
var picklist_labels_js_1 = require("./picklist-labels.js");
|
|
33
|
+
Object.defineProperty(exports, "createCatalogWriteLabelResolver", { enumerable: true, get: function () { return picklist_labels_js_1.createCatalogWriteLabelResolver; } });
|
|
29
34
|
//# sourceMappingURL=v3.js.map
|
package/dist/cjs/v3.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.js","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"v3.js","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,2DAAyC;AACzC,+CAA6B;AAC7B,gDAA8B;AAC9B,8CAA4B;AAC5B,gDAA8B;AAC9B,oDAAkC;AAClC,4CAA0B;AAC1B,sDAAoC;AACpC,gEAA8C;AAE9C,uDAAqC;AACrC,yDAAuC;AACvC,wDAAsC;AACtC,oDAAkC;AAElC,2DAAqE;AAA7D,qIAAA,+BAA+B,OAAA","sourcesContent":["export * from \"./generated/v3.js\";\nexport * from \"./generated/v3-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\nexport * from \"./mobile-preflight.js\";\nexport * from \"./write-labels.js\";\n\nexport {createCatalogWriteLabelResolver} from './picklist-labels.js';\nexport type {PicklistCatalogOption,PicklistCatalogSnapshot,CatalogWriteLabelResolver} from './picklist-labels.js';\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AssessmentDefinition } from './metadata.js';
|
|
2
|
+
import type { EncodingOptions } from './encoding.js';
|
|
3
|
+
export interface WriteLabelObservation {
|
|
4
|
+
tenant: string;
|
|
5
|
+
response: unknown;
|
|
6
|
+
}
|
|
7
|
+
export type ReadBackWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {
|
|
8
|
+
readonly tenant: string;
|
|
9
|
+
};
|
|
10
|
+
/** Builds labels only from exact readback evidence. It never infers HUD suffixes.
|
|
11
|
+
* Unobserved or changed options return undefined, so the standard encoder refuses them. */
|
|
12
|
+
export declare function createReadBackWriteLabelResolver(definition: AssessmentDefinition, observations: readonly WriteLabelObservation[]): ReadBackWriteLabelResolver;
|
|
13
|
+
//# sourceMappingURL=write-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-labels.d.ts","sourceRoot":"","sources":["../../src/write-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,oBAAoB,EAAmC,MAAM,eAAe,CAAC;AAE1F,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAInD,MAAM,WAAW,qBAAqB;IAAE,MAAM,EAAC,MAAM,CAAC;IAAA,QAAQ,EAAC,OAAO,CAAC;CAAC;AACxE,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,GAAG;IAAC,QAAQ,CAAC,MAAM,EAAC,MAAM,CAAA;CAAC,CAAC;AAE/G;2FAC2F;AAC3F,wBAAgB,gCAAgC,CAC/C,UAAU,EAAC,oBAAoB,EAC/B,YAAY,EAAC,SAAS,qBAAqB,EAAE,GAC5C,0BAA0B,CA2C3B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createReadBackWriteLabelResolver = createReadBackWriteLabelResolver;
|
|
4
|
+
const metadata_js_1 = require("./metadata.js");
|
|
5
|
+
const errors_js_1 = require("./errors.js");
|
|
6
|
+
const validation_js_1 = require("./validation.js");
|
|
7
|
+
/** Builds labels only from exact readback evidence. It never infers HUD suffixes.
|
|
8
|
+
* Unobserved or changed options return undefined, so the standard encoder refuses them. */
|
|
9
|
+
function createReadBackWriteLabelResolver(definition, observations) {
|
|
10
|
+
const questions = new Map();
|
|
11
|
+
for (const { question } of (0, metadata_js_1.flattenQuestions)(definition.questions)) {
|
|
12
|
+
if (question.questionType !== 'lookup')
|
|
13
|
+
continue;
|
|
14
|
+
const prior = questions.get(question.questionId);
|
|
15
|
+
if (prior && JSON.stringify(prior) !== JSON.stringify(question))
|
|
16
|
+
throw new errors_js_1.ValidationError('ambiguous write-label question');
|
|
17
|
+
questions.set(question.questionId, structuredClone(question));
|
|
18
|
+
}
|
|
19
|
+
const labels = new Map();
|
|
20
|
+
const identity = (questionId, optionId) => JSON.stringify([questionId, optionId]);
|
|
21
|
+
const visit = (value, depth = 0) => {
|
|
22
|
+
if (depth > 40)
|
|
23
|
+
throw new errors_js_1.ValidationError('write-label observation exceeds nesting limit');
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
for (const child of value)
|
|
26
|
+
visit(child, depth + 1);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!(0, validation_js_1.isRecord)(value))
|
|
30
|
+
return;
|
|
31
|
+
if (value.question_type === 'lookup' && typeof value.question_id === 'number') {
|
|
32
|
+
const question = questions.get(value.question_id);
|
|
33
|
+
if (question) {
|
|
34
|
+
if (value.virt_field_name !== question.fieldName)
|
|
35
|
+
throw new errors_js_1.ValidationError('write-label question identity mismatch');
|
|
36
|
+
const raw = value.answer_value;
|
|
37
|
+
const id = typeof raw === 'number' ? raw : typeof raw === 'string' && /^\d+$/.test(raw) ? Number(raw) : null;
|
|
38
|
+
if (id !== null && Number.isSafeInteger(id) && typeof value.answer_value_text === 'string' && value.answer_value_text.trim()) {
|
|
39
|
+
const options = question.options.filter(option => option.id === id);
|
|
40
|
+
if (options.length !== 1)
|
|
41
|
+
throw new errors_js_1.ValidationError('write-label option identity mismatch', [question.fieldName ?? String(question.questionId)]);
|
|
42
|
+
const key = identity(question.questionId, id), prior = labels.get(key);
|
|
43
|
+
if (prior !== undefined && prior !== value.answer_value_text)
|
|
44
|
+
throw new errors_js_1.ValidationError('conflicting write-label observations', [question.fieldName ?? String(question.questionId)]);
|
|
45
|
+
labels.set(key, value.answer_value_text);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Traverse known response/assessment containers only. Do not interpret arbitrary strings as data.
|
|
50
|
+
for (const key of ['value', 'values', 'sub_assessment_question_list', 'sub_assessment_answer_list', 'sub_assessment_list'])
|
|
51
|
+
if (value[key] !== undefined)
|
|
52
|
+
visit(value[key], depth + 1);
|
|
53
|
+
};
|
|
54
|
+
for (const observation of observations) {
|
|
55
|
+
if (observation.tenant !== definition.tenant)
|
|
56
|
+
throw new errors_js_1.ValidationError('write-label observation tenant mismatch');
|
|
57
|
+
visit(observation.response);
|
|
58
|
+
}
|
|
59
|
+
const sameOption = (a, b) => a.id === b.id && a.picklistId === b.picklistId && a.code === b.code && a.picklistCode === b.picklistCode && a.name === b.name && a.hudVisibility === b.hudVisibility;
|
|
60
|
+
const resolver = (question, option) => {
|
|
61
|
+
const known = questions.get(question.questionId);
|
|
62
|
+
if (!known || known.fieldName !== question.fieldName || question.questionType !== 'lookup' || !known.options.some(o => sameOption(o, option)))
|
|
63
|
+
return undefined;
|
|
64
|
+
return labels.get(identity(question.questionId, option.id));
|
|
65
|
+
};
|
|
66
|
+
return Object.freeze(Object.assign(resolver, { tenant: definition.tenant }));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=write-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-labels.js","sourceRoot":"","sources":["../../src/write-labels.ts"],"names":[],"mappings":"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","sourcesContent":["import type {AssessmentDefinition,PicklistOption,QuestionDefinition} from './metadata.js';\nimport {flattenQuestions} from './metadata.js';\nimport type {EncodingOptions} from './encoding.js';\nimport {ValidationError} from './errors.js';\nimport {isRecord} from './validation.js';\n\nexport interface WriteLabelObservation {tenant:string;response:unknown;}\nexport type ReadBackWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {readonly tenant:string};\n\n/** Builds labels only from exact readback evidence. It never infers HUD suffixes.\n * Unobserved or changed options return undefined, so the standard encoder refuses them. */\nexport function createReadBackWriteLabelResolver(\n definition:AssessmentDefinition,\n observations:readonly WriteLabelObservation[],\n):ReadBackWriteLabelResolver{\n const questions=new Map<number,QuestionDefinition>();\n for(const {question} of flattenQuestions(definition.questions)){\n if(question.questionType!=='lookup')continue;\n const prior=questions.get(question.questionId);\n if(prior&&JSON.stringify(prior)!==JSON.stringify(question))throw new ValidationError('ambiguous write-label question');\n questions.set(question.questionId,structuredClone(question));\n }\n const labels=new Map<string,string>();\n const identity=(questionId:number,optionId:number)=>JSON.stringify([questionId,optionId]);\n const visit=(value:unknown,depth=0):void=>{\n if(depth>40)throw new ValidationError('write-label observation exceeds nesting limit');\n if(Array.isArray(value)){for(const child of value)visit(child,depth+1);return;}\n if(!isRecord(value))return;\n if(value.question_type==='lookup'&&typeof value.question_id==='number'){\n const question=questions.get(value.question_id);\n if(question){\n if(value.virt_field_name!==question.fieldName)throw new ValidationError('write-label question identity mismatch');\n const raw=value.answer_value;\n const id=typeof raw==='number'?raw:typeof raw==='string'&&/^\\d+$/.test(raw)?Number(raw):null;\n if(id!==null&&Number.isSafeInteger(id)&&typeof value.answer_value_text==='string'&&value.answer_value_text.trim()){\n const options=question.options.filter(option=>option.id===id);\n if(options.length!==1)throw new ValidationError('write-label option identity mismatch',[question.fieldName??String(question.questionId)]);\n const key=identity(question.questionId,id),prior=labels.get(key);\n if(prior!==undefined&&prior!==value.answer_value_text)throw new ValidationError('conflicting write-label observations',[question.fieldName??String(question.questionId)]);\n labels.set(key,value.answer_value_text);\n }\n }\n }\n // Traverse known response/assessment containers only. Do not interpret arbitrary strings as data.\n for(const key of ['value','values','sub_assessment_question_list','sub_assessment_answer_list','sub_assessment_list'])if(value[key]!==undefined)visit(value[key],depth+1);\n };\n for(const observation of observations){\n if(observation.tenant!==definition.tenant)throw new ValidationError('write-label observation tenant mismatch');\n visit(observation.response);\n }\n const sameOption=(a:PicklistOption,b:PicklistOption)=>a.id===b.id&&a.picklistId===b.picklistId&&a.code===b.code&&a.picklistCode===b.picklistCode&&a.name===b.name&&a.hudVisibility===b.hudVisibility;\n const resolver=(question:QuestionDefinition,option:PicklistOption)=>{\n const known=questions.get(question.questionId);\n if(!known||known.fieldName!==question.fieldName||question.questionType!=='lookup'||!known.options.some(o=>sameOption(o,option)))return undefined;\n return labels.get(identity(question.questionId,option.id));\n };\n return Object.freeze(Object.assign(resolver,{tenant:definition.tenant}));\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { WellSkyClient } from './generated/v3.js';
|
|
2
|
+
import { ValidationError } from './errors.js';
|
|
3
|
+
type RawMobileWrite = Parameters<WellSkyClient['assessmentsMobile']['addAnswer']>[0];
|
|
4
|
+
export type CheckedMobileWriteOptions = Omit<RawMobileWrite, 'query'> & {
|
|
5
|
+
query: {
|
|
6
|
+
dateEffective: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type MobilePreflightCode = 'MOBILE_PREFLIGHT_INPUT_INVALID' | 'MOBILE_PREFLIGHT_READ_FAILED' | 'MOBILE_PREFLIGHT_UNAVAILABLE' | 'MOBILE_ANSWER_EXISTS' | 'MOBILE_PREFLIGHT_CANCELLED';
|
|
10
|
+
export declare class MobileAnswerPreflightError extends ValidationError {
|
|
11
|
+
readonly code: MobilePreflightCode;
|
|
12
|
+
readonly committed = false;
|
|
13
|
+
constructor(code: MobilePreflightCode, fields?: readonly string[], cause?: unknown);
|
|
14
|
+
}
|
|
15
|
+
/** Read-before-write protection for scalar inserts, including questions shared by instruments.
|
|
16
|
+
* Does not journal, retry writes, or make the read/write pair atomic. */
|
|
17
|
+
export declare function writeMobileAnswersChecked(api: Pick<WellSkyClient, 'assessments' | 'assessmentsMobile'>, options: CheckedMobileWriteOptions): ReturnType<WellSkyClient['assessmentsMobile']['addAnswer']>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=mobile-preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-preflight.d.ts","sourceRoot":"","sources":["../../src/mobile-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAY,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAC;AAK5C,KAAK,cAAc,GAAG,UAAU,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,cAAc,EAAC,OAAO,CAAC,GAAG;IAAC,KAAK,EAAC;QAAC,aAAa,EAAC,MAAM,CAAA;KAAC,CAAA;CAAC,CAAC;AACtG,MAAM,MAAM,mBAAmB,GAAG,gCAAgC,GAAC,8BAA8B,GAAC,8BAA8B,GAAC,sBAAsB,GAAC,4BAA4B,CAAC;AACrL,qBAAa,0BAA2B,SAAQ,eAAe;IAElD,QAAQ,CAAC,IAAI,EAAC,mBAAmB;IAD7C,QAAQ,CAAC,SAAS,SAAO;gBACJ,IAAI,EAAC,mBAAmB,EAAC,MAAM,GAAC,SAAS,MAAM,EAAK,EAAC,KAAK,CAAC,EAAC,OAAO;CAIxF;AAED;yEACyE;AACzE,wBAAsB,yBAAyB,CAC9C,GAAG,EAAC,IAAI,CAAC,aAAa,EAAC,aAAa,GAAC,mBAAmB,CAAC,EACzD,OAAO,EAAC,yBAAyB,GAChC,UAAU,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,WAAW,CAAC,CAAC,CAkC5D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ValidationError } from './errors.js';
|
|
2
|
+
import { parseRestInstant } from './encoding.js';
|
|
3
|
+
import { toItems } from './runtime.js';
|
|
4
|
+
import { isRecord } from './validation.js';
|
|
5
|
+
export class MobileAnswerPreflightError extends ValidationError {
|
|
6
|
+
code;
|
|
7
|
+
committed = false;
|
|
8
|
+
constructor(code, fields = [], cause) {
|
|
9
|
+
super('mobile assessment preflight', fields);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.name = 'MobileAnswerPreflightError';
|
|
12
|
+
if (cause !== undefined)
|
|
13
|
+
Object.defineProperty(this, 'cause', { value: cause, enumerable: false });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Read-before-write protection for scalar inserts, including questions shared by instruments.
|
|
17
|
+
* Does not journal, retry writes, or make the read/write pair atomic. */
|
|
18
|
+
export async function writeMobileAnswersChecked(api, options) {
|
|
19
|
+
function fail(code, fields = [], cause) { throw new MobileAnswerPreflightError(code, fields, cause); }
|
|
20
|
+
const checkSignal = () => { if (options.signal?.aborted)
|
|
21
|
+
fail('MOBILE_PREFLIGHT_CANCELLED', [], options.signal.reason); };
|
|
22
|
+
if (!options?.path || !Number.isSafeInteger(options.path.clientId) || options.path.clientId <= 0 || typeof options.path.assessmentCode !== 'string' || !options.path.assessmentCode.trim() || !Array.isArray(options.body) || !options.body.length || typeof options.query?.dateEffective !== 'string')
|
|
23
|
+
fail('MOBILE_PREFLIGHT_INPUT_INVALID');
|
|
24
|
+
const instant = options.query.dateEffective;
|
|
25
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.000)?(?:Z|[+-]\d{2}:\d{2})$/.test(instant) || !Number.isFinite(parseRestInstant(instant)) || new Date(instant.slice(0, 19) + 'Z').toISOString().slice(0, 19) !== instant.slice(0, 19))
|
|
26
|
+
fail('MOBILE_PREFLIGHT_INPUT_INVALID', ['dateEffective']);
|
|
27
|
+
checkSignal();
|
|
28
|
+
const captured = { ...options, path: { ...options.path }, query: { ...options.query }, body: structuredClone(options.body) };
|
|
29
|
+
const scalars = [], seen = new Set(), ids = new Set();
|
|
30
|
+
for (const q of captured.body) {
|
|
31
|
+
if (!isRecord(q) || typeof q.question_type !== 'string' || typeof q.virt_field_name !== 'string' || !q.virt_field_name || typeof q.question_id !== 'number' || !Number.isSafeInteger(q.question_id) || q.question_id <= 0 || seen.has(q.virt_field_name) || ids.has(q.question_id))
|
|
32
|
+
fail('MOBILE_PREFLIGHT_INPUT_INVALID');
|
|
33
|
+
seen.add(q.virt_field_name);
|
|
34
|
+
ids.add(q.question_id);
|
|
35
|
+
if (q.question_type !== 'sub_assessment')
|
|
36
|
+
scalars.push({ id: q.question_id, field: q.virt_field_name, type: q.question_type });
|
|
37
|
+
}
|
|
38
|
+
if (scalars.length) {
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
response = await api.assessments.get({ path: captured.path, query: { dateEffective: new Date(parseRestInstant(instant) + 1000).toISOString() }, ...(options.signal ? { signal: options.signal } : {}), ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }), ...(options.correlationId === undefined ? {} : { correlationId: options.correlationId }) });
|
|
42
|
+
}
|
|
43
|
+
catch (cause) {
|
|
44
|
+
fail('MOBILE_PREFLIGHT_READ_FAILED', scalars.map(q => q.field), cause);
|
|
45
|
+
}
|
|
46
|
+
const rows = toItems(response), conflicts = [];
|
|
47
|
+
for (const q of scalars) {
|
|
48
|
+
const found = rows.filter(r => r.virt_field_name === q.field);
|
|
49
|
+
if (found.length !== 1 || found[0]?.question_id !== q.id || found[0]?.question_type !== q.type)
|
|
50
|
+
fail('MOBILE_PREFLIGHT_UNAVAILABLE', [q.field]);
|
|
51
|
+
const row = found[0];
|
|
52
|
+
if (!row)
|
|
53
|
+
fail('MOBILE_PREFLIGHT_UNAVAILABLE', [q.field]);
|
|
54
|
+
if (row.date_effective !== null && row.date_effective !== undefined && row.date_effective !== '') {
|
|
55
|
+
const recorded = parseRestInstant(row.date_effective);
|
|
56
|
+
if (!Number.isFinite(recorded) || recorded > parseRestInstant(instant))
|
|
57
|
+
fail('MOBILE_PREFLIGHT_UNAVAILABLE', [q.field]);
|
|
58
|
+
if (recorded === parseRestInstant(instant))
|
|
59
|
+
conflicts.push(q.field);
|
|
60
|
+
}
|
|
61
|
+
else if (row.answer_value !== null && row.answer_value !== undefined && row.answer_value !== '')
|
|
62
|
+
fail('MOBILE_PREFLIGHT_UNAVAILABLE', [q.field]);
|
|
63
|
+
}
|
|
64
|
+
if (conflicts.length)
|
|
65
|
+
fail('MOBILE_ANSWER_EXISTS', conflicts);
|
|
66
|
+
}
|
|
67
|
+
checkSignal();
|
|
68
|
+
return api.assessmentsMobile.addAnswer(captured);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=mobile-preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-preflight.js","sourceRoot":"","sources":["../../src/mobile-preflight.ts"],"names":[],"mappings":"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","sourcesContent":["import type {WellSkyClient,Operations} from './generated/v3.js';\nimport {ValidationError} from './errors.js';\nimport {parseRestInstant} from './encoding.js';\nimport {toItems} from './runtime.js';\nimport {isRecord} from './validation.js';\n\ntype RawMobileWrite = Parameters<WellSkyClient['assessmentsMobile']['addAnswer']>[0];\nexport type CheckedMobileWriteOptions = Omit<RawMobileWrite,'query'> & {query:{dateEffective:string}};\nexport type MobilePreflightCode = 'MOBILE_PREFLIGHT_INPUT_INVALID'|'MOBILE_PREFLIGHT_READ_FAILED'|'MOBILE_PREFLIGHT_UNAVAILABLE'|'MOBILE_ANSWER_EXISTS'|'MOBILE_PREFLIGHT_CANCELLED';\nexport class MobileAnswerPreflightError extends ValidationError {\n readonly committed=false;\n constructor(readonly code:MobilePreflightCode,fields:readonly string[]=[],cause?:unknown){\n super('mobile assessment preflight',fields);this.name='MobileAnswerPreflightError';\n if(cause!==undefined)Object.defineProperty(this,'cause',{value:cause,enumerable:false});\n }\n}\n\n/** Read-before-write protection for scalar inserts, including questions shared by instruments.\n * Does not journal, retry writes, or make the read/write pair atomic. */\nexport async function writeMobileAnswersChecked(\n api:Pick<WellSkyClient,'assessments'|'assessmentsMobile'>,\n options:CheckedMobileWriteOptions,\n):ReturnType<WellSkyClient['assessmentsMobile']['addAnswer']>{\n function fail(code:MobilePreflightCode,fields:readonly string[]=[],cause?:unknown):never{throw new MobileAnswerPreflightError(code,fields,cause);}\n const checkSignal=()=>{if(options.signal?.aborted)fail('MOBILE_PREFLIGHT_CANCELLED',[],options.signal.reason);};\n if(!options?.path||!Number.isSafeInteger(options.path.clientId)||options.path.clientId<=0||typeof options.path.assessmentCode!=='string'||!options.path.assessmentCode.trim()||!Array.isArray(options.body)||!options.body.length||typeof options.query?.dateEffective!=='string')fail('MOBILE_PREFLIGHT_INPUT_INVALID');\n const instant=options.query.dateEffective;\n if(!/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.000)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(instant)||!Number.isFinite(parseRestInstant(instant))||new Date(instant.slice(0,19)+'Z').toISOString().slice(0,19)!==instant.slice(0,19))fail('MOBILE_PREFLIGHT_INPUT_INVALID',['dateEffective']);\n checkSignal();\n const captured={...options,path:{...options.path},query:{...options.query},body:structuredClone(options.body)};\n const scalars:Array<{id:number;field:string;type:string}>=[],seen=new Set<string>(),ids=new Set<number>();\n for(const q of captured.body){\n if(!isRecord(q)||typeof q.question_type!=='string'||typeof q.virt_field_name!=='string'||!q.virt_field_name||typeof q.question_id!=='number'||!Number.isSafeInteger(q.question_id)||q.question_id<=0||seen.has(q.virt_field_name)||ids.has(q.question_id))fail('MOBILE_PREFLIGHT_INPUT_INVALID');\n seen.add(q.virt_field_name);ids.add(q.question_id);\n if(q.question_type!=='sub_assessment')scalars.push({id:q.question_id,field:q.virt_field_name,type:q.question_type});\n }\n if(scalars.length){\n let response:Awaited<ReturnType<WellSkyClient['assessments']['get']>>;\n try{response=await api.assessments.get({path:captured.path,query:{dateEffective:new Date(parseRestInstant(instant)+1000).toISOString()},...(options.signal?{signal:options.signal}:{}),...(options.timeoutMs===undefined?{}:{timeoutMs:options.timeoutMs}),...(options.correlationId===undefined?{}:{correlationId:options.correlationId})});}\n catch(cause){fail('MOBILE_PREFLIGHT_READ_FAILED',scalars.map(q=>q.field),cause);}\n const rows=toItems<Operations['GET /assessments/{clientId}/{assessmentCode}']['item']>(response),conflicts:string[]=[];\n for(const q of scalars){\n const found=rows.filter(r=>r.virt_field_name===q.field);\n if(found.length!==1||found[0]?.question_id!==q.id||found[0]?.question_type!==q.type)fail('MOBILE_PREFLIGHT_UNAVAILABLE',[q.field]);\n const row=found[0];\n if(!row)fail('MOBILE_PREFLIGHT_UNAVAILABLE',[q.field]);\n if(row.date_effective!==null&&row.date_effective!==undefined&&row.date_effective!==''){\n const recorded=parseRestInstant(row.date_effective);\n if(!Number.isFinite(recorded)||recorded>parseRestInstant(instant))fail('MOBILE_PREFLIGHT_UNAVAILABLE',[q.field]);\n if(recorded===parseRestInstant(instant))conflicts.push(q.field);\n }else if(row.answer_value!==null&&row.answer_value!==undefined&&row.answer_value!=='')fail('MOBILE_PREFLIGHT_UNAVAILABLE',[q.field]);\n }\n if(conflicts.length)fail('MOBILE_ANSWER_EXISTS',conflicts);\n }\n checkSignal();\n return api.assessmentsMobile.addAnswer(captured);\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AssessmentDefinition } from './metadata.js';
|
|
2
|
+
import type { EncodingOptions } from './encoding.js';
|
|
3
|
+
export interface PicklistCatalogOption {
|
|
4
|
+
optionId: number;
|
|
5
|
+
picklistId: number;
|
|
6
|
+
code: string | null;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PicklistCatalogSnapshot {
|
|
10
|
+
source: 'gwt-rpc';
|
|
11
|
+
tenant: string;
|
|
12
|
+
clientId: number;
|
|
13
|
+
count: number;
|
|
14
|
+
values: PicklistCatalogOption[];
|
|
15
|
+
}
|
|
16
|
+
export type CatalogWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {
|
|
17
|
+
readonly tenant: string;
|
|
18
|
+
};
|
|
19
|
+
/** Exact catalog names joined by identity, without reading any stored answer.
|
|
20
|
+
* Only choices present in the supplied assessment definition can resolve. */
|
|
21
|
+
export declare function createCatalogWriteLabelResolver(definition: AssessmentDefinition, catalog: PicklistCatalogSnapshot): CatalogWriteLabelResolver;
|
|
22
|
+
//# sourceMappingURL=picklist-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picklist-labels.d.ts","sourceRoot":"","sources":["../../src/picklist-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,oBAAoB,EAAmC,MAAM,eAAe,CAAC;AAE1F,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAGnD,MAAM,WAAW,qBAAqB;IAAE,QAAQ,EAAC,MAAM,CAAC;IAAA,UAAU,EAAC,MAAM,CAAC;IAAA,IAAI,EAAC,MAAM,GAAC,IAAI,CAAC;IAAA,IAAI,EAAC,MAAM,CAAC;CAAC;AACxG,MAAM,WAAW,uBAAuB;IAAE,MAAM,EAAC,SAAS,CAAC;IAAA,MAAM,EAAC,MAAM,CAAC;IAAA,QAAQ,EAAC,MAAM,CAAC;IAAA,KAAK,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,qBAAqB,EAAE,CAAC;CAAC;AACtI,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,GAAG;IAAC,QAAQ,CAAC,MAAM,EAAC,MAAM,CAAA;CAAC,CAAC;AAE9G;6EAC6E;AAC7E,wBAAgB,+BAA+B,CAAC,UAAU,EAAC,oBAAoB,EAAC,OAAO,EAAC,uBAAuB,GAAE,yBAAyB,CAoBzI"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { flattenQuestions } from './metadata.js';
|
|
2
|
+
import { ValidationError } from './errors.js';
|
|
3
|
+
/** Exact catalog names joined by identity, without reading any stored answer.
|
|
4
|
+
* Only choices present in the supplied assessment definition can resolve. */
|
|
5
|
+
export function createCatalogWriteLabelResolver(definition, catalog) {
|
|
6
|
+
const fail = () => { throw new ValidationError('incomplete or mismatched picklist label catalog'); };
|
|
7
|
+
if (catalog?.source !== 'gwt-rpc' || catalog.tenant !== definition.tenant || !Number.isSafeInteger(catalog.clientId) || catalog.clientId <= 0 || !Array.isArray(catalog.values) || catalog.count !== catalog.values.length)
|
|
8
|
+
fail();
|
|
9
|
+
const rows = new Map();
|
|
10
|
+
for (const row of catalog.values) {
|
|
11
|
+
if (!row || !Number.isSafeInteger(row.optionId) || row.optionId <= 0 || !Number.isSafeInteger(row.picklistId) || row.picklistId <= 0 || row.code !== null && typeof row.code !== 'string' || typeof row.name !== 'string' || !row.name.trim() || rows.has(row.optionId))
|
|
12
|
+
fail();
|
|
13
|
+
rows.set(row.optionId, { ...row });
|
|
14
|
+
}
|
|
15
|
+
const signature = (q, o) => JSON.stringify([q.questionId, q.fieldName, q.questionType, o.id, o.picklistId, o.code, o.picklistCode, o.name, o.hudVisibility]);
|
|
16
|
+
const labels = new Map();
|
|
17
|
+
for (const { question } of flattenQuestions(definition.questions)) {
|
|
18
|
+
if (question.questionType !== 'lookup')
|
|
19
|
+
continue;
|
|
20
|
+
for (const option of question.options) {
|
|
21
|
+
const row = rows.get(option.id);
|
|
22
|
+
if (!row || row.picklistId !== option.picklistId || row.code !== option.code) {
|
|
23
|
+
fail();
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
labels.set(signature(question, option), row.name);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const resolver = (question, option) => labels.get(signature(question, option));
|
|
30
|
+
return Object.freeze(Object.assign(resolver, { tenant: definition.tenant }));
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=picklist-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picklist-labels.js","sourceRoot":"","sources":["../../src/picklist-labels.ts"],"names":[],"mappings":"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","sourcesContent":["import type {AssessmentDefinition,PicklistOption,QuestionDefinition} from './metadata.js';\nimport {flattenQuestions} from './metadata.js';\nimport type {EncodingOptions} from './encoding.js';\nimport {ValidationError} from './errors.js';\n\nexport interface PicklistCatalogOption {optionId:number;picklistId:number;code:string|null;name:string;}\nexport interface PicklistCatalogSnapshot {source:'gwt-rpc';tenant:string;clientId:number;count:number;values:PicklistCatalogOption[];}\nexport type CatalogWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {readonly tenant:string};\n\n/** Exact catalog names joined by identity, without reading any stored answer.\n * Only choices present in the supplied assessment definition can resolve. */\nexport function createCatalogWriteLabelResolver(definition:AssessmentDefinition,catalog:PicklistCatalogSnapshot):CatalogWriteLabelResolver{\n const fail=()=>{throw new ValidationError('incomplete or mismatched picklist label catalog');};\n if(catalog?.source!=='gwt-rpc'||catalog.tenant!==definition.tenant||!Number.isSafeInteger(catalog.clientId)||catalog.clientId<=0||!Array.isArray(catalog.values)||catalog.count!==catalog.values.length)fail();\n const rows=new Map<number,PicklistCatalogOption>();\n for(const row of catalog.values){\n if(!row||!Number.isSafeInteger(row.optionId)||row.optionId<=0||!Number.isSafeInteger(row.picklistId)||row.picklistId<=0||row.code!==null&&typeof row.code!=='string'||typeof row.name!=='string'||!row.name.trim()||rows.has(row.optionId))fail();\n rows.set(row.optionId,{...row});\n }\n const signature=(q:QuestionDefinition,o:PicklistOption)=>JSON.stringify([q.questionId,q.fieldName,q.questionType,o.id,o.picklistId,o.code,o.picklistCode,o.name,o.hudVisibility]);\n const labels=new Map<string,string>();\n for(const {question}of flattenQuestions(definition.questions)){\n if(question.questionType!=='lookup')continue;\n for(const option of question.options){\n const row=rows.get(option.id);\n if(!row||row.picklistId!==option.picklistId||row.code!==option.code){fail();continue;}\n labels.set(signature(question,option),row.name);\n }\n }\n const resolver=(question:QuestionDefinition,option:PicklistOption)=>labels.get(signature(question,option));\n return Object.freeze(Object.assign(resolver,{tenant:definition.tenant}));\n}\n"]}
|
package/dist/esm/v2.d.ts
CHANGED
|
@@ -10,4 +10,8 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
17
|
//# sourceMappingURL=v2.d.ts.map
|
package/dist/esm/v2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAC,qBAAqB,EAAC,uBAAuB,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/esm/v2.js
CHANGED
|
@@ -10,4 +10,7 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
16
|
//# sourceMappingURL=v2.js.map
|
package/dist/esm/v2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC","sourcesContent":["export * from \"./generated/v2.js\";\nexport * from \"./generated/v2-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../src/v2.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC","sourcesContent":["export * from \"./generated/v2.js\";\nexport * from \"./generated/v2-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\nexport * from \"./mobile-preflight.js\";\nexport * from \"./write-labels.js\";\n\nexport {createCatalogWriteLabelResolver} from './picklist-labels.js';\nexport type {PicklistCatalogOption,PicklistCatalogSnapshot,CatalogWriteLabelResolver} from './picklist-labels.js';\n"]}
|
package/dist/esm/v3.d.ts
CHANGED
|
@@ -10,4 +10,8 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
17
|
//# sourceMappingURL=v3.d.ts.map
|
package/dist/esm/v3.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAC,qBAAqB,EAAC,uBAAuB,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/esm/v3.js
CHANGED
|
@@ -10,4 +10,7 @@ export * from "./subassessments.js";
|
|
|
10
10
|
export * from "./enrollment-verifications.js";
|
|
11
11
|
export * from "./gwt-enrollments.js";
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
|
+
export * from "./mobile-preflight.js";
|
|
14
|
+
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
13
16
|
//# sourceMappingURL=v3.js.map
|
package/dist/esm/v3.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.js","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC","sourcesContent":["export * from \"./generated/v3.js\";\nexport * from \"./generated/v3-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"v3.js","sourceRoot":"","sources":["../../src/v3.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAE9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAC,+BAA+B,EAAC,MAAM,sBAAsB,CAAC","sourcesContent":["export * from \"./generated/v3.js\";\nexport * from \"./generated/v3-models.js\";\nexport * from \"./runtime.js\";\nexport * from \"./metadata.js\";\nexport * from \"./errors.js\";\nexport * from \"./encoding.js\";\nexport * from \"./verification.js\";\nexport * from \"./bulk.js\";\nexport * from \"./subassessments.js\";\nexport * from \"./enrollment-verifications.js\";\n\nexport * from \"./gwt-enrollments.js\";\nexport * from \"./program-discovery.js\";\nexport * from \"./mobile-preflight.js\";\nexport * from \"./write-labels.js\";\n\nexport {createCatalogWriteLabelResolver} from './picklist-labels.js';\nexport type {PicklistCatalogOption,PicklistCatalogSnapshot,CatalogWriteLabelResolver} from './picklist-labels.js';\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AssessmentDefinition } from './metadata.js';
|
|
2
|
+
import type { EncodingOptions } from './encoding.js';
|
|
3
|
+
export interface WriteLabelObservation {
|
|
4
|
+
tenant: string;
|
|
5
|
+
response: unknown;
|
|
6
|
+
}
|
|
7
|
+
export type ReadBackWriteLabelResolver = NonNullable<EncodingOptions['writeLabel']> & {
|
|
8
|
+
readonly tenant: string;
|
|
9
|
+
};
|
|
10
|
+
/** Builds labels only from exact readback evidence. It never infers HUD suffixes.
|
|
11
|
+
* Unobserved or changed options return undefined, so the standard encoder refuses them. */
|
|
12
|
+
export declare function createReadBackWriteLabelResolver(definition: AssessmentDefinition, observations: readonly WriteLabelObservation[]): ReadBackWriteLabelResolver;
|
|
13
|
+
//# sourceMappingURL=write-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-labels.d.ts","sourceRoot":"","sources":["../../src/write-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,oBAAoB,EAAmC,MAAM,eAAe,CAAC;AAE1F,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAInD,MAAM,WAAW,qBAAqB;IAAE,MAAM,EAAC,MAAM,CAAC;IAAA,QAAQ,EAAC,OAAO,CAAC;CAAC;AACxE,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,GAAG;IAAC,QAAQ,CAAC,MAAM,EAAC,MAAM,CAAA;CAAC,CAAC;AAE/G;2FAC2F;AAC3F,wBAAgB,gCAAgC,CAC/C,UAAU,EAAC,oBAAoB,EAC/B,YAAY,EAAC,SAAS,qBAAqB,EAAE,GAC5C,0BAA0B,CA2C3B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { flattenQuestions } from './metadata.js';
|
|
2
|
+
import { ValidationError } from './errors.js';
|
|
3
|
+
import { isRecord } from './validation.js';
|
|
4
|
+
/** Builds labels only from exact readback evidence. It never infers HUD suffixes.
|
|
5
|
+
* Unobserved or changed options return undefined, so the standard encoder refuses them. */
|
|
6
|
+
export function createReadBackWriteLabelResolver(definition, observations) {
|
|
7
|
+
const questions = new Map();
|
|
8
|
+
for (const { question } of flattenQuestions(definition.questions)) {
|
|
9
|
+
if (question.questionType !== 'lookup')
|
|
10
|
+
continue;
|
|
11
|
+
const prior = questions.get(question.questionId);
|
|
12
|
+
if (prior && JSON.stringify(prior) !== JSON.stringify(question))
|
|
13
|
+
throw new ValidationError('ambiguous write-label question');
|
|
14
|
+
questions.set(question.questionId, structuredClone(question));
|
|
15
|
+
}
|
|
16
|
+
const labels = new Map();
|
|
17
|
+
const identity = (questionId, optionId) => JSON.stringify([questionId, optionId]);
|
|
18
|
+
const visit = (value, depth = 0) => {
|
|
19
|
+
if (depth > 40)
|
|
20
|
+
throw new ValidationError('write-label observation exceeds nesting limit');
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
for (const child of value)
|
|
23
|
+
visit(child, depth + 1);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(value))
|
|
27
|
+
return;
|
|
28
|
+
if (value.question_type === 'lookup' && typeof value.question_id === 'number') {
|
|
29
|
+
const question = questions.get(value.question_id);
|
|
30
|
+
if (question) {
|
|
31
|
+
if (value.virt_field_name !== question.fieldName)
|
|
32
|
+
throw new ValidationError('write-label question identity mismatch');
|
|
33
|
+
const raw = value.answer_value;
|
|
34
|
+
const id = typeof raw === 'number' ? raw : typeof raw === 'string' && /^\d+$/.test(raw) ? Number(raw) : null;
|
|
35
|
+
if (id !== null && Number.isSafeInteger(id) && typeof value.answer_value_text === 'string' && value.answer_value_text.trim()) {
|
|
36
|
+
const options = question.options.filter(option => option.id === id);
|
|
37
|
+
if (options.length !== 1)
|
|
38
|
+
throw new ValidationError('write-label option identity mismatch', [question.fieldName ?? String(question.questionId)]);
|
|
39
|
+
const key = identity(question.questionId, id), prior = labels.get(key);
|
|
40
|
+
if (prior !== undefined && prior !== value.answer_value_text)
|
|
41
|
+
throw new ValidationError('conflicting write-label observations', [question.fieldName ?? String(question.questionId)]);
|
|
42
|
+
labels.set(key, value.answer_value_text);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Traverse known response/assessment containers only. Do not interpret arbitrary strings as data.
|
|
47
|
+
for (const key of ['value', 'values', 'sub_assessment_question_list', 'sub_assessment_answer_list', 'sub_assessment_list'])
|
|
48
|
+
if (value[key] !== undefined)
|
|
49
|
+
visit(value[key], depth + 1);
|
|
50
|
+
};
|
|
51
|
+
for (const observation of observations) {
|
|
52
|
+
if (observation.tenant !== definition.tenant)
|
|
53
|
+
throw new ValidationError('write-label observation tenant mismatch');
|
|
54
|
+
visit(observation.response);
|
|
55
|
+
}
|
|
56
|
+
const sameOption = (a, b) => a.id === b.id && a.picklistId === b.picklistId && a.code === b.code && a.picklistCode === b.picklistCode && a.name === b.name && a.hudVisibility === b.hudVisibility;
|
|
57
|
+
const resolver = (question, option) => {
|
|
58
|
+
const known = questions.get(question.questionId);
|
|
59
|
+
if (!known || known.fieldName !== question.fieldName || question.questionType !== 'lookup' || !known.options.some(o => sameOption(o, option)))
|
|
60
|
+
return undefined;
|
|
61
|
+
return labels.get(identity(question.questionId, option.id));
|
|
62
|
+
};
|
|
63
|
+
return Object.freeze(Object.assign(resolver, { tenant: definition.tenant }));
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=write-labels.js.map
|