@rytass/bpm-core-client 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +69 -3
  4. package/package.json +5 -4
  5. package/src/index.js +7 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/api-auth-client.d.ts +73 -0
  8. package/src/lib/api-auth-client.js +121 -0
  9. package/src/lib/api-auth-client.js.map +1 -0
  10. package/src/lib/form/form-api.d.ts +48 -0
  11. package/src/lib/form/form-api.js +228 -0
  12. package/src/lib/form/form-api.js.map +1 -0
  13. package/src/lib/form/form-rendering.d.ts +52 -0
  14. package/src/lib/form/form-rendering.js +341 -0
  15. package/src/lib/form/form-rendering.js.map +1 -0
  16. package/src/lib/form/index.js +6 -0
  17. package/src/lib/form/index.js.map +1 -0
  18. package/src/lib/graphql-client.d.ts +45 -0
  19. package/src/lib/graphql-client.js +92 -0
  20. package/src/lib/graphql-client.js.map +1 -0
  21. package/src/lib/member-api.d.ts +49 -0
  22. package/src/lib/member-api.js +72 -0
  23. package/src/lib/member-api.js.map +1 -0
  24. package/src/lib/organization/index.js +5 -0
  25. package/src/lib/organization/index.js.map +1 -0
  26. package/src/lib/organization/organization-api.d.ts +168 -0
  27. package/src/lib/organization/organization-api.js +394 -0
  28. package/src/lib/organization/organization-api.js.map +1 -0
  29. package/src/lib/template/index.js +5 -0
  30. package/src/lib/template/index.js.map +1 -0
  31. package/src/lib/template/template-api.d.ts +150 -0
  32. package/src/lib/template/template-api.js +407 -0
  33. package/src/lib/template/template-api.js.map +1 -0
  34. package/src/lib/workflow/index.js +5 -0
  35. package/src/lib/workflow/index.js.map +1 -0
  36. package/src/lib/workflow/workflow-api.d.ts +376 -0
  37. package/src/lib/workflow/workflow-api.js +867 -0
  38. package/src/lib/workflow/workflow-api.js.map +1 -0
  39. package/eslint.config.mjs +0 -19
  40. package/jest.config.cts +0 -10
  41. package/project.json +0 -66
  42. package/src/lib/api-auth-client.ts +0 -169
  43. package/src/lib/form/form-api.spec.ts +0 -81
  44. package/src/lib/form/form-api.ts +0 -388
  45. package/src/lib/form/form-rendering.ts +0 -580
  46. package/src/lib/graphql-client.spec.ts +0 -65
  47. package/src/lib/graphql-client.ts +0 -114
  48. package/src/lib/member-api.ts +0 -129
  49. package/src/lib/organization/organization-api.spec.ts +0 -90
  50. package/src/lib/organization/organization-api.ts +0 -710
  51. package/src/lib/template/template-api.spec.ts +0 -88
  52. package/src/lib/template/template-api.ts +0 -772
  53. package/src/lib/workflow/workflow-api.spec.ts +0 -132
  54. package/src/lib/workflow/workflow-api.ts +0 -1749
  55. package/tsconfig.json +0 -27
  56. package/tsconfig.lib.json +0 -16
  57. package/tsconfig.spec.json +0 -16
  58. /package/src/{index.ts → index.d.ts} +0 -0
  59. /package/src/lib/form/{index.ts → index.d.ts} +0 -0
  60. /package/src/lib/organization/{index.ts → index.d.ts} +0 -0
  61. /package/src/lib/template/{index.ts → index.d.ts} +0 -0
  62. /package/src/lib/workflow/{index.ts → index.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -8,6 +8,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  Releases are managed by [`nx release`](https://nx.dev/recipes/nx-release) with
9
9
  Conventional Commits — see `nx.json` for the release config.
10
10
 
11
+ ## 0.1.5 — 2026-05-28
12
+
13
+ ### Documentation
14
+
15
+ - **README "Organization mirror pattern" section.** Condensed pointer to
16
+ the full pattern in `@rytass/bpm-core-nestjs-module`'s README plus a
17
+ client-side worked example using `createOrgUnit`, `updateOrgUnit`,
18
+ `deleteOrgUnit`, `commitOrgUnitTreeDraft`, `createPosition`,
19
+ `createMembership`, `createManagerResolution`. Clarifies that BPM owns
20
+ the org graph and host applications mirror their existing org data in
21
+ rather than expose a resolver (in contrast to the member-resolver
22
+ pattern).
23
+
24
+ ### Why a patch
25
+
26
+ No type or runtime change. README only.
27
+
28
+ ## 0.1.4 — 2026-05-27
29
+
30
+ No source changes. Bumped in lockstep with
31
+ `@rytass/bpm-core-nestjs-module@0.1.4` (re-publish after the 0.1.3
32
+ backend tarball shipped only `.ts` source — see that package's CHANGELOG).
33
+
34
+ ## 0.1.3 — 2026-05-27 (deprecated on npm)
35
+
36
+ Lockstep bump alongside the broken 0.1.3 backend release. Avoid;
37
+ upgrade directly to 0.1.4 or newer.
38
+
11
39
  ## 0.1.2 — 2026-05-27
12
40
 
13
41
  No source changes. Bumped in lockstep with
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rytass
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -151,9 +151,9 @@ default endpoint, no cookie jar. Treat them the same as Server Components.
151
151
 
152
152
  ## Endpoint Resolution
153
153
 
154
- By default the client targets the same origin (no `/api` prefix) — see
155
- [`docs/10-bpm-embedding-auth.md`](../../docs/10-bpm-embedding-auth.md) for the
156
- host contract. Endpoint resolution rules:
154
+ By default the client targets the same origin (no `/api` prefix) — see the
155
+ "Embedding & auth" section of `@rytass/bpm-core-nestjs-module`'s README for
156
+ the host-side contract. Endpoint resolution rules:
157
157
 
158
158
  | Source | Behavior |
159
159
  | ----------------------------------------------- | -------------------------------------------------------------------------- |
@@ -206,6 +206,72 @@ Every subpath uses the same `requestGraphQl` transport from the root. Hosts
206
206
  can mix and match — for example a read-only dashboard might only import
207
207
  `workflow` queries, never reaching for `/organization` mutations.
208
208
 
209
+ ## Organization Mirror Pattern (Important)
210
+
211
+ > **TL;DR:** BPM owns the org graph (`org_units`, `positions`,
212
+ > `memberships`, `manager_resolutions`). Hosts with their own org model
213
+ > mirror data **into** BPM via the `/organization` mutations rather than
214
+ > exposing a host-side resolver. See the
215
+ > "Organization Data Ownership" section of
216
+ > `@rytass/bpm-core-nestjs-module`'s README for the rationale.
217
+
218
+ The integration shape is **asymmetric** with `BPMMemberResolver`:
219
+ member identity stays in the host's user table and BPM reaches in via
220
+ the resolver token; the org structure lives in BPM and the host pushes
221
+ data in. Three rules keep the mirror idempotent:
222
+
223
+ 1. **Use `code` as the natural key.** Both `OrgUnit` and `Position`
224
+ carry a unique `code` you control. On every sync, look up by `code`
225
+ before deciding INSERT vs UPDATE.
226
+ 2. **Stash the host-FK in `metadata`.** Both entities carry an opaque
227
+ `metadata` JSON BPM never introspects — store your host's primary
228
+ key there to chase pointers back during reconciliation.
229
+ 3. **Soft-delete via the `delete*` mutations.** They set `deletedAt`;
230
+ live queries (`orgUnits`, `orgUnitCount`, etc.) filter soft-deleted
231
+ rows automatically.
232
+
233
+ Quick wire-up using only this package's exports:
234
+
235
+ ```ts
236
+ import {
237
+ createOrgUnit,
238
+ updateOrgUnit,
239
+ orgUnits,
240
+ } from '@rytass/bpm-core-client/organization';
241
+
242
+ async function upsertOrgUnit(hostUnit: {
243
+ code: string;
244
+ name: string;
245
+ type: 'COMPANY' | 'DIVISION' | 'DEPARTMENT' | 'TEAM';
246
+ parentCode: string | null;
247
+ hostId: string;
248
+ }): Promise<string> {
249
+ const existing = (await orgUnits({ searchText: hostUnit.code })).find(
250
+ (u) => u.code === hostUnit.code,
251
+ );
252
+ const parentId = hostUnit.parentCode
253
+ ? (await orgUnits({ searchText: hostUnit.parentCode })).find(
254
+ (u) => u.code === hostUnit.parentCode,
255
+ )?.id ?? null
256
+ : null;
257
+ const metadataJson = JSON.stringify({ hostId: hostUnit.hostId });
258
+
259
+ if (existing) {
260
+ return (
261
+ await updateOrgUnit({
262
+ id: existing.id,
263
+ input: { ...hostUnit, parentId, metadataJson },
264
+ })
265
+ ).id;
266
+ }
267
+ return (await createOrgUnit({ ...hostUnit, parentId, metadataJson })).id;
268
+ }
269
+ ```
270
+
271
+ `createPosition`, `createMembership`, `updateMembership`, and
272
+ `createManagerResolution` follow the same pattern. For bulk tree moves
273
+ in one transaction, see `commitOrgUnitTreeDraft`.
274
+
209
275
  ## Auth REST Endpoints
210
276
 
211
277
  The BPM wrapper-host exposes the following endpoints under the host root (no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-client",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Framework-agnostic TypeScript client for the Rytass BPM approval workflow GraphQL surface: fetch-based GraphQL transport, REST auth client, pre-baked typed operations for organization, member, form, template, and workflow.",
5
5
  "keywords": [
6
6
  "bpm",
@@ -73,9 +73,10 @@
73
73
  }
74
74
  },
75
75
  "peerDependencies": {
76
- "@rytass/bpm-core-shared": "^0.1.3"
76
+ "@rytass/bpm-core-shared": "^0.1.5"
77
77
  },
78
78
  "dependencies": {
79
79
  "tslib": "^2.3.0"
80
- }
81
- }
80
+ },
81
+ "type": "commonjs"
82
+ }
package/src/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./lib/api-auth-client"), exports);
5
+ tslib_1.__exportStar(require("./lib/graphql-client"), exports);
6
+ tslib_1.__exportStar(require("./lib/member-api"), exports);
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/bpm-core-client/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,+DAAqC;AACrC,2DAAiC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Authenticated BPM member returned by {@link loginApi} and
3
+ * {@link readApiCurrentMember}.
4
+ *
5
+ * Mirrors the shape that BPM-compatible wrapper hosts emit from their
6
+ * `POST /auth/login` and `GET /auth/me` endpoints. Roles and permissions
7
+ * are used by BPM's `BPMAdminGuard` / `BPMDesignerGuard`.
8
+ */
9
+ export interface ApiMember {
10
+ readonly email: string;
11
+ readonly expiresAt: string;
12
+ readonly memberId: string;
13
+ readonly name: string;
14
+ readonly permissions: readonly string[];
15
+ readonly roles: readonly string[];
16
+ }
17
+ /**
18
+ * Reduced member shape returned by {@link listApiTestMembers}. Excludes
19
+ * `permissions` and `expiresAt` because the test-members endpoint is meant
20
+ * for picker UIs in dev / demo, not for session establishment.
21
+ */
22
+ export interface ApiPublicMember {
23
+ readonly email: string;
24
+ readonly memberId: string;
25
+ readonly name: string;
26
+ readonly roles: readonly string[];
27
+ }
28
+ /**
29
+ * Lists seeded test members exposed by the host's `/auth/test-members`
30
+ * endpoint. Hosts targeting production typically disable this endpoint or
31
+ * gate it behind a feature flag.
32
+ */
33
+ export declare function listApiTestMembers(): Promise<readonly ApiPublicMember[]>;
34
+ /**
35
+ * Performs a login against the host's `POST /auth/login` endpoint. On
36
+ * success the host issues an HTTP-only session cookie that subsequent
37
+ * {@link requestGraphQl} calls automatically carry, because
38
+ * {@link requestApi} uses `credentials: 'include'`.
39
+ *
40
+ * Throws on HTTP errors with a message extracted from the response body
41
+ * when available.
42
+ *
43
+ * @param input.identifier - Member id, email, or any other identifier the
44
+ * host understands.
45
+ * @param input.password - Cleartext credential — TLS is the consumer's
46
+ * responsibility.
47
+ */
48
+ export declare function loginApi(input: {
49
+ readonly identifier: string;
50
+ readonly password: string;
51
+ }): Promise<ApiMember>;
52
+ /**
53
+ * Calls `POST /auth/logout` on the host. The host clears the session
54
+ * cookie. Safe to call when not logged in (host should return 200).
55
+ */
56
+ export declare function logoutApi(): Promise<void>;
57
+ /**
58
+ * Reads the currently authenticated member from `GET /auth/me`.
59
+ *
60
+ * Returns `null` when the host replies `401`, which is the conventional
61
+ * way to signal "no active session". Any other HTTP failure throws.
62
+ */
63
+ export declare function readApiCurrentMember(): Promise<ApiMember | null>;
64
+ /**
65
+ * Resolves the base URL used by the REST `/auth/*` calls.
66
+ *
67
+ * Resolution order:
68
+ * 1. `process.env.NEXT_PUBLIC_API_AUTH_URL` if non-empty.
69
+ * 2. Derived from {@link readGraphQlEndpoint}'s origin — the host is
70
+ * assumed to expose both `/graphql` and `/auth/*` at the same origin.
71
+ */
72
+ export declare function readApiBaseUrl(): string;
73
+ export declare function resolveApiBaseUrlFromGraphQlEndpoint(graphQlEndpoint: string): string;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listApiTestMembers = listApiTestMembers;
4
+ exports.loginApi = loginApi;
5
+ exports.logoutApi = logoutApi;
6
+ exports.readApiCurrentMember = readApiCurrentMember;
7
+ exports.readApiBaseUrl = readApiBaseUrl;
8
+ exports.resolveApiBaseUrlFromGraphQlEndpoint = resolveApiBaseUrlFromGraphQlEndpoint;
9
+ const graphql_client_1 = require("./graphql-client");
10
+ /**
11
+ * Lists seeded test members exposed by the host's `/auth/test-members`
12
+ * endpoint. Hosts targeting production typically disable this endpoint or
13
+ * gate it behind a feature flag.
14
+ */
15
+ async function listApiTestMembers() {
16
+ return requestApi('/auth/test-members');
17
+ }
18
+ /**
19
+ * Performs a login against the host's `POST /auth/login` endpoint. On
20
+ * success the host issues an HTTP-only session cookie that subsequent
21
+ * {@link requestGraphQl} calls automatically carry, because
22
+ * {@link requestApi} uses `credentials: 'include'`.
23
+ *
24
+ * Throws on HTTP errors with a message extracted from the response body
25
+ * when available.
26
+ *
27
+ * @param input.identifier - Member id, email, or any other identifier the
28
+ * host understands.
29
+ * @param input.password - Cleartext credential — TLS is the consumer's
30
+ * responsibility.
31
+ */
32
+ async function loginApi(input) {
33
+ return requestApi('/auth/login', {
34
+ body: JSON.stringify(input),
35
+ headers: { 'Content-Type': 'application/json' },
36
+ method: 'POST',
37
+ });
38
+ }
39
+ /**
40
+ * Calls `POST /auth/logout` on the host. The host clears the session
41
+ * cookie. Safe to call when not logged in (host should return 200).
42
+ */
43
+ async function logoutApi() {
44
+ await requestApi('/auth/logout', {
45
+ method: 'POST',
46
+ });
47
+ }
48
+ /**
49
+ * Reads the currently authenticated member from `GET /auth/me`.
50
+ *
51
+ * Returns `null` when the host replies `401`, which is the conventional
52
+ * way to signal "no active session". Any other HTTP failure throws.
53
+ */
54
+ async function readApiCurrentMember() {
55
+ try {
56
+ return await requestApi('/auth/me');
57
+ }
58
+ catch (error) {
59
+ if (error instanceof ApiRequestError && error.status === 401) {
60
+ return null;
61
+ }
62
+ throw error;
63
+ }
64
+ }
65
+ /**
66
+ * Resolves the base URL used by the REST `/auth/*` calls.
67
+ *
68
+ * Resolution order:
69
+ * 1. `process.env.NEXT_PUBLIC_API_AUTH_URL` if non-empty.
70
+ * 2. Derived from {@link readGraphQlEndpoint}'s origin — the host is
71
+ * assumed to expose both `/graphql` and `/auth/*` at the same origin.
72
+ */
73
+ function readApiBaseUrl() {
74
+ const explicitApiBaseUrl = process.env.NEXT_PUBLIC_API_AUTH_URL?.trim();
75
+ if (explicitApiBaseUrl) {
76
+ return explicitApiBaseUrl.replace(/\/$/, '');
77
+ }
78
+ const graphQlEndpoint = (0, graphql_client_1.readGraphQlEndpoint)();
79
+ return resolveApiBaseUrlFromGraphQlEndpoint(graphQlEndpoint);
80
+ }
81
+ function resolveApiBaseUrlFromGraphQlEndpoint(graphQlEndpoint) {
82
+ if (!isAbsoluteUrl(graphQlEndpoint)) {
83
+ return '';
84
+ }
85
+ const endpoint = new URL(graphQlEndpoint);
86
+ endpoint.pathname = '/';
87
+ endpoint.search = '';
88
+ endpoint.hash = '';
89
+ return endpoint.toString().replace(/\/$/, '');
90
+ }
91
+ async function requestApi(path, init) {
92
+ const response = await fetch(`${readApiBaseUrl()}${path}`, {
93
+ credentials: 'include',
94
+ ...init,
95
+ });
96
+ if (!response.ok) {
97
+ throw new ApiRequestError(response.status, await readError(response));
98
+ }
99
+ return (await response.json());
100
+ }
101
+ async function readError(response) {
102
+ try {
103
+ const payload = (await response.json());
104
+ return typeof payload.message === 'string'
105
+ ? payload.message
106
+ : `BPM API request failed with HTTP ${response.status}`;
107
+ }
108
+ catch {
109
+ return `BPM API request failed with HTTP ${response.status}`;
110
+ }
111
+ }
112
+ class ApiRequestError extends Error {
113
+ constructor(status, message) {
114
+ super(message);
115
+ this.status = status;
116
+ }
117
+ }
118
+ function isAbsoluteUrl(value) {
119
+ return value.startsWith('http://') || value.startsWith('https://');
120
+ }
121
+ //# sourceMappingURL=api-auth-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-auth-client.js","sourceRoot":"","sources":["../../../../../libs/bpm-core-client/src/lib/api-auth-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { FormDefinitionSchema, FormFieldDefinition, FormUiSchema } from '@rytass/bpm-core-shared/form';
2
+ export interface FormDefinitionRecord {
3
+ readonly currentVersionId: string | null;
4
+ readonly currentVersionCreatedAt: string | null;
5
+ readonly currentVersionNumber: number | null;
6
+ readonly currentVersionPublishedAt: string | null;
7
+ readonly description: string | null;
8
+ readonly id: string;
9
+ readonly name: string;
10
+ readonly updatedAt: string;
11
+ }
12
+ export type FormDefinitionListStatus = 'DRAFT' | 'PUBLISHED';
13
+ export interface FormDefinitionVersionRecord {
14
+ readonly id: string;
15
+ readonly publishedAt: string | null;
16
+ readonly schema: FormDefinitionSchema;
17
+ readonly schemaJson: string;
18
+ readonly status: 'ARCHIVED' | 'DRAFT' | 'PUBLISHED';
19
+ readonly uiSchema: FormUiSchema;
20
+ readonly uiSchemaJson: string;
21
+ readonly updatedAt: string;
22
+ readonly version: number;
23
+ }
24
+ export interface FormBuilderRecord {
25
+ readonly definition: FormDefinitionRecord;
26
+ readonly versions: readonly FormDefinitionVersionRecord[];
27
+ }
28
+ export interface FormSchemaLintResult {
29
+ readonly errors: readonly string[];
30
+ readonly valid: boolean;
31
+ }
32
+ export declare function listFormDefinitions(): Promise<readonly FormDefinitionRecord[]>;
33
+ export declare function listFormDefinitionsPage({ page, pageSize, status, }: {
34
+ readonly page: number;
35
+ readonly pageSize: number;
36
+ readonly status?: FormDefinitionListStatus | null;
37
+ }): Promise<{
38
+ readonly forms: readonly FormDefinitionRecord[];
39
+ readonly totalCount: number;
40
+ }>;
41
+ export declare function createFormDefinition(name: string): Promise<string>;
42
+ export declare function updateFormDefinition(id: string, name: string): Promise<FormDefinitionRecord>;
43
+ export declare function readFormBuilder(formDefinitionId: string): Promise<FormBuilderRecord>;
44
+ export declare function updateFormDefinitionDraft(versionId: string, schema: FormDefinitionSchema, uiSchema: FormUiSchema): Promise<FormDefinitionVersionRecord>;
45
+ export declare function publishFormDefinitionVersion(versionId: string): Promise<FormDefinitionVersionRecord>;
46
+ export declare function forkFormDefinition(formDefinitionId: string): Promise<FormDefinitionVersionRecord>;
47
+ export declare function lintFormSchema(schema: FormDefinitionSchema, uiSchema: FormUiSchema): Promise<FormSchemaLintResult>;
48
+ export declare function createFieldDefinition(type: FormFieldDefinition['type'], index: number): FormFieldDefinition;
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listFormDefinitions = listFormDefinitions;
4
+ exports.listFormDefinitionsPage = listFormDefinitionsPage;
5
+ exports.createFormDefinition = createFormDefinition;
6
+ exports.updateFormDefinition = updateFormDefinition;
7
+ exports.readFormBuilder = readFormBuilder;
8
+ exports.updateFormDefinitionDraft = updateFormDefinitionDraft;
9
+ exports.publishFormDefinitionVersion = publishFormDefinitionVersion;
10
+ exports.forkFormDefinition = forkFormDefinition;
11
+ exports.lintFormSchema = lintFormSchema;
12
+ exports.createFieldDefinition = createFieldDefinition;
13
+ const graphql_client_1 = require("../graphql-client");
14
+ async function listFormDefinitions() {
15
+ const data = await (0, graphql_client_1.requestGraphQl)(`query FormDefinitions {
16
+ formDefinitions {
17
+ currentVersionCreatedAt
18
+ currentVersionId
19
+ currentVersionNumber
20
+ currentVersionPublishedAt
21
+ description
22
+ id
23
+ name
24
+ updatedAt
25
+ }
26
+ }`);
27
+ return data.formDefinitions;
28
+ }
29
+ async function listFormDefinitionsPage({ page, pageSize, status, }) {
30
+ const data = await (0, graphql_client_1.requestGraphQl)(`query FormDefinitionsPage(
31
+ $page: Int!
32
+ $pageSize: Int!
33
+ $status: FormDefinitionListStatus
34
+ ) {
35
+ formDefinitions(page: $page, pageSize: $pageSize, status: $status) {
36
+ currentVersionCreatedAt
37
+ currentVersionId
38
+ currentVersionNumber
39
+ currentVersionPublishedAt
40
+ description
41
+ id
42
+ name
43
+ updatedAt
44
+ }
45
+ formDefinitionCount(status: $status)
46
+ }`, { page, pageSize, status: status ?? null });
47
+ return {
48
+ forms: data.formDefinitions,
49
+ totalCount: data.formDefinitionCount,
50
+ };
51
+ }
52
+ async function createFormDefinition(name) {
53
+ const data = await (0, graphql_client_1.requestGraphQl)(`mutation CreateFormDefinition($input: CreateFormDefinitionInput!) {
54
+ createFormDefinition(input: $input) {
55
+ id
56
+ }
57
+ }`, {
58
+ input: {
59
+ createdByMemberId: null,
60
+ description: null,
61
+ name,
62
+ schemaJson: null,
63
+ uiSchemaJson: null,
64
+ },
65
+ });
66
+ return data.createFormDefinition.id;
67
+ }
68
+ async function updateFormDefinition(id, name) {
69
+ const data = await (0, graphql_client_1.requestGraphQl)(`mutation UpdateFormDefinition($input: UpdateFormDefinitionInput!) {
70
+ updateFormDefinition(input: $input) {
71
+ currentVersionCreatedAt
72
+ currentVersionId
73
+ currentVersionNumber
74
+ currentVersionPublishedAt
75
+ description
76
+ id
77
+ name
78
+ updatedAt
79
+ }
80
+ }`, {
81
+ input: {
82
+ description: null,
83
+ id,
84
+ name,
85
+ },
86
+ });
87
+ return data.updateFormDefinition;
88
+ }
89
+ async function readFormBuilder(formDefinitionId) {
90
+ const data = await (0, graphql_client_1.requestGraphQl)(`query FormBuilder($id: String!) {
91
+ formDefinition(id: $id) {
92
+ currentVersionCreatedAt
93
+ currentVersionId
94
+ currentVersionNumber
95
+ currentVersionPublishedAt
96
+ description
97
+ id
98
+ name
99
+ updatedAt
100
+ }
101
+ formDefinitionVersions(formDefinitionId: $id) {
102
+ id
103
+ publishedAt
104
+ schemaJson
105
+ status
106
+ uiSchemaJson
107
+ updatedAt
108
+ version
109
+ }
110
+ }`, { id: formDefinitionId });
111
+ return {
112
+ definition: data.formDefinition,
113
+ versions: data.formDefinitionVersions.map(parseVersionJson),
114
+ };
115
+ }
116
+ async function updateFormDefinitionDraft(versionId, schema, uiSchema) {
117
+ const data = await (0, graphql_client_1.requestGraphQl)(`mutation UpdateFormDefinitionDraft($input: UpdateFormDefinitionDraftInput!) {
118
+ updateFormDefinitionDraft(input: $input) {
119
+ id
120
+ publishedAt
121
+ schemaJson
122
+ status
123
+ uiSchemaJson
124
+ updatedAt
125
+ version
126
+ }
127
+ }`, {
128
+ input: {
129
+ schemaJson: JSON.stringify(schema),
130
+ uiSchemaJson: JSON.stringify(uiSchema),
131
+ versionId,
132
+ },
133
+ });
134
+ return parseVersionJson(data.updateFormDefinitionDraft);
135
+ }
136
+ async function publishFormDefinitionVersion(versionId) {
137
+ const data = await (0, graphql_client_1.requestGraphQl)(`mutation PublishFormDefinitionVersion($versionId: String!) {
138
+ publishFormDefinitionVersion(versionId: $versionId) {
139
+ id
140
+ publishedAt
141
+ schemaJson
142
+ status
143
+ uiSchemaJson
144
+ updatedAt
145
+ version
146
+ }
147
+ }`, { versionId });
148
+ return parseVersionJson(data.publishFormDefinitionVersion);
149
+ }
150
+ async function forkFormDefinition(formDefinitionId) {
151
+ const data = await (0, graphql_client_1.requestGraphQl)(`mutation ForkFormDefinition($formDefinitionId: String!) {
152
+ forkFormDefinition(formDefinitionId: $formDefinitionId) {
153
+ id
154
+ publishedAt
155
+ schemaJson
156
+ status
157
+ uiSchemaJson
158
+ updatedAt
159
+ version
160
+ }
161
+ }`, { formDefinitionId });
162
+ return parseVersionJson(data.forkFormDefinition);
163
+ }
164
+ async function lintFormSchema(schema, uiSchema) {
165
+ const data = await (0, graphql_client_1.requestGraphQl)(`query LintFormSchema($input: LintFormSchemaInput!) {
166
+ lintFormSchema(input: $input) {
167
+ errors
168
+ valid
169
+ }
170
+ }`, {
171
+ input: {
172
+ schemaJson: JSON.stringify(schema),
173
+ uiSchemaJson: JSON.stringify(uiSchema),
174
+ },
175
+ });
176
+ return data.lintFormSchema;
177
+ }
178
+ function createFieldDefinition(type, index) {
179
+ const fieldKey = `${type}_${index}`;
180
+ const base = {
181
+ fieldKey,
182
+ label: readDefaultFieldLabel(type, index),
183
+ required: false,
184
+ type,
185
+ };
186
+ if (type === 'select' || type === 'radio' || type === 'checkbox') {
187
+ return {
188
+ ...base,
189
+ options: [
190
+ { label: '選項 A', value: 'option_a' },
191
+ { label: '選項 B', value: 'option_b' },
192
+ ],
193
+ type,
194
+ };
195
+ }
196
+ if (type === 'file_upload') {
197
+ return {
198
+ ...base,
199
+ maxFiles: 1,
200
+ type,
201
+ };
202
+ }
203
+ return base;
204
+ }
205
+ function parseVersionJson(version) {
206
+ return {
207
+ ...version,
208
+ schema: JSON.parse(version.schemaJson),
209
+ uiSchema: JSON.parse(version.uiSchemaJson),
210
+ };
211
+ }
212
+ function readDefaultFieldLabel(type, index) {
213
+ const labels = {
214
+ boolean: '開關',
215
+ checkbox: '複選',
216
+ date: '日期',
217
+ datetime: '日期時間',
218
+ file_upload: '附件',
219
+ money: '金額',
220
+ number: '數字',
221
+ radio: '單選',
222
+ select: '下拉選單',
223
+ text: '文字',
224
+ textarea: '長文字',
225
+ };
226
+ return `${labels[type]} ${index}`;
227
+ }
228
+ //# sourceMappingURL=form-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-api.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core-client/src/lib/form/form-api.ts"],"names":[],"mappings":"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"}