@media-quest/builder 0.0.7 → 0.0.9

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.
@@ -10,12 +10,22 @@ import type { BuilderRuleDto } from "./rulebuilder";
10
10
  import { BuilderRule } from "./rulebuilder";
11
11
  import { DefaultThemeCompiler } from "./theme/default-theme-compiler";
12
12
  import { ImageFile } from "./media-files";
13
- import { SchemaDto, DUtil } from "@media-quest/engine";
13
+ import { SchemaDto, DUtil, PageID, SchemaID } from "@media-quest/engine";
14
+ import { PagePrefix, SchemaPrefix, SchemaPrefixValue } from "./prefix";
14
15
  const U = DUtil;
16
+
17
+ class PrimitiveWrapper<T> {
18
+ constructor(private readonly _value: T) {}
19
+
20
+ get value(): T {
21
+ return this._value;
22
+ }
23
+ }
24
+
15
25
  // type SchemaHash = string & { __MD5__HASH: true };
16
26
  export interface BuilderSchemaDto {
17
- readonly id: string;
18
- readonly prefix: string;
27
+ readonly id: SchemaID;
28
+ readonly prefix: SchemaPrefixValue;
19
29
  readonly mainImage: ImageFile | false;
20
30
  readonly backgroundColor: string;
21
31
  readonly name: string;
@@ -33,6 +43,7 @@ export interface SchemaBuildOutput {
33
43
  }
34
44
 
35
45
  export class BuilderSchema {
46
+ private readonly _prefix: SchemaPrefix;
36
47
  baseHeight = 1300;
37
48
  baseWidth = 1024;
38
49
  backgroundColor = "#000000";
@@ -43,16 +54,22 @@ export class BuilderSchema {
43
54
  return [...this._rules];
44
55
  }
45
56
 
57
+ get prefix(): SchemaPrefixValue {
58
+ return this._prefix.value;
59
+ }
60
+
46
61
  private readonly _tagCollection: TagCollection = TagCollection.create();
47
62
  get tags(): ReadonlyArray<BuilderTag> {
48
63
  return [...this._tagCollection];
49
64
  }
50
- public static create(id: string, name: string, prefix: string) {
51
- return new BuilderSchema(id, name, prefix);
65
+ public static create(id: SchemaID, name: string, prefix: SchemaPrefixValue) {
66
+ const schemaPrefix = SchemaPrefix.castOrCreateRandom(prefix);
67
+ return new BuilderSchema(id, name, schemaPrefix);
52
68
  }
53
69
 
54
70
  public static fromJson(dto: BuilderSchemaDto): BuilderSchema {
55
- const schema = new BuilderSchema(dto.id, dto.name, dto.prefix);
71
+ const schemaPrefix = SchemaPrefix.castOrCreateRandom(dto.prefix);
72
+ const schema = new BuilderSchema(dto.id, dto.name, schemaPrefix);
56
73
  const pages = dto.pages.map(BuilderPage.fromJson);
57
74
  schema._tagCollection.init(dto.tags);
58
75
  schema.backgroundColor = dto.backgroundColor;
@@ -87,13 +104,16 @@ export class BuilderSchema {
87
104
  return dto;
88
105
  }
89
106
  private constructor(
90
- public readonly id: string,
107
+ public readonly id: SchemaID,
91
108
  public name: string,
92
- public prefix: string,
93
- ) {}
109
+ _prefix: SchemaPrefix,
110
+ ) {
111
+ this._prefix = _prefix;
112
+ }
94
113
 
95
114
  addPage(type: BuilderPageType, atIndex = -1): BuilderPage {
96
- const newPage = BuilderPage.create(type, "");
115
+ const pagePrefix = PagePrefix.create();
116
+ const newPage = BuilderPage.create(type, pagePrefix.value);
97
117
  if (atIndex >= 0 && atIndex < this.pages.length) {
98
118
  this.pages.splice(atIndex, 0, newPage);
99
119
  } else {
@@ -188,9 +208,9 @@ export class BuilderSchema {
188
208
  return excludeByTagDto;
189
209
  });
190
210
  const jumpActions: JumpToPageAction[] = [];
191
- const prefix = "";
211
+ const prefix = this.prefix;
192
212
  this.pages.forEach((page, index) => {
193
- const pageVariables = page.getQuestionVariables(prefix, index);
213
+ const pageVariables = page.getQuestionVariables(this._prefix, index);
194
214
  qVars.push(...pageVariables);
195
215
  const mainText = page.mainText.text;
196
216
  const jumpAction: JumpToPageAction = {
@@ -221,25 +241,6 @@ export class BuilderSchema {
221
241
  this._tagCollection.add(builderTag);
222
242
  }
223
243
 
224
- // getHash(): SchemaHash {
225
- // const md5 = MD5(this.toJson());
226
- // return
227
- // }
228
-
229
- // hasChanged(hash: SchemaHash): boolean {
230
- // return hash !== this.getHash();
231
- // }
232
-
233
- private getQuestionVariables(withModulePrefix = false): ReadonlyArray<QuestionVariable> {
234
- const prefix = withModulePrefix ? this.prefix : "";
235
- const all = this.pages
236
- .map((page, index) => {
237
- return page.getQuestionVariables(prefix, index);
238
- })
239
- .flat(1);
240
- return all;
241
- }
242
-
243
244
  compile(): SchemaBuildOutput {
244
245
  const moduleDto = this.toJson();
245
246
  const imp = new DefaultThemeCompiler();
@@ -21,14 +21,9 @@ type BuilderObjectType =
21
21
  export namespace BuilderObjectId {
22
22
  export type QuestionOptionID = string & { __OPTION__ID__: true };
23
23
  export type QuestionID = string & { __QUESTION__ID__: true };
24
- export type VideoFileID = string & { __VIDEO__ID__: true };
25
- export type AudioFileID = string & { __AUDIO__ID__: true };
26
- export type ImageID = string & { __IMAGE__ID__: true };
27
24
  export type TextID = string & { __TEXT__ID__: true };
28
25
  export type MainTextID = string & { __MAIN__TEXT__ID__: true };
29
- export type PageID = string & { __PAGE__ID__: true };
30
26
  export type TagId = string & { __TAG__ID__: true };
31
-
32
27
  export const createTagId = (): TagId => {
33
28
  return createId("builder-tag") as TagId;
34
29
  };
@@ -46,9 +41,6 @@ export namespace BuilderObjectId {
46
41
  export const questionId = (): QuestionID => {
47
42
  return createId("builder-question") as QuestionID;
48
43
  };
49
- export const pageId = (): PageID => {
50
- return createId("builder-page") as PageID;
51
- };
52
44
 
53
45
  const createId = (type: BuilderObjectType): string => {
54
46
  const id = U.randomString(24);
@@ -0,0 +1,5 @@
1
+ describe("Prefix", () => {
2
+ it("should create an instance", () => {
3
+ expect(true).toBeTruthy();
4
+ });
5
+ });
package/src/prefix.ts ADDED
@@ -0,0 +1,107 @@
1
+ export type SchemaPrefixValue = string & { __SCHEMA_PREFIX__: true };
2
+ export type PagePrefixValue = string & { __PAGE_PREFIX__: true };
3
+ // export type QuestionPrefixValue = string & { __QUESTION_PREFIX__: true };
4
+ export type VarID = `${SchemaPrefixValue}_${PagePrefixValue}`;
5
+ export const VarID = {
6
+ create: (schemaPrefix: SchemaPrefixValue, pagePrefix: PagePrefixValue): VarID => {
7
+ const varId = schemaPrefix + "_" + pagePrefix;
8
+ return varId as VarID;
9
+ },
10
+ };
11
+ const createRandomPrefix = <const P extends string>(length: number): P => {
12
+ const letters = "abcdefghijklmnopqrstuvyz";
13
+ const all = letters + letters.toUpperCase();
14
+ let result = "";
15
+ for (let i = 0; i < length; i++) {
16
+ const char = all.charAt(Math.floor(Math.random() * all.length));
17
+ result += char;
18
+ }
19
+ return result as P;
20
+ };
21
+ export class SchemaPrefix {
22
+ public static readonly MIN_LENGTH = 1;
23
+ private static randomLen = 5;
24
+ public static readonly MAX_LENGTH = 16;
25
+ public static fromValue = (value: SchemaPrefixValue): SchemaPrefix => {
26
+ return new SchemaPrefix(value);
27
+ };
28
+
29
+ public static fromValueOrThrow = (value: string): SchemaPrefix => {
30
+ if (!SchemaPrefix.isValid(value)) throw new Error("Invalid prefix");
31
+ return new SchemaPrefix(value);
32
+ };
33
+ public static fromString = (value: string): SchemaPrefix | false => {
34
+ if (!SchemaPrefix.isValid(value)) return false;
35
+ return new SchemaPrefix(value);
36
+ };
37
+ public static castOrCreateRandom = (value: string): SchemaPrefix => {
38
+ const v = SchemaPrefix.isValid(value) ? value : createRandomPrefix<SchemaPrefixValue>(SchemaPrefix.randomLen);
39
+ return new SchemaPrefix(v);
40
+ };
41
+
42
+ public static isValid = (prefix: string | 999): prefix is SchemaPrefixValue => {
43
+ if (typeof prefix !== "string") return false;
44
+ if (prefix.length < SchemaPrefix.MIN_LENGTH) return false;
45
+ if (prefix.length > SchemaPrefix.MAX_LENGTH) return false;
46
+ return true;
47
+ };
48
+
49
+ get value(): SchemaPrefixValue {
50
+ return this._value;
51
+ }
52
+
53
+ set value(value: string) {
54
+ if (!SchemaPrefix.isValid(value)) {
55
+ console.log("INVALID PREFIX", value);
56
+ } else {
57
+ this._value = value;
58
+ }
59
+ }
60
+ private constructor(private _value: SchemaPrefixValue) {}
61
+ }
62
+ export class PagePrefix {
63
+ public static readonly MIN_LENGTH = 1;
64
+ private static randomLen = 5;
65
+ public static readonly MAX_LENGTH = 16;
66
+ public static fromValue = (value: PagePrefixValue): PagePrefix => {
67
+ return new PagePrefix(value);
68
+ };
69
+
70
+ public static create = (): PagePrefix => {
71
+ const v = createRandomPrefix<PagePrefixValue>(PagePrefix.randomLen);
72
+ return new PagePrefix(v);
73
+ };
74
+ public static fromString = (value: string): PagePrefix | false => {
75
+ if (!PagePrefix.isValid(value)) return false;
76
+ return new PagePrefix(value);
77
+ };
78
+
79
+ public static fromStringOrThrow = (value: string): PagePrefixValue => {
80
+ if (!PagePrefix.isValid(value)) throw new Error("Invalid prefix");
81
+ return value;
82
+ };
83
+ public static castOrCreateRandom = (value: string): PagePrefix => {
84
+ const v = PagePrefix.isValid(value) ? value : createRandomPrefix<PagePrefixValue>(PagePrefix.randomLen);
85
+ return new PagePrefix(v);
86
+ };
87
+
88
+ public static isValid = (prefix: string | 999): prefix is PagePrefixValue => {
89
+ if (typeof prefix !== "string") return false;
90
+ if (prefix.length < SchemaPrefix.MIN_LENGTH) return false;
91
+ if (prefix.length > SchemaPrefix.MAX_LENGTH) return false;
92
+ return true;
93
+ };
94
+
95
+ get value(): PagePrefixValue {
96
+ return this._value;
97
+ }
98
+
99
+ set value(value: string) {
100
+ if (!PagePrefix.isValid(value)) {
101
+ console.log("INVALID PREFIX", value);
102
+ } else {
103
+ this._value = value;
104
+ }
105
+ }
106
+ private constructor(private _value: PagePrefixValue) {}
107
+ }
package/src/public-api.ts CHANGED
@@ -8,6 +8,6 @@ export { BuilderMainText, type BuilderMainTextDto } from "./BuilderMainText";
8
8
  export { type BuilderMainVideoDto } from "./BuilderMainVideoDto";
9
9
  export { type BuilderTagDto, BuilderTag, TagCollection } from "./BuilderTag";
10
10
  export { type AudioFile, type ImageFile, type VideoFile } from "./media-files";
11
-
11
+ export * from "./prefix";
12
12
  // Public Api of rule-builder
13
13
  export * from "./rulebuilder";
@@ -3,38 +3,50 @@ import { RuleBuilderTestUtils as U } from "./RuleBuilder-test-utils";
3
3
  import { RuleInput } from "./RuleInput";
4
4
  import type { BuilderConditionGroupDto } from "./condition/Builder-condition-group";
5
5
  import { BuilderConditionDto } from "./condition/Builder-condition";
6
- import { Condition } from "@media-quest/engine";
6
+ import { Condition, PageID } from "@media-quest/engine";
7
+ import { PagePrefix, VarID, SchemaPrefix } from "../prefix";
7
8
 
8
- const { createBuilderVariables_A_H } = U;
9
- let questionVariables = createBuilderVariables_A_H();
10
- const createDto = (): {
9
+ const { createPagesAndVars_A_H } = U;
10
+
11
+ const sxx = SchemaPrefix.fromValueOrThrow("sxx");
12
+ let varsAndPages_A_H = createPagesAndVars_A_H(sxx);
13
+
14
+ const varId = (sxx: SchemaPrefix, pxx: string): VarID => {
15
+ const pagePrefix = PagePrefix.fromStringOrThrow(pxx);
16
+ return VarID.create(sxx.value, pagePrefix);
17
+ };
18
+ const createDto = (
19
+ modulePrefix: SchemaPrefix,
20
+ ): {
11
21
  ruleInput: RuleInput;
12
22
  builderRuleDto: BuilderRuleDto;
13
23
  } => {
14
- const v1 = U.createRuleVariable("v1", 1);
15
- const v2 = U.createRuleVariable("v2", 2);
16
- const v3 = U.createRuleVariable("v3", 3);
17
- const v4 = U.createRuleVariable("v4", 4);
18
- const vg1 = U.createRuleVariable("vg1", 5);
19
- const vg2 = U.createRuleVariable("vg2", 6);
20
- const vg3 = U.createRuleVariable("vg3", 7);
21
- const vg4 = U.createRuleVariable("vg4", 8);
24
+ const v1 = U.createRuleVariable(varId(modulePrefix, "v1"), 1);
25
+ const v2 = U.createRuleVariable(varId(modulePrefix, "v2"), 2);
26
+ const v3 = U.createRuleVariable(varId(modulePrefix, "v3"), 3);
27
+ const v4 = U.createRuleVariable(varId(modulePrefix, "v4"), 4);
28
+ const vg1 = U.createRuleVariable(varId(modulePrefix, "vg1"), 5);
29
+ const vg2 = U.createRuleVariable(varId(modulePrefix, "vg2"), 6);
30
+ const vg3 = U.createRuleVariable(varId(modulePrefix, "vg3"), 7);
31
+ const vg4 = U.createRuleVariable(varId(modulePrefix, "vg4"), 8);
22
32
  const variableList = [v1, v2, v3, v4, vg1, vg2, vg3, vg4];
23
33
  const tagAction1 = U.excludeByTagAction("tag1");
24
34
  const tagAction2 = U.excludeByTagAction("tag2");
25
35
  const tagAction3 = U.excludeByTagAction("tag3");
26
36
  const tagAction4 = U.excludeByTagAction("tag4");
27
- const pageAction1 = U.excludeByPageIdAction(v1.varId, v1.pageNumber);
28
- const pageAction2 = U.excludeByPageIdAction(v2.varId, v2.pageNumber);
29
- const pageAction3 = U.excludeByPageIdAction(v3.varId, v3.pageNumber);
30
- const pageAction4 = U.excludeByPageIdAction(v4.varId, v4.pageNumber);
31
- const jumpToPageAction1 = U.jumpToPageAction(v1.varId, v1.pageNumber);
32
- const jumpToPageAction2 = U.jumpToPageAction(v2.varId, v2.pageNumber);
33
- const jumpToPageAction3 = U.jumpToPageAction(v3.varId, v3.pageNumber);
34
- const jumpToPageAction4 = U.jumpToPageAction(v4.varId, v1.pageNumber);
35
-
36
- // const pageAction =
37
- // const excludeByTagList = [];
37
+ const pageId1 = PageID.create();
38
+ const pageId2 = PageID.create();
39
+ const pageId3 = PageID.create();
40
+ const pageId4 = PageID.create();
41
+ const pageAction1 = U.excludeByPageIdAction(pageId1, v1.pageNumber);
42
+ const pageAction2 = U.excludeByPageIdAction(pageId2, v2.pageNumber);
43
+ const pageAction3 = U.excludeByPageIdAction(pageId3, v3.pageNumber);
44
+ const pageAction4 = U.excludeByPageIdAction(pageId4, v4.pageNumber);
45
+ const jumpToPageAction1 = U.jumpToPageAction(pageId1, v1.pageNumber);
46
+ const jumpToPageAction2 = U.jumpToPageAction(pageId2, v2.pageNumber);
47
+ const jumpToPageAction3 = U.jumpToPageAction(pageId3, v3.pageNumber);
48
+ const jumpToPageAction4 = U.jumpToPageAction(pageId4, v1.pageNumber);
49
+
38
50
  const ruleInput = new RuleInput(
39
51
  variableList,
40
52
  [],
@@ -60,7 +72,7 @@ const createDto = (): {
60
72
  const builderRuleDto1: BuilderRuleDto = {
61
73
  type: "any",
62
74
  jumpToPage: false,
63
- excludePages: [v1.varId, v3.varId],
75
+ excludePages: [pageId1, pageId3],
64
76
  excludeTags: [tagAction1.tag, tagAction2.tag],
65
77
  name: "kitchen-sink",
66
78
  conditions: [c1, c2, group3, c3, c4],
@@ -78,9 +90,17 @@ let dto: BuilderRuleDto = {
78
90
  };
79
91
 
80
92
  const excludeByTagActionList = U.excludeByTagActionList();
81
- const pageActions = questionVariables.map((q) => U.excludeByPageIdAction(q.varId, q.pageNumber));
82
-
83
- let ruleInput = new RuleInput(questionVariables, [], [...pageActions], excludeByTagActionList, []);
93
+ // const pageActions = questionVariables.list.map((q) => U.excludeByPageIdAction(q.pageId, q.pageNumber));
94
+ // const pageActions = questionVariables.map((q) => U.excludeByPageIdAction(, q.pageNumber));
95
+ // const pageActions = varsAndPages_A_H.pageIds((p) => U.excludeByPageIdAction(p.pageId, p.pageNumber));
96
+ let ruleInput = new RuleInput(
97
+ varsAndPages_A_H.list,
98
+ [],
99
+ [...varsAndPages_A_H.pageIdList.map((id, index) => U.excludeByPageIdAction(id, index))],
100
+ excludeByTagActionList,
101
+ [],
102
+ );
103
+ // let ruleInput = new RuleInput(questionVariables.list, [], [], excludeByTagActionList, []);
84
104
 
85
105
  let rule: BuilderRule = BuilderRule.fromDto(dto, ruleInput);
86
106
 
@@ -187,7 +207,8 @@ describe("Builder Rule", () => {
187
207
  });
188
208
 
189
209
  test("fromJSON -> toJSON -> are equal.", () => {
190
- const data = createDto();
210
+ const schemaPrefix = SchemaPrefix.fromValueOrThrow("ax");
211
+ const data = createDto(schemaPrefix);
191
212
 
192
213
  const localRule = BuilderRule.fromDto(data.builderRuleDto, data.ruleInput);
193
214
 
@@ -212,8 +233,11 @@ describe("Builder Rule", () => {
212
233
  expect(ruleInput.excludeByTagActions.length).toStrictEqual(10);
213
234
  });
214
235
 
236
+ // TODO FIX THIS TEST.
215
237
  test("toEngineRuleWorks: ", () => {
216
- const input = createDto().ruleInput;
238
+ const schemaPrefix = SchemaPrefix.fromValueOrThrow("ax");
239
+ const dto = createDto(schemaPrefix);
240
+ const input = dto.ruleInput;
217
241
  const v1 = input.questionVars[0];
218
242
  const v2 = input.questionVars[1];
219
243
  const tag1 = input.excludeByTagActions[0];
@@ -247,26 +271,30 @@ describe("Builder Rule", () => {
247
271
  type: "all",
248
272
  };
249
273
 
250
- const dtoWithOneCondition: BuilderRuleDto = {
274
+ expect(c1.variableId).toBe(schemaPrefix.value + "_v1");
275
+
276
+ const dtoWithThreeCondition: BuilderRuleDto = {
251
277
  type: "all",
252
278
  name: "dto-with-one-condition",
253
279
  excludePages: [pageAction1.pageId],
254
280
  excludeTags: [tag1.tag],
255
- jumpToPage: v1.varId,
281
+ jumpToPage: pageAction1.pageId,
256
282
  conditions: [c1, conditionGroupALL, conditionGroupANY],
257
283
  };
258
284
 
259
285
  const actionCount =
260
- dtoWithOneCondition.excludeTags.length +
261
- dtoWithOneCondition.excludePages.length +
262
- (dtoWithOneCondition.jumpToPage ? 1 : 0);
286
+ dtoWithThreeCondition.excludeTags.length +
287
+ dtoWithThreeCondition.excludePages.length +
288
+ (dtoWithThreeCondition.jumpToPage ? 1 : 0);
289
+
290
+ const rule = BuilderRule.fromDto(dtoWithThreeCondition, input);
263
291
 
264
- const rule = BuilderRule.fromDto(dtoWithOneCondition, input);
265
292
  const engineRule = rule.toEngineRule();
266
293
 
267
294
  // console.log(rule);
268
295
  expect(engineRule.all.length).toBe(3);
269
296
  expect(engineRule.some.length).toBe(0);
297
+ // expect(engineRule.all[0]).toBe(0);
270
298
 
271
299
  const simple1 = engineRule.all.find(
272
300
  (c) => c.kind === "numeric-condition" && c.referenceId === c1.variableId,
@@ -286,6 +314,7 @@ describe("Builder Rule", () => {
286
314
  expect(complexChild1.value).toBe(c2.value);
287
315
  expect(complexChild1.referenceLabel).toBe(v2.label);
288
316
  expect(complexChild1.operator === "eq").toBeTruthy();
317
+ // expect(engineRule.onSuccess).toBe(1);
289
318
  expect(engineRule.onSuccess.length).toBe(actionCount);
290
319
  });
291
320
  });
@@ -132,18 +132,18 @@ export class BuilderRule extends BuilderObject<"builder-rule", BuilderRuleDto> {
132
132
  };
133
133
  return dto;
134
134
  }
135
- toEngineRule(modulePrefix: string): PageQueRules {
135
+ toEngineRule(): PageQueRules {
136
136
  const conditions: Condition[] = [];
137
137
  this._conditions.forEach((c) => {
138
138
  if (c) {
139
139
  if (c instanceof BuilderCondition) {
140
- const simpleCondition = c.toEngineCondition(modulePrefix);
140
+ const simpleCondition = c.toEngineCondition();
141
141
  if (simpleCondition) {
142
142
  conditions.push(simpleCondition);
143
143
  }
144
144
  }
145
145
  if (c instanceof BuilderConditionGroup) {
146
- const complexCondition = c.toEngineConditionComplex(modulePrefix);
146
+ const complexCondition = c.toEngineConditionComplex();
147
147
  if (complexCondition) conditions.push(complexCondition);
148
148
  }
149
149
  }
@@ -1,19 +1,21 @@
1
+ import { PageID } from "@media-quest/engine";
2
+
1
3
  export interface ExcludeByPageAction {
2
- readonly kind: 'exclude-by-pageId';
3
- readonly pageId: string;
4
+ readonly kind: "exclude-by-pageId";
5
+ readonly pageId: PageID;
4
6
  readonly mainText: string;
5
7
  readonly pageNumber: number;
6
8
  }
7
9
 
8
10
  export interface JumpToPageAction {
9
- readonly kind: 'jump-to-page';
10
- readonly pageId: string;
11
+ readonly kind: "jump-to-page";
12
+ readonly pageId: PageID;
11
13
  readonly mainText: string;
12
14
  readonly pageNumber: number;
13
15
  }
14
16
 
15
17
  export interface ExcludeByTagAction {
16
- readonly kind: 'exclude-by-tag';
18
+ readonly kind: "exclude-by-tag";
17
19
  readonly tag: string;
18
20
  readonly description: string;
19
21
  readonly pageCount: number;