@zuplo/cli 6.72.8 → 6.72.10
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/node_modules/@posthog/core/dist/surveys/activation.d.ts +20 -0
- package/node_modules/@posthog/core/dist/surveys/activation.d.ts.map +1 -0
- package/node_modules/@posthog/core/dist/surveys/activation.js +45 -0
- package/node_modules/@posthog/core/dist/surveys/activation.mjs +8 -0
- package/node_modules/@posthog/core/dist/surveys/events.d.ts +1 -4
- package/node_modules/@posthog/core/dist/surveys/events.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/surveys/index.d.ts +2 -0
- package/node_modules/@posthog/core/dist/surveys/index.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/surveys/index.js +16 -2
- package/node_modules/@posthog/core/dist/surveys/index.mjs +3 -1
- package/node_modules/@posthog/core/dist/surveys/keys.d.ts +14 -0
- package/node_modules/@posthog/core/dist/surveys/keys.d.ts.map +1 -0
- package/node_modules/@posthog/core/dist/surveys/keys.js +45 -0
- package/node_modules/@posthog/core/dist/surveys/keys.mjs +8 -0
- package/node_modules/@posthog/core/dist/types.d.ts +87 -76
- package/node_modules/@posthog/core/dist/types.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/types.js +65 -76
- package/node_modules/@posthog/core/dist/types.mjs +66 -77
- package/node_modules/@posthog/core/package.json +1 -1
- package/node_modules/@posthog/core/src/surveys/activation.spec.ts +61 -0
- package/node_modules/@posthog/core/src/surveys/activation.ts +28 -0
- package/node_modules/@posthog/core/src/surveys/events.ts +1 -5
- package/node_modules/@posthog/core/src/surveys/index.ts +2 -0
- package/node_modules/@posthog/core/src/surveys/keys.spec.ts +29 -0
- package/node_modules/@posthog/core/src/surveys/keys.ts +23 -0
- package/node_modules/@posthog/core/src/types.ts +88 -76
- package/node_modules/@posthog/types/dist/posthog-config.d.ts +14 -0
- package/node_modules/@posthog/types/dist/posthog-config.d.ts.map +1 -1
- package/node_modules/@posthog/types/package.json +1 -1
- package/node_modules/@posthog/types/src/posthog-config.ts +15 -0
- package/node_modules/@zuplo/core/customer.cli.minified.js +1 -1
- package/node_modules/@zuplo/core/index.minified.js +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-K77Z5PRN.js +30 -0
- package/node_modules/@zuplo/runtime/out/esm/chunk-K77Z5PRN.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/{chunk-HKSZ4V6H.js → chunk-NIKKAYJU.js} +86 -86
- package/node_modules/@zuplo/runtime/out/esm/chunk-NIKKAYJU.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/sdks/aws/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +124 -55
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/avvio/.github/dependabot.yml +42 -2
- package/node_modules/avvio/.github/workflows/ci.yml +1 -1
- package/node_modules/avvio/.github/workflows/lock-threads.yml +19 -0
- package/node_modules/avvio/LICENSE +1 -3
- package/node_modules/avvio/README.md +4 -4
- package/node_modules/avvio/{boot.js → index.js} +8 -2
- package/node_modules/avvio/package.json +8 -8
- package/node_modules/avvio/test/esm.mjs +1 -1
- package/node_modules/avvio/test/gh-issues/fastify-6843.test.js +48 -0
- package/node_modules/avvio/test/on-ready-timeout-await.test.js +1 -1
- package/node_modules/avvio/test/types/index.ts +1 -1
- package/node_modules/avvio/test/types/tsconfig.json +5 -2
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/package.json +6 -6
- package/node_modules/@zuplo/runtime/out/esm/chunk-GBIUQ4JJ.js +0 -30
- package/node_modules/@zuplo/runtime/out/esm/chunk-GBIUQ4JJ.js.map +0 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-HKSZ4V6H.js.map +0 -1
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-HKSZ4V6H.js.LEGAL.txt → chunk-NIKKAYJU.js.LEGAL.txt} +0 -0
|
@@ -89,82 +89,71 @@ const FeatureFlagError = {
|
|
|
89
89
|
UNKNOWN_ERROR: 'unknown_error',
|
|
90
90
|
apiError: (status)=>`api_error_${status}`
|
|
91
91
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
SurveySchedule["Once"] = "once";
|
|
158
|
-
SurveySchedule["Recurring"] = "recurring";
|
|
159
|
-
SurveySchedule["Always"] = "always";
|
|
160
|
-
return SurveySchedule;
|
|
161
|
-
}({});
|
|
162
|
-
var ActionStepStringMatching = /*#__PURE__*/ function(ActionStepStringMatching) {
|
|
163
|
-
ActionStepStringMatching["Contains"] = "contains";
|
|
164
|
-
ActionStepStringMatching["Exact"] = "exact";
|
|
165
|
-
ActionStepStringMatching["Regex"] = "regex";
|
|
166
|
-
return ActionStepStringMatching;
|
|
167
|
-
}({});
|
|
92
|
+
const SurveyPosition = {
|
|
93
|
+
TopLeft: 'top_left',
|
|
94
|
+
TopCenter: 'top_center',
|
|
95
|
+
TopRight: 'top_right',
|
|
96
|
+
MiddleLeft: 'middle_left',
|
|
97
|
+
MiddleCenter: 'middle_center',
|
|
98
|
+
MiddleRight: 'middle_right',
|
|
99
|
+
Left: 'left',
|
|
100
|
+
Right: 'right',
|
|
101
|
+
Center: 'center'
|
|
102
|
+
};
|
|
103
|
+
const SurveyWidgetType = {
|
|
104
|
+
Button: 'button',
|
|
105
|
+
Tab: 'tab',
|
|
106
|
+
Selector: 'selector'
|
|
107
|
+
};
|
|
108
|
+
const SurveyType = {
|
|
109
|
+
Popover: 'popover',
|
|
110
|
+
API: 'api',
|
|
111
|
+
Widget: 'widget',
|
|
112
|
+
ExternalSurvey: 'external_survey'
|
|
113
|
+
};
|
|
114
|
+
const SurveyQuestionDescriptionContentType = {
|
|
115
|
+
Html: 'html',
|
|
116
|
+
Text: 'text'
|
|
117
|
+
};
|
|
118
|
+
const SurveyValidationType = {
|
|
119
|
+
MinLength: 'min_length',
|
|
120
|
+
MaxLength: 'max_length'
|
|
121
|
+
};
|
|
122
|
+
const SurveyRatingDisplay = {
|
|
123
|
+
Number: 'number',
|
|
124
|
+
Emoji: 'emoji'
|
|
125
|
+
};
|
|
126
|
+
const SurveyQuestionType = {
|
|
127
|
+
Open: 'open',
|
|
128
|
+
MultipleChoice: 'multiple_choice',
|
|
129
|
+
SingleChoice: 'single_choice',
|
|
130
|
+
Rating: 'rating',
|
|
131
|
+
Link: 'link'
|
|
132
|
+
};
|
|
133
|
+
const SurveyQuestionBranchingType = {
|
|
134
|
+
NextQuestion: 'next_question',
|
|
135
|
+
End: 'end',
|
|
136
|
+
ResponseBased: 'response_based',
|
|
137
|
+
SpecificQuestion: 'specific_question'
|
|
138
|
+
};
|
|
139
|
+
const SurveyMatchType = {
|
|
140
|
+
Regex: 'regex',
|
|
141
|
+
NotRegex: 'not_regex',
|
|
142
|
+
Exact: 'exact',
|
|
143
|
+
IsNot: 'is_not',
|
|
144
|
+
Icontains: 'icontains',
|
|
145
|
+
NotIcontains: 'not_icontains'
|
|
146
|
+
};
|
|
147
|
+
const SurveySchedule = {
|
|
148
|
+
Once: 'once',
|
|
149
|
+
Recurring: 'recurring',
|
|
150
|
+
Always: 'always'
|
|
151
|
+
};
|
|
152
|
+
const ActionStepStringMatching = {
|
|
153
|
+
Contains: 'contains',
|
|
154
|
+
Exact: 'exact',
|
|
155
|
+
Regex: 'regex'
|
|
156
|
+
};
|
|
168
157
|
const knownUnsafeEditableEvent = [
|
|
169
158
|
'$snapshot',
|
|
170
159
|
'$pageview',
|
|
@@ -46,82 +46,71 @@ const FeatureFlagError = {
|
|
|
46
46
|
UNKNOWN_ERROR: 'unknown_error',
|
|
47
47
|
apiError: (status)=>`api_error_${status}`
|
|
48
48
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
SurveySchedule["Once"] = "once";
|
|
115
|
-
SurveySchedule["Recurring"] = "recurring";
|
|
116
|
-
SurveySchedule["Always"] = "always";
|
|
117
|
-
return SurveySchedule;
|
|
118
|
-
}({});
|
|
119
|
-
var types_ActionStepStringMatching = /*#__PURE__*/ function(ActionStepStringMatching) {
|
|
120
|
-
ActionStepStringMatching["Contains"] = "contains";
|
|
121
|
-
ActionStepStringMatching["Exact"] = "exact";
|
|
122
|
-
ActionStepStringMatching["Regex"] = "regex";
|
|
123
|
-
return ActionStepStringMatching;
|
|
124
|
-
}({});
|
|
49
|
+
const SurveyPosition = {
|
|
50
|
+
TopLeft: 'top_left',
|
|
51
|
+
TopCenter: 'top_center',
|
|
52
|
+
TopRight: 'top_right',
|
|
53
|
+
MiddleLeft: 'middle_left',
|
|
54
|
+
MiddleCenter: 'middle_center',
|
|
55
|
+
MiddleRight: 'middle_right',
|
|
56
|
+
Left: 'left',
|
|
57
|
+
Right: 'right',
|
|
58
|
+
Center: 'center'
|
|
59
|
+
};
|
|
60
|
+
const SurveyWidgetType = {
|
|
61
|
+
Button: 'button',
|
|
62
|
+
Tab: 'tab',
|
|
63
|
+
Selector: 'selector'
|
|
64
|
+
};
|
|
65
|
+
const SurveyType = {
|
|
66
|
+
Popover: 'popover',
|
|
67
|
+
API: 'api',
|
|
68
|
+
Widget: 'widget',
|
|
69
|
+
ExternalSurvey: 'external_survey'
|
|
70
|
+
};
|
|
71
|
+
const SurveyQuestionDescriptionContentType = {
|
|
72
|
+
Html: 'html',
|
|
73
|
+
Text: 'text'
|
|
74
|
+
};
|
|
75
|
+
const SurveyValidationType = {
|
|
76
|
+
MinLength: 'min_length',
|
|
77
|
+
MaxLength: 'max_length'
|
|
78
|
+
};
|
|
79
|
+
const SurveyRatingDisplay = {
|
|
80
|
+
Number: 'number',
|
|
81
|
+
Emoji: 'emoji'
|
|
82
|
+
};
|
|
83
|
+
const SurveyQuestionType = {
|
|
84
|
+
Open: 'open',
|
|
85
|
+
MultipleChoice: 'multiple_choice',
|
|
86
|
+
SingleChoice: 'single_choice',
|
|
87
|
+
Rating: 'rating',
|
|
88
|
+
Link: 'link'
|
|
89
|
+
};
|
|
90
|
+
const SurveyQuestionBranchingType = {
|
|
91
|
+
NextQuestion: 'next_question',
|
|
92
|
+
End: 'end',
|
|
93
|
+
ResponseBased: 'response_based',
|
|
94
|
+
SpecificQuestion: 'specific_question'
|
|
95
|
+
};
|
|
96
|
+
const SurveyMatchType = {
|
|
97
|
+
Regex: 'regex',
|
|
98
|
+
NotRegex: 'not_regex',
|
|
99
|
+
Exact: 'exact',
|
|
100
|
+
IsNot: 'is_not',
|
|
101
|
+
Icontains: 'icontains',
|
|
102
|
+
NotIcontains: 'not_icontains'
|
|
103
|
+
};
|
|
104
|
+
const SurveySchedule = {
|
|
105
|
+
Once: 'once',
|
|
106
|
+
Recurring: 'recurring',
|
|
107
|
+
Always: 'always'
|
|
108
|
+
};
|
|
109
|
+
const ActionStepStringMatching = {
|
|
110
|
+
Contains: 'contains',
|
|
111
|
+
Exact: 'exact',
|
|
112
|
+
Regex: 'regex'
|
|
113
|
+
};
|
|
125
114
|
const knownUnsafeEditableEvent = [
|
|
126
115
|
'$snapshot',
|
|
127
116
|
'$pageview',
|
|
@@ -141,4 +130,4 @@ const knownUnsafeEditableEvent = [
|
|
|
141
130
|
const knownUnsafeEditableEventProperty = [
|
|
142
131
|
'token'
|
|
143
132
|
];
|
|
144
|
-
export {
|
|
133
|
+
export { ActionStepStringMatching, types_Compression as Compression, FeatureFlagError, types_PostHogPersistedProperty as PostHogPersistedProperty, SurveyMatchType, SurveyPosition, SurveyQuestionBranchingType, SurveyQuestionDescriptionContentType, SurveyQuestionType, SurveyRatingDisplay, SurveySchedule, SurveyType, SurveyValidationType, SurveyWidgetType, knownUnsafeEditableEvent, knownUnsafeEditableEventProperty };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, expect, it } from '@jest/globals'
|
|
2
|
+
import { SurveySchedule } from '../types'
|
|
3
|
+
import { canSurveyActivateRepeatedly, doesSurveyActivateByEvent } from './activation'
|
|
4
|
+
|
|
5
|
+
describe('doesSurveyActivateByEvent', () => {
|
|
6
|
+
const cases: [string, Parameters<typeof doesSurveyActivateByEvent>[0], boolean][] = [
|
|
7
|
+
['non-empty event values', { conditions: { events: { values: [{ name: 'event' }] } } }, true],
|
|
8
|
+
['empty event values', { conditions: { events: { values: [] } } }, false],
|
|
9
|
+
['undefined conditions', { conditions: undefined }, false],
|
|
10
|
+
['null conditions', { conditions: null }, false],
|
|
11
|
+
['null events', { conditions: { events: null } }, false],
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
it.each(cases)('%s returns %p', (_name, survey, expected) => {
|
|
15
|
+
expect(doesSurveyActivateByEvent(survey)).toBe(expected)
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('canSurveyActivateRepeatedly', () => {
|
|
20
|
+
const cases: [string, Parameters<typeof canSurveyActivateRepeatedly>[0], boolean][] = [
|
|
21
|
+
['always schedule without events', { schedule: SurveySchedule.Always }, true],
|
|
22
|
+
[
|
|
23
|
+
'events with repeated activation enabled',
|
|
24
|
+
{
|
|
25
|
+
schedule: SurveySchedule.Once,
|
|
26
|
+
conditions: { events: { repeatedActivation: true, values: [{ name: 'event' }] } },
|
|
27
|
+
},
|
|
28
|
+
true,
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
'events with repeated activation disabled',
|
|
32
|
+
{
|
|
33
|
+
schedule: SurveySchedule.Once,
|
|
34
|
+
conditions: { events: { repeatedActivation: false, values: [{ name: 'event' }] } },
|
|
35
|
+
},
|
|
36
|
+
false,
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
'events without repeated activation',
|
|
40
|
+
{
|
|
41
|
+
schedule: SurveySchedule.Once,
|
|
42
|
+
conditions: { events: { values: [{ name: 'event' }] } },
|
|
43
|
+
},
|
|
44
|
+
false,
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
'repeated activation without event values',
|
|
48
|
+
{
|
|
49
|
+
schedule: SurveySchedule.Once,
|
|
50
|
+
conditions: { events: { repeatedActivation: true, values: [] } },
|
|
51
|
+
},
|
|
52
|
+
false,
|
|
53
|
+
],
|
|
54
|
+
['undefined schedule without events', { schedule: undefined }, false],
|
|
55
|
+
['null schedule without events', { schedule: null }, false],
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
it.each(cases)('%s returns %p', (_name, survey, expected) => {
|
|
59
|
+
expect(canSurveyActivateRepeatedly(survey)).toBe(expected)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Survey, SurveySchedule } from '../types'
|
|
2
|
+
|
|
3
|
+
// conditions is narrowed to the fields these predicates actually read, so both SDKs'
|
|
4
|
+
// Survey shapes (which still drift in nested condition types) satisfy it structurally.
|
|
5
|
+
type SurveyForRepeatActivation = Pick<Survey, 'schedule'> & {
|
|
6
|
+
conditions?: {
|
|
7
|
+
events?: {
|
|
8
|
+
repeatedActivation?: boolean
|
|
9
|
+
values?: { name: string }[]
|
|
10
|
+
} | null
|
|
11
|
+
} | null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function doesSurveyActivateByEvent(survey: SurveyForRepeatActivation): boolean {
|
|
15
|
+
return !!survey.conditions?.events?.values?.length
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Platform-independent part of "can this survey show again after being seen":
|
|
20
|
+
* event-repeated activation or an 'always' schedule. SDKs may OR in
|
|
21
|
+
* platform-specific state (e.g. the web SDK's in-progress partial responses).
|
|
22
|
+
*/
|
|
23
|
+
export function canSurveyActivateRepeatedly(survey: SurveyForRepeatActivation): boolean {
|
|
24
|
+
return (
|
|
25
|
+
(doesSurveyActivateByEvent(survey) && !!survey.conditions?.events?.repeatedActivation) ||
|
|
26
|
+
survey.schedule === SurveySchedule.Always
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SurveyWithIteration } from './keys'
|
|
1
2
|
import { SurveyResponses, SurveyResponseValue } from '../types'
|
|
2
3
|
import { isArray, isNullish, isUndefined } from '../utils'
|
|
3
4
|
|
|
@@ -73,8 +74,3 @@ type SurveyQuestionForResponses = {
|
|
|
73
74
|
type SurveyForResponses = {
|
|
74
75
|
questions: SurveyQuestionForResponses[]
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
-
type SurveyWithIteration = {
|
|
78
|
-
id: string
|
|
79
|
-
current_iteration?: number | null
|
|
80
|
-
}
|
|
@@ -16,3 +16,5 @@ export {
|
|
|
16
16
|
getLanguageFromStoredPersonProperties,
|
|
17
17
|
normalizeLanguageCode,
|
|
18
18
|
} from './translations'
|
|
19
|
+
export { canSurveyActivateRepeatedly, doesSurveyActivateByEvent } from './activation'
|
|
20
|
+
export { getSurveyIterationKey, isSurveyKeyForSurvey, type SurveyWithIteration } from './keys'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, it } from '@jest/globals'
|
|
2
|
+
import { getSurveyIterationKey, isSurveyKeyForSurvey } from './keys'
|
|
3
|
+
|
|
4
|
+
describe('getSurveyIterationKey', () => {
|
|
5
|
+
const cases: [number | null | undefined, string][] = [
|
|
6
|
+
[2, 'survey-1_2'],
|
|
7
|
+
[1, 'survey-1_1'],
|
|
8
|
+
[0, 'survey-1'],
|
|
9
|
+
[null, 'survey-1'],
|
|
10
|
+
[undefined, 'survey-1'],
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
it.each(cases)('current_iteration %p produces key %p', (currentIteration, expected) => {
|
|
14
|
+
expect(getSurveyIterationKey({ id: 'survey-1', current_iteration: currentIteration })).toBe(expected)
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('isSurveyKeyForSurvey', () => {
|
|
19
|
+
it.each([
|
|
20
|
+
['bare id', 'abc', 'abc', true],
|
|
21
|
+
['first iteration', 'abc_1', 'abc', true],
|
|
22
|
+
['later iteration', 'abc_12', 'abc', true],
|
|
23
|
+
['different survey id', 'def_1', 'abc', false],
|
|
24
|
+
['prefix collision with bare id', 'abcd', 'abc', false],
|
|
25
|
+
['prefix collision with iteration key', 'abcd_1', 'abc', false],
|
|
26
|
+
])('%s: key %p for survey %p returns %p', (_name, key, surveyId, expected) => {
|
|
27
|
+
expect(isSurveyKeyForSurvey(key, surveyId)).toBe(expected)
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Survey } from '../types'
|
|
2
|
+
|
|
3
|
+
export type SurveyWithIteration = Pick<Survey, 'id' | 'current_iteration'>
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* True when a stored display-state key belongs to the given survey: its bare id
|
|
7
|
+
* or any iteration-qualified `id_n` key.
|
|
8
|
+
*/
|
|
9
|
+
export function isSurveyKeyForSurvey(key: string, surveyId: string): boolean {
|
|
10
|
+
return key === surveyId || key.startsWith(`${surveyId}_`)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Iteration-qualified survey identifier ('id' or 'id_iteration'), used to key
|
|
15
|
+
* per-survey display state (seen, in-progress, ...). Keying by iteration lets a
|
|
16
|
+
* repeating survey become visible again when a new iteration starts.
|
|
17
|
+
*/
|
|
18
|
+
export function getSurveyIterationKey(survey: SurveyWithIteration): string {
|
|
19
|
+
if (survey.current_iteration && survey.current_iteration > 0) {
|
|
20
|
+
return `${survey.id}_${survey.current_iteration}`
|
|
21
|
+
}
|
|
22
|
+
return survey.id
|
|
23
|
+
}
|