@solidxai/core 0.1.13-beta.4 → 0.1.13-beta.6
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/.claude/settings.local.json +16 -0
- package/CHANGELOG.md +1053 -0
- package/CLAUDE.md +26 -0
- package/dist/commands/run-tests.command.d.ts +7 -1
- package/dist/commands/run-tests.command.d.ts.map +1 -1
- package/dist/commands/run-tests.command.js +49 -3
- package/dist/commands/run-tests.command.js.map +1 -1
- package/dist/constants/chatter-message.constants.d.ts +1 -0
- package/dist/constants/chatter-message.constants.d.ts.map +1 -1
- package/dist/constants/chatter-message.constants.js +3 -1
- package/dist/constants/chatter-message.constants.js.map +1 -1
- package/dist/constants/user.constants.d.ts +2 -0
- package/dist/constants/user.constants.d.ts.map +1 -0
- package/dist/constants/user.constants.js +5 -0
- package/dist/constants/user.constants.js.map +1 -0
- package/dist/controllers/chatter-message.controller.d.ts +5 -0
- package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
- package/dist/controllers/chatter-message.controller.js +14 -0
- package/dist/controllers/chatter-message.controller.js.map +1 -1
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +36 -0
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +12 -7
- package/dist/services/chatter-message.service.d.ts +10 -0
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +44 -3
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud.service.d.ts +2 -0
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +13 -1
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +40 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +22 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/testing/adapters/ui/playwright-adapter.d.ts +5 -0
- package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -1
- package/dist/testing/adapters/ui/playwright-adapter.js +17 -1
- package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -1
- package/dist/testing/adapters/ui/ui.types.d.ts +2 -0
- package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -1
- package/dist/testing/adapters/ui/ui.types.js.map +1 -1
- package/dist/testing/steps/ui/actions.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/actions.step.js +6 -2
- package/dist/testing/steps/ui/actions.step.js.map +1 -1
- package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/assertions.step.js +11 -3
- package/dist/testing/steps/ui/assertions.step.js.map +1 -1
- package/dist/testing/steps/ui/form.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/form.step.js +9 -3
- package/dist/testing/steps/ui/form.step.js.map +1 -1
- package/dist/testing/steps/ui/manual.step.js +1 -1
- package/dist/testing/steps/ui/manual.step.js.map +1 -1
- package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/navigation.step.js +3 -1
- package/dist/testing/steps/ui/navigation.step.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/run-tests.command.ts +47 -1
- package/src/constants/chatter-message.constants.ts +12 -0
- package/src/constants/user.constants.ts +13 -0
- package/src/controllers/chatter-message.controller.ts +8 -0
- package/src/entities/user.entity.ts +53 -36
- package/src/seeders/seed-data/solid-core-metadata.json +12 -7
- package/src/services/1.js +6 -0
- package/src/services/chatter-message.service.ts +86 -4
- package/src/services/crud.service.ts +31 -1
- package/src/services/settings/default-settings-provider.service.ts +22 -0
- package/src/testing/README.md +64 -2
- package/src/testing/adapters/ui/playwright-adapter.ts +25 -0
- package/src/testing/adapters/ui/ui.types.ts +2 -0
- package/src/testing/steps/ui/actions.step.ts +8 -4
- package/src/testing/steps/ui/assertions.step.ts +18 -5
- package/src/testing/steps/ui/form.step.ts +16 -6
- package/src/testing/steps/ui/manual.step.ts +1 -1
- package/src/testing/steps/ui/navigation.step.ts +4 -2
- package/dist-tests/api/authenticate.spec.js +0 -119
- package/dist-tests/api/authenticate.spec.js.map +0 -1
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
- package/dist-tests/api/ping.spec.js +0 -21
- package/dist-tests/api/ping.spec.js.map +0 -1
- package/dist-tests/helpers/auth.js +0 -41
- package/dist-tests/helpers/auth.js.map +0 -1
- package/dist-tests/helpers/env.js +0 -11
- package/dist-tests/helpers/env.js.map +0 -1
- package/docs/agent-builder/notebook-lm-prompt-for-agent-builder.md +0 -136
- package/docs/agent-builder/team-ready-note-agent-builder.md +0 -305
- package/docs/agent-hub-grooming.md +0 -301
- package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +0 -438
- package/docs/dashboards/dashboard-curl-smoke-tests.txt +0 -146
- package/docs/dashboards/delete-legacy-dashboard-metadata.sql +0 -172
- package/docs/datasource-introspection-ddl-analysis.md +0 -326
- package/docs/datasource-introspection-implementation-plan.md +0 -306
- package/docs/grouping-enhancements.md +0 -89
- package/docs/java-spring/README.md +0 -3
- package/docs/java-spring/solid-core-module-deep-dive-report.md +0 -1317
- package/docs/module-package-import-handoff.md +0 -691
- package/docs/seed-changes.md +0 -65
- package/docs/test-data-workflow.md +0 -200
- package/docs/type-declaration-import-issue.md +0 -24
- package/docs/workflow/business-automation-example-notes.md +0 -309
- package/docs/workflow/control-flow-node-addition-sop.md +0 -324
- package/docs/workflow/data-engineering-pipeline-example-notes.md +0 -330
- package/docs/workflow/foreach-example-notes.md +0 -187
- package/docs/workflow/hello-world-example-notes.md +0 -271
- package/docs/workflow/kestra-concepts-plugins-blueprints.md +0 -315
- package/docs/workflow/loop-until-example-notes.md +0 -198
- package/docs/workflow/microservices-and-apis-example-notes.md +0 -264
- package/docs/workflow/samples.md +0 -25
- package/docs/workflow/what-is-kestra.md +0 -79
- package/docs/workflow/workflow-core-module-handoff-summary.md +0 -191
- package/docs/workflow/workflow-module-brd.md +0 -185
- package/docs/workflow/workflow-module-domain-model.md +0 -252
- package/docs/workflow/workflow-module-metadata-dsl.md +0 -302
- package/docs/workflow/workflow-module-technical-spec.md +0 -293
- package/docs/workflow/workflow-node-type-contracts.md +0 -635
- package/docs/workflow/workflow-node-ui-metadata-contract.md +0 -1262
- package/docs/workflow/workflow-solidx-model-field-spec.md +0 -284
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assertions.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/assertions.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"assertions.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/assertions.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAiBxD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAwDnE"}
|
|
@@ -14,7 +14,10 @@ function registerAssertionSteps(registry) {
|
|
|
14
14
|
if (!input.selector) {
|
|
15
15
|
throw new Error('Missing "selector" in step.with for op "ui.expectVisible"');
|
|
16
16
|
}
|
|
17
|
-
await page.waitForSelector(input.selector, {
|
|
17
|
+
await page.waitForSelector(input.selector, {
|
|
18
|
+
state: "visible",
|
|
19
|
+
timeout: ctx.ui?.resolveTimeout(input.timeoutMs),
|
|
20
|
+
});
|
|
18
21
|
});
|
|
19
22
|
registry.register("ui.expectHidden", async (ctx, step) => {
|
|
20
23
|
const page = requirePage(ctx, "ui.expectHidden");
|
|
@@ -22,7 +25,10 @@ function registerAssertionSteps(registry) {
|
|
|
22
25
|
if (!input.selector) {
|
|
23
26
|
throw new Error('Missing "selector" in step.with for op "ui.expectHidden"');
|
|
24
27
|
}
|
|
25
|
-
await page.waitForSelector(input.selector, {
|
|
28
|
+
await page.waitForSelector(input.selector, {
|
|
29
|
+
state: "hidden",
|
|
30
|
+
timeout: ctx.ui?.resolveTimeout(input.timeoutMs),
|
|
31
|
+
});
|
|
26
32
|
});
|
|
27
33
|
registry.register("ui.expectText", async (ctx, step) => {
|
|
28
34
|
const page = requirePage(ctx, "ui.expectText");
|
|
@@ -30,7 +36,9 @@ function registerAssertionSteps(registry) {
|
|
|
30
36
|
if (!input.selector) {
|
|
31
37
|
throw new Error('Missing "selector" in step.with for op "ui.expectText"');
|
|
32
38
|
}
|
|
33
|
-
const text = await page
|
|
39
|
+
const text = await page
|
|
40
|
+
.locator(input.selector)
|
|
41
|
+
.innerText({ timeout: ctx.ui?.resolveTimeout(input.timeoutMs) });
|
|
34
42
|
if (input.equals !== undefined) {
|
|
35
43
|
if (text !== input.equals) {
|
|
36
44
|
throw new Error(`Expected text to equal "${input.equals}" but got "${text}"`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assertions.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/assertions.step.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"assertions.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/assertions.step.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype VisibleInput = { selector: string; timeoutMs?: number };\ntype ExpectTextInput = {\n selector: string;\n equals?: string;\n contains?: string;\n timeoutMs?: number;\n};\n\nfunction requirePage(ctx: TestContext, op: string) {\n if (!ctx.ui || !ctx.ui.page) {\n throw new Error(`Missing UI page on context for op \"${op}\"`);\n }\n return ctx.ui.page;\n}\n\nexport function registerAssertionSteps(registry: StepRegistry): void {\n registry.register(\"ui.expectVisible\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.expectVisible\");\n const input = (step.with ?? {}) as VisibleInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.expectVisible\"');\n }\n await page.waitForSelector(input.selector, {\n state: \"visible\",\n timeout: ctx.ui?.resolveTimeout(input.timeoutMs),\n });\n });\n\n registry.register(\"ui.expectHidden\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.expectHidden\");\n const input = (step.with ?? {}) as VisibleInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.expectHidden\"');\n }\n await page.waitForSelector(input.selector, {\n state: \"hidden\",\n timeout: ctx.ui?.resolveTimeout(input.timeoutMs),\n });\n });\n\n registry.register(\"ui.expectText\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.expectText\");\n const input = (step.with ?? {}) as ExpectTextInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.expectText\"');\n }\n\n const text = await page\n .locator(input.selector)\n .innerText({ timeout: ctx.ui?.resolveTimeout(input.timeoutMs) });\n if (input.equals !== undefined) {\n if (text !== input.equals) {\n throw new Error(\n `Expected text to equal \"${input.equals}\" but got \"${text}\"`,\n );\n }\n return;\n }\n if (input.contains !== undefined) {\n if (!text.includes(input.contains)) {\n throw new Error(\n `Expected text to contain \"${input.contains}\" but got \"${text}\"`,\n );\n }\n return;\n }\n\n throw new Error(\n 'Missing \"equals\" or \"contains\" in step.with for op \"ui.expectText\"',\n );\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/form.step.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"form.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/form.step.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAiBxD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CA8C9D"}
|
|
@@ -51,7 +51,9 @@ function registerFormSteps(registry) {
|
|
|
51
51
|
if (input.value === undefined) {
|
|
52
52
|
throw new Error('Missing "value" in step.with for op "ui.fill"');
|
|
53
53
|
}
|
|
54
|
-
await page.fill(input.selector, String(input.value)
|
|
54
|
+
await page.fill(input.selector, String(input.value), {
|
|
55
|
+
timeout: ctx.ui?.resolveTimeout(input.timeoutMs),
|
|
56
|
+
});
|
|
55
57
|
});
|
|
56
58
|
registry.register("ui.select", async (ctx, step) => {
|
|
57
59
|
const page = requirePage(ctx, "ui.select");
|
|
@@ -62,7 +64,9 @@ function registerFormSteps(registry) {
|
|
|
62
64
|
if (input.value === undefined) {
|
|
63
65
|
throw new Error('Missing "value" in step.with for op "ui.select"');
|
|
64
66
|
}
|
|
65
|
-
await page.selectOption(input.selector, String(input.value)
|
|
67
|
+
await page.selectOption(input.selector, String(input.value), {
|
|
68
|
+
timeout: ctx.ui?.resolveTimeout(input.timeoutMs),
|
|
69
|
+
});
|
|
66
70
|
});
|
|
67
71
|
registry.register("ui.uploadFile", async (ctx, step) => {
|
|
68
72
|
const page = requirePage(ctx, "ui.uploadFile");
|
|
@@ -77,7 +81,9 @@ function registerFormSteps(registry) {
|
|
|
77
81
|
const resolved = Array.isArray(input.filePath)
|
|
78
82
|
? input.filePath.map((p) => path.resolve(cwd, String(p)))
|
|
79
83
|
: path.resolve(cwd, String(input.filePath));
|
|
80
|
-
await page.setInputFiles(input.selector, resolved
|
|
84
|
+
await page.setInputFiles(input.selector, resolved, {
|
|
85
|
+
timeout: ctx.ui?.resolveTimeout(input.timeoutMs),
|
|
86
|
+
});
|
|
81
87
|
});
|
|
82
88
|
}
|
|
83
89
|
//# sourceMappingURL=form.step.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/form.step.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"form.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/form.step.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\";\n\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype FillInput = { selector: string; value: string; timeoutMs?: number };\ntype SelectInput = { selector: string; value: string; timeoutMs?: number };\ntype UploadFileInput = {\n selector: string;\n filePath: string | string[];\n timeoutMs?: number;\n};\n\nfunction requirePage(ctx: TestContext, op: string) {\n if (!ctx.ui || !ctx.ui.page) {\n throw new Error(`Missing UI page on context for op \"${op}\"`);\n }\n return ctx.ui.page;\n}\n\nexport function registerFormSteps(registry: StepRegistry): void {\n registry.register(\"ui.fill\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.fill\");\n const input = (step.with ?? {}) as FillInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.fill\"');\n }\n if (input.value === undefined) {\n throw new Error('Missing \"value\" in step.with for op \"ui.fill\"');\n }\n await page.fill(input.selector, String(input.value), {\n timeout: ctx.ui?.resolveTimeout(input.timeoutMs),\n });\n });\n\n registry.register(\"ui.select\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.select\");\n const input = (step.with ?? {}) as SelectInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.select\"');\n }\n if (input.value === undefined) {\n throw new Error('Missing \"value\" in step.with for op \"ui.select\"');\n }\n await page.selectOption(input.selector, String(input.value), {\n timeout: ctx.ui?.resolveTimeout(input.timeoutMs),\n });\n });\n\n registry.register(\"ui.uploadFile\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.uploadFile\");\n const input = (step.with ?? {}) as UploadFileInput;\n if (!input.selector) {\n throw new Error('Missing \"selector\" in step.with for op \"ui.uploadFile\"');\n }\n if (input.filePath === undefined || input.filePath === null) {\n throw new Error('Missing \"filePath\" in step.with for op \"ui.uploadFile\"');\n }\n const cwd = process.cwd();\n const resolved = Array.isArray(input.filePath)\n ? input.filePath.map((p) => path.resolve(cwd, String(p)))\n : path.resolve(cwd, String(input.filePath));\n await page.setInputFiles(input.selector, resolved, {\n timeout: ctx.ui?.resolveTimeout(input.timeoutMs),\n });\n });\n}\n"]}
|
|
@@ -15,7 +15,7 @@ function registerManualSteps(registry) {
|
|
|
15
15
|
const inputConfig = (step.with ?? {});
|
|
16
16
|
const message = inputConfig.message?.trim() || "Manual interaction required.";
|
|
17
17
|
const prompt = inputConfig.prompt?.trim() || "Press Enter to continue...";
|
|
18
|
-
const timeoutMs = inputConfig.timeoutMs;
|
|
18
|
+
const timeoutMs = ctx.ui?.resolveTimeout(inputConfig.timeoutMs);
|
|
19
19
|
const bringToFront = inputConfig.bringToFront ?? true;
|
|
20
20
|
if (ctx.ui?.isHeadless()) {
|
|
21
21
|
throw new Error('Op "ui.waitForManual" requires headed mode. Re-run with --headless false.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manual.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/manual.step.ts"],"names":[],"mappings":";;AAwBA,kDAuDC;AA/ED,qDAAyD;AACzD,+CAAgE;AAgBhE,SAAS,WAAW,CAAC,GAAgB,EAAE,EAAU;IAC/C,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAgB,mBAAmB,CAAC,QAAsB;IACxD,QAAQ,CAAC,QAAQ,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAgB,EAAE,IAAY,EAAE,EAAE;QAC7E,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAClD,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAuB,CAAC;QAC5D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,8BAA8B,CAAC;QAC9E,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,4BAA4B,CAAC;QAC1E,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"manual.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/manual.step.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\n\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype WaitForManualInput = {\n message?: string;\n prompt?: string;\n waitForSelector?: string;\n waitForUrlContains?: string;\n waitForUrlEquals?: string;\n timeoutMs?: number;\n bringToFront?: boolean;\n};\n\nfunction requirePage(ctx: TestContext, op: string) {\n if (!ctx.ui || !ctx.ui.page) {\n throw new Error(`Missing UI page on context for op \"${op}\"`);\n }\n return ctx.ui.page;\n}\n\nexport function registerManualSteps(registry: StepRegistry): void {\n registry.register(\"ui.waitForManual\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.waitForManual\");\n const inputConfig = (step.with ?? {}) as WaitForManualInput;\n const message = inputConfig.message?.trim() || \"Manual interaction required.\";\n const prompt = inputConfig.prompt?.trim() || \"Press Enter to continue...\";\n const timeoutMs = ctx.ui?.resolveTimeout(inputConfig.timeoutMs);\n const bringToFront = inputConfig.bringToFront ?? true;\n\n if (ctx.ui?.isHeadless()) {\n throw new Error('Op \"ui.waitForManual\" requires headed mode. Re-run with --headless false.');\n }\n if (!input.isTTY || !output.isTTY) {\n throw new Error('Op \"ui.waitForManual\" requires an interactive terminal (TTY).');\n }\n\n if (bringToFront) {\n await page.bringToFront();\n }\n\n console.log(\"\");\n console.log(\"════════ Manual Interaction Required ════════\");\n console.log(message);\n console.log(`Scenario: ${ctx.scenarioId}`);\n console.log(`Current URL: ${page.url()}`);\n console.log(prompt);\n\n const rl = createInterface({ input, output });\n try {\n await rl.question(\"\");\n } finally {\n rl.close();\n }\n\n if (inputConfig.waitForSelector) {\n await page.waitForSelector(inputConfig.waitForSelector, {\n state: \"visible\",\n timeout: timeoutMs,\n });\n }\n\n if (inputConfig.waitForUrlEquals) {\n await page.waitForURL(\n (url) => url.toString() === inputConfig.waitForUrlEquals,\n { timeout: timeoutMs },\n );\n }\n\n if (inputConfig.waitForUrlContains) {\n await page.waitForURL(\n (url) => url.toString().includes(String(inputConfig.waitForUrlContains)),\n { timeout: timeoutMs },\n );\n }\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/navigation.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYxD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"navigation.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/navigation.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYxD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAwCpE"}
|
|
@@ -15,7 +15,9 @@ function registerNavigationSteps(registry) {
|
|
|
15
15
|
throw new Error('Missing "url" in step.with for op "ui.goto"');
|
|
16
16
|
}
|
|
17
17
|
const url = ctx.ui?.resolveUrl(input.url) ?? input.url;
|
|
18
|
-
await page.goto(url
|
|
18
|
+
await page.goto(url, {
|
|
19
|
+
timeout: ctx.ui?.resolveNavigationTimeout(input.timeoutMs),
|
|
20
|
+
});
|
|
19
21
|
});
|
|
20
22
|
registry.register("ui.expectUrl", async (ctx, step) => {
|
|
21
23
|
const page = requirePage(ctx, "ui.expectUrl");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/navigation.step.ts"],"names":[],"mappings":";;AAcA,
|
|
1
|
+
{"version":3,"file":"navigation.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/ui/navigation.step.ts"],"names":[],"mappings":";;AAcA,0DAwCC;AA/CD,SAAS,WAAW,CAAC,GAAgB,EAAE,EAAU;IAC/C,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAgB,uBAAuB,CAAC,QAAsB;IAC5D,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,GAAgB,EAAE,IAAY,EAAE,EAAE;QACpE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAc,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC;QACvD,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACnB,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,wBAAwB,CAAC,KAAK,CAAC,SAAS,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,KAAK,EAAE,GAAgB,EAAE,IAAY,EAAE,EAAE;QACzE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAmB,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE3B,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CACb,0BAA0B,KAAK,CAAC,MAAM,cAAc,OAAO,GAAG,CAC/D,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,4BAA4B,KAAK,CAAC,QAAQ,cAAc,OAAO,GAAG,CACnE,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype GotoInput = { url: string; timeoutMs?: number };\ntype ExpectUrlInput = { equals?: string; contains?: string };\n\nfunction requirePage(ctx: TestContext, op: string) {\n if (!ctx.ui || !ctx.ui.page) {\n throw new Error(`Missing UI page on context for op \"${op}\"`);\n }\n return ctx.ui.page;\n}\n\nexport function registerNavigationSteps(registry: StepRegistry): void {\n registry.register(\"ui.goto\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.goto\");\n const input = (step.with ?? {}) as GotoInput;\n if (!input.url) {\n throw new Error('Missing \"url\" in step.with for op \"ui.goto\"');\n }\n const url = ctx.ui?.resolveUrl(input.url) ?? input.url;\n await page.goto(url, {\n timeout: ctx.ui?.resolveNavigationTimeout(input.timeoutMs),\n });\n });\n\n registry.register(\"ui.expectUrl\", async (ctx: TestContext, step: OpStep) => {\n const page = requirePage(ctx, \"ui.expectUrl\");\n const input = (step.with ?? {}) as ExpectUrlInput;\n const current = page.url();\n\n if (input.equals !== undefined) {\n if (current !== input.equals) {\n throw new Error(\n `Expected URL to equal \"${input.equals}\" but got \"${current}\"`,\n );\n }\n return;\n }\n\n if (input.contains !== undefined) {\n if (!current.includes(input.contains)) {\n throw new Error(\n `Expected URL to contain \"${input.contains}\" but got \"${current}\"`,\n );\n }\n return;\n }\n\n throw new Error(\n 'Missing \"equals\" or \"contains\" in step.with for op \"ui.expectUrl\"',\n );\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidxai/core",
|
|
3
|
-
"version": "0.1.13-beta.
|
|
3
|
+
"version": "0.1.13-beta.6",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -7,6 +7,8 @@ import { WebhookReporter } from 'src/testing/reporter/webhook-reporter';
|
|
|
7
7
|
import { runFromMetadata } from 'src/testing/runner/run-from-metadata';
|
|
8
8
|
import type { TestingMetadata } from 'src/testing/contracts/testing-metadata.types';
|
|
9
9
|
import { SpecRegistry } from 'src/testing/core/spec-registry';
|
|
10
|
+
import { SettingService } from 'src/services/setting.service';
|
|
11
|
+
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
10
12
|
|
|
11
13
|
interface TestRunCommandOptions {
|
|
12
14
|
module?: string;
|
|
@@ -18,6 +20,8 @@ interface TestRunCommandOptions {
|
|
|
18
20
|
apiBaseUrl?: string;
|
|
19
21
|
uiBaseUrl?: string;
|
|
20
22
|
headless?: boolean;
|
|
23
|
+
uiTimeoutMs?: number;
|
|
24
|
+
uiNavigationTimeoutMs?: number;
|
|
21
25
|
timeoutMs?: number;
|
|
22
26
|
retries?: number;
|
|
23
27
|
listSpecs?: boolean;
|
|
@@ -34,6 +38,7 @@ export class TestRunCommand extends CommandRunner {
|
|
|
34
38
|
|
|
35
39
|
constructor(
|
|
36
40
|
private readonly moduleMetadataHelperService: ModuleMetadataHelperService,
|
|
41
|
+
private readonly settingService: SettingService,
|
|
37
42
|
) {
|
|
38
43
|
super();
|
|
39
44
|
}
|
|
@@ -89,6 +94,14 @@ export class TestRunCommand extends CommandRunner {
|
|
|
89
94
|
const apiBaseUrl = options?.apiBaseUrl ?? process.env.BASE_URL;
|
|
90
95
|
const uiBaseUrl = options?.uiBaseUrl ?? process.env.FRONTEND_BASE_URL;
|
|
91
96
|
const headless = options?.headless ?? true;
|
|
97
|
+
const uiTimeoutMs =
|
|
98
|
+
options?.uiTimeoutMs
|
|
99
|
+
?? toPositiveNumber(process.env.UI_TIMEOUT_MS)
|
|
100
|
+
?? toPositiveNumber(this.settingService.getConfigValue<SolidCoreSetting>('uiTestDefaultTimeoutMs'));
|
|
101
|
+
const uiNavigationTimeoutMs =
|
|
102
|
+
options?.uiNavigationTimeoutMs
|
|
103
|
+
?? toPositiveNumber(process.env.UI_NAVIGATION_TIMEOUT_MS)
|
|
104
|
+
?? toPositiveNumber(this.settingService.getConfigValue<SolidCoreSetting>('uiTestNavigationTimeoutMs'));
|
|
92
105
|
const printApiLogs = options?.printApiLogs ?? false;
|
|
93
106
|
|
|
94
107
|
const webhookUrl = process.env.SOLIDCTL_WEBHOOK_URL;
|
|
@@ -105,7 +118,12 @@ export class TestRunCommand extends CommandRunner {
|
|
|
105
118
|
skipScenarioIds,
|
|
106
119
|
reporter,
|
|
107
120
|
api: apiBaseUrl ? { baseUrl: apiBaseUrl } : undefined,
|
|
108
|
-
ui: {
|
|
121
|
+
ui: {
|
|
122
|
+
baseUrl: uiBaseUrl,
|
|
123
|
+
headless,
|
|
124
|
+
defaultTimeoutMs: uiTimeoutMs,
|
|
125
|
+
navigationTimeoutMs: uiNavigationTimeoutMs,
|
|
126
|
+
},
|
|
109
127
|
defaults: {
|
|
110
128
|
timeoutMs: options?.timeoutMs,
|
|
111
129
|
retries: options?.retries,
|
|
@@ -225,6 +243,26 @@ export class TestRunCommand extends CommandRunner {
|
|
|
225
243
|
return val === 'false' ? false : true;
|
|
226
244
|
}
|
|
227
245
|
|
|
246
|
+
@Option({
|
|
247
|
+
flags: '--ui-timeout-ms [number]',
|
|
248
|
+
description:
|
|
249
|
+
'Default timeout in ms for UI steps (waits, clicks, fills). Defaults to process.env.UI_TIMEOUT_MS, then the uiTestDefaultTimeoutMs setting, then 30000.',
|
|
250
|
+
required: false,
|
|
251
|
+
})
|
|
252
|
+
parseUiTimeoutMs(val: string): number {
|
|
253
|
+
return Number(val);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@Option({
|
|
257
|
+
flags: '--ui-navigation-timeout-ms [number]',
|
|
258
|
+
description:
|
|
259
|
+
'Default timeout in ms for ui.goto navigation. Defaults to process.env.UI_NAVIGATION_TIMEOUT_MS, then the uiTestNavigationTimeoutMs setting, then --ui-timeout-ms.',
|
|
260
|
+
required: false,
|
|
261
|
+
})
|
|
262
|
+
parseUiNavigationTimeoutMs(val: string): number {
|
|
263
|
+
return Number(val);
|
|
264
|
+
}
|
|
265
|
+
|
|
228
266
|
@Option({
|
|
229
267
|
flags: '--timeout-ms [number]',
|
|
230
268
|
description: 'Default scenario timeout in milliseconds.',
|
|
@@ -262,6 +300,14 @@ function splitCsv(value?: string): string[] | undefined {
|
|
|
262
300
|
return items.length ? items : undefined;
|
|
263
301
|
}
|
|
264
302
|
|
|
303
|
+
// Accepts unknown because settings come back already parsed as numbers, while env
|
|
304
|
+
// vars arrive as strings.
|
|
305
|
+
function toPositiveNumber(value?: unknown): number | undefined {
|
|
306
|
+
if (value === null || value === undefined || value === '') return undefined;
|
|
307
|
+
const parsed = Number(value);
|
|
308
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
265
311
|
function resolveSpecPath(entry: string, metadataPath: string): string {
|
|
266
312
|
if (path.isAbsolute(entry)) {
|
|
267
313
|
return entry;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { USER_SUMMARY_FIELDS } from 'src/constants/user.constants';
|
|
2
|
+
|
|
1
3
|
export const CHATTER_MESSAGE_TYPE = {
|
|
2
4
|
AUDIT: 'audit',
|
|
3
5
|
CUSTOM: 'custom',
|
|
@@ -16,3 +18,13 @@ export const CHATTER_MESSAGE_STATUS = {
|
|
|
16
18
|
PENDING: 'pending',
|
|
17
19
|
COMPLETED: 'completed',
|
|
18
20
|
} as const;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Columns of the message author exposed by the chatter APIs.
|
|
24
|
+
*
|
|
25
|
+
* The chatter panel renders `fullName` (name label + initials avatar) and uses `id`
|
|
26
|
+
* for the own-note edit check; the admin list/form/tree views display `fullName` via
|
|
27
|
+
* each view's `coModelFieldToDisplay`. That is exactly the platform-wide summary
|
|
28
|
+
* shape, so this is an alias rather than a second list to keep in step.
|
|
29
|
+
*/
|
|
30
|
+
export const CHATTER_MESSAGE_USER_FIELDS = USER_SUMMARY_FIELDS;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The columns of a `User` that are safe to embed in another entity's API response.
|
|
3
|
+
*
|
|
4
|
+
* Whenever a user is attached to a record the caller asked for - a `createdBy` /
|
|
5
|
+
* `updatedBy` populate, a chatter message author - the caller wants to display who it
|
|
6
|
+
* was, not to read their profile. Everything else on `User` is PII (email, mobile),
|
|
7
|
+
* authz metadata (roles, apiKeys) or secret, and the embedded user is frequently
|
|
8
|
+
* someone the viewer has no other visibility of.
|
|
9
|
+
*
|
|
10
|
+
* `fullName` is nullable; consumers that need a fallback should use the record's own
|
|
11
|
+
* context rather than widening this list.
|
|
12
|
+
*/
|
|
13
|
+
export const USER_SUMMARY_FIELDS = ['id', 'fullName'] as const;
|
|
@@ -95,6 +95,14 @@ export class ChatterMessageController {
|
|
|
95
95
|
return this.service.find(query);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
@ApiBearerAuth("jwt")
|
|
99
|
+
@ApiQuery({ name: 'search', required: false, type: String })
|
|
100
|
+
@ApiQuery({ name: 'limit', required: false, type: Number })
|
|
101
|
+
@Get('mentionable-users')
|
|
102
|
+
async getMentionableUsers(@Query() query: any) {
|
|
103
|
+
return this.service.getMentionableUsers(query?.search, query?.limit ? +query.limit : undefined);
|
|
104
|
+
}
|
|
105
|
+
|
|
98
106
|
@ApiBearerAuth("jwt")
|
|
99
107
|
@Get(':id')
|
|
100
108
|
async findOne(@Param('id') id: string, @Query() query: any) {
|
|
@@ -5,6 +5,23 @@ import { UserViewMetadata } from 'src/entities/user-view-metadata.entity'
|
|
|
5
5
|
import { UserApiKey } from 'src/entities/user-api-key.entity'
|
|
6
6
|
import { Exclude, Expose } from "class-transformer";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Serialization is locked down twice over, and both halves are load-bearing:
|
|
10
|
+
*
|
|
11
|
+
* - The class-level `@Exclude()` below makes User itself an allowlist: only `@Expose()`d
|
|
12
|
+
* properties are serialized.
|
|
13
|
+
* - Every other property additionally carries its own `@Exclude()`. That looks redundant
|
|
14
|
+
* here, and for `User` it is - but class-transformer resolves the *class-level* strategy
|
|
15
|
+
* with a direct lookup on the exact constructor (MetadataStorage.getStrategy), so a
|
|
16
|
+
* subclass inherits nothing and falls back to `exposeAll`. Since this entity is a
|
|
17
|
+
* `@TableInheritance` root that consuming projects extend (see
|
|
18
|
+
* IExtensionUserCreationProvider), an extension user that forgets its own `@Exclude()`
|
|
19
|
+
* would otherwise serialize the password hash and every OAuth/verification token.
|
|
20
|
+
* Property-level metadata *is* walked up the prototype chain, so the per-property
|
|
21
|
+
* decorators are what actually protect subclasses.
|
|
22
|
+
*
|
|
23
|
+
* Keep both. Adding a new column? Give it `@Expose()` or `@Exclude()` - never neither.
|
|
24
|
+
*/
|
|
8
25
|
@Entity("ss_user")
|
|
9
26
|
@TableInheritance({ column: { type: "varchar", name: "type", default: "User" } })
|
|
10
27
|
@Exclude()
|
|
@@ -30,7 +47,7 @@ export class User extends CommonEntity {
|
|
|
30
47
|
mobile: string;
|
|
31
48
|
|
|
32
49
|
@Column({ type: "varchar", nullable: true })
|
|
33
|
-
|
|
50
|
+
@Exclude()
|
|
34
51
|
password: string;
|
|
35
52
|
|
|
36
53
|
@Column({ nullable: true, default: true })
|
|
@@ -38,67 +55,67 @@ export class User extends CommonEntity {
|
|
|
38
55
|
forcePasswordChange: boolean = true;
|
|
39
56
|
|
|
40
57
|
@Column({ type: "varchar", default: "local" })
|
|
41
|
-
|
|
58
|
+
@Exclude()
|
|
42
59
|
lastLoginProvider: string = "local";
|
|
43
60
|
|
|
44
61
|
@Column({ type: "varchar", nullable: true })
|
|
45
|
-
|
|
62
|
+
@Exclude()
|
|
46
63
|
accessCode: string;
|
|
47
64
|
|
|
48
65
|
@Column({ type: "varchar", nullable: true })
|
|
49
|
-
|
|
66
|
+
@Exclude()
|
|
50
67
|
googleAccessToken: string;
|
|
51
68
|
|
|
52
69
|
@Column({ type: "varchar", nullable: true })
|
|
53
|
-
|
|
70
|
+
@Exclude()
|
|
54
71
|
googleId: string;
|
|
55
72
|
|
|
56
73
|
@Column({ type: "varchar", nullable: true })
|
|
57
|
-
|
|
74
|
+
@Exclude()
|
|
58
75
|
googleProfilePicture: string;
|
|
59
76
|
|
|
60
77
|
@Column({ type: "varchar", nullable: true })
|
|
61
|
-
|
|
78
|
+
@Exclude()
|
|
62
79
|
facebookId: string;
|
|
63
80
|
|
|
64
81
|
@Column({ type: "varchar", nullable: true })
|
|
65
|
-
|
|
82
|
+
@Exclude()
|
|
66
83
|
facebookAccessToken: string;
|
|
67
84
|
|
|
68
85
|
@Column({ type: "varchar", nullable: true })
|
|
69
|
-
|
|
86
|
+
@Exclude()
|
|
70
87
|
facebookProfilePicture: string;
|
|
71
88
|
|
|
72
89
|
@Column({ type: "varchar", nullable: true })
|
|
73
|
-
|
|
90
|
+
@Exclude()
|
|
74
91
|
appleId: string;
|
|
75
92
|
|
|
76
93
|
@Column({ type: "varchar", nullable: true })
|
|
77
|
-
|
|
94
|
+
@Exclude()
|
|
78
95
|
appleAccessToken: string;
|
|
79
96
|
|
|
80
97
|
@Column({ type: "varchar", nullable: true })
|
|
81
|
-
|
|
98
|
+
@Exclude()
|
|
82
99
|
microsoftId: string;
|
|
83
100
|
|
|
84
101
|
@Column({ type: "varchar", nullable: true })
|
|
85
|
-
|
|
102
|
+
@Exclude()
|
|
86
103
|
microsoftAccessToken: string;
|
|
87
104
|
|
|
88
105
|
@Column({ type: "varchar", nullable: true })
|
|
89
|
-
|
|
106
|
+
@Exclude()
|
|
90
107
|
microsoftProfilePicture: string;
|
|
91
108
|
|
|
92
109
|
@Column({ type: "varchar", nullable: true })
|
|
93
|
-
|
|
110
|
+
@Exclude()
|
|
94
111
|
microsoftActiveDirectoryId: string;
|
|
95
112
|
|
|
96
113
|
@Column({ type: "varchar", nullable: true })
|
|
97
|
-
|
|
114
|
+
@Exclude()
|
|
98
115
|
microsoftActiveDirectoryAccessToken: string;
|
|
99
116
|
|
|
100
117
|
@Column({ type: "varchar", nullable: true })
|
|
101
|
-
|
|
118
|
+
@Exclude()
|
|
102
119
|
microsoftActiveDirectoryProfilePicture: string;
|
|
103
120
|
|
|
104
121
|
@Index()
|
|
@@ -107,63 +124,63 @@ export class User extends CommonEntity {
|
|
|
107
124
|
active: boolean = true;
|
|
108
125
|
|
|
109
126
|
@Column({ nullable: true })
|
|
110
|
-
|
|
127
|
+
@Exclude()
|
|
111
128
|
forgotPasswordConfirmedAt: Date;
|
|
112
129
|
|
|
113
130
|
@Column({ type: "varchar", nullable: true })
|
|
114
|
-
|
|
131
|
+
@Exclude()
|
|
115
132
|
verificationTokenOnForgotPassword: string;
|
|
116
133
|
|
|
117
134
|
@Column({ nullable: true })
|
|
118
|
-
|
|
135
|
+
@Exclude()
|
|
119
136
|
verificationTokenOnForgotPasswordExpiresAt: Date;
|
|
120
137
|
|
|
121
138
|
@Column({ nullable: true })
|
|
122
|
-
|
|
139
|
+
@Exclude()
|
|
123
140
|
emailVerifiedOnRegistrationAt: Date;
|
|
124
141
|
|
|
125
142
|
@Column({ type: "varchar", nullable: true })
|
|
126
|
-
|
|
143
|
+
@Exclude()
|
|
127
144
|
emailVerificationTokenOnRegistration: string;
|
|
128
145
|
|
|
129
146
|
@Column({ nullable: true })
|
|
130
|
-
|
|
147
|
+
@Exclude()
|
|
131
148
|
emailVerificationTokenOnRegistrationExpiresAt: Date;
|
|
132
149
|
|
|
133
150
|
@Column({ nullable: true })
|
|
134
|
-
|
|
151
|
+
@Exclude()
|
|
135
152
|
mobileVerifiedOnRegistrationAt: Date;
|
|
136
153
|
|
|
137
154
|
@Column({ type: "varchar", nullable: true })
|
|
138
|
-
|
|
155
|
+
@Exclude()
|
|
139
156
|
mobileVerificationTokenOnRegistration: string;
|
|
140
157
|
|
|
141
158
|
@Column({ nullable: true })
|
|
142
|
-
|
|
159
|
+
@Exclude()
|
|
143
160
|
mobileVerificationTokenOnRegistrationExpiresAt: Date;
|
|
144
161
|
|
|
145
162
|
@Column({ nullable: true })
|
|
146
|
-
|
|
163
|
+
@Exclude()
|
|
147
164
|
emailVerifiedOnLoginAt: Date;
|
|
148
165
|
|
|
149
166
|
@Column({ type: "varchar", nullable: true })
|
|
150
|
-
|
|
167
|
+
@Exclude()
|
|
151
168
|
emailVerificationTokenOnLogin: string;
|
|
152
169
|
|
|
153
170
|
@Column({ nullable: true })
|
|
154
|
-
|
|
171
|
+
@Exclude()
|
|
155
172
|
emailVerificationTokenOnLoginExpiresAt: Date;
|
|
156
173
|
|
|
157
174
|
@Column({ nullable: true })
|
|
158
|
-
|
|
175
|
+
@Exclude()
|
|
159
176
|
mobileVerifiedOnLoginAt: Date;
|
|
160
177
|
|
|
161
178
|
@Column({ type: "varchar", nullable: true })
|
|
162
|
-
|
|
179
|
+
@Exclude()
|
|
163
180
|
mobileVerificationTokenOnLogin: string;
|
|
164
181
|
|
|
165
182
|
@Column({ nullable: true })
|
|
166
|
-
|
|
183
|
+
@Exclude()
|
|
167
184
|
mobileVerificationTokenOnLoginExpiresAt: Date;
|
|
168
185
|
|
|
169
186
|
@Column({ type: "varchar", nullable: true })
|
|
@@ -176,18 +193,18 @@ export class User extends CommonEntity {
|
|
|
176
193
|
roles: RoleMetadata[];
|
|
177
194
|
|
|
178
195
|
@OneToMany(() => UserViewMetadata, userViewMetadata => userViewMetadata.user, { cascade: true })
|
|
179
|
-
|
|
196
|
+
@Exclude()
|
|
180
197
|
userViewMetadata: UserViewMetadata[];
|
|
181
198
|
|
|
182
|
-
|
|
199
|
+
@Exclude()
|
|
183
200
|
@Column({ type: "varchar", default: "bcrypt" })
|
|
184
201
|
passwordScheme: string;
|
|
185
202
|
|
|
186
|
-
|
|
203
|
+
@Exclude()
|
|
187
204
|
@Column({ type: "int", default: 1 })
|
|
188
205
|
passwordSchemeVersion: number;
|
|
189
206
|
|
|
190
|
-
|
|
207
|
+
@Exclude()
|
|
191
208
|
@Column({ nullable: true })
|
|
192
209
|
rehashedAt: Date;
|
|
193
210
|
|