Skip to content

Commit 817f92e

Browse files
committed
feat(client): add scoped routes and expand runtime API surface
1 parent 62806fd commit 817f92e

52 files changed

Lines changed: 4483 additions & 435 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 220 additions & 211 deletions
Large diffs are not rendered by default.

src/module.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import { addComponent, addImports, addPlugin, addTypeTemplate, createResolver, defineNuxtModule } from '@nuxt/kit'
2-
import type { FormForgeClientConfig, FormForgeDatetimeMode, FormForgeUploadMode } from './runtime/types'
2+
import type {
3+
FormForgeClientConfig,
4+
FormForgeDatetimeMode,
5+
FormForgeScopedRouteMap,
6+
FormForgeScopeParams,
7+
FormForgeUploadMode
8+
} from './runtime/types'
39

410
export interface ModuleOptions {
511
baseURL?: string
12+
baseURLParams?: Record<string, string | number | undefined>
13+
scopedRoutes?: FormForgeScopedRouteMap
14+
defaultScope?: string
15+
scopeParams?: FormForgeScopeParams
616
credentials?: RequestCredentials
717
headers?: Record<string, string>
818
uploadMode?: FormForgeUploadMode
@@ -21,6 +31,9 @@ export default defineNuxtModule<ModuleOptions>({
2131
},
2232
defaults: {
2333
baseURL: '/api/formforge/v1',
34+
scopedRoutes: {},
35+
defaultScope: undefined,
36+
scopeParams: {},
2437
credentials: 'include',
2538
headers: {},
2639
uploadMode: 'staged',
@@ -36,6 +49,10 @@ export default defineNuxtModule<ModuleOptions>({
3649
nuxt.options.runtimeConfig.public.formforge = {
3750
...runtimeConfig,
3851
baseURL: options.baseURL,
52+
baseURLParams: options.baseURLParams,
53+
scopedRoutes: options.scopedRoutes,
54+
defaultScope: options.defaultScope,
55+
scopeParams: options.scopeParams,
3956
credentials: options.credentials,
4057
headers: options.headers,
4158
uploadMode: options.uploadMode,
@@ -55,6 +72,16 @@ export default defineNuxtModule<ModuleOptions>({
5572
filePath: resolver.resolve('./runtime/renderers/default/FormForgeBuilder.vue')
5673
})
5774

75+
addComponent({
76+
name: 'FormForgeResponse',
77+
filePath: resolver.resolve('./runtime/renderers/default/FormForgeResponse.vue')
78+
})
79+
80+
addComponent({
81+
name: 'FormForgeCategoryCreateModal',
82+
filePath: resolver.resolve('./runtime/renderers/default/FormForgeCategoryCreateModal.vue')
83+
})
84+
5885
if (options.autoImports === true) {
5986
addImports([
6087
{ from: resolver.resolve('./runtime/composables/useFormForgeApi'), name: 'useFormForgeApi' },
@@ -69,6 +96,8 @@ export default defineNuxtModule<ModuleOptions>({
6996
{ from: resolver.resolve('./runtime/composables/useFormForgeSubmit'), name: 'useFormForgeSubmit' },
7097
{ from: resolver.resolve('./runtime/composables/useFormForgeSubmission'), name: 'useFormForgeSubmission' },
7198
{ from: resolver.resolve('./runtime/composables/useFormForgeResponses'), name: 'useFormForgeResponses' },
99+
{ from: resolver.resolve('./runtime/composables/useFormForgeCategory'), name: 'useFormForgeCategory' },
100+
{ from: resolver.resolve('./runtime/composables/useFormForgeCategory'), name: 'useFormForgeCategoryOptions' },
72101
{ from: resolver.resolve('./runtime/composables/useFormForgeManagement'), name: 'useFormForgeManagement' },
73102
{ from: resolver.resolve('./runtime/composables/useFormForgeWizard'), name: 'useFormForgeWizard' },
74103
{ from: resolver.resolve('./runtime/composables/useFormForgeBuilder'), name: 'useFormForgeBuilder' }

src/runtime/api/categories.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import type {
2+
FormForgeCategory,
3+
FormForgeCategoryCreateInput,
4+
FormForgeCategoryListQuery,
5+
FormForgeCategoryListResponse,
6+
FormForgeCategoryUpdateInput,
7+
FormForgeHttpAdapter,
8+
FormForgeJsonObject
9+
} from '../types'
10+
import type { FormForgeMutationOptions } from './management'
11+
import { normalizeFormForgeCategory, normalizeFormForgeCategoryListResponse } from '../utils/category'
12+
import { pickFormForgeDataEnvelope } from '../utils/object'
13+
import { resolveEndpointPath, type FormForgeRequestOptions } from './request'
14+
15+
function withMutationHeaders(options: FormForgeMutationOptions = {}): Record<string, string> {
16+
if (options.idempotencyKey === undefined || options.idempotencyKey === '') {
17+
return {}
18+
}
19+
20+
return {
21+
'Idempotency-Key': options.idempotencyKey
22+
}
23+
}
24+
25+
function toJsonObject(input: FormForgeCategoryCreateInput | FormForgeCategoryUpdateInput): FormForgeJsonObject {
26+
return JSON.parse(JSON.stringify(input)) as FormForgeJsonObject
27+
}
28+
29+
function normalizeSingleCategory(payload: FormForgeJsonObject): FormForgeCategory {
30+
const dataEnvelope = pickFormForgeDataEnvelope(payload)
31+
const normalized = normalizeFormForgeCategory(dataEnvelope)
32+
33+
if (normalized !== null) {
34+
return normalized
35+
}
36+
37+
return {
38+
id: 0,
39+
key: '',
40+
name: '',
41+
description: null,
42+
is_active: false,
43+
meta: {},
44+
created_at: null,
45+
updated_at: null
46+
}
47+
}
48+
49+
export async function fetchFormForgeCategories(
50+
http: FormForgeHttpAdapter,
51+
query: FormForgeCategoryListQuery = {},
52+
options: FormForgeRequestOptions = {}
53+
): Promise<FormForgeCategoryListResponse> {
54+
const resolvedQuery: Record<string, string | number | boolean | undefined> = {
55+
per_page: query.per_page,
56+
search: query.search,
57+
is_active: query.is_active === undefined ? undefined : (query.is_active ? 1 : 0)
58+
}
59+
60+
const response = await http<FormForgeJsonObject>({
61+
path: resolveEndpointPath(options.endpoint, '/categories', {}, options.scope),
62+
method: 'GET',
63+
query: resolvedQuery
64+
})
65+
66+
return normalizeFormForgeCategoryListResponse(response.data)
67+
}
68+
69+
export async function fetchFormForgeCategory(
70+
http: FormForgeHttpAdapter,
71+
categoryKey: string,
72+
options: FormForgeRequestOptions = {}
73+
): Promise<FormForgeCategory> {
74+
const response = await http<FormForgeJsonObject>({
75+
path: resolveEndpointPath(options.endpoint, `/categories/${categoryKey}`, {
76+
categoryKey
77+
}, options.scope),
78+
method: 'GET'
79+
})
80+
81+
return normalizeSingleCategory(response.data)
82+
}
83+
84+
export async function createFormForgeCategory(
85+
http: FormForgeHttpAdapter,
86+
input: FormForgeCategoryCreateInput,
87+
options: FormForgeMutationOptions = {}
88+
): Promise<FormForgeCategory> {
89+
const response = await http<FormForgeJsonObject>({
90+
path: resolveEndpointPath(options.endpoint, '/categories', {}, options.scope),
91+
method: 'POST',
92+
headers: withMutationHeaders(options),
93+
json: toJsonObject(input)
94+
})
95+
96+
return normalizeSingleCategory(response.data)
97+
}
98+
99+
export async function patchFormForgeCategory(
100+
http: FormForgeHttpAdapter,
101+
categoryKey: string,
102+
input: FormForgeCategoryUpdateInput,
103+
options: FormForgeMutationOptions = {}
104+
): Promise<FormForgeCategory> {
105+
const response = await http<FormForgeJsonObject>({
106+
path: resolveEndpointPath(options.endpoint, `/categories/${categoryKey}`, {
107+
categoryKey
108+
}, options.scope),
109+
method: 'PATCH',
110+
headers: withMutationHeaders(options),
111+
json: toJsonObject(input)
112+
})
113+
114+
return normalizeSingleCategory(response.data)
115+
}
116+
117+
export async function deleteFormForgeCategory(
118+
http: FormForgeHttpAdapter,
119+
categoryKey: string,
120+
options: FormForgeMutationOptions = {}
121+
): Promise<FormForgeCategory> {
122+
const response = await http<FormForgeJsonObject>({
123+
path: resolveEndpointPath(options.endpoint, `/categories/${categoryKey}`, {
124+
categoryKey
125+
}, options.scope),
126+
method: 'DELETE',
127+
headers: withMutationHeaders(options)
128+
})
129+
130+
return normalizeSingleCategory(response.data)
131+
}

0 commit comments

Comments
 (0)