Reference
Questionnaire module
Reusable in-memory policy for deciding when an unshown questionnaire prompt is due.
arcane/modules/Questionnaire.js provides a synchronous, in-memory policy for
deciding when an application may present a one-time questionnaire prompt. It
does not initialize timestamps, persist state, create or order modals, or open a
questionnaire URL. Those responsibilities remain with the consuming
application.
Loading and exports
Import the class and its default delay from the shared module:
import {
DEFAULT_QUESTIONNAIRE_NOTIFICATION_TIME_MS,
Questionnaire
} from './arcane/modules/Questionnaire.js';
The module exports:
| Export | Description |
|---|---|
DEFAULT_QUESTIONNAIRE_NOTIFICATION_TIME_MS |
Exactly 604,800,000 elapsed milliseconds, or seven 24-hour periods |
Questionnaire |
An independent evaluator whose notification delay exists only for the lifetime of that instance |
There is no default export.
Constructing Questionnaire has no side effects. It does not start a timer,
read global state, load a user, or dispatch an event.
Eligibility rule
checkQuestionnaireShown(firstBootUp, questionnaireShown, now) returns true
only when every condition below is satisfied:
questionnaireShownis exactlyfalse.firstBootUpis a positive safe-integer timestamp in milliseconds.nowis finite and is not earlier thanfirstBootUp.now - firstBootUpis greater than or equal to the configured notification delay.
The default boundary is exact elapsed time rather than calendar-day arithmetic:
now - firstBootUp < 604,800,000 returns false
now - firstBootUp >= 604,800,000 returns true
A firstBootUp value of 0, a missing or malformed timestamp, a timestamp in
the future, or any shown-state value other than the boolean false returns
false. Invalid eligibility state fails closed and does not throw.
Despite its name, checkQuestionnaireShown() answers whether an unshown prompt
is due. It does not report whether a questionnaire was completed.
API
new Questionnaire()
Creates an evaluator with the default seven-day notification delay. Each instance owns its own delay, so changing one instance does not affect another.
setNotificationTime(notificationTime)
Replaces the instance's delay with a positive finite number of milliseconds,
including a positive fractional value. The change is in memory only and is not
serialized or shared with another instance. The method returns undefined.
The method throws a RangeError with
notificationTime must be a positive finite number when the supplied value is
zero, negative, NaN, infinite, or not a number.
checkQuestionnaireShown(firstBootUp, questionnaireShown, now = Date.now())
Synchronously returns a boolean using the eligibility rule above. Supplying
now makes the result deterministic for tests. Omitting it uses Date.now() at
the time of the call.
Application-owned integration
The application should initialize and persist its timestamp separately, invoke
the evaluator from an application lifecycle event or page load, and present its
own user interface only when the evaluator returns true:
const questionnaire=new Questionnaire();
if(user.firstBootUp===0){
await user.updateExplicit({firstBootUp:Date.now()});
}else if(questionnaire.checkQuestionnaireShown(
user.firstBootUp,
user.questionnaireShown
)){
const opened=await applicationModal.open();
if(opened){
await user.updateExplicit({questionnaireShown:true});
}
}
The example is orchestration, not behavior supplied by Questionnaire. A
consumer may use different field names or persistence as long as it maps them
to the same timestamp and boolean contract.
Operational boundaries
| Concern | Module behavior |
|---|---|
| Synchronous | Both public methods complete synchronously |
| Asynchronous | No promises, background tasks, polling, or timers |
| Persistent | No; delay and evaluation state remain in memory |
| Destructive | No |
| Networked | No; the module never loads or validates a form URL |
| User interface | No; modal creation, readiness, ordering, content, and focus remain application-owned |
An application must own any asynchronous modal task and observe its failures. It should mark a prompt as shown only after presentation succeeds if it needs a failed presentation to remain eligible on a later load. Showing a prompt is not proof that a third-party questionnaire was opened, submitted, or completed.