@solidxai/core 0.1.13-beta.12 → 0.1.13-beta.13
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 +570 -0
- package/CLAUDE.md +26 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +1 -1
- package/dist/services/chatter-message.service.d.ts +4 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +4 -1
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +1 -2
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +2 -16
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +1 -1
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/draft-publish-helper.service.d.ts +1 -0
- package/dist/services/draft-publish-helper.service.d.ts.map +1 -1
- package/dist/services/draft-publish-helper.service.js +38 -4
- package/dist/services/draft-publish-helper.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +62 -6
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +34 -3
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/theme/theme-registry.d.ts +14 -0
- package/dist/theme/theme-registry.d.ts.map +1 -0
- package/dist/theme/theme-registry.js +147 -0
- package/dist/theme/theme-registry.js.map +1 -0
- package/package.json +1 -1
- package/src/seeders/seed-data/solid-core-metadata.json +1 -1
- package/src/services/1.js +6 -0
- package/src/services/chatter-message.service.ts +22 -1
- package/src/services/crud-helper.service.ts +19 -16
- package/src/services/crud.service.ts +2 -1
- package/src/services/draft-publish-helper.service.ts +56 -4
- package/src/services/settings/default-settings-provider.service.ts +34 -3
- package/src/theme/theme-registry.ts +181 -0
- 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,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const env_1 = require("../helpers/env");
|
|
5
|
-
const baseURL = process.env.API_BASE_URL ?? "http://localhost:3000";
|
|
6
|
-
const TEST_USER_EMAIL = (0, env_1.getRequiredEnv)("TEST_USER_EMAIL");
|
|
7
|
-
const TEST_USER_PASSWORD = (0, env_1.getRequiredEnv)("TEST_USER_PASSWORD");
|
|
8
|
-
function base64UrlDecode(input) {
|
|
9
|
-
const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
10
|
-
const padded = normalized.length % 4 === 0
|
|
11
|
-
? normalized
|
|
12
|
-
: normalized.padEnd(normalized.length + (4 - (normalized.length % 4)), "=");
|
|
13
|
-
return Buffer.from(padded, "base64").toString("utf-8");
|
|
14
|
-
}
|
|
15
|
-
function validateJwt(token) {
|
|
16
|
-
const parts = token.split(".");
|
|
17
|
-
if (parts.length !== 3) {
|
|
18
|
-
throw new Error("JWT must have three dot-separated parts.");
|
|
19
|
-
}
|
|
20
|
-
const headerJson = JSON.parse(base64UrlDecode(parts[0]));
|
|
21
|
-
const payloadJson = JSON.parse(base64UrlDecode(parts[1]));
|
|
22
|
-
if (!headerJson || typeof headerJson !== "object") {
|
|
23
|
-
throw new Error("JWT header must be a JSON object.");
|
|
24
|
-
}
|
|
25
|
-
if (!payloadJson || typeof payloadJson !== "object") {
|
|
26
|
-
throw new Error("JWT payload must be a JSON object.");
|
|
27
|
-
}
|
|
28
|
-
if (typeof payloadJson.exp !== "number") {
|
|
29
|
-
throw new Error("JWT payload.exp must be a number.");
|
|
30
|
-
}
|
|
31
|
-
return payloadJson;
|
|
32
|
-
}
|
|
33
|
-
(0, test_1.test)("API: authenticate succeeds with valid credentials", async () => {
|
|
34
|
-
const api = await test_1.request.newContext({
|
|
35
|
-
baseURL,
|
|
36
|
-
extraHTTPHeaders: {
|
|
37
|
-
accept: "*/*",
|
|
38
|
-
"content-type": "application/json",
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
try {
|
|
42
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
43
|
-
data: {
|
|
44
|
-
email: TEST_USER_EMAIL,
|
|
45
|
-
username: "",
|
|
46
|
-
password: TEST_USER_PASSWORD,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
50
|
-
const json = await res.json();
|
|
51
|
-
(0, test_1.expect)(json.statusCode).toBe(200);
|
|
52
|
-
(0, test_1.expect)(Array.isArray(json.message)).toBe(true);
|
|
53
|
-
(0, test_1.expect)(json.message.length).toBe(0);
|
|
54
|
-
(0, test_1.expect)(json.error).toBe("");
|
|
55
|
-
const user = json.data?.user;
|
|
56
|
-
(0, test_1.expect)(user, "Expected data.user to be an object.").toBeTruthy();
|
|
57
|
-
(0, test_1.expect)(typeof user).toBe("object");
|
|
58
|
-
const email = user?.email;
|
|
59
|
-
(0, test_1.expect)(typeof email).toBe("string");
|
|
60
|
-
if (email === TEST_USER_EMAIL) {
|
|
61
|
-
(0, test_1.expect)(email).toBe(TEST_USER_EMAIL);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
(0, test_1.expect)(email.length).toBeGreaterThan(0);
|
|
65
|
-
}
|
|
66
|
-
(0, test_1.expect)(typeof user?.mobile).toBe("string");
|
|
67
|
-
(0, test_1.expect)(typeof user?.username).toBe("string");
|
|
68
|
-
(0, test_1.expect)(typeof user?.forcePasswordChange).toBe("boolean");
|
|
69
|
-
(0, test_1.expect)(typeof user?.id).toBe("number");
|
|
70
|
-
const roles = user?.roles;
|
|
71
|
-
(0, test_1.expect)(Array.isArray(roles)).toBe(true);
|
|
72
|
-
if (Array.isArray(roles)) {
|
|
73
|
-
(0, test_1.expect)(roles.every((role) => typeof role === "string")).toBe(true);
|
|
74
|
-
(0, test_1.expect)(roles).toContain("Admin");
|
|
75
|
-
}
|
|
76
|
-
const accessToken = json.data?.accessToken;
|
|
77
|
-
const refreshToken = json.data?.refreshToken;
|
|
78
|
-
(0, test_1.expect)(typeof accessToken).toBe("string");
|
|
79
|
-
(0, test_1.expect)(typeof refreshToken).toBe("string");
|
|
80
|
-
const accessPayload = validateJwt(accessToken);
|
|
81
|
-
const refreshPayload = validateJwt(refreshToken);
|
|
82
|
-
(0, test_1.expect)(typeof accessPayload.exp).toBe("number");
|
|
83
|
-
(0, test_1.expect)(typeof refreshPayload.exp).toBe("number");
|
|
84
|
-
}
|
|
85
|
-
finally {
|
|
86
|
-
await api.dispose();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
(0, test_1.test)("API: authenticate fails with wrong password", async () => {
|
|
90
|
-
const api = await test_1.request.newContext({
|
|
91
|
-
baseURL,
|
|
92
|
-
extraHTTPHeaders: {
|
|
93
|
-
accept: "*/*",
|
|
94
|
-
"content-type": "application/json",
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
try {
|
|
98
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
99
|
-
data: {
|
|
100
|
-
email: TEST_USER_EMAIL,
|
|
101
|
-
username: "",
|
|
102
|
-
password: `${TEST_USER_PASSWORD}__wrong`,
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
(0, test_1.expect)(res.status()).toBe(401);
|
|
106
|
-
const json = await res.json();
|
|
107
|
-
(0, test_1.expect)(json.statusCode).toBe(401);
|
|
108
|
-
(0, test_1.expect)(json.statusCodeMessage).toBe("Unauthorized");
|
|
109
|
-
(0, test_1.expect)(json.message).toBe("Invalid credentials");
|
|
110
|
-
(0, test_1.expect)(json.error).toBe("Invalid credentials");
|
|
111
|
-
(0, test_1.expect)(json.data?.statusCode).toBe(401);
|
|
112
|
-
(0, test_1.expect)(json.data?.error).toBe("Unauthorized");
|
|
113
|
-
(0, test_1.expect)(json.data?.message).toBe("Invalid credentials");
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
await api.dispose();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
//# sourceMappingURL=authenticate.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../../tests/api/authenticate.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\nimport { getRequiredEnv } from \"../helpers/env\";\n\ntype JwtPayload = {\n exp?: number;\n [key: string]: unknown;\n};\n\nconst baseURL = process.env.API_BASE_URL ?? \"http://localhost:3000\";\nconst TEST_USER_EMAIL = getRequiredEnv(\"TEST_USER_EMAIL\");\nconst TEST_USER_PASSWORD = getRequiredEnv(\"TEST_USER_PASSWORD\");\n\nfunction base64UrlDecode(input: string): string {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded =\n normalized.length % 4 === 0\n ? normalized\n : normalized.padEnd(\n normalized.length + (4 - (normalized.length % 4)),\n \"=\"\n );\n return Buffer.from(padded, \"base64\").toString(\"utf-8\");\n}\n\nfunction validateJwt(token: string): JwtPayload {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"JWT must have three dot-separated parts.\");\n }\n\n const headerJson = JSON.parse(base64UrlDecode(parts[0]));\n const payloadJson = JSON.parse(base64UrlDecode(parts[1]));\n\n if (!headerJson || typeof headerJson !== \"object\") {\n throw new Error(\"JWT header must be a JSON object.\");\n }\n\n if (!payloadJson || typeof payloadJson !== \"object\") {\n throw new Error(\"JWT payload must be a JSON object.\");\n }\n\n if (typeof payloadJson.exp !== \"number\") {\n throw new Error(\"JWT payload.exp must be a number.\");\n }\n\n return payloadJson as JwtPayload;\n}\n\ntest(\"API: authenticate succeeds with valid credentials\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: TEST_USER_PASSWORD,\n },\n });\n\n expect(res.status()).toBe(200);\n const json = await res.json();\n\n expect(json.statusCode).toBe(200);\n expect(Array.isArray(json.message)).toBe(true);\n expect(json.message.length).toBe(0);\n expect(json.error).toBe(\"\");\n\n const user = json.data?.user as Record<string, unknown> | undefined;\n expect(user, \"Expected data.user to be an object.\").toBeTruthy();\n expect(typeof user).toBe(\"object\");\n\n const email = user?.email;\n expect(typeof email).toBe(\"string\");\n if (email === TEST_USER_EMAIL) {\n expect(email).toBe(TEST_USER_EMAIL);\n } else {\n // If your API returns a fixed system email, replace this with an exact match.\n expect((email as string).length).toBeGreaterThan(0);\n }\n\n expect(typeof user?.mobile).toBe(\"string\");\n expect(typeof user?.username).toBe(\"string\");\n expect(typeof user?.forcePasswordChange).toBe(\"boolean\");\n expect(typeof user?.id).toBe(\"number\");\n\n const roles = user?.roles;\n expect(Array.isArray(roles)).toBe(true);\n if (Array.isArray(roles)) {\n expect(roles.every((role) => typeof role === \"string\")).toBe(true);\n expect(roles).toContain(\"Admin\");\n }\n\n const accessToken = json.data?.accessToken;\n const refreshToken = json.data?.refreshToken;\n expect(typeof accessToken).toBe(\"string\");\n expect(typeof refreshToken).toBe(\"string\");\n\n const accessPayload = validateJwt(accessToken as string);\n const refreshPayload = validateJwt(refreshToken as string);\n\n expect(typeof accessPayload.exp).toBe(\"number\");\n expect(typeof refreshPayload.exp).toBe(\"number\");\n } finally {\n await api.dispose();\n }\n});\n\ntest(\"API: authenticate fails with wrong password\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: `${TEST_USER_PASSWORD}__wrong`,\n },\n });\n\n expect(res.status()).toBe(401);\n const json = await res.json();\n\n expect(json.statusCode).toBe(401);\n expect(json.statusCodeMessage).toBe(\"Unauthorized\");\n expect(json.message).toBe(\"Invalid credentials\");\n expect(json.error).toBe(\"Invalid credentials\");\n expect(json.data?.statusCode).toBe(401);\n expect(json.data?.error).toBe(\"Unauthorized\");\n expect(json.data?.message).toBe(\"Invalid credentials\");\n } finally {\n await api.dispose();\n }\n});\n"]}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const auth_1 = require("../helpers/auth");
|
|
5
|
-
const baseURL = process.env.API_BASE_URL ?? "http://localhost:3000";
|
|
6
|
-
async function getCityByName(name) {
|
|
7
|
-
const api = await test_1.request.newContext({
|
|
8
|
-
baseURL,
|
|
9
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
10
|
-
});
|
|
11
|
-
try {
|
|
12
|
-
const res = await api.get(`/api/city-master?filters[name][$eq]=${encodeURIComponent(name)}&limit=1&offset=0`);
|
|
13
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
14
|
-
const json = await res.json();
|
|
15
|
-
const record = json?.data?.records?.[0];
|
|
16
|
-
(0, test_1.expect)(record, `Expected city '${name}' in testData`).toBeTruthy();
|
|
17
|
-
(0, test_1.expect)(record.id, "Expected record to have id").toBeTruthy();
|
|
18
|
-
return record;
|
|
19
|
-
}
|
|
20
|
-
finally {
|
|
21
|
-
await api.dispose();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
test_1.test.describe("CRUDService.findOne (cityMaster)", () => {
|
|
25
|
-
(0, test_1.test)("returns a city by id", async () => {
|
|
26
|
-
const city = await getCityByName("Mumbai");
|
|
27
|
-
const api = await test_1.request.newContext({
|
|
28
|
-
baseURL,
|
|
29
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
30
|
-
});
|
|
31
|
-
try {
|
|
32
|
-
const res = await api.get(`/api/city-master/${city.id}`);
|
|
33
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
34
|
-
const json = await res.json();
|
|
35
|
-
(0, test_1.expect)(json?.data?.id).toBe(city.id);
|
|
36
|
-
(0, test_1.expect)(json?.data?.name).toBe("Mumbai");
|
|
37
|
-
(0, test_1.expect)(json?.data?.description).toBe("Mumbai city");
|
|
38
|
-
}
|
|
39
|
-
finally {
|
|
40
|
-
await api.dispose();
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
(0, test_1.test)("supports fields[] selection", async () => {
|
|
44
|
-
const city = await getCityByName("Pune");
|
|
45
|
-
const api = await test_1.request.newContext({
|
|
46
|
-
baseURL,
|
|
47
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
48
|
-
});
|
|
49
|
-
try {
|
|
50
|
-
const res = await api.get(`/api/city-master/${city.id}?fields[]=id&fields[]=name`);
|
|
51
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
52
|
-
const json = await res.json();
|
|
53
|
-
(0, test_1.expect)(json?.data?.id).toBe(city.id);
|
|
54
|
-
(0, test_1.expect)(json?.data?.name).toBe("Pune");
|
|
55
|
-
(0, test_1.expect)(json?.data?.description).toBeUndefined();
|
|
56
|
-
(0, test_1.expect)(json?.data?.state).toBeUndefined();
|
|
57
|
-
}
|
|
58
|
-
finally {
|
|
59
|
-
await api.dispose();
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
(0, test_1.test)("supports populate=state", async () => {
|
|
63
|
-
const city = await getCityByName("Bengaluru");
|
|
64
|
-
const api = await test_1.request.newContext({
|
|
65
|
-
baseURL,
|
|
66
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
67
|
-
});
|
|
68
|
-
try {
|
|
69
|
-
const res = await api.get(`/api/city-master/${city.id}?populate=state`);
|
|
70
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
71
|
-
const json = await res.json();
|
|
72
|
-
(0, test_1.expect)(json?.data?.name).toBe("Bengaluru");
|
|
73
|
-
(0, test_1.expect)(json?.data?.state).toBeTruthy();
|
|
74
|
-
(0, test_1.expect)(json?.data?.state?.name).toBe("Karnataka");
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
await api.dispose();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
(0, test_1.test)("returns 404 for missing id", async () => {
|
|
81
|
-
const api = await test_1.request.newContext({
|
|
82
|
-
baseURL,
|
|
83
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
84
|
-
});
|
|
85
|
-
try {
|
|
86
|
-
const res = await api.get(`/api/city-master/99999999`);
|
|
87
|
-
(0, test_1.expect)(res.status()).toBe(404);
|
|
88
|
-
const json = await res.json();
|
|
89
|
-
(0, test_1.expect)(String(json?.message)).toContain("cityMaster");
|
|
90
|
-
(0, test_1.expect)(String(json?.message)).toContain("not found");
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
await api.dispose();
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
//# sourceMappingURL=crud-service.findOne.cityMaster.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crud-service.findOne.cityMaster.spec.js","sourceRoot":"","sources":["../../tests/api/crud-service.findOne.cityMaster.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\nimport { getAuthHeaders } from \"../helpers/auth\";\n\nconst baseURL = process.env.API_BASE_URL ?? \"http://localhost:3000\";\n\nasync function getCityByName(name: string) {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(\n `/api/city-master?filters[name][$eq]=${encodeURIComponent(name)}&limit=1&offset=0`\n );\n expect(res.status()).toBe(200);\n const json = await res.json();\n\n const record = json?.data?.records?.[0];\n expect(record, `Expected city '${name}' in testData`).toBeTruthy();\n expect(record.id, \"Expected record to have id\").toBeTruthy();\n\n return record;\n } finally {\n await api.dispose();\n }\n}\n\ntest.describe(\"CRUDService.findOne (cityMaster)\", () => {\n test(\"returns a city by id\", async () => {\n const city = await getCityByName(\"Mumbai\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/${city.id}`);\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.id).toBe(city.id);\n expect(json?.data?.name).toBe(\"Mumbai\");\n expect(json?.data?.description).toBe(\"Mumbai city\");\n } finally {\n await api.dispose();\n }\n });\n\n test(\"supports fields[] selection\", async () => {\n const city = await getCityByName(\"Pune\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(\n `/api/city-master/${city.id}?fields[]=id&fields[]=name`\n );\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.id).toBe(city.id);\n expect(json?.data?.name).toBe(\"Pune\");\n expect(json?.data?.description).toBeUndefined();\n expect(json?.data?.state).toBeUndefined();\n } finally {\n await api.dispose();\n }\n });\n\n test(\"supports populate=state\", async () => {\n const city = await getCityByName(\"Bengaluru\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/${city.id}?populate=state`);\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.name).toBe(\"Bengaluru\");\n expect(json?.data?.state).toBeTruthy();\n expect(json?.data?.state?.name).toBe(\"Karnataka\");\n } finally {\n await api.dispose();\n }\n });\n\n test(\"returns 404 for missing id\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/99999999`);\n expect(res.status()).toBe(404);\n\n const json = await res.json();\n expect(String(json?.message)).toContain(\"cityMaster\");\n expect(String(json?.message)).toContain(\"not found\");\n } finally {\n await api.dispose();\n }\n });\n});\n"]}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
(0, test_1.test)("GET /api/ping returns pong", async () => {
|
|
5
|
-
const baseURL = process.env.BASE_URL || "http://localhost:3000";
|
|
6
|
-
if (!baseURL) {
|
|
7
|
-
throw new Error("baseURL is not configured. Set API_BASE_URL or use the default.");
|
|
8
|
-
}
|
|
9
|
-
const api = await test_1.request.newContext({ baseURL });
|
|
10
|
-
const res = await api.get("/api/ping");
|
|
11
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
12
|
-
const body = await res.json();
|
|
13
|
-
(0, test_1.expect)(body).toEqual({
|
|
14
|
-
statusCode: 200,
|
|
15
|
-
message: [],
|
|
16
|
-
error: "",
|
|
17
|
-
data: { pong: "v1.0.2" },
|
|
18
|
-
});
|
|
19
|
-
await api.dispose();
|
|
20
|
-
});
|
|
21
|
-
//# sourceMappingURL=ping.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ping.spec.js","sourceRoot":"","sources":["../../tests/api/ping.spec.ts"],"names":[],"mappings":";;AAAA,2CAAyD;AAEzD,IAAA,WAAI,EAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,uBAAuB,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,cAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAElD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAA,aAAM,EAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC;QACnB,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,EAAE;QACT,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACzB,CAAC,CAAC;IAEH,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\n\ntest(\"GET /api/ping returns pong\", async () => {\n const baseURL = process.env.BASE_URL || \"http://localhost:3000\";\n if (!baseURL) {\n throw new Error(\"baseURL is not configured. Set API_BASE_URL or use the default.\");\n }\n const api = await request.newContext({ baseURL });\n\n const res = await api.get(\"/api/ping\");\n\n expect(res.status()).toBe(200);\n\n const body = await res.json();\n expect(body).toEqual({\n statusCode: 200,\n message: [],\n error: \"\",\n data: { pong: \"v1.0.2\" },\n });\n\n await api.dispose();\n});\n"]}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAccessToken = getAccessToken;
|
|
4
|
-
exports.getAuthHeaders = getAuthHeaders;
|
|
5
|
-
const test_1 = require("@playwright/test");
|
|
6
|
-
const env_1 = require("./env");
|
|
7
|
-
async function getAccessToken(baseURL) {
|
|
8
|
-
const TEST_USER_EMAIL = (0, env_1.getRequiredEnv)("TEST_USER_EMAIL");
|
|
9
|
-
const TEST_USER_PASSWORD = (0, env_1.getRequiredEnv)("TEST_USER_PASSWORD");
|
|
10
|
-
const api = await test_1.request.newContext({
|
|
11
|
-
baseURL,
|
|
12
|
-
extraHTTPHeaders: {
|
|
13
|
-
accept: "*/*",
|
|
14
|
-
"content-type": "application/json",
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
try {
|
|
18
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
19
|
-
data: {
|
|
20
|
-
email: TEST_USER_EMAIL,
|
|
21
|
-
username: "",
|
|
22
|
-
password: TEST_USER_PASSWORD,
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
26
|
-
const json = await res.json();
|
|
27
|
-
const token = json?.data?.accessToken;
|
|
28
|
-
(0, test_1.expect)(token, "Expected access token from authenticate endpoint.").toBeTruthy();
|
|
29
|
-
return token;
|
|
30
|
-
}
|
|
31
|
-
finally {
|
|
32
|
-
await api.dispose();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
async function getAuthHeaders(baseURL) {
|
|
36
|
-
const token = await getAccessToken(baseURL);
|
|
37
|
-
return {
|
|
38
|
-
authorization: `Bearer ${token}`,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../tests/helpers/auth.ts"],"names":[],"mappings":";;AAGA,wCA6BC;AAED,wCAKC;AAvCD,2CAAmD;AACnD,+BAAuC;AAEhC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,eAAe,GAAG,IAAA,oBAAc,EAAC,iBAAiB,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,IAAA,oBAAc,EAAC,oBAAoB,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,MAAM,cAAO,CAAC,UAAU,CAAC;QACnC,OAAO;QACP,gBAAgB,EAAE;YAChB,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE;YAClD,IAAI,EAAE;gBACJ,KAAK,EAAE,eAAe;gBACtB,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAA,aAAM,EAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,WAAiC,CAAC;QAC5D,IAAA,aAAM,EAAC,KAAK,EAAE,mDAAmD,CAAC,CAAC,UAAU,EAAE,CAAC;QAChF,OAAO,KAAe,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO;QACL,aAAa,EAAE,UAAU,KAAK,EAAE;KACjC,CAAC;AACJ,CAAC","sourcesContent":["import { expect, request } from \"@playwright/test\";\nimport { getRequiredEnv } from \"./env\";\n\nexport async function getAccessToken(baseURL: string) {\n const TEST_USER_EMAIL = getRequiredEnv(\"TEST_USER_EMAIL\");\n const TEST_USER_PASSWORD = getRequiredEnv(\"TEST_USER_PASSWORD\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: TEST_USER_PASSWORD,\n },\n });\n\n expect(res.status()).toBe(200);\n const json = await res.json();\n const token = json?.data?.accessToken as string | undefined;\n expect(token, \"Expected access token from authenticate endpoint.\").toBeTruthy();\n return token as string;\n } finally {\n await api.dispose();\n }\n}\n\nexport async function getAuthHeaders(baseURL: string) {\n const token = await getAccessToken(baseURL);\n return {\n authorization: `Bearer ${token}`,\n };\n}\n"]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRequiredEnv = getRequiredEnv;
|
|
4
|
-
function getRequiredEnv(name) {
|
|
5
|
-
const value = process.env[name];
|
|
6
|
-
if (!value) {
|
|
7
|
-
throw new Error(`Missing required env var: ${name}`);
|
|
8
|
-
}
|
|
9
|
-
return value;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=env.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../tests/helpers/env.ts"],"names":[],"mappings":";;AAAA,wCAMC;AAND,SAAgB,cAAc,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["export function getRequiredEnv(name: string): string {\n const value = process.env[name];\n if (!value) {\n throw new Error(`Missing required env var: ${name}`);\n }\n return value;\n}\n"]}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
Use this as a copy-paste prompt for NotebookLM.
|
|
2
|
-
|
|
3
|
-
:::writing{variant="document" id="73942"}
|
|
4
|
-
Create a neat, professional presentation from the notes below.
|
|
5
|
-
|
|
6
|
-
Audience: SolidX internal product/engineering team
|
|
7
|
-
Purpose: Explain the vision for an installable “AI Agent Builder / AI Agent Registry” module in SolidX
|
|
8
|
-
Tone: Clear, strategic, practical, product-oriented
|
|
9
|
-
Output: A slide-by-slide presentation outline with titles, bullet points, and suggested diagrams
|
|
10
|
-
|
|
11
|
-
Presentation title:
|
|
12
|
-
“SolidX AI Agent Builder: Metadata-Driven Enterprise Agents”
|
|
13
|
-
|
|
14
|
-
Create around 10–12 slides.
|
|
15
|
-
|
|
16
|
-
Structure the presentation as follows:
|
|
17
|
-
|
|
18
|
-
Slide 1: Title Slide
|
|
19
|
-
- SolidX AI Agent Builder / Agent Registry
|
|
20
|
-
- Metadata-driven enterprise agents
|
|
21
|
-
- Position this as the next evolution of SolidX workflows
|
|
22
|
-
|
|
23
|
-
Slide 2: Why This Module?
|
|
24
|
-
Explain the problem:
|
|
25
|
-
- Enterprises need AI agents, but they also need governance, security, auditability, and workflow integration
|
|
26
|
-
- Most agents today are hardcoded or isolated prototypes
|
|
27
|
-
- SolidX can make agents configurable, reusable, governed, and workflow-aware
|
|
28
|
-
|
|
29
|
-
Slide 3: Core Concept
|
|
30
|
-
Explain:
|
|
31
|
-
- AI agents become first-class SolidX metadata entities
|
|
32
|
-
- Each agent is defined using metadata
|
|
33
|
-
- Agent behaviour is configured, not hardcoded
|
|
34
|
-
- Mini-SWE provides the autonomous runtime loop
|
|
35
|
-
|
|
36
|
-
Include visual:
|
|
37
|
-
Agent Definition + Skills + Tools + Knowledge Base + Policies = Runnable Enterprise Agent
|
|
38
|
-
|
|
39
|
-
Slide 4: Installable SolidX Module
|
|
40
|
-
Explain:
|
|
41
|
-
- AI Agent Builder can be installed as a SolidX module
|
|
42
|
-
- It brings its own domain model
|
|
43
|
-
- It can include entities such as Agent, Skill, Tool, Knowledge Base, Policy, Agent Run, Tool Call Log
|
|
44
|
-
- Configuration can be stored directly in metadata JSON
|
|
45
|
-
- Runtime execution records can be stored in database tables
|
|
46
|
-
|
|
47
|
-
Slide 5: Agent Configuration UI
|
|
48
|
-
Explain what users can configure:
|
|
49
|
-
- Agent name and description
|
|
50
|
-
- System instructions
|
|
51
|
-
- Allowed skills
|
|
52
|
-
- Allowed tools
|
|
53
|
-
- Linked knowledge bases
|
|
54
|
-
- Runtime limits
|
|
55
|
-
- Approval policies
|
|
56
|
-
- Output schema
|
|
57
|
-
|
|
58
|
-
Mention that this can be built using native SolidX CRUD screens or a custom Agent Builder UI.
|
|
59
|
-
|
|
60
|
-
Slide 6: Skills Registry
|
|
61
|
-
Explain:
|
|
62
|
-
- Skills are reusable know-how
|
|
63
|
-
- They define how the agent performs a task
|
|
64
|
-
- Examples: Contract Review, Invoice Validation, Customer Escalation Handling, Code Review, Document Classification
|
|
65
|
-
- A skill may contain instructions, prompt templates, examples, decision criteria, and output expectations
|
|
66
|
-
|
|
67
|
-
Make clear:
|
|
68
|
-
Skill = how the agent thinks/performs a task
|
|
69
|
-
|
|
70
|
-
Slide 7: Tool Registry
|
|
71
|
-
Explain:
|
|
72
|
-
- Tools are executable capabilities
|
|
73
|
-
- Examples: Send Email, Search Gmail, Query Database, Create Ticket, Read File, Call API, Search Knowledge Base
|
|
74
|
-
- SolidX can provide a screen where all registered or discovered tools are visible
|
|
75
|
-
- Tools may come from native SolidX APIs, internal systems, MCP servers, Composio, or custom enterprise integrations
|
|
76
|
-
|
|
77
|
-
Make clear:
|
|
78
|
-
Tool = what action the agent can perform
|
|
79
|
-
|
|
80
|
-
Slide 8: Knowledge Base
|
|
81
|
-
Explain:
|
|
82
|
-
- Agents can be attached to specific knowledge bases
|
|
83
|
-
- Examples: company policies, product documentation, SOPs, technical specifications, contract templates
|
|
84
|
-
- Knowledge gives the agent controlled enterprise context
|
|
85
|
-
- Knowledge can be attached to agents, skills, or workflows
|
|
86
|
-
|
|
87
|
-
Slide 9: Agent Runtime Using Mini-SWE
|
|
88
|
-
Explain:
|
|
89
|
-
- Each agent runs as a Mini-SWE loop
|
|
90
|
-
- When invoked, SolidX spawns an Agent Run
|
|
91
|
-
- The runtime receives goal, user input, metadata, skills, tools, knowledge context, policies, and output schema
|
|
92
|
-
- The loop performs: Plan → Act → Use Tool → Observe → Re-plan → Complete
|
|
93
|
-
|
|
94
|
-
Include diagram:
|
|
95
|
-
SolidX Agent Metadata → Mini-SWE Runtime → Tool Calls / Knowledge Search → Structured Result
|
|
96
|
-
|
|
97
|
-
Slide 10: Test Interface
|
|
98
|
-
Explain:
|
|
99
|
-
- Once configured, users can test the agent inside SolidX
|
|
100
|
-
- Default interface: chat-based console
|
|
101
|
-
- Future channels: voice, WhatsApp, Slack, email, embedded app widget
|
|
102
|
-
- This allows business users and developers to validate agents before attaching them to workflows
|
|
103
|
-
|
|
104
|
-
Slide 11: Workflow Integration
|
|
105
|
-
Explain:
|
|
106
|
-
- Any SolidX workflow can include an Agent Handoff step
|
|
107
|
-
- Workflow creates Agent Run
|
|
108
|
-
- Agent works asynchronously
|
|
109
|
-
- Agent returns result via callback/event
|
|
110
|
-
- Workflow continues deterministically
|
|
111
|
-
|
|
112
|
-
Include diagram:
|
|
113
|
-
Workflow → Agent Handoff → Mini-SWE Agent Run → Result Callback → Workflow Continues
|
|
114
|
-
|
|
115
|
-
Slide 12: Strategic Value
|
|
116
|
-
Explain the positioning:
|
|
117
|
-
- SolidX becomes an enterprise agent platform
|
|
118
|
-
- Agents become configurable, reusable, governed, auditable, workflow-aware, tool-aware, and knowledge-aware
|
|
119
|
-
- SolidX remains the control plane
|
|
120
|
-
- Mini-SWE becomes the execution loop
|
|
121
|
-
- Skills provide task expertise
|
|
122
|
-
- Tools provide actions
|
|
123
|
-
- Knowledge bases provide enterprise context
|
|
124
|
-
|
|
125
|
-
End with a strong closing message:
|
|
126
|
-
“SolidX AI Agent Builder turns agents from isolated prototypes into governed, reusable enterprise capabilities.”
|
|
127
|
-
|
|
128
|
-
Design guidance:
|
|
129
|
-
- Use clean enterprise SaaS style
|
|
130
|
-
- Prefer diagrams over dense text
|
|
131
|
-
- Use simple boxes and arrows
|
|
132
|
-
- Use consistent terminology: Agent, Skill, Tool, Knowledge Base, Policy, Agent Run
|
|
133
|
-
- Avoid hype-heavy language
|
|
134
|
-
- Keep each slide concise
|
|
135
|
-
- Add speaker notes for each slide explaining the idea in simple terms
|
|
136
|
-
:::
|