@choiceapps/communityservices-sdk 0.7.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 +7 -0
- package/browser/enrollment-workflow.d.mts +4 -2
- package/browser/enrollment-workflow.mjs +13 -5
- package/browser/entry-correction.mjs +7 -7
- package/browser/index.d.mts +4 -1
- package/browser/index.mjs +1 -1
- package/browser/playwright-session.mjs +20 -5
- 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 +2 -0
- package/dist/cjs/v2.d.ts.map +1 -1
- package/dist/cjs/v2.js +3 -0
- package/dist/cjs/v2.js.map +1 -1
- package/dist/cjs/v3.d.ts +2 -0
- package/dist/cjs/v3.d.ts.map +1 -1
- package/dist/cjs/v3.js +3 -0
- package/dist/cjs/v3.js.map +1 -1
- 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 +2 -0
- package/dist/esm/v2.d.ts.map +1 -1
- package/dist/esm/v2.js +1 -0
- package/dist/esm/v2.js.map +1 -1
- package/dist/esm/v3.d.ts +2 -0
- package/dist/esm/v3.d.ts.map +1 -1
- package/dist/esm/v3.js +1 -0
- package/dist/esm/v3.js.map +1 -1
- package/docs/assessments.md +19 -1
- package/docs/capabilities.md +7 -1
- package/docs/enrollments.md +3 -1
- package/docs/reference.md +2 -2
- package/docs/vendor-issues/lookup-write-labels.md +13 -0
- package/examples/README.md +1 -0
- package/examples/catalog-write-labels.mts +15 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0 - 2026-11-11
|
|
4
|
+
|
|
5
|
+
- Resolve full lookup write labels without existing answers using `enrollmentSession.readPicklistOptions` and `createCatalogWriteLabelResolver`.
|
|
6
|
+
- Discover labels automatically in enrollment workflows when the configured session supports catalog reads and no explicit `writeLabel` override is supplied, including corrections and mandatory carry-forward.
|
|
7
|
+
- Match option ID, picklist ID and code; preserve full names including HUD suffixes, and reject incomplete or mismatched catalogs before writes. Read explicit option IDs in bounded batches.
|
|
8
|
+
- Read-only training verification matched 1,288 distinct catalog options to Coordinated Entry metadata from three synthetic clients, including the shared enhanced yes/no list and living-situation options. Live profile dropdowns matched the DOB-quality catalog labels. No new assessment writes were performed.
|
|
9
|
+
|
|
3
10
|
## 0.7.0 - 2026-11-10
|
|
4
11
|
|
|
5
12
|
- Add `createReadBackWriteLabelResolver` for exact observed lookup labels, including HUD suffixes. Unobserved options remain unresolved; no suffix is inferred from metadata.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {DateOfBirth} from './date-of-birth.mjs';
|
|
2
|
-
import type {Answers, AssessmentDefinition, EncodingOptions, GwtEnrollmentHelpers, Provider, WellSkyClient} from '../dist/esm/index.js';
|
|
2
|
+
import type {PicklistCatalogSnapshot, Answers, AssessmentDefinition, EncodingOptions, GwtEnrollmentHelpers, Provider, WellSkyClient} from '../dist/esm/index.js';
|
|
3
3
|
import type {UiMutationStore,EnrollmentReader} from './index.mjs';
|
|
4
4
|
import type {ProviderAssessmentItem, ProgramDiscovery} from './program-discovery.mjs';
|
|
5
5
|
import type {HouseholdExitUi,HouseholdExitDetailInput} from './household-exit.mjs';
|
|
@@ -41,6 +41,8 @@ export interface EnrollmentDiscoveryInput {
|
|
|
41
41
|
entryDate:string;
|
|
42
42
|
}
|
|
43
43
|
export interface EnrollmentWorkflowDiscovery {
|
|
44
|
+
/** Current exact label catalog when automatic browser discovery is available. */
|
|
45
|
+
picklistOptions?:PicklistCatalogSnapshot;
|
|
44
46
|
provider:Provider;
|
|
45
47
|
entry:{assessment:ProviderAssessmentItem;definition:AssessmentDefinition};
|
|
46
48
|
interim:{assessment:ProviderAssessmentItem;definition:AssessmentDefinition};
|
|
@@ -254,7 +256,7 @@ export interface EnrollmentWorkflowOptions {
|
|
|
254
256
|
* `standard` writes them through `assessments.create` with every mandatory answer, after the mobile scalars;
|
|
255
257
|
* every mandatory question must be a lookup. An unfinished journal never reconciles in the other mode. */
|
|
256
258
|
yesNoWrites?:'mobile'|'standard';
|
|
257
|
-
/**
|
|
259
|
+
/** Explicit tenant-verified override. When omitted, a configured readPicklistOptions reader supplies exact catalog labels automatically. */
|
|
258
260
|
writeLabel?:EncodingOptions['writeLabel'];
|
|
259
261
|
}
|
|
260
262
|
export class EnrollmentWorkflowError extends Error {
|
|
@@ -6,7 +6,7 @@ import {createEntryRowRegistrar} from './entry-row-registration.mjs';
|
|
|
6
6
|
import {createHouseholdEnrollmentDiscovery} from './household-enrollment-discovery.mjs';
|
|
7
7
|
import {workflowErrorCode} from './workflow-error-codes.mjs';
|
|
8
8
|
import {createHash} from 'node:crypto';
|
|
9
|
-
import {readProgramCatalog,encodeAnswers,encodeNewSubassessmentRow,toItems,parseRestInstant} from '../dist/esm/index.js';
|
|
9
|
+
import {readProgramCatalog,flattenQuestions,createCatalogWriteLabelResolver,encodeAnswers,encodeNewSubassessmentRow,toItems,parseRestInstant} from '../dist/esm/index.js';
|
|
10
10
|
|
|
11
11
|
const object=v=>v!==null&&typeof v==='object'&&!Array.isArray(v);
|
|
12
12
|
const positive=v=>Number.isSafeInteger(v)&&v>0;
|
|
@@ -128,7 +128,7 @@ export function createEnrollmentWorkflow({api,discovery,helpers,store,enrollment
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
if(typeof discovery?.getProviderAssessments!=='function'||typeof helpers?.createInterimUpdate!=='function'||!store)fail('REST API, discovery, enrollment helpers and durable store required');
|
|
131
|
-
if(!['mobile','standard'].includes(yesNoWrites)||yesNoWrites==='standard'&&(typeof writeLabel!=='function'||typeof api.assessments?.create!=='function'))fail('yesNoWrites must be mobile, or standard with writeLabel and assessments.create');
|
|
131
|
+
if(!['mobile','standard'].includes(yesNoWrites)||yesNoWrites==='standard'&&(typeof writeLabel!=='function'&&typeof enrollmentSession?.readPicklistOptions!=='function'||typeof api.assessments?.create!=='function'))fail('yesNoWrites must be mobile, or standard with writeLabel and assessments.create');
|
|
132
132
|
if(!object(assessmentLocations))fail('assessment locations must be a map by Entry/Exit type');
|
|
133
133
|
for(const [type,locations]of Object.entries(assessmentLocations)){
|
|
134
134
|
if(!entryExitTypes.includes(type))fail('unsupported Entry/Exit type in assessment locations');
|
|
@@ -149,7 +149,14 @@ export function createEnrollmentWorkflow({api,discovery,helpers,store,enrollment
|
|
|
149
149
|
if(definition.tenant!==api.tenant||definition.assessmentCode!==assessment.code||definition.unresolvedPicklists.length)fail('assessment metadata incomplete');
|
|
150
150
|
resolved[phase]={assessment,definition};
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
let picklistOptions;
|
|
153
|
+
if(writeLabel===undefined&&typeof enrollmentSession?.readPicklistOptions==='function'){
|
|
154
|
+
const optionIds=[...new Set(Object.values(resolved).flatMap(({definition})=>flattenQuestions(definition.questions).filter(({question})=>question.questionType==='lookup').flatMap(({question})=>question.options.map(o=>o.id))))];
|
|
155
|
+
picklistOptions=await enrollmentSession.readPicklistOptions({clientId:input.clientId,optionIds});
|
|
156
|
+
if(picklistOptions?.clientId!==input.clientId)fail('picklist catalog client mismatch',{code:'PICKLIST_CATALOG_CONTEXT_MISMATCH'});
|
|
157
|
+
for(const {definition}of Object.values(resolved))createCatalogWriteLabelResolver(definition,picklistOptions);
|
|
158
|
+
}
|
|
159
|
+
return {provider:providers[0],...resolved,...(picklistOptions?{picklistOptions}:{})};
|
|
153
160
|
};
|
|
154
161
|
const scope=clientId=>JSON.stringify([tenantScope,'enrollment-workflow',clientId]);
|
|
155
162
|
const reservationScope=clientId=>JSON.stringify([tenantScope,'household-workflow-reservation',clientId]);
|
|
@@ -210,7 +217,8 @@ export function createEnrollmentWorkflow({api,discovery,helpers,store,enrollment
|
|
|
210
217
|
const definition=discovered[kind].definition,code=definition.assessmentCode,at=kind==='entry'?input.entryDate:(input.exitDate??input.reviewDate);
|
|
211
218
|
const exitSchemaHash=kind==='exit'?hash({assessment:discovered.exit.assessment,questions:definition.questions}):undefined;
|
|
212
219
|
if(record&&kind==='exit'&&record.exitSchemaHash!==exitSchemaHash)fail('exit assessment configuration changed');
|
|
213
|
-
const
|
|
220
|
+
const operationWriteLabel=writeLabel??(discovered.picklistOptions?createCatalogWriteLabelResolver(definition,discovered.picklistOptions):undefined);
|
|
221
|
+
const plan=compile(definition,input.assessment,{yesNoWrites,writeLabel:operationWriteLabel});
|
|
214
222
|
const carriesBirthDate=plan.carry.includes('SVPPROFDOB'),hasBirthDate=plan.dateOfBirth!==undefined||carriesBirthDate;
|
|
215
223
|
let carriedBirthDate;
|
|
216
224
|
if(hasBirthDate){
|
|
@@ -266,7 +274,7 @@ export function createEnrollmentWorkflow({api,discovery,helpers,store,enrollment
|
|
|
266
274
|
const recorded=initial.find(q=>q.virt_field_name===m.virt_field_name)?.answer_value;
|
|
267
275
|
if(m.carry){
|
|
268
276
|
const question=definition.questions.find(q=>q.fieldName===m.virt_field_name),options=question.options.filter(o=>String(o.id)===String(recorded));
|
|
269
|
-
const label=options.length===1?
|
|
277
|
+
const label=options.length===1?operationWriteLabel?.(question,options[0]):undefined;
|
|
270
278
|
if(!label)fail(`carried mandatory answer ${m.virt_field_name} has no verified write label`,{code:'LOOKUP_WRITE_LABEL_UNAVAILABLE',fields:[m.virt_field_name]});
|
|
271
279
|
if(m.virt_field_name==='HUD_RELATIONTOHOH')checkHeadAnswer(recorded);
|
|
272
280
|
return {question_id:m.question_id,question_type:m.question_type,virt_field_name:m.virt_field_name,answer_value:label,expected:String(recorded)};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {createHash} from 'node:crypto';
|
|
2
|
-
import {encodeAnswers,parseRestInstant,toItems} from '../dist/esm/index.js';
|
|
2
|
+
import {createCatalogWriteLabelResolver,encodeAnswers,parseRestInstant,toItems} from '../dist/esm/index.js';
|
|
3
3
|
|
|
4
4
|
const object=v=>v!==null&&typeof v==='object'&&!Array.isArray(v);
|
|
5
5
|
const canonical=v=>JSON.stringify(v,(_,x)=>object(x)?Object.fromEntries(Object.keys(x).sort().map(k=>[k,x[k]])):x);
|
|
@@ -24,7 +24,7 @@ export function createEntryCorrector({api,store,enrollmentSession,writeLabel,dis
|
|
|
24
24
|
if(type==='int'||type==='money'){const n=Number(v);if(!Number.isFinite(n))fail('invalid stored correction number');return n;}
|
|
25
25
|
return String(v);
|
|
26
26
|
};
|
|
27
|
-
const encode=(questions,answers,clear,endpoint)=>{
|
|
27
|
+
const encode=(questions,answers,clear,endpoint,writeLabel)=>{
|
|
28
28
|
if(!object(answers)||!Array.isArray(clear)||new Set(clear).size!==clear.length||clear.some(f=>typeof f!=='string'||Object.hasOwn(answers,f)))fail('invalid or conflicting correction answers and clears');
|
|
29
29
|
const index=new Map(questions.map(q=>[q.fieldName,q]));
|
|
30
30
|
const unsupportedClears=clear.filter(field=>index.get(field)?.questionType==='yes_no');
|
|
@@ -94,7 +94,7 @@ export function createEntryCorrector({api,store,enrollmentSession,writeLabel,dis
|
|
|
94
94
|
const discovered=await discover({clientId:input.clientId,providerId,type,entryDate:at});
|
|
95
95
|
const schemaHash=hash({providerId:discovered.provider.providerId,entry:{assessment:discovered.entry.assessment,questions:discovered.entry.definition.questions},interim:{assessment:discovered.interim.assessment,questions:discovered.interim.definition.questions}});
|
|
96
96
|
if(schemaHash!==entry.schemaHash||record&&schemaHash!==record.schemaHash)fail('program assessment configuration changed');
|
|
97
|
-
const definition=discovered.entry.definition,code=definition.assessmentCode;
|
|
97
|
+
const definition=discovered.entry.definition,operationWriteLabel=writeLabel??(discovered.picklistOptions?createCatalogWriteLabelResolver(discovered.entry.definition,discovered.picklistOptions):undefined),code=definition.assessmentCode;
|
|
98
98
|
const snapshot=async()=>{
|
|
99
99
|
const raw=await readQuestions(input.clientId,code,readAt),current=await readQuestions(input.clientId,code,new Date(Math.max(Date.now(),parseRestInstant(readAt))).toISOString());
|
|
100
100
|
const scalars={},rows={};
|
|
@@ -145,7 +145,7 @@ export function createEntryCorrector({api,store,enrollmentSession,writeLabel,dis
|
|
|
145
145
|
if(!record){
|
|
146
146
|
readOverrides(observed);
|
|
147
147
|
const answers=input.answers??{},clear=input.clear??[];
|
|
148
|
-
const scalarBody=encode(definition.questions,answers,clear,'standalone'),scalarExpected=expected(definition.questions,scalarBody,answers);
|
|
148
|
+
const scalarBody=encode(definition.questions,answers,clear,'standalone',operationWriteLabel),scalarExpected=expected(definition.questions,scalarBody,answers);
|
|
149
149
|
// The standard endpoint requires every mandatory scalar, even if this patch leaves it unchanged.
|
|
150
150
|
if(scalarBody.length)for(const q of definition.questions.filter(q=>q.mandatory&&!['label','blank','sub_assessment'].includes(q.questionType)&&!scalarBody.some(c=>c.virt_field_name===q.fieldName))){
|
|
151
151
|
if(q.fieldName==='SVPPROFDOB'||!scalarTypes.has(q.questionType))fail('unsupported mandatory correction field');
|
|
@@ -153,10 +153,10 @@ export function createEntryCorrector({api,store,enrollmentSession,writeLabel,dis
|
|
|
153
153
|
if(prior?.answer_value===null||prior?.answer_value===undefined||prior?.answer_value==='')fail('mandatory correction field requires an explicit answer or clear');
|
|
154
154
|
let body;
|
|
155
155
|
if(q.questionType==='lookup'){
|
|
156
|
-
const options=q.options.filter(o=>String(o.id)===String(prior.answer_value)),label=options.length===1?
|
|
156
|
+
const options=q.options.filter(o=>String(o.id)===String(prior.answer_value)),label=options.length===1?operationWriteLabel?.(q,options[0]):undefined;
|
|
157
157
|
if(!label)fail('mandatory correction lookup label unavailable');
|
|
158
158
|
body=[{question_id:q.questionId,question_type:q.questionType,virt_field_name:q.fieldName,answer_value:label}];
|
|
159
|
-
}else body=encodeAnswers([q],{[q.fieldName]:{value:prior.answer_value}},{endpoint:'standalone',writeLabel});
|
|
159
|
+
}else body=encodeAnswers([q],{[q.fieldName]:{value:prior.answer_value}},{endpoint:'standalone',writeLabel:operationWriteLabel});
|
|
160
160
|
if(body.length!==1)fail('mandatory correction field could not be encoded');scalarBody.push(body[0]);
|
|
161
161
|
scalarExpected.push({...body[0],answer_value:prior.answer_value});
|
|
162
162
|
}
|
|
@@ -165,7 +165,7 @@ export function createEntryCorrector({api,store,enrollmentSession,writeLabel,dis
|
|
|
165
165
|
fields(patch,['key','parentField','answers','clear']);key(patch.key);
|
|
166
166
|
const id=entry.rows[patch.key],parent=definition.questions.find(q=>q.fieldName===patch.parentField&&q.questionType==='sub_assessment');
|
|
167
167
|
if(!positive(id)||ids.has(id)||!parent||!observed.rows[parent.fieldName]?.[id]||entry.rowParents?.[patch.key]&&entry.rowParents[patch.key]!==patch.parentField)fail('correction requires an existing entry row key and matching parent');ids.add(id);
|
|
168
|
-
const cells=encode(parent.children,patch.answers??{},patch.clear??[],'mobile');if(!cells.length)fail('empty row correction');
|
|
168
|
+
const cells=encode(parent.children,patch.answers??{},patch.clear??[],'mobile',operationWriteLabel);if(!cells.length)fail('empty row correction');
|
|
169
169
|
rowPlans.push({id,parentField:parent.fieldName,questionId:parent.questionId,cells});
|
|
170
170
|
}
|
|
171
171
|
if(!scalarBody.length&&!rowPlans.length)fail('empty entry correction');
|
package/browser/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {UiConnection,UiConnectionOptions} from './connection.mjs';
|
|
2
2
|
import type {Browser, BrowserContext, BrowserType, Page} from 'playwright-core';
|
|
3
|
-
import type {GwtEnrollmentExit,GwtEnrollmentHelpers,GwtEnrollmentSession,GwtEnrollmentSnapshot,GwtMutationStore} from '../dist/esm/index.js';
|
|
3
|
+
import type {PicklistCatalogSnapshot,GwtEnrollmentExit,GwtEnrollmentHelpers,GwtEnrollmentSession,GwtEnrollmentSnapshot,GwtMutationStore} from '../dist/esm/index.js';
|
|
4
4
|
export interface LoginOptions extends UiConnectionOptions {
|
|
5
5
|
chromium: BrowserType;
|
|
6
6
|
envFile?: string;
|
|
@@ -29,12 +29,15 @@ export interface EnrollmentListSnapshot {
|
|
|
29
29
|
}
|
|
30
30
|
export interface EnrollmentReader {
|
|
31
31
|
readonly connection?:UiConnection;
|
|
32
|
+
/** Exact full names for explicit REST option IDs; does not read existing answers. */
|
|
33
|
+
readPicklistOptions?(target:{clientId:number;optionIds:readonly number[]}):Promise<PicklistCatalogSnapshot>;
|
|
32
34
|
readEnrollment(target:{clientId:number;enrollmentId:number}):Promise<PlaywrightEnrollmentSnapshot>;
|
|
33
35
|
/** Built-in sessions supply this complete, counted list, including exited entries.
|
|
34
36
|
* Legacy custom readers without it retain REST list behavior. */
|
|
35
37
|
listEnrollments?(target:{clientId:number}):Promise<EnrollmentListSnapshot>;
|
|
36
38
|
}
|
|
37
39
|
export interface EnrollmentCatalogReader extends EnrollmentReader {
|
|
40
|
+
readPicklistOptions(target:{clientId:number;optionIds:readonly number[]}):Promise<PicklistCatalogSnapshot>;
|
|
38
41
|
listEnrollments(target:{clientId:number}):Promise<EnrollmentListSnapshot>;
|
|
39
42
|
}
|
|
40
43
|
export function openUiSession(options:LoginOptions):Promise<UiSession>;
|
package/browser/index.mjs
CHANGED
|
@@ -10,7 +10,7 @@ export async function openEnrollmentSession({store,...loginOptions}) {
|
|
|
10
10
|
try {
|
|
11
11
|
const helpers=createPlaywrightEnrollmentHelpers({page:session.page,store,...session.connection});
|
|
12
12
|
const reader=createPlaywrightGwtSession({page:session.page,...session.connection});
|
|
13
|
-
const enrollmentSession={connection:session.connection,readEnrollment:target=>withPageLock(session.page,()=>reader.readEnrollment(target)),listEnrollments:target=>withPageLock(session.page,()=>reader.listEnrollments(target))};
|
|
13
|
+
const enrollmentSession={connection:session.connection,readEnrollment:target=>withPageLock(session.page,()=>reader.readEnrollment(target)),listEnrollments:target=>withPageLock(session.page,()=>reader.listEnrollments(target)),readPicklistOptions:target=>withPageLock(session.page,()=>reader.readPicklistOptions(target))};
|
|
14
14
|
return Object.assign(session,{helpers,enrollmentSession,workflows:createClientWorkflows({page:session.page,store})});
|
|
15
15
|
}catch(error){await session.close();throw error;}
|
|
16
16
|
}
|
|
@@ -84,10 +84,10 @@ export function createPlaywrightGwtSession({page,tenant,moduleBaseUrl}) {
|
|
|
84
84
|
try{const r=await fetch(url,{method:'POST',headers,body,credentials:'same-origin',redirect:'error',signal:controller.signal});return {status:r.status,body:await r.text()};}finally{clearTimeout(timer);}
|
|
85
85
|
},request);
|
|
86
86
|
};
|
|
87
|
-
const mapped=async
|
|
87
|
+
const mapped=async(query,limit=1001)=>{
|
|
88
88
|
if(!wire||!/^SELECT /.test(query)||/[|\\\r\n]/.test(query))throw Error('Invalid mapped read');
|
|
89
|
-
const strings=[moduleBaseUrl,wire.policy,rpcInterface,'getMappedResults','java.lang.String/2004016611','java.util.HashMap/1797211028','I','Z',query
|
|
90
|
-
const body=['7','0',strings.length,...strings,1,2,3,4,5,5,6,7,7,8,9,0,0,
|
|
89
|
+
const strings=[moduleBaseUrl,wire.policy,rpcInterface,'getMappedResults','java.lang.String/2004016611','java.util.HashMap/1797211028','I','Z',query+` LIMIT ${limit},0`];
|
|
90
|
+
const body=['7','0',strings.length,...strings,1,2,3,4,5,5,6,7,7,8,9,0,0,limit,1,''].join('|');
|
|
91
91
|
const response=await post({url:moduleBaseUrl+'service/MetaQueryService',headers:wire.headers,body});if(response.status!==200)throw Error('Mapped read failed');
|
|
92
92
|
const data=decodeMappedResponse(response.body);if(data.total!==data.rows.length||data.total>1000)throw Error('Incomplete enrollment list');return data.rows;
|
|
93
93
|
};
|
|
@@ -100,7 +100,7 @@ export function createPlaywrightGwtSession({page,tenant,moduleBaseUrl}) {
|
|
|
100
100
|
if(ids.some(n=>!Number.isSafeInteger(n)||n<=0))throw Error('Invalid household tree');
|
|
101
101
|
await closeDialogs();return [...new Set([target.clientId,...ids])].sort((a,b)=>a-b);
|
|
102
102
|
};
|
|
103
|
-
const
|
|
103
|
+
const openReadContext=async clientId=>{
|
|
104
104
|
id(clientId);await guard();wire=undefined;let captured;
|
|
105
105
|
const listener=request=>{
|
|
106
106
|
if(request.url()===moduleBaseUrl+'service/MetaQueryService'&&request.postData()?.startsWith('7|0|')){
|
|
@@ -111,6 +111,9 @@ export function createPlaywrightGwtSession({page,tenant,moduleBaseUrl}) {
|
|
|
111
111
|
page.on('request',listener);
|
|
112
112
|
try{await openClient(clientId);wire=await captured;}finally{page.off('request',listener);}
|
|
113
113
|
if(!wire?.policy||Object.values(wire.headers).some(v=>!v))throw Error('Fresh enrollment list context unavailable');
|
|
114
|
+
};
|
|
115
|
+
const listEnrollments=async({clientId})=>{
|
|
116
|
+
await openReadContext(clientId);
|
|
114
117
|
const rows=await mapped(`SELECT e.entryExitId AS enrollmentId, e.clientId AS clientId, e.entryDate AS projectStartDate, e.exitDate AS projectExitDate, e.providerId AS enrollmentProvider, e.typeEntryExit.name AS type, e.groupId AS groupId FROM SpEntryExit AS e WHERE e.active = TRUE AND e.client.active = TRUE AND e.clientId = ${clientId} ORDER BY e.entryExitId`);
|
|
115
118
|
const ids=new Set();
|
|
116
119
|
for(const row of rows){
|
|
@@ -120,6 +123,18 @@ export function createPlaywrightGwtSession({page,tenant,moduleBaseUrl}) {
|
|
|
120
123
|
}
|
|
121
124
|
return {source:'gwt-rpc',tenant,clientId,count:rows.length,values:rows.map(row=>({...row,isActive:true,grouped:row.groupId!==null}))};
|
|
122
125
|
};
|
|
126
|
+
const readPicklistOptions=async({clientId,optionIds})=>{
|
|
127
|
+
id(clientId);if(!Array.isArray(optionIds)||optionIds.length>10000)throw Error('Invalid picklist option IDs');
|
|
128
|
+
const ids=[...new Set(optionIds.map(id))].sort((a,b)=>a-b),values=[];
|
|
129
|
+
if(ids.length)await openReadContext(clientId);
|
|
130
|
+
for(let offset=0;offset<ids.length;offset+=200){
|
|
131
|
+
const chunk=ids.slice(offset,offset+200);
|
|
132
|
+
const rows=await mapped(`SELECT v.picklistValueId AS optionId, v.picklistId AS picklistId, v.name AS name, v.code AS code FROM SpPicklistValue AS v WHERE v.picklistValueId IN (${chunk.join(',')}) ORDER BY v.picklistValueId`,200);
|
|
133
|
+
if(rows.length!==chunk.length||new Set(rows.map(r=>r.optionId)).size!==chunk.length||rows.some(r=>!chunk.includes(r.optionId)||!Number.isSafeInteger(r.picklistId)||r.picklistId<=0||typeof r.name!=='string'||!r.name.trim()||r.code!==null&&typeof r.code!=='string'))throw Error('Incomplete picklist option catalog');
|
|
134
|
+
values.push(...rows);
|
|
135
|
+
}
|
|
136
|
+
return {source:'gwt-rpc',tenant,clientId,count:values.length,values};
|
|
137
|
+
};
|
|
123
138
|
const readEnrollment=async target=>{
|
|
124
139
|
const model=await openTarget(target),householdClientIds=await householdIds(target);
|
|
125
140
|
const entries=await mapped(`SELECT e.entryExitId AS enrollmentId, e.clientId AS clientId, e.entryDate AS projectStartDate, e.groupId AS groupId, e.providerId AS providerId, e.typeEntryExit.name AS enrollmentType FROM SpEntryExit AS e WHERE e.active = TRUE AND e.entryExitId = ${id(target.enrollmentId)} AND e.clientId = ${id(target.clientId)}`);
|
|
@@ -213,7 +228,7 @@ export function createPlaywrightGwtSession({page,tenant,moduleBaseUrl}) {
|
|
|
213
228
|
try{await save.click();const result=await Promise.race([captured,new Promise(resolve=>{timer=setTimeout(()=>resolve(null),15000);})]);if(!result)throw Error('Expected mutation was not captured');pending=digest(JSON.stringify({url:result.url,headers:result.headers,body:result.body}));return result;}
|
|
214
229
|
finally{clearTimeout(timer);await page.unroute('**/service/**',handler);await ready();await closeDialogs();}
|
|
215
230
|
};
|
|
216
|
-
return {connection:resolveUiConnection({tenant,moduleBaseUrl}),readEnrollment,listEnrollments,prepare,async send(request){
|
|
231
|
+
return {connection:resolveUiConnection({tenant,moduleBaseUrl}),readEnrollment,listEnrollments,readPicklistOptions,prepare,async send(request){
|
|
217
232
|
checkGeneration();const fingerprint=digest(JSON.stringify(request));if(!pending||fingerprint!==pending)throw Error('Only the newly prepared request can be sent once');pending=undefined;return post(request);
|
|
218
233
|
}};
|
|
219
234
|
}
|
|
@@ -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,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
|
@@ -12,4 +12,6 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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);
|
|
@@ -28,4 +29,6 @@ __exportStar(require("./gwt-enrollments.js"), exports);
|
|
|
28
29
|
__exportStar(require("./program-discovery.js"), exports);
|
|
29
30
|
__exportStar(require("./mobile-preflight.js"), exports);
|
|
30
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; } });
|
|
31
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
|
@@ -12,4 +12,6 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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);
|
|
@@ -28,4 +29,6 @@ __exportStar(require("./gwt-enrollments.js"), exports);
|
|
|
28
29
|
__exportStar(require("./program-discovery.js"), exports);
|
|
29
30
|
__exportStar(require("./mobile-preflight.js"), exports);
|
|
30
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; } });
|
|
31
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,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
|
@@ -12,4 +12,6 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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
|
@@ -12,4 +12,5 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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"]}
|
|
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
|
@@ -12,4 +12,6 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
16
|
+
export type { PicklistCatalogOption, PicklistCatalogSnapshot, CatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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
|
@@ -12,4 +12,5 @@ export * from "./gwt-enrollments.js";
|
|
|
12
12
|
export * from "./program-discovery.js";
|
|
13
13
|
export * from "./mobile-preflight.js";
|
|
14
14
|
export * from "./write-labels.js";
|
|
15
|
+
export { createCatalogWriteLabelResolver } from './picklist-labels.js';
|
|
15
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;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,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"]}
|
|
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"]}
|
package/docs/assessments.md
CHANGED
|
@@ -29,7 +29,25 @@ The default metadata cache TTL is 60 seconds with 100 entries per client. Config
|
|
|
29
29
|
|
|
30
30
|
WellSky requires a client context and known assessment code for these reads. There is no documented global assessment-list or standalone picklist-list endpoint. Mobile option metadata has no effective-date filter, so definitions explicitly identify its options as current even when the generic assessment read is dated. Metadata also does not provide a complete questionnaire branching engine.
|
|
31
31
|
|
|
32
|
-
Use the raw `assessments.get`, `assessmentsMobile.getAnswers`, and `enrollments.getAssessment` methods for recorded answers. Use `encodeAnswers` and `encodeNewSubassessmentRow` for endpoint-specific encoding. Mobile lookups use option IDs; standalone/enrollment lookups require an explicit `writeLabel` resolver with tenant-verified labels. Raw option names are not assumed to be valid write labels. Some HUD-marked choices require `(HUD)` in the full write label even when metadata `name` omits it. Do not infer this from trailing whitespace or append the suffix to every option.
|
|
32
|
+
Use the raw `assessments.get`, `assessmentsMobile.getAnswers`, and `enrollments.getAssessment` methods for recorded answers. Use `encodeAnswers` and `encodeNewSubassessmentRow` for endpoint-specific encoding. Mobile lookups use option IDs; standalone/enrollment lookups require an explicit `writeLabel` resolver with tenant-verified labels. Raw option names are not assumed to be valid write labels. Some HUD-marked choices require `(HUD)` in the full write label even when metadata `name` omits it. Do not infer this from trailing whitespace or append the suffix to every option. Use the catalog resolver below for exact labels without existing answers, or retain an explicitly verified callback; recorded `answer_value_text` also supplies evidence for observed options. Provider answers are refused for mobile writes because that endpoint can silently discard them. Answer-state code mappings and multi-value serialization are caller-supplied; a refusal is never converted to `No`.
|
|
33
|
+
|
|
34
|
+
## Resolve lookup labels before an answer exists
|
|
35
|
+
|
|
36
|
+
The browser enrollment session exposes `readPicklistOptions({clientId, optionIds})`. It reads the current GWT picklist catalog and returns complete, counted rows with `optionId`, `picklistId`, `code`, and the exact full `name`. It needs an authenticated session and client context, but no existing enrollment or answer. Only explicit positive option IDs are queried, in batches of 200; missing, duplicated or malformed results stop discovery.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import {flattenQuestions, createCatalogWriteLabelResolver} from '@choiceapps/communityservices-sdk';
|
|
40
|
+
const definition = await api.assessments.getDefinition({clientId, assessmentCode});
|
|
41
|
+
const optionIds = [...new Set(flattenQuestions(definition.questions)
|
|
42
|
+
.filter(({question}) => question.questionType === 'lookup')
|
|
43
|
+
.flatMap(({question}) => question.options.map(option => option.id)))];
|
|
44
|
+
const catalog = await session.enrollmentSession.readPicklistOptions({clientId, optionIds});
|
|
45
|
+
const writeLabel = createCatalogWriteLabelResolver(definition, catalog);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The resolver matches option ID, picklist ID and code, preserves the full catalog name, and permits only options already allowed by the question definition. HUD and non-HUD choices have distinct IDs. It never appends a suffix, guesses from whitespace, or broadens the question's allowed list. Missing identity evidence or a tenant mismatch throws before encoding. The immutable resolver returns `undefined` if called with changed option metadata.
|
|
49
|
+
|
|
50
|
+
`createEnrollmentWorkflow` uses this catalog automatically when its `enrollmentSession` has `readPicklistOptions` and `writeLabel` is omitted. This covers standard entry/interim/exit batches, mandatory carry-forward and `correctEntry`. Explicit callbacks take precedence and skip automatic catalog reads. Legacy custom sessions without this reader still need a callback. Raw REST clients do not acquire UI access implicitly. See [the typed example](../examples/catalog-write-labels.mts) and [read-only evidence](vendor-issues/lookup-write-labels.md).
|
|
33
51
|
|
|
34
52
|
## Resolve exact lookup write labels from readback
|
|
35
53
|
|
package/docs/capabilities.md
CHANGED
|
@@ -98,4 +98,10 @@ The integrator reports these training-tenant results on November 10 and 11, 2026
|
|
|
98
98
|
|
|
99
99
|
The integrator has not tested household adoption followed by `createHouseholdInterim`, scalar correction on an adopted enrollment, or a new correction key after resolution. Synthetic tests do not replace that acceptance.
|
|
100
100
|
|
|
101
|
-
The 0.7.0 label resolver, group flags, household discovery, row registration, error codes and mobile collision preflight have local regression coverage, not new live tenant acceptance.
|
|
101
|
+
The 0.7.0 label resolver, group flags, household discovery, row registration, error codes and mobile collision preflight have local regression coverage, not new live tenant acceptance. In 0.7.0, full write labels remained unresolved for unobserved options; the 0.8.0 catalog reader below removes that limitation when UI catalog access is available. Household discovery refuses ambiguous current-membership matches. Yes/no blanking remains unsupported; no alternative route has been verified.
|
|
102
|
+
|
|
103
|
+
## Catalog label verification, November 11, 2026
|
|
104
|
+
|
|
105
|
+
Read-only training checks matched all 1,288 distinct option IDs in the Coordinated Entry instrument to current GWT catalog rows across three synthetic clients (4,089 question/option pairs). Catalog names differed from REST metadata names for 139 option occurrences in one definition. The five enhanced yes/no HUD questions shared a catalog; plain yes/no alternatives had separate option IDs. The visible profile DOB-quality dropdown matched the catalog's full labels. This establishes metadata identity and displayed labels without prior-answer evidence, not fresh acceptance of every standard write. Existing enrollment and answer records were left unchanged.
|
|
106
|
+
|
|
107
|
+
SDK 0.8.0 uses the catalog automatically for workflows with a built-in enrollment session. REST-only applications can supply a catalog resolver or retain their explicit callback. See [catalog evidence and limitations](vendor-issues/lookup-write-labels.md).
|
package/docs/enrollments.md
CHANGED
|
@@ -130,7 +130,7 @@ Every mandatory label is resolved before the first write. The `yesno` stage veri
|
|
|
130
130
|
|
|
131
131
|
## Correct an existing entry assessment
|
|
132
132
|
|
|
133
|
-
`correctEntry` patches an entry at its original effective timestamp. Supply the verified `createEnrollment` key as `enrollmentKey` and a new stable `key` for each correction. Configure `enrollmentSession
|
|
133
|
+
`correctEntry` patches an entry at its original effective timestamp. Supply the verified `createEnrollment` key as `enrollmentKey` and a new stable `key` for each correction. Configure `enrollmentSession`; built-in sessions discover exact lookup labels automatically. An explicit `writeLabel` callback overrides that discovery. A correction requires an open enrollment with no interim reviews or exit workflows.
|
|
134
134
|
|
|
135
135
|
```ts
|
|
136
136
|
const corrected = await workflow.correctEntry({
|
|
@@ -234,6 +234,8 @@ const detail = await session.enrollmentSession.readEnrollment({
|
|
|
234
234
|
|
|
235
235
|
Use the session returned by `openEnrollmentSession`. Lists include open and exited entries, validate complete counts, and refuse more than 1,000 records. List rows and details include `groupId` and `grouped`. The flag describes a stored group link, including a group with one participant; it is not a member count and requires no per-row detail reads. These fields are required on managed catalog rows and optional on custom detail-reader contracts for compatibility. `groupId` is never a household ID. For a verified household match from a head enrollment, use `discoverHouseholdEnrollment` below.
|
|
236
236
|
|
|
237
|
+
The same session also exposes `readPicklistOptions({clientId, optionIds})` for exact labels before answers exist. It uses fresh read context, validates counted results, and makes no record writes. Enrollment workflows use it automatically unless `writeLabel` is supplied. See [catalog lookup labels](assessments.md#resolve-lookup-labels-before-an-answer-exists).
|
|
238
|
+
|
|
237
239
|
## Individual enrollment exits
|
|
238
240
|
|
|
239
241
|
Use `exitEnrollment` to end a standalone person's program enrollment. It requires a verified `createEnrollment` entry in the same durable store. Supply `enrollmentSession: session.enrollmentSession` and `exitUi: createHouseholdExitUi({page: session.page})` when constructing the workflow. The same exit UI port serves individual and household forms.
|
package/docs/reference.md
CHANGED
|
@@ -8,14 +8,14 @@ Only the package export paths below are supported import entry points. Declarati
|
|
|
8
8
|
|
|
9
9
|
Import from `@choiceapps/communityservices-sdk`, `@choiceapps/communityservices-sdk/v3`, or `@choiceapps/communityservices-sdk/v2`. The root selects V3 and also exports the testing helpers. Each version supplies its own generated HTTP models and fixed version header.
|
|
10
10
|
|
|
11
|
-
Runtime exports at the root: `MobileAnswerPreflightError`, `writeMobileAnswersChecked`, `createReadBackWriteLabelResolver`, `AmbiguousCommitError`, `AssessmentMetadata`, `AuthError`, `CooldownError`, `DefinitionDriftError`, `FakeControl`, `FakeWellSkyClient`, `GwtEnrollmentConflictError`, `GwtEnrollmentHelpers`, `SubassessmentEditor`, `TenantMismatchError`, `ThrottledError`, `UnknownPicklistValueError`, `UpstreamError`, `ValidationError`, `WellSkyClient`, `WellSkyError`, `apiVersion`, `buildAssessmentDefinition`, `compareDefinition`, `createFakeWellSkyClient`, `createInMemoryGwtMutationStore`, `createWellSkyClient`, `encodeAnswers`, `encodeNewSubassessmentRow`, `flattenQuestions`, `mapBulk`, `operationRoutes`, `parseRestInstant`, `readEnrollmentVerifications`, `readOutcome`, `readProgramCatalog`, `resolvePicklistOption`, `semanticHash`, `specSha256`, `toItems`, `verifyWrite`.
|
|
11
|
+
Runtime exports at the root: `MobileAnswerPreflightError`, `writeMobileAnswersChecked`, `createReadBackWriteLabelResolver`, `createCatalogWriteLabelResolver`, `AmbiguousCommitError`, `AssessmentMetadata`, `AuthError`, `CooldownError`, `DefinitionDriftError`, `FakeControl`, `FakeWellSkyClient`, `GwtEnrollmentConflictError`, `GwtEnrollmentHelpers`, `SubassessmentEditor`, `TenantMismatchError`, `ThrottledError`, `UnknownPicklistValueError`, `UpstreamError`, `ValidationError`, `WellSkyClient`, `WellSkyError`, `apiVersion`, `buildAssessmentDefinition`, `compareDefinition`, `createFakeWellSkyClient`, `createInMemoryGwtMutationStore`, `createWellSkyClient`, `encodeAnswers`, `encodeNewSubassessmentRow`, `flattenQuestions`, `mapBulk`, `operationRoutes`, `parseRestInstant`, `readEnrollmentVerifications`, `readOutcome`, `readProgramCatalog`, `resolvePicklistOption`, `semanticHash`, `specSha256`, `toItems`, `verifyWrite`.
|
|
12
12
|
|
|
13
13
|
| Contract | Declaration | Guide |
|
|
14
14
|
| --- | --- | --- |
|
|
15
15
|
| HTTP clients and generated models | [V3](../dist/esm/generated/v3.d.ts), [V2](../dist/esm/generated/v2.d.ts) | [REST](rest-client.md), [API table](../API.md) |
|
|
16
16
|
| Authentication, transport, responses and errors | [Runtime](../dist/esm/runtime.d.ts) | [Configuration](configuration.md), [recovery](troubleshooting.md) |
|
|
17
17
|
| Metadata and picklists | [Metadata](../dist/esm/metadata.d.ts) | [Assessments](assessments.md) |
|
|
18
|
-
| Checked mobile inserts and exact lookup labels | [Preflight](../dist/esm/mobile-preflight.d.ts), [labels](../dist/esm/write-labels.d.ts) | [Assessments](assessments.md) |
|
|
18
|
+
| Checked mobile inserts and exact lookup labels | [Preflight](../dist/esm/mobile-preflight.d.ts), [readback labels](../dist/esm/write-labels.d.ts), [catalog labels](../dist/esm/picklist-labels.d.ts) | [Assessments](assessments.md) |
|
|
19
19
|
| Answer encoding | [Encoding](../dist/esm/encoding.d.ts) | [Dates and answers](dates-and-answers.md) |
|
|
20
20
|
| Write verification | [Verification](../dist/esm/verification.d.ts) | [REST](rest-client.md) |
|
|
21
21
|
| Program catalog | [Program discovery](../dist/esm/program-discovery.d.ts) | [Enrollments](enrollments.md) |
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Exact lookup write labels from the UI catalog
|
|
2
|
+
|
|
3
|
+
On November 11, 2026, read-only inspection of the training application's current GWT catalog established a way to discover full lookup labels before an answer exists.
|
|
4
|
+
|
|
5
|
+
REST assessment option metadata can omit `(HUD)` from `name`. The current UI's `SpPicklistValue.name` retains it. A mapped query returns `picklistValueId`, `picklistId`, `code` and `name` together. HUD and non-HUD enhanced yes/no choices are separate catalog records. `show_on_hud_nonhud_site` and trailing whitespace are not reliable substitutes for those identities.
|
|
6
|
+
|
|
7
|
+
The read used the application's observed `MetaQueryService` / `GenericService.getMappedResults` wire context and selected only explicit option IDs already enumerated by REST metadata. The [browser reader](../../browser/playwright-session.mjs) implements the same query with bounded batches and counted result validation. The [public resolver contract](../../dist/esm/picklist-labels.d.ts) joins IDs and codes while retaining the question's allowed choices.
|
|
8
|
+
|
|
9
|
+
Evidence: Coordinated Entry definitions for three synthetic clients matched all 1,288 distinct option IDs (4,089 question/option pairs). Full names differed from REST metadata for 139 occurrences in a definition. Disabling condition, domestic violence, non-cash benefits, health insurance and income-source questions shared the enhanced yes/no list. Living-situation and homelessness-history options were included. The visible profile DOB-quality dropdown matched its full catalog names, including all displayed options rather than only the selected answer.
|
|
10
|
+
|
|
11
|
+
No enrollment or assessment was saved during this inspection. No new REST writes were made to test acceptance of every returned label. Private captures, client identifiers and tenant-specific catalogs are excluded from the package. This internal GWT route is not part of the published REST Swagger; schema, permission, count or identity failures must stop discovery. Explicit application callbacks remain available for deployments without the catalog reader.
|
|
12
|
+
|
|
13
|
+
See [assessment integration](../assessments.md#resolve-lookup-labels-before-an-answer-exists) for usage.
|
package/examples/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Every file here ships with the package and imports the public `@choiceapps/commu
|
|
|
15
15
|
| [program-discovery.ts](program-discovery.ts) | Program and VA-entry assessment discovery | Exported function; authenticated page required |
|
|
16
16
|
| [enrollment-workflow.mts](enrollment-workflow.mts) | Single entry and interim assessment plans | Exported function; caller supplies plans and dependencies |
|
|
17
17
|
| [individual-exit-workflow.mts](individual-exit-workflow.mts) | Standalone program enrollment exit and assessment | Verified entry key, enrollment reader, exit UI port and durable store required |
|
|
18
|
+
| [catalog-write-labels.mts](catalog-write-labels.mts) | Discover full lookup labels without existing answers; automatic workflow configuration | Authenticated enrollment session and current assessment definition required |
|
|
18
19
|
| [checked-assessment-writes.mts](checked-assessment-writes.mts) | Exact readback lookup labels and checked mobile scalar inserts | Unobserved labels remain unresolved; preflight does not make writes atomic |
|
|
19
20
|
| [enrollment-discovery-and-correction.mts](enrollment-discovery-and-correction.mts) | Discover/adopt from the head and bind existing correction rows | Explicit row IDs and unique verified household membership required |
|
|
20
21
|
| [entry-correction-workflow.mts](entry-correction-workflow.mts) | Same-date scalar clears and existing row edits | Original entry/row keys, verified lookup labels and durable store required |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {createCatalogWriteLabelResolver,flattenQuestions,type WellSkyClient} from '@choiceapps/communityservices-sdk';
|
|
2
|
+
import {createEnrollmentWorkflow,type EnrollmentCatalogReader,type EnrollmentWorkflowOptions} from '@choiceapps/communityservices-sdk/browser';
|
|
3
|
+
|
|
4
|
+
/** Standalone encoders can discover exact labels before any option has been answered. */
|
|
5
|
+
export async function discoverLabels(api:WellSkyClient,enrollmentSession:EnrollmentCatalogReader,input:{clientId:number;assessmentCode:string}){
|
|
6
|
+
const definition=await api.assessments.getDefinition(input);
|
|
7
|
+
const optionIds=[...new Set(flattenQuestions(definition.questions).filter(({question})=>question.questionType==='lookup').flatMap(({question})=>question.options.map(o=>o.id)))];
|
|
8
|
+
const catalog=await enrollmentSession.readPicklistOptions({clientId:input.clientId,optionIds});
|
|
9
|
+
return {definition,writeLabel:createCatalogWriteLabelResolver(definition,catalog)};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Built-in enrollment sessions discover labels automatically when writeLabel is omitted. */
|
|
13
|
+
export function automaticWorkflow(options:Omit<EnrollmentWorkflowOptions,'writeLabel'|'yesNoWrites'|'enrollmentSession'>&{enrollmentSession:EnrollmentCatalogReader}){
|
|
14
|
+
return createEnrollmentWorkflow({...options,yesNoWrites:'standard'});
|
|
15
|
+
}
|
package/package.json
CHANGED