@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.
Files changed (66) hide show
  1. package/node_modules/@posthog/core/dist/surveys/activation.d.ts +20 -0
  2. package/node_modules/@posthog/core/dist/surveys/activation.d.ts.map +1 -0
  3. package/node_modules/@posthog/core/dist/surveys/activation.js +45 -0
  4. package/node_modules/@posthog/core/dist/surveys/activation.mjs +8 -0
  5. package/node_modules/@posthog/core/dist/surveys/events.d.ts +1 -4
  6. package/node_modules/@posthog/core/dist/surveys/events.d.ts.map +1 -1
  7. package/node_modules/@posthog/core/dist/surveys/index.d.ts +2 -0
  8. package/node_modules/@posthog/core/dist/surveys/index.d.ts.map +1 -1
  9. package/node_modules/@posthog/core/dist/surveys/index.js +16 -2
  10. package/node_modules/@posthog/core/dist/surveys/index.mjs +3 -1
  11. package/node_modules/@posthog/core/dist/surveys/keys.d.ts +14 -0
  12. package/node_modules/@posthog/core/dist/surveys/keys.d.ts.map +1 -0
  13. package/node_modules/@posthog/core/dist/surveys/keys.js +45 -0
  14. package/node_modules/@posthog/core/dist/surveys/keys.mjs +8 -0
  15. package/node_modules/@posthog/core/dist/types.d.ts +87 -76
  16. package/node_modules/@posthog/core/dist/types.d.ts.map +1 -1
  17. package/node_modules/@posthog/core/dist/types.js +65 -76
  18. package/node_modules/@posthog/core/dist/types.mjs +66 -77
  19. package/node_modules/@posthog/core/package.json +1 -1
  20. package/node_modules/@posthog/core/src/surveys/activation.spec.ts +61 -0
  21. package/node_modules/@posthog/core/src/surveys/activation.ts +28 -0
  22. package/node_modules/@posthog/core/src/surveys/events.ts +1 -5
  23. package/node_modules/@posthog/core/src/surveys/index.ts +2 -0
  24. package/node_modules/@posthog/core/src/surveys/keys.spec.ts +29 -0
  25. package/node_modules/@posthog/core/src/surveys/keys.ts +23 -0
  26. package/node_modules/@posthog/core/src/types.ts +88 -76
  27. package/node_modules/@posthog/types/dist/posthog-config.d.ts +14 -0
  28. package/node_modules/@posthog/types/dist/posthog-config.d.ts.map +1 -1
  29. package/node_modules/@posthog/types/package.json +1 -1
  30. package/node_modules/@posthog/types/src/posthog-config.ts +15 -0
  31. package/node_modules/@zuplo/core/customer.cli.minified.js +1 -1
  32. package/node_modules/@zuplo/core/index.minified.js +1 -1
  33. package/node_modules/@zuplo/core/package.json +1 -1
  34. package/node_modules/@zuplo/graphql/package.json +1 -1
  35. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  36. package/node_modules/@zuplo/otel/package.json +1 -1
  37. package/node_modules/@zuplo/runtime/out/esm/chunk-K77Z5PRN.js +30 -0
  38. package/node_modules/@zuplo/runtime/out/esm/chunk-K77Z5PRN.js.map +1 -0
  39. package/node_modules/@zuplo/runtime/out/esm/{chunk-HKSZ4V6H.js → chunk-NIKKAYJU.js} +86 -86
  40. package/node_modules/@zuplo/runtime/out/esm/chunk-NIKKAYJU.js.map +1 -0
  41. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  42. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  43. package/node_modules/@zuplo/runtime/out/esm/sdks/aws/index.js +1 -1
  44. package/node_modules/@zuplo/runtime/out/types/index.d.ts +124 -55
  45. package/node_modules/@zuplo/runtime/package.json +1 -1
  46. package/node_modules/avvio/.github/dependabot.yml +42 -2
  47. package/node_modules/avvio/.github/workflows/ci.yml +1 -1
  48. package/node_modules/avvio/.github/workflows/lock-threads.yml +19 -0
  49. package/node_modules/avvio/LICENSE +1 -3
  50. package/node_modules/avvio/README.md +4 -4
  51. package/node_modules/avvio/{boot.js → index.js} +8 -2
  52. package/node_modules/avvio/package.json +8 -8
  53. package/node_modules/avvio/test/esm.mjs +1 -1
  54. package/node_modules/avvio/test/gh-issues/fastify-6843.test.js +48 -0
  55. package/node_modules/avvio/test/on-ready-timeout-await.test.js +1 -1
  56. package/node_modules/avvio/test/types/index.ts +1 -1
  57. package/node_modules/avvio/test/types/tsconfig.json +5 -2
  58. package/node_modules/ws/lib/receiver.js +15 -32
  59. package/node_modules/ws/lib/websocket-server.js +4 -4
  60. package/node_modules/ws/lib/websocket.js +4 -4
  61. package/node_modules/ws/package.json +5 -1
  62. package/package.json +6 -6
  63. package/node_modules/@zuplo/runtime/out/esm/chunk-GBIUQ4JJ.js +0 -30
  64. package/node_modules/@zuplo/runtime/out/esm/chunk-GBIUQ4JJ.js.map +0 -1
  65. package/node_modules/@zuplo/runtime/out/esm/chunk-HKSZ4V6H.js.map +0 -1
  66. /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
- var SurveyPosition = /*#__PURE__*/ function(SurveyPosition) {
93
- SurveyPosition["TopLeft"] = "top_left";
94
- SurveyPosition["TopCenter"] = "top_center";
95
- SurveyPosition["TopRight"] = "top_right";
96
- SurveyPosition["MiddleLeft"] = "middle_left";
97
- SurveyPosition["MiddleCenter"] = "middle_center";
98
- SurveyPosition["MiddleRight"] = "middle_right";
99
- SurveyPosition["Left"] = "left";
100
- SurveyPosition["Right"] = "right";
101
- SurveyPosition["Center"] = "center";
102
- return SurveyPosition;
103
- }({});
104
- var SurveyWidgetType = /*#__PURE__*/ function(SurveyWidgetType) {
105
- SurveyWidgetType["Button"] = "button";
106
- SurveyWidgetType["Tab"] = "tab";
107
- SurveyWidgetType["Selector"] = "selector";
108
- return SurveyWidgetType;
109
- }({});
110
- var SurveyType = /*#__PURE__*/ function(SurveyType) {
111
- SurveyType["Popover"] = "popover";
112
- SurveyType["API"] = "api";
113
- SurveyType["Widget"] = "widget";
114
- SurveyType["ExternalSurvey"] = "external_survey";
115
- return SurveyType;
116
- }({});
117
- var SurveyQuestionDescriptionContentType = /*#__PURE__*/ function(SurveyQuestionDescriptionContentType) {
118
- SurveyQuestionDescriptionContentType["Html"] = "html";
119
- SurveyQuestionDescriptionContentType["Text"] = "text";
120
- return SurveyQuestionDescriptionContentType;
121
- }({});
122
- var SurveyValidationType = /*#__PURE__*/ function(SurveyValidationType) {
123
- SurveyValidationType["MinLength"] = "min_length";
124
- SurveyValidationType["MaxLength"] = "max_length";
125
- return SurveyValidationType;
126
- }({});
127
- var SurveyRatingDisplay = /*#__PURE__*/ function(SurveyRatingDisplay) {
128
- SurveyRatingDisplay["Number"] = "number";
129
- SurveyRatingDisplay["Emoji"] = "emoji";
130
- return SurveyRatingDisplay;
131
- }({});
132
- var SurveyQuestionType = /*#__PURE__*/ function(SurveyQuestionType) {
133
- SurveyQuestionType["Open"] = "open";
134
- SurveyQuestionType["MultipleChoice"] = "multiple_choice";
135
- SurveyQuestionType["SingleChoice"] = "single_choice";
136
- SurveyQuestionType["Rating"] = "rating";
137
- SurveyQuestionType["Link"] = "link";
138
- return SurveyQuestionType;
139
- }({});
140
- var SurveyQuestionBranchingType = /*#__PURE__*/ function(SurveyQuestionBranchingType) {
141
- SurveyQuestionBranchingType["NextQuestion"] = "next_question";
142
- SurveyQuestionBranchingType["End"] = "end";
143
- SurveyQuestionBranchingType["ResponseBased"] = "response_based";
144
- SurveyQuestionBranchingType["SpecificQuestion"] = "specific_question";
145
- return SurveyQuestionBranchingType;
146
- }({});
147
- var SurveyMatchType = /*#__PURE__*/ function(SurveyMatchType) {
148
- SurveyMatchType["Regex"] = "regex";
149
- SurveyMatchType["NotRegex"] = "not_regex";
150
- SurveyMatchType["Exact"] = "exact";
151
- SurveyMatchType["IsNot"] = "is_not";
152
- SurveyMatchType["Icontains"] = "icontains";
153
- SurveyMatchType["NotIcontains"] = "not_icontains";
154
- return SurveyMatchType;
155
- }({});
156
- var SurveySchedule = /*#__PURE__*/ function(SurveySchedule) {
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
- var types_SurveyPosition = /*#__PURE__*/ function(SurveyPosition) {
50
- SurveyPosition["TopLeft"] = "top_left";
51
- SurveyPosition["TopCenter"] = "top_center";
52
- SurveyPosition["TopRight"] = "top_right";
53
- SurveyPosition["MiddleLeft"] = "middle_left";
54
- SurveyPosition["MiddleCenter"] = "middle_center";
55
- SurveyPosition["MiddleRight"] = "middle_right";
56
- SurveyPosition["Left"] = "left";
57
- SurveyPosition["Right"] = "right";
58
- SurveyPosition["Center"] = "center";
59
- return SurveyPosition;
60
- }({});
61
- var types_SurveyWidgetType = /*#__PURE__*/ function(SurveyWidgetType) {
62
- SurveyWidgetType["Button"] = "button";
63
- SurveyWidgetType["Tab"] = "tab";
64
- SurveyWidgetType["Selector"] = "selector";
65
- return SurveyWidgetType;
66
- }({});
67
- var types_SurveyType = /*#__PURE__*/ function(SurveyType) {
68
- SurveyType["Popover"] = "popover";
69
- SurveyType["API"] = "api";
70
- SurveyType["Widget"] = "widget";
71
- SurveyType["ExternalSurvey"] = "external_survey";
72
- return SurveyType;
73
- }({});
74
- var types_SurveyQuestionDescriptionContentType = /*#__PURE__*/ function(SurveyQuestionDescriptionContentType) {
75
- SurveyQuestionDescriptionContentType["Html"] = "html";
76
- SurveyQuestionDescriptionContentType["Text"] = "text";
77
- return SurveyQuestionDescriptionContentType;
78
- }({});
79
- var types_SurveyValidationType = /*#__PURE__*/ function(SurveyValidationType) {
80
- SurveyValidationType["MinLength"] = "min_length";
81
- SurveyValidationType["MaxLength"] = "max_length";
82
- return SurveyValidationType;
83
- }({});
84
- var types_SurveyRatingDisplay = /*#__PURE__*/ function(SurveyRatingDisplay) {
85
- SurveyRatingDisplay["Number"] = "number";
86
- SurveyRatingDisplay["Emoji"] = "emoji";
87
- return SurveyRatingDisplay;
88
- }({});
89
- var types_SurveyQuestionType = /*#__PURE__*/ function(SurveyQuestionType) {
90
- SurveyQuestionType["Open"] = "open";
91
- SurveyQuestionType["MultipleChoice"] = "multiple_choice";
92
- SurveyQuestionType["SingleChoice"] = "single_choice";
93
- SurveyQuestionType["Rating"] = "rating";
94
- SurveyQuestionType["Link"] = "link";
95
- return SurveyQuestionType;
96
- }({});
97
- var types_SurveyQuestionBranchingType = /*#__PURE__*/ function(SurveyQuestionBranchingType) {
98
- SurveyQuestionBranchingType["NextQuestion"] = "next_question";
99
- SurveyQuestionBranchingType["End"] = "end";
100
- SurveyQuestionBranchingType["ResponseBased"] = "response_based";
101
- SurveyQuestionBranchingType["SpecificQuestion"] = "specific_question";
102
- return SurveyQuestionBranchingType;
103
- }({});
104
- var types_SurveyMatchType = /*#__PURE__*/ function(SurveyMatchType) {
105
- SurveyMatchType["Regex"] = "regex";
106
- SurveyMatchType["NotRegex"] = "not_regex";
107
- SurveyMatchType["Exact"] = "exact";
108
- SurveyMatchType["IsNot"] = "is_not";
109
- SurveyMatchType["Icontains"] = "icontains";
110
- SurveyMatchType["NotIcontains"] = "not_icontains";
111
- return SurveyMatchType;
112
- }({});
113
- var types_SurveySchedule = /*#__PURE__*/ function(SurveySchedule) {
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 { types_ActionStepStringMatching as ActionStepStringMatching, types_Compression as Compression, FeatureFlagError, types_PostHogPersistedProperty as PostHogPersistedProperty, types_SurveyMatchType as SurveyMatchType, types_SurveyPosition as SurveyPosition, types_SurveyQuestionBranchingType as SurveyQuestionBranchingType, types_SurveyQuestionDescriptionContentType as SurveyQuestionDescriptionContentType, types_SurveyQuestionType as SurveyQuestionType, types_SurveyRatingDisplay as SurveyRatingDisplay, types_SurveySchedule as SurveySchedule, types_SurveyType as SurveyType, types_SurveyValidationType as SurveyValidationType, types_SurveyWidgetType as SurveyWidgetType, knownUnsafeEditableEvent, knownUnsafeEditableEventProperty };
133
+ export { ActionStepStringMatching, types_Compression as Compression, FeatureFlagError, types_PostHogPersistedProperty as PostHogPersistedProperty, SurveyMatchType, SurveyPosition, SurveyQuestionBranchingType, SurveyQuestionDescriptionContentType, SurveyQuestionType, SurveyRatingDisplay, SurveySchedule, SurveyType, SurveyValidationType, SurveyWidgetType, knownUnsafeEditableEvent, knownUnsafeEditableEventProperty };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/core",
3
- "version": "1.41.0",
3
+ "version": "1.41.1",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },
@@ -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
+ }