exnet-routing 0.0.0

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 (74) hide show
  1. package/.github/workflows/release.yml +31 -0
  2. package/.prettierignore +2 -0
  3. package/.releaserc.json +13 -0
  4. package/README.md +1 -0
  5. package/core/_type.ts +110 -0
  6. package/core/_untils.ts +142 -0
  7. package/core/index.ts +15 -0
  8. package/eslint.config.js +50 -0
  9. package/index.ts +131 -0
  10. package/models/_banniere.ts +33 -0
  11. package/models/_billing_center.ts +167 -0
  12. package/models/_calcul_range.ts +12 -0
  13. package/models/_calcul_range_price.ts +17 -0
  14. package/models/_calcul_weight.ts +11 -0
  15. package/models/_calcul_weight_price.ts +18 -0
  16. package/models/_chat.ts +19 -0
  17. package/models/_chat_message.ts +19 -0
  18. package/models/_contact.ts +179 -0
  19. package/models/_contact_visible.ts +14 -0
  20. package/models/_country.ts +13 -0
  21. package/models/_customer.ts +148 -0
  22. package/models/_emballage.ts +23 -0
  23. package/models/_exportation.ts +12 -0
  24. package/models/_facturation_line.ts +90 -0
  25. package/models/_facture.ts +34 -0
  26. package/models/_facture_line.ts +32 -0
  27. package/models/_fuel.ts +14 -0
  28. package/models/_historique_action.ts +21 -0
  29. package/models/_information_chauffeur.ts +27 -0
  30. package/models/_information_importante.ts +17 -0
  31. package/models/_livraison_chauffeur.ts +17 -0
  32. package/models/_manifest.ts +58 -0
  33. package/models/_prise_de_poste.ts +166 -0
  34. package/models/_ramassage_chauffeur.ts +23 -0
  35. package/models/_ref_coef.ts +14 -0
  36. package/models/_ref_countrie.ts +15 -0
  37. package/models/_ref_facture.ts +12 -0
  38. package/models/_ref_import_export_price.ts +17 -0
  39. package/models/_salarie.ts +45 -0
  40. package/models/_shipping.ts +79 -0
  41. package/models/_shipping_affected.ts +16 -0
  42. package/models/_shipping_classification.ts +29 -0
  43. package/models/_shipping_comment.ts +17 -0
  44. package/models/_shipping_course.ts +23 -0
  45. package/models/_shipping_detail.ts +26 -0
  46. package/models/_shipping_detail_info_supplementaire.ts +34 -0
  47. package/models/_shipping_document.ts +19 -0
  48. package/models/_shipping_emballage.ts +27 -0
  49. package/models/_shipping_manifest.ts +16 -0
  50. package/models/_shipping_package.ts +29 -0
  51. package/models/_shipping_pod.ts +18 -0
  52. package/models/_shipping_proforma.ts +19 -0
  53. package/models/_shipping_proforma_line.ts +19 -0
  54. package/models/_shipping_tracking.ts +52 -0
  55. package/models/_tracking_visible.ts +14 -0
  56. package/models/_type_diagnobag.ts +30 -0
  57. package/models/_type_emballage.ts +24 -0
  58. package/models/_type_sonde.ts +24 -0
  59. package/models/_type_transport.ts +21 -0
  60. package/models/_untils.ts +72 -0
  61. package/models/_user.ts +463 -0
  62. package/models/_user_billing_center.ts +16 -0
  63. package/models/_user_login_historie.ts +18 -0
  64. package/models/_vehicule.ts +45 -0
  65. package/models/_vehicule_affected.ts +16 -0
  66. package/models/index.ts +56 -0
  67. package/package.json +34 -0
  68. package/prettier.config.js +7 -0
  69. package/routes/admin.ts +703 -0
  70. package/routes/driver.ts +5 -0
  71. package/routes/ops.ts +286 -0
  72. package/routes/public.ts +53 -0
  73. package/routes/user.ts +191 -0
  74. package/tsconfig.json +22 -0
@@ -0,0 +1,31 @@
1
+ name: Release
2
+ on:
3
+ pull_request:
4
+ branches:
5
+ - rec
6
+ types: [closed]
7
+
8
+ jobs:
9
+ release:
10
+ name: Release
11
+ if: github.event.pull_request.merged == true
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - name: Setup Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: "lts/*"
23
+
24
+ - name: Install dependencies
25
+ run: npm ci
26
+
27
+ - name: Release
28
+ env:
29
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
31
+ run: npx semantic-release
@@ -0,0 +1,2 @@
1
+ .next
2
+ node_modules
@@ -0,0 +1,13 @@
1
+ {
2
+ "branches": ["rec"],
3
+ "plugins": [
4
+ "@semantic-release/commit-analyzer",
5
+ "@semantic-release/release-notes-generator",
6
+ "@semantic-release/changelog",
7
+ "@semantic-release/npm",
8
+ ["@semantic-release/git", {
9
+ "assets": ["package.json", "CHANGELOG.md"],
10
+ "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
11
+ }]
12
+ ]
13
+ }
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # app-backend-v4-routing
package/core/_type.ts ADDED
@@ -0,0 +1,110 @@
1
+ import { z } from "zod"
2
+ import { index } from "./index"
3
+
4
+ type ApiService = typeof index
5
+
6
+ export type IHttpMethod = "GET" | "POST" | "PUT" | "DELETE"
7
+ export type IHttpMethodWithBody = "POST" | "PUT" | "DELETE"
8
+ export type IHttpMethodWithoutBody = "GET"
9
+
10
+ export const response = <R extends z.ZodObject<any> | z.ZodArray<any> | z.ZodNull>(data: R) => {
11
+ return z
12
+ .object({
13
+ data,
14
+ message: z.string().optional(),
15
+ status: z.number().optional(),
16
+ error: z.never().optional(),
17
+ success: z.literal(true),
18
+ })
19
+ .or(
20
+ z.object({
21
+ data: z.never(),
22
+ message: z.string(),
23
+ status: z.number().optional(),
24
+ error: z.object({
25
+ message: z.string(),
26
+ info: z.object({
27
+ status: z.number(),
28
+ code: z.string(),
29
+ messages: z.array(
30
+ z.object({
31
+ message: z.string(),
32
+ rule: z.string().optional(),
33
+ field: z.string().optional(),
34
+ })
35
+ ),
36
+ }),
37
+ }),
38
+ success: z.never(),
39
+ })
40
+ )
41
+ }
42
+
43
+ export type IBaseRoute = {
44
+ url: string
45
+ searchParams?: z.ZodObject<any>
46
+ params?: z.ZodObject<any>
47
+ response: ReturnType<typeof response>
48
+ }
49
+ export type IRoute = IBaseRoute &
50
+ (
51
+ | {
52
+ method: IHttpMethodWithBody
53
+
54
+ body?: z.ZodObject<any>
55
+ }
56
+ | {
57
+ method: IHttpMethodWithoutBody
58
+ body?: never
59
+ }
60
+ )
61
+
62
+ export type NestedRoute = {
63
+ [K: string]: NestedRoute | IRoute
64
+ }
65
+
66
+ export const IApiType = <T extends NestedRoute>(api: T) => api
67
+
68
+ export type TransformApi<T extends NestedRoute> = {
69
+ [K in keyof T]: T[K] extends NestedRoute
70
+ ? TransformApi<T[K]>
71
+ : T[K]["body"] extends z.ZodObject<any>
72
+ ? T[K]["searchParams"] extends z.ZodObject<any>
73
+ ? T[K]["params"] extends z.ZodObject<any>
74
+ ? (params: {
75
+ body: z.infer<T[K]["body"]>
76
+ searchParams: z.infer<T[K]["searchParams"]>
77
+ queryParams: z.infer<T[K]["params"]>
78
+ }) => Promise<z.infer<T[K]["response"]>>
79
+ : (params: {
80
+ body: z.infer<T[K]["body"]>
81
+ searchParams: z.infer<T[K]["searchParams"]>
82
+ }) => Promise<z.infer<T[K]["response"]>>
83
+ : T[K]["params"] extends z.ZodObject<any>
84
+ ? (params: {
85
+ body: z.infer<T[K]["body"]>
86
+ queryParams: z.infer<T[K]["params"]>
87
+ }) => Promise<z.infer<T[K]["response"]>>
88
+ : (params: { body: z.infer<T[K]["body"]> }) => Promise<z.infer<T[K]["response"]>>
89
+ : T[K]["searchParams"] extends z.ZodObject<any>
90
+ ? T[K]["params"] extends z.ZodObject<any>
91
+ ? (params: {
92
+ searchParams: z.infer<T[K]["searchParams"]>
93
+ queryParams: z.infer<T[K]["params"]>
94
+ }) => Promise<z.infer<T[K]["response"]>>
95
+ : (params: { searchParams: z.infer<T[K]["searchParams"]> }) => Promise<z.infer<T[K]["response"]>>
96
+ : T[K]["params"] extends z.ZodObject<any>
97
+ ? (params: { queryParams: z.infer<T[K]["params"]> }) => Promise<z.infer<T[K]["response"]>>
98
+ : () => Promise<z.infer<T[K]["response"]>>
99
+ }
100
+
101
+ // Awaited<ReturnType<IRouterApi["user"]["commission"]["get"]>>["data"]
102
+
103
+ export type ApiRouteResponse<Route extends (...args: any) => Promise<any>> = Awaited<ReturnType<Route>>["data"]
104
+
105
+ export type IRouterApi = TransformApi<ApiService>
106
+
107
+ export type IRouteFunction = (...params: any[]) => Promise<IRoute["response"]>
108
+ export type IRouteGroup = {
109
+ [name: string]: IRouteFunction | IRouteGroup
110
+ }
@@ -0,0 +1,142 @@
1
+ import { join } from "node:path"
2
+ import axios from "axios"
3
+ import { IRoute, IRouteFunction, IRouteGroup, IRouterApi } from "./_type"
4
+ import { NestedRoute } from "./_type"
5
+ import { z } from "zod"
6
+
7
+ let host: string | undefined
8
+ let baseUrl: string | undefined
9
+
10
+ export const apiUrlBuilder = (segment = "", baseUrl = "", host = "") => {
11
+ const path = join(baseUrl, segment)
12
+ return host + path
13
+ }
14
+
15
+ export const apiFetch = {
16
+ setHostApi: (h: string) => {
17
+ host = h
18
+ },
19
+ setBaseUrl: (b: string) => {
20
+ baseUrl = b
21
+ },
22
+
23
+ fetch: async (
24
+ urlInput: string,
25
+ method?: RequestInit["method"] | undefined,
26
+ body?: unknown,
27
+ searchParams?: unknown,
28
+ queryParams?: {
29
+ [key: string]: string
30
+ }
31
+ ) => {
32
+ let url = apiUrlBuilder(urlInput, baseUrl, host)
33
+ if (queryParams) {
34
+ for (const [key, value] of Object.entries(queryParams)) {
35
+ url = url.replace(`:${key}`, value)
36
+ }
37
+ }
38
+ if (searchParams) {
39
+ const searchParamsString = new URLSearchParams(searchParams as Record<string, string>).toString()
40
+ url += `?${searchParamsString}`
41
+ }
42
+ const res = await axios({
43
+ method,
44
+ url,
45
+ data: body,
46
+ })
47
+ return res.data
48
+ },
49
+ }
50
+
51
+ export const isRoute = (value: NestedRoute | IRoute): value is IRoute => {
52
+ return "method" in value
53
+ }
54
+
55
+ export const isSubRoute = (value: NestedRoute | IRoute): value is NestedRoute => {
56
+ return !isRoute(value)
57
+ }
58
+
59
+ export const parseApiRoute = <T extends NestedRoute | IRoute, K extends IRouteGroup>(
60
+ key: string | undefined,
61
+ subRoute: T,
62
+ result: K,
63
+ hostApi: string,
64
+ basePath: string
65
+ ) => {
66
+ apiFetch.setHostApi(hostApi)
67
+ apiFetch.setBaseUrl(basePath)
68
+ if (isRoute(subRoute) && key) {
69
+ const route = subRoute
70
+ if (route.body) {
71
+ if (route.searchParams) {
72
+ if (route.params) {
73
+ ;(result as unknown as IRouteFunction) = (
74
+ body: typeof route.body extends z.ZodObject<any> ? z.infer<typeof route.body> : undefined,
75
+ searchParams: typeof route.searchParams extends z.ZodObject<any>
76
+ ? z.infer<typeof route.searchParams>
77
+ : undefined,
78
+ queryParams: typeof route.params extends z.ZodObject<any> ? z.infer<typeof route.params> : undefined
79
+ ) => apiFetch.fetch(route.url, route.method, body, searchParams, queryParams)
80
+ } else {
81
+ ;(result as unknown as IRouteFunction) = (
82
+ body: typeof route.body extends z.ZodObject<any> ? z.infer<typeof route.body> : undefined,
83
+ searchParams: typeof route.searchParams extends z.ZodObject<any>
84
+ ? z.infer<typeof route.searchParams>
85
+ : undefined
86
+ ) => apiFetch.fetch(route.url, route.method, body, searchParams)
87
+ }
88
+ } else {
89
+ if (route.params) {
90
+ ;(result as unknown as IRouteFunction) = (
91
+ body: typeof route.body extends z.ZodObject<any> ? z.infer<typeof route.body> : undefined,
92
+ queryParams: typeof route.params extends z.ZodObject<any> ? z.infer<typeof route.params> : undefined
93
+ ) => apiFetch.fetch(route.url, route.method, body, undefined, queryParams)
94
+ } else {
95
+ ;(result as unknown as IRouteFunction) = (
96
+ body: typeof route.body extends z.ZodObject<any> ? z.infer<typeof route.body> : undefined
97
+ ) => apiFetch.fetch(route.url, route.method, body)
98
+ }
99
+ }
100
+ } else if (route.searchParams) {
101
+ if (route.params) {
102
+ ;(result as unknown as IRouteFunction) = (
103
+ searchParams: typeof route.searchParams extends z.ZodObject<any>
104
+ ? z.infer<typeof route.searchParams>
105
+ : undefined,
106
+ queryParams: typeof route.params extends z.ZodObject<any> ? z.infer<typeof route.params> : undefined
107
+ ) => apiFetch.fetch(route.url, route.method, undefined, searchParams, queryParams)
108
+ } else {
109
+ ;(result as unknown as IRouteFunction) = (
110
+ searchParams: typeof route.searchParams extends z.ZodObject<any>
111
+ ? z.infer<typeof route.searchParams>
112
+ : undefined
113
+ ) => apiFetch.fetch(route.url, route.method, undefined, searchParams)
114
+ }
115
+ } else {
116
+ if (route.params) {
117
+ ;(result as unknown as IRouteFunction) = (
118
+ queryParams: typeof route.params extends z.ZodObject<any> ? z.infer<typeof route.params> : undefined
119
+ ) => apiFetch.fetch(route.url, route.method, undefined, undefined, queryParams)
120
+ } else {
121
+ ;(result as unknown as IRouteFunction) = () => apiFetch.fetch(route.url, route.method)
122
+ }
123
+ }
124
+ } else if (isSubRoute(subRoute)) {
125
+ for (const [key, value] of Object.entries(subRoute)) {
126
+ ;(result as IRouteGroup)[key] = parseApiRoute(
127
+ key,
128
+ value as NestedRoute | IRoute,
129
+ ((result as IRouteGroup)[key] ?? {}) as IRouteGroup,
130
+ hostApi,
131
+ basePath
132
+ )
133
+ }
134
+ }
135
+ return result
136
+ }
137
+
138
+ export const parseApiRoutes = <T extends NestedRoute>(api: T, hostApi: string, basePath: string) => {
139
+ const result = {} as IRouterApi
140
+ const response = parseApiRoute(undefined, api, result, hostApi, basePath)
141
+ return response
142
+ }
package/core/index.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { opsRoutes } from "routes/ops"
2
+ import { adminRoutes } from "./../routes/admin"
3
+ import { publicRoutes } from "./../routes/public"
4
+ import { userRoutes } from "./../routes/user"
5
+ import { IApiType } from "./_type"
6
+ import { driverRoutes } from "routes/driver"
7
+
8
+ export const index = IApiType({
9
+ user: userRoutes,
10
+ public: publicRoutes,
11
+ admin: adminRoutes,
12
+ ops: opsRoutes,
13
+ driver: driverRoutes,
14
+ })
15
+ export type ApiService = typeof index
@@ -0,0 +1,50 @@
1
+ const importPlugin = require("eslint-plugin-import")
2
+ const simpleImportSort = require("eslint-plugin-simple-import-sort")
3
+ const unusedImports = require("eslint-plugin-unused-imports")
4
+ const typescriptPlugin = require("@typescript-eslint/eslint-plugin")
5
+ const typescriptParser = require("@typescript-eslint/parser")
6
+
7
+ module.exports = [
8
+ {
9
+ files: ["**/*.ts"],
10
+ languageOptions: {
11
+ parser: typescriptParser,
12
+ parserOptions: {
13
+ project: "./tsconfig.json",
14
+ sourceType: "module",
15
+ },
16
+ },
17
+ plugins: {
18
+ import: importPlugin,
19
+ "simple-import-sort": simpleImportSort,
20
+ "unused-imports": unusedImports,
21
+ "@typescript-eslint": typescriptPlugin,
22
+ },
23
+ rules: {
24
+ "unused-imports/no-unused-imports": "error",
25
+ "@typescript-eslint/no-unused-vars": [
26
+ "warn",
27
+ {
28
+ argsIgnorePattern: "^_",
29
+ varsIgnorePattern: "^_",
30
+ },
31
+ ],
32
+ "max-params": ["error", 6],
33
+ "simple-import-sort/imports": "off",
34
+ "simple-import-sort/exports": "off",
35
+ "no-console": ["error", { allow: ["warn", "error"] }],
36
+ },
37
+ settings: {
38
+ "import/resolver": {
39
+ typescript: {
40
+ alwaysTryTypes: true,
41
+ project: "./tsconfig.json",
42
+ },
43
+ },
44
+ node: {
45
+ extensions: [".ts", ".js", ".json"],
46
+ },
47
+ },
48
+ ignores: ["node_modules", "build", "packages/**"],
49
+ },
50
+ ]
package/index.ts ADDED
@@ -0,0 +1,131 @@
1
+ import { parseApiRoutes } from "core/_untils"
2
+ import { index } from "./core/index"
3
+ import { IRouterApi } from "core/_type"
4
+
5
+ export class APIRouter {
6
+ private hostApi: string
7
+ private basePath: string
8
+ public rt: IRouterApi
9
+
10
+ constructor(hostApi: string, basePath: string) {
11
+ this.hostApi = hostApi
12
+ this.basePath = basePath
13
+ this.rt = parseApiRoutes(index, this.hostApi, this.basePath)
14
+ }
15
+
16
+ setHostApi(hostApi: string) {
17
+ this.hostApi = hostApi
18
+ this.rt = parseApiRoutes(index, this.hostApi, this.basePath)
19
+ }
20
+
21
+ setBasePath(basePath: string) {
22
+ this.basePath = basePath
23
+ this.rt = parseApiRoutes(index, this.hostApi, this.basePath)
24
+ }
25
+
26
+ routes() {
27
+ return this.rt
28
+ }
29
+
30
+ getHostApi() {
31
+ return this.hostApi
32
+ }
33
+
34
+ getBasePath() {
35
+ return this.basePath
36
+ }
37
+ }
38
+
39
+ // Demo use
40
+ // exemple
41
+ // import { IContact, IContactCreateByUser, IPaginationData } from "models"
42
+
43
+ // const api = new APIRouter("http://localhost:3000", "/api/v1")
44
+
45
+ // try {
46
+ // const { success, data, error, message } = await api.routes().user.contact.liste({
47
+ // searchParams: {
48
+ // page: 1,
49
+ // limit: 10,
50
+ // search: "John",
51
+ // sortBy: "createdAt",
52
+ // direction: "asc",
53
+ // }
54
+ // })
55
+ // if (success) {
56
+ // console.log(data)
57
+ // const finalData: IPaginationData<IContact> = data
58
+ // console.log(finalData.meta.currentPage)
59
+ // console.log(finalData.meta.perPage)
60
+ // console.log(finalData.meta.total)
61
+ // console.log(finalData.meta.lastPage)
62
+ // console.log(finalData.meta.firstPage)
63
+ // console.log(finalData.meta.lastPageUrl)
64
+ // console.log(finalData.meta.nextPageUrl)
65
+ // console.log(finalData.meta.previousPageUrl)
66
+ // console.log(finalData.meta.firstPageUrl)
67
+
68
+ // console.log(finalData.data.map((item: IContact) => item.fullName))
69
+ // } else {
70
+ // console.log(error, message)
71
+ // }
72
+ // } catch (error) {
73
+ // console.log(error)
74
+ // }
75
+
76
+ // try {
77
+ // const { success, data, error, message } = await api.routes().user.contact.detail({
78
+ // queryParams: {
79
+ // id: "1",
80
+ // }
81
+ // })
82
+ // if (success) {
83
+ // console.log(data)
84
+ // const finalData: IContact = data
85
+ // console.log(finalData.fullName)
86
+ // } else {
87
+ // console.log(error, message)
88
+ // }
89
+ // } catch (error) {
90
+ // console.log(error)
91
+ // }
92
+
93
+ // try {
94
+ // const input: IContactCreateByUser = {
95
+ // fullName: "John Doe",
96
+ // firstName: "John",
97
+ // lastName: "Doe",
98
+ // emailOne: "john.doe@example.com",
99
+ // address: "123 Main St, Anytown, USA",
100
+ // city: "Anytown",
101
+ // countryId: 1,
102
+ // isParis: true,
103
+ // isMedical: true,
104
+ // isService: true,
105
+ // addressOne: "123 Main St, Anytown, USA",
106
+ // postalCode: "12345",
107
+ // numCode: "12345",
108
+ // telephoneOne: "1234567890",
109
+ // company: "John Doe",
110
+ // typeContact: "John Doe",
111
+ // addressTwo: "123 Main St, Anytown, USA",
112
+ // civility: "John Doe",
113
+ // numCodeOne: "12345",
114
+ // numCodeTwo: "12345",
115
+ // telephoneTwo: "1234567890",
116
+ // emailTwo: "john.doe@example.com",
117
+ // comments: "John Doe",
118
+ // }
119
+ // const { success, data, error, message } = await api.routes().user.contact.create({
120
+ // body: input,
121
+ // })
122
+ // if (success) {
123
+ // console.log(data)
124
+ // const finalData: IContact = data
125
+ // console.log(finalData.fullName)
126
+ // } else {
127
+ // console.log(error, message)
128
+ // }
129
+ // } catch (error) {
130
+ // console.log(error)
131
+ // }
@@ -0,0 +1,33 @@
1
+ import { z } from "zod"
2
+ import { DateTime } from "luxon"
3
+
4
+ export const BanniereSchema = z.object({
5
+ id: z.number(),
6
+ createdAt: z.date().transform((date) => DateTime.fromJSDate(date)),
7
+ updatedAt: z.date().transform((date) => DateTime.fromJSDate(date)),
8
+ libelle: z.string().nullable(),
9
+ contenus: z.string().nullable(),
10
+ imageUrl: z.string().nullable(),
11
+ active: z.boolean(),
12
+ withImage: z.boolean(),
13
+ })
14
+
15
+ export const BanniereCreateSchema = z.object({
16
+ libelle: z.string(),
17
+ contenus: z.string(),
18
+ image: z.any().optional(), // Pour le file upload
19
+ active: z.boolean(),
20
+ withImage: z.boolean(),
21
+ })
22
+
23
+ export const BanniereUpdateSchema = z.object({
24
+ libelle: z.string().optional(),
25
+ contenus: z.string().optional(),
26
+ image: z.any().optional(), // Pour le file upload
27
+ withImage: z.boolean().optional(),
28
+ active: z.boolean().optional(),
29
+ })
30
+
31
+ export type IBanniere = z.infer<typeof BanniereSchema>
32
+ export type IBanniereCreate = z.infer<typeof BanniereCreateSchema>
33
+ export type IBanniereUpdate = z.infer<typeof BanniereUpdateSchema>