Skip to content

Commit 85ba1fc

Browse files
committed
creating an Entity
1 parent 589b467 commit 85ba1fc

File tree

3 files changed

+340
-0
lines changed

3 files changed

+340
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { PageServerLoad } from "./$types";
2+
import { error } from "@sveltejs/kit";
3+
import { SessionOAuthHelper } from "$lib/oauth/sessionHelper";
4+
5+
export const load: PageServerLoad = async ({ locals }) => {
6+
const session = locals.session;
7+
8+
if (!session?.data?.user) {
9+
throw error(401, "Unauthorized");
10+
}
11+
12+
const sessionOAuth = SessionOAuthHelper.getSessionOAuth(session);
13+
const accessToken = sessionOAuth?.accessToken;
14+
15+
if (!accessToken) {
16+
throw error(401, "No API access token available");
17+
}
18+
19+
return {};
20+
};
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
<script lang="ts">
2+
import { goto } from "$app/navigation";
3+
4+
let entityName = $state("");
5+
let entityDescription = $state("");
6+
let schemaJson = $state(`{
7+
"properties": {
8+
"name": {
9+
"type": "string",
10+
"description": "Name field",
11+
"example": "Example Name"
12+
},
13+
"age": {
14+
"type": "integer",
15+
"description": "Age in years",
16+
"minimum": 0,
17+
"maximum": 150
18+
},
19+
"active": {
20+
"type": "boolean",
21+
"description": "Is active",
22+
"example": true
23+
}
24+
},
25+
"required": ["name"]
26+
}`);
27+
let isSubmitting = $state(false);
28+
let schemaError = $state("");
29+
30+
function validateSchema(): boolean {
31+
try {
32+
const parsed = JSON.parse(schemaJson);
33+
if (!parsed.properties || typeof parsed.properties !== "object") {
34+
schemaError = "Schema must have a 'properties' object";
35+
return false;
36+
}
37+
schemaError = "";
38+
return true;
39+
} catch (e) {
40+
schemaError = e instanceof Error ? e.message : "Invalid JSON";
41+
return false;
42+
}
43+
}
44+
45+
async function handleSubmit(e: Event) {
46+
e.preventDefault();
47+
48+
if (!entityName.trim()) {
49+
alert("Entity name is required");
50+
return;
51+
}
52+
53+
if (!validateSchema()) {
54+
alert("Please fix the schema errors");
55+
return;
56+
}
57+
58+
isSubmitting = true;
59+
60+
try {
61+
const schema = JSON.parse(schemaJson);
62+
63+
// Construct the system dynamic entity payload
64+
const payload: Record<string, any> = {};
65+
payload[entityName] = {
66+
description: entityDescription || `${entityName} entity`,
67+
required: schema.required || [],
68+
properties: schema.properties,
69+
};
70+
71+
const response = await fetch(`/api/dynamic-entities/system/create`, {
72+
method: "POST",
73+
headers: {
74+
"Content-Type": "application/json",
75+
},
76+
credentials: "include",
77+
body: JSON.stringify(payload),
78+
});
79+
80+
if (!response.ok) {
81+
const error = await response.json();
82+
throw new Error(error.error || error.message || "Failed to create entity");
83+
}
84+
85+
alert("System dynamic entity created successfully");
86+
goto("/dynamic-entities/system");
87+
} catch (error) {
88+
alert(
89+
error instanceof Error ? error.message : "Failed to create entity",
90+
);
91+
console.error("Create error:", error);
92+
} finally {
93+
isSubmitting = false;
94+
}
95+
}
96+
</script>
97+
98+
<svelte:head>
99+
<title>Create System Dynamic Entity - API Manager</title>
100+
</svelte:head>
101+
102+
<div class="container mx-auto max-w-4xl px-4 py-8">
103+
<!-- Header -->
104+
<div class="mb-6">
105+
<a
106+
href="/dynamic-entities/system"
107+
class="mb-4 inline-flex items-center text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
108+
>
109+
<svg
110+
class="mr-2 h-4 w-4"
111+
fill="none"
112+
stroke="currentColor"
113+
viewBox="0 0 24 24"
114+
>
115+
<path
116+
stroke-linecap="round"
117+
stroke-linejoin="round"
118+
stroke-width="2"
119+
d="M15 19l-7-7 7-7"
120+
/>
121+
</svg>
122+
Back to System Dynamic Entities
123+
</a>
124+
<h1 class="text-3xl font-bold text-gray-900 dark:text-gray-100">
125+
Create System Dynamic Entity
126+
</h1>
127+
<p class="mt-1 text-gray-600 dark:text-gray-400">
128+
Define a new system dynamic entity schema
129+
</p>
130+
</div>
131+
132+
<!-- Form -->
133+
<div
134+
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800"
135+
>
136+
<form onsubmit={handleSubmit} class="space-y-6">
137+
<!-- Entity Name -->
138+
<div>
139+
<label
140+
for="entityName"
141+
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
142+
>
143+
Entity Name <span class="text-red-600">*</span>
144+
</label>
145+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
146+
The name of your entity (e.g., Piano, Guitar, Customer)
147+
</p>
148+
<input
149+
type="text"
150+
id="entityName"
151+
bind:value={entityName}
152+
required
153+
placeholder="e.g., Piano"
154+
class="mt-2 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100"
155+
/>
156+
</div>
157+
158+
<!-- Description -->
159+
<div>
160+
<label
161+
for="description"
162+
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
163+
>
164+
Description
165+
</label>
166+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
167+
A brief description of this entity
168+
</p>
169+
<input
170+
type="text"
171+
id="description"
172+
bind:value={entityDescription}
173+
placeholder="e.g., Musical instrument entity"
174+
class="mt-2 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100"
175+
/>
176+
</div>
177+
178+
<!-- Schema JSON -->
179+
<div>
180+
<label
181+
for="schema"
182+
class="block text-sm font-medium text-gray-700 dark:text-gray-300"
183+
>
184+
Schema (JSON) <span class="text-red-600">*</span>
185+
</label>
186+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
187+
Define the properties of your entity in JSON format
188+
</p>
189+
<textarea
190+
id="schema"
191+
bind:value={schemaJson}
192+
oninput={() => validateSchema()}
193+
rows="15"
194+
class="mt-2 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 font-mono text-sm text-gray-900 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100"
195+
></textarea>
196+
{#if schemaError}
197+
<p class="mt-2 text-sm text-red-600 dark:text-red-400">
198+
{schemaError}
199+
</p>
200+
{/if}
201+
</div>
202+
203+
<!-- Help Text -->
204+
<div
205+
class="rounded-lg border border-blue-200 bg-blue-50 p-4 dark:border-blue-800 dark:bg-blue-900/20"
206+
>
207+
<h3 class="text-sm font-semibold text-blue-900 dark:text-blue-100">
208+
Schema Format Guide
209+
</h3>
210+
<ul
211+
class="mt-2 space-y-1 text-xs text-blue-800 dark:text-blue-200"
212+
>
213+
<li>
214+
<strong>properties:</strong> Define fields with type, description, and
215+
validation rules
216+
</li>
217+
<li>
218+
<strong>type:</strong> Can be "string", "number", "integer", "boolean",
219+
"DATE_WITH_DAY"
220+
</li>
221+
<li>
222+
<strong>required:</strong> Array of required field names (optional)
223+
</li>
224+
<li>
225+
<strong>minimum/maximum:</strong> For numeric validation (optional)
226+
</li>
227+
<li>
228+
<strong>minLength/maxLength:</strong> For string validation (optional)
229+
</li>
230+
<li>
231+
<strong>example:</strong> Example value for the field (optional)
232+
</li>
233+
</ul>
234+
</div>
235+
236+
<!-- Actions -->
237+
<div class="flex justify-end gap-3 border-t pt-4 dark:border-gray-700">
238+
<a
239+
href="/dynamic-entities/system"
240+
class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"
241+
>
242+
Cancel
243+
</a>
244+
<button
245+
type="submit"
246+
disabled={isSubmitting}
247+
class="inline-flex items-center rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-blue-500 dark:hover:bg-blue-600"
248+
>
249+
{#if isSubmitting}
250+
Creating...
251+
{:else}
252+
Create Entity
253+
{/if}
254+
</button>
255+
</div>
256+
</form>
257+
</div>
258+
</div>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { json } from "@sveltejs/kit";
2+
import type { RequestHandler } from "./$types";
3+
import { obp_requests } from "$lib/obp/requests";
4+
import { SessionOAuthHelper } from "$lib/oauth/sessionHelper";
5+
import { createLogger } from "$lib/utils/logger";
6+
7+
const logger = createLogger("SystemDynamicEntityCreateAPI");
8+
9+
export const POST: RequestHandler = async ({ request, locals }) => {
10+
const session = locals.session;
11+
12+
if (!session?.data?.user) {
13+
return json({ error: "Unauthorized" }, { status: 401 });
14+
}
15+
16+
const sessionOAuth = SessionOAuthHelper.getSessionOAuth(session);
17+
const accessToken = sessionOAuth?.accessToken;
18+
19+
if (!accessToken) {
20+
logger.warn("No access token available");
21+
return json({ error: "No API access token available" }, { status: 401 });
22+
}
23+
24+
try {
25+
const body = await request.json();
26+
27+
if (!body || typeof body !== "object") {
28+
return json(
29+
{ error: "Request body must be a valid object" },
30+
{ status: 400 },
31+
);
32+
}
33+
34+
logger.info("Creating system dynamic entity");
35+
logger.info("Payload:", JSON.stringify(body, null, 2));
36+
37+
const endpoint = `/obp/v4.0.0/management/system-dynamic-entities`;
38+
const response = await obp_requests.post(endpoint, body, accessToken);
39+
40+
logger.info("System dynamic entity created successfully");
41+
return json(response);
42+
} catch (err) {
43+
logger.error("Error creating system dynamic entity:", err);
44+
45+
let errorMessage = "Failed to create system dynamic entity";
46+
let obpErrorCode = undefined;
47+
48+
if (err instanceof Error) {
49+
errorMessage = err.message;
50+
if ("obpErrorCode" in err) {
51+
obpErrorCode = (err as any).obpErrorCode;
52+
}
53+
}
54+
55+
const errorResponse: any = { error: errorMessage };
56+
if (obpErrorCode) {
57+
errorResponse.obpErrorCode = obpErrorCode;
58+
}
59+
60+
return json(errorResponse, { status: 500 });
61+
}
62+
};

0 commit comments

Comments
 (0)