effect-orpc 0.1.4 → 0.2.1

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.
@@ -0,0 +1,192 @@
1
+ import type { OmitChainMethodDeep } from "@orpc/shared";
2
+ import { describe, expectTypeOf, it } from "vitest";
3
+
4
+ import type {
5
+ EffectContractProcedureBuilderWithInputOutput,
6
+ EffectContractRouterBuilder,
7
+ } from "../index";
8
+ import { eoc } from "../index";
9
+ import {
10
+ type BaseMeta,
11
+ baseErrorMap,
12
+ generalSchema,
13
+ inputSchema,
14
+ outputSchema,
15
+ ping,
16
+ pong,
17
+ } from "./shared";
18
+
19
+ const generalBuilder = eoc
20
+ .$meta({ mode: "dev" } as BaseMeta)
21
+ .$input(inputSchema)
22
+ .errors(baseErrorMap);
23
+
24
+ describe("parity: @orpc/contract builder-variants.test-d.ts", () => {
25
+ describe("EffectContractProcedureBuilder", () => {
26
+ const builder = eoc.errors(baseErrorMap).meta({ mode: "dev" } as BaseMeta);
27
+
28
+ it("backward compatibility", () => {
29
+ const expected = {} as OmitChainMethodDeep<
30
+ typeof generalBuilder,
31
+ "$meta" | "$route" | "$input" | "prefix" | "tag" | "router"
32
+ >;
33
+
34
+ expectTypeOf<keyof typeof builder>().toEqualTypeOf<
35
+ keyof typeof expected
36
+ >();
37
+ });
38
+
39
+ it(".errors / .meta / .route / .input / .output", () => {
40
+ expectTypeOf(
41
+ builder.errors({ INVALID: { message: "invalid" } }),
42
+ ).toBeObject();
43
+ expectTypeOf(builder.meta({ log: true })).toBeObject();
44
+ expectTypeOf(builder.route({ method: "GET" })).toBeObject();
45
+ expectTypeOf(builder.input(generalSchema)).toBeObject();
46
+ expectTypeOf(builder.output(generalSchema)).toBeObject();
47
+
48
+ // @ts-expect-error - schema is invalid
49
+ builder.errors({ TOO_MANY_REQUESTS: { data: {} } });
50
+ // @ts-expect-error - invalid method
51
+ builder.route({ method: "INVALID" });
52
+ // @ts-expect-error - schema is invalid
53
+ builder.input({});
54
+ // @ts-expect-error - schema is invalid
55
+ builder.output({});
56
+ });
57
+ });
58
+
59
+ describe("EffectContractProcedureBuilderWithInput", () => {
60
+ const builder = eoc
61
+ .errors(baseErrorMap)
62
+ .meta({ mode: "dev" })
63
+ .input(inputSchema);
64
+
65
+ it("backward compatibility", () => {
66
+ const expected = {} as OmitChainMethodDeep<
67
+ typeof generalBuilder,
68
+ "$meta" | "$route" | "$input" | "prefix" | "tag" | "router" | "input"
69
+ >;
70
+
71
+ expectTypeOf<keyof typeof builder>().toEqualTypeOf<
72
+ keyof typeof expected
73
+ >();
74
+ });
75
+
76
+ it(".errors / .meta / .route / .output", () => {
77
+ expectTypeOf(
78
+ builder.errors({ INVALID: { message: "invalid" } }),
79
+ ).toBeObject();
80
+ expectTypeOf(builder.meta({ log: true })).toBeObject();
81
+ expectTypeOf(builder.route({ method: "GET" })).toBeObject();
82
+ expectTypeOf(builder.output(generalSchema)).toExtend<
83
+ EffectContractProcedureBuilderWithInputOutput<
84
+ typeof inputSchema,
85
+ typeof generalSchema,
86
+ typeof baseErrorMap,
87
+ BaseMeta
88
+ >
89
+ >();
90
+ });
91
+ });
92
+
93
+ describe("EffectContractProcedureBuilderWithOutput", () => {
94
+ const builder = eoc
95
+ .errors(baseErrorMap)
96
+ .meta({ mode: "dev" })
97
+ .output(outputSchema);
98
+
99
+ it("backward compatibility", () => {
100
+ const expected = {} as OmitChainMethodDeep<
101
+ typeof generalBuilder,
102
+ "$meta" | "$route" | "$input" | "prefix" | "tag" | "router" | "output"
103
+ >;
104
+
105
+ expectTypeOf<keyof typeof builder>().toEqualTypeOf<
106
+ keyof typeof expected
107
+ >();
108
+ });
109
+
110
+ it(".errors / .meta / .route / .input", () => {
111
+ expectTypeOf(
112
+ builder.errors({ INVALID: { message: "invalid" } }),
113
+ ).toBeObject();
114
+ expectTypeOf(builder.meta({ log: true })).toBeObject();
115
+ expectTypeOf(builder.route({ method: "GET" })).toBeObject();
116
+ expectTypeOf(builder.input(generalSchema)).toExtend<
117
+ EffectContractProcedureBuilderWithInputOutput<
118
+ typeof generalSchema,
119
+ typeof outputSchema,
120
+ typeof baseErrorMap,
121
+ BaseMeta
122
+ >
123
+ >();
124
+ });
125
+ });
126
+
127
+ describe("EffectContractProcedureBuilderWithInputOutput", () => {
128
+ const builder = eoc
129
+ .errors(baseErrorMap)
130
+ .meta({ mode: "dev" })
131
+ .input(inputSchema)
132
+ .output(outputSchema);
133
+
134
+ it("backward compatibility", () => {
135
+ const expected = {} as OmitChainMethodDeep<
136
+ typeof generalBuilder,
137
+ | "$meta"
138
+ | "$route"
139
+ | "$input"
140
+ | "prefix"
141
+ | "tag"
142
+ | "router"
143
+ | "input"
144
+ | "output"
145
+ >;
146
+
147
+ expectTypeOf<keyof typeof builder>().toEqualTypeOf<
148
+ keyof typeof expected
149
+ >();
150
+ });
151
+
152
+ it(".errors / .meta / .route", () => {
153
+ expectTypeOf(
154
+ builder.errors({ INVALID: { message: "invalid" } }),
155
+ ).toBeObject();
156
+ expectTypeOf(builder.meta({ log: true })).toBeObject();
157
+ expectTypeOf(builder.route({ method: "GET" })).toBeObject();
158
+ });
159
+ });
160
+
161
+ describe("EffectContractRouterBuilder", () => {
162
+ const builder = eoc.errors(baseErrorMap).prefix("/api");
163
+
164
+ it("backward compatibility", () => {
165
+ expectTypeOf(builder.errors).toBeFunction();
166
+ expectTypeOf(builder.prefix).toBeFunction();
167
+ expectTypeOf(builder.tag).toBeFunction();
168
+ expectTypeOf(builder.router).toBeFunction();
169
+ });
170
+
171
+ it(".errors / .prefix / .tag / .router", () => {
172
+ expectTypeOf(
173
+ builder.errors({ INVALID: { message: "invalid" } }),
174
+ ).toBeObject();
175
+ expectTypeOf(builder.prefix("/api")).toExtend<
176
+ EffectContractRouterBuilder<typeof baseErrorMap, BaseMeta>
177
+ >();
178
+ expectTypeOf(builder.tag("tag1", "tag2")).toExtend<
179
+ EffectContractRouterBuilder<typeof baseErrorMap, BaseMeta>
180
+ >();
181
+ expectTypeOf(builder.router({ ping, pong })).toExtend<{
182
+ ping: typeof ping;
183
+ pong: typeof pong;
184
+ }>();
185
+
186
+ // @ts-expect-error - invalid prefix
187
+ builder.prefix(1);
188
+ // @ts-expect-error - invalid tag
189
+ builder.tag(1);
190
+ });
191
+ });
192
+ });
@@ -0,0 +1,222 @@
1
+ import { ContractBuilder, isContractProcedure } from "@orpc/contract";
2
+ import { describe, expect, expectTypeOf, it } from "vitest";
3
+
4
+ import { effectErrorMapToErrorMap, eoc } from "../index";
5
+ import {
6
+ baseErrorMap,
7
+ baseMeta,
8
+ baseRoute,
9
+ generalSchema,
10
+ inputSchema,
11
+ outputSchema,
12
+ ping,
13
+ pong,
14
+ } from "./shared";
15
+
16
+ const builder = eoc
17
+ .$meta(baseMeta)
18
+ .$route(baseRoute)
19
+ .$input(inputSchema)
20
+ .errors(baseErrorMap);
21
+
22
+ describe("parity: @orpc/contract builder.test.ts", () => {
23
+ it("is a contract procedure", () => {
24
+ expect(eoc).toSatisfy(isContractProcedure);
25
+ });
26
+
27
+ it(".$meta", () => {
28
+ const meta = { dev: true, log: true };
29
+ const applied = builder.$meta(meta);
30
+
31
+ expect(applied).toBeInstanceOf(ContractBuilder);
32
+ expect(applied).not.toBe(builder);
33
+ expect(applied["~orpc"]).toEqual({
34
+ ...builder["~orpc"],
35
+ meta,
36
+ });
37
+ });
38
+
39
+ it(".$route", () => {
40
+ const route = { method: "GET", path: "/api" } as const;
41
+ const applied = builder.$route(route);
42
+
43
+ expect(applied).toBeInstanceOf(ContractBuilder);
44
+ expect(applied).not.toBe(builder);
45
+ expect(applied["~orpc"]).toEqual({
46
+ ...builder["~orpc"],
47
+ route,
48
+ });
49
+ });
50
+
51
+ it(".$input", () => {
52
+ const applied = builder.$input(generalSchema);
53
+
54
+ expect(applied).toBeInstanceOf(ContractBuilder);
55
+ expect(applied).not.toBe(builder);
56
+ expect(applied["~orpc"]).toEqual({
57
+ ...builder["~orpc"],
58
+ inputSchema: generalSchema,
59
+ });
60
+ });
61
+
62
+ it(".errors", () => {
63
+ const errors = {
64
+ BAD_GATEWAY: { data: outputSchema },
65
+ OVERRIDE: { message: "override" },
66
+ } as const;
67
+ const applied = builder.errors(errors);
68
+
69
+ expect(applied).toBeInstanceOf(ContractBuilder);
70
+ expect(applied).not.toBe(builder);
71
+ expect(applied["~orpc"]).toEqual({
72
+ ...builder["~orpc"],
73
+ errorMap: effectErrorMapToErrorMap({
74
+ ...baseErrorMap,
75
+ ...errors,
76
+ }),
77
+ });
78
+ });
79
+
80
+ it(".meta", () => {
81
+ const meta = { dev: true, log: true };
82
+ const applied = builder.meta(meta);
83
+
84
+ expect(applied).toBeInstanceOf(ContractBuilder);
85
+ expect(applied).not.toBe(builder);
86
+ expect(applied["~orpc"]).toEqual({
87
+ ...builder["~orpc"],
88
+ meta: { ...builder["~orpc"].meta, ...meta },
89
+ });
90
+ });
91
+
92
+ it(".route", () => {
93
+ const route = { method: "GET", path: "/path" } as const;
94
+ const applied = builder.route(route);
95
+
96
+ expect(applied).toBeInstanceOf(ContractBuilder);
97
+ expect(applied).not.toBe(builder);
98
+ expect(applied["~orpc"]).toEqual({
99
+ ...builder["~orpc"],
100
+ route: { ...builder["~orpc"].route, ...route },
101
+ });
102
+ });
103
+
104
+ it(".input", () => {
105
+ const applied = builder.input(generalSchema);
106
+
107
+ expect(applied).toBeInstanceOf(ContractBuilder);
108
+ expect(applied).not.toBe(builder);
109
+ expect(applied["~orpc"]).toEqual({
110
+ ...builder["~orpc"],
111
+ inputSchema: generalSchema,
112
+ });
113
+ });
114
+
115
+ it(".output", () => {
116
+ const applied = builder.output(generalSchema);
117
+
118
+ expect(applied).toBeInstanceOf(ContractBuilder);
119
+ expect(applied).not.toBe(builder);
120
+ expect(applied["~orpc"]).toEqual({
121
+ ...builder["~orpc"],
122
+ outputSchema: generalSchema,
123
+ });
124
+ });
125
+
126
+ it(".prefix", () => {
127
+ const applied = builder.prefix("/api") as any;
128
+
129
+ expect(applied).toBeInstanceOf(ContractBuilder);
130
+ expect(applied).not.toBe(builder);
131
+ expect(applied["~orpc"]).toEqual({
132
+ ...builder["~orpc"],
133
+ prefix: "/api",
134
+ });
135
+ });
136
+
137
+ it(".tag", () => {
138
+ const applied = builder.tag("tag1", "tag2") as any;
139
+
140
+ expect(applied).toBeInstanceOf(ContractBuilder);
141
+ expect(applied).not.toBe(builder);
142
+ expect(applied["~orpc"]).toEqual({
143
+ ...builder["~orpc"],
144
+ tags: ["tag1", "tag2"],
145
+ });
146
+ });
147
+
148
+ it(".router", () => {
149
+ const router = builder.router({ ping, pong });
150
+
151
+ expect(router.ping["~orpc"].route.path).toBe("/base");
152
+ expect(router.ping["~orpc"].meta).toEqual(baseMeta);
153
+ expect(router.ping["~orpc"].errorMap).toEqual(baseErrorMap);
154
+ });
155
+ });
156
+
157
+ describe("parity: @orpc/contract builder.test-d.ts", () => {
158
+ const typedBuilder = builder;
159
+
160
+ it("is a contract procedure", () => {
161
+ expectTypeOf(typedBuilder["~orpc"]).toBeObject();
162
+ });
163
+
164
+ it("preserves ContractBuilder typing for root methods", () => {
165
+ expectTypeOf(typedBuilder.$meta<{ auth?: boolean }>({})).toBeObject();
166
+
167
+ expectTypeOf(typedBuilder.$route({ method: "GET", path: "/api" })).toExtend<
168
+ typeof typedBuilder
169
+ >();
170
+
171
+ expectTypeOf(typedBuilder.$input(generalSchema)).toBeObject();
172
+
173
+ expectTypeOf(
174
+ typedBuilder.errors({
175
+ INVALID: { message: "invalid" },
176
+ OVERRIDE: { message: "override" },
177
+ }),
178
+ ).toBeObject();
179
+
180
+ expectTypeOf(typedBuilder.meta({ log: true })).toBeObject();
181
+ expectTypeOf(typedBuilder.route({ method: "GET" })).toBeObject();
182
+ expectTypeOf(typedBuilder.input(generalSchema)).toBeObject();
183
+ expectTypeOf(typedBuilder.output(generalSchema)).toBeObject();
184
+ expectTypeOf(typedBuilder.prefix("/api")).toBeObject();
185
+ expectTypeOf(typedBuilder.tag("tag1", "tag2")).toBeObject();
186
+ expectTypeOf(typedBuilder.router({ ping, pong })).toExtend<{
187
+ ping: typeof ping;
188
+ pong: typeof pong;
189
+ }>();
190
+ });
191
+
192
+ it("preserves ContractBuilder constraints", () => {
193
+ // @ts-expect-error - initial meta is required
194
+ typedBuilder.$meta<{ auth?: boolean }>();
195
+ // @ts-expect-error - auth is missing in initial meta
196
+ typedBuilder.$meta<{ auth: boolean }>({});
197
+ // @ts-expect-error - invalid method
198
+ typedBuilder.$route({ method: "INVALID" });
199
+ // @ts-expect-error - invalid schema
200
+ typedBuilder.$input({});
201
+ // @ts-expect-error - schema is invalid
202
+ typedBuilder.errors({ TOO_MANY_REQUESTS: { data: {} } });
203
+ // @ts-expect-error - invalid meta
204
+ typedBuilder.meta({ meta: "INVALID" });
205
+ // @ts-expect-error - invalid method
206
+ typedBuilder.route({ method: "INVALID" });
207
+ // @ts-expect-error - invalid schema
208
+ typedBuilder.input({});
209
+ // @ts-expect-error - invalid schema
210
+ typedBuilder.output({});
211
+ // @ts-expect-error - invalid prefix
212
+ typedBuilder.prefix(1);
213
+ // @ts-expect-error - invalid tag
214
+ typedBuilder.tag(1);
215
+ });
216
+
217
+ it("keeps eoc-specific tagged error normalization separate", () => {
218
+ const applied = eoc.errors(baseErrorMap);
219
+
220
+ expectTypeOf(applied["~orpc"].errorMap).toBeObject();
221
+ });
222
+ });
@@ -0,0 +1,210 @@
1
+ import type { ContractProcedure, Schema } from "@orpc/contract";
2
+ import type {
3
+ Builder,
4
+ DecoratedMiddleware,
5
+ Middleware,
6
+ MiddlewareOutputFn,
7
+ } from "@orpc/server";
8
+ import type { OmitChainMethodDeep } from "@orpc/shared";
9
+ import { describe, expectTypeOf, it } from "vitest";
10
+ import z from "zod";
11
+
12
+ import {
13
+ EffectBuilder,
14
+ EffectDecoratedProcedure,
15
+ makeEffectORPC,
16
+ } from "../index";
17
+ import type { CurrentContext, InitialContext } from "./parity-shared";
18
+ import { runtime } from "./parity-shared";
19
+ import type { AssertExtends } from "./shared";
20
+ import {
21
+ baseErrorMap,
22
+ baseMeta,
23
+ type BaseMeta,
24
+ inputSchema,
25
+ outputSchema,
26
+ } from "./shared";
27
+
28
+ const typedBuilder = {} as EffectBuilder<
29
+ InitialContext,
30
+ CurrentContext,
31
+ typeof inputSchema,
32
+ typeof outputSchema,
33
+ typeof baseErrorMap,
34
+ BaseMeta,
35
+ never,
36
+ never
37
+ >;
38
+
39
+ const rootBuilder = makeEffectORPC(runtime)
40
+ .$context<InitialContext>()
41
+ .$meta(baseMeta)
42
+ .$input(inputSchema)
43
+ .errors(baseErrorMap);
44
+
45
+ const withMiddlewares = rootBuilder.use(({ next }) =>
46
+ next({ context: { auth: true as boolean } }),
47
+ );
48
+
49
+ const procedureBuilder = withMiddlewares.meta(baseMeta);
50
+ const withInput = procedureBuilder.input(inputSchema);
51
+ const withOutput = procedureBuilder.output(outputSchema);
52
+ const withInputOutput = withInput.output(outputSchema);
53
+
54
+ describe("parity: @orpc/server builder.test-d.ts", () => {
55
+ it("exposes every upstream builder key", () => {
56
+ type MissingEffectBuilderKeys = Exclude<
57
+ keyof Builder<
58
+ InitialContext,
59
+ CurrentContext,
60
+ typeof inputSchema,
61
+ typeof outputSchema,
62
+ typeof baseErrorMap,
63
+ BaseMeta
64
+ >,
65
+ keyof typeof typedBuilder
66
+ >;
67
+
68
+ expectTypeOf<MissingEffectBuilderKeys>().toEqualTypeOf<never>();
69
+ });
70
+
71
+ it("is a contract procedure", () => {
72
+ expectTypeOf<
73
+ AssertExtends<
74
+ typeof typedBuilder,
75
+ ContractProcedure<
76
+ typeof inputSchema,
77
+ typeof outputSchema,
78
+ typeof baseErrorMap,
79
+ BaseMeta
80
+ >
81
+ >
82
+ >().toEqualTypeOf<true>();
83
+ });
84
+
85
+ it(".$config / .$context / .$meta / .$route / .$input", () => {
86
+ expectTypeOf(
87
+ rootBuilder.$config({
88
+ initialInputValidationIndex: Number.NEGATIVE_INFINITY,
89
+ initialOutputValidationIndex: Number.POSITIVE_INFINITY,
90
+ }),
91
+ ).toBeObject();
92
+
93
+ expectTypeOf(rootBuilder.$context()).toBeObject();
94
+ expectTypeOf(rootBuilder.$context<{ anything: string }>()).toBeObject();
95
+ expectTypeOf(rootBuilder.$meta<{ auth?: boolean }>({})).toBeObject();
96
+ expectTypeOf(rootBuilder.$route({ method: "GET" })).toBeObject();
97
+
98
+ const schema = z.void();
99
+ expectTypeOf(rootBuilder.$input(schema)).toBeObject();
100
+ expectTypeOf(rootBuilder.$input<Schema<void, unknown>>()).toBeObject();
101
+
102
+ rootBuilder.$config({
103
+ // @ts-expect-error - must be number
104
+ initialInputValidationIndex: "INVALID",
105
+ });
106
+ // @ts-expect-error - initial meta is required
107
+ rootBuilder.$meta<{ auth?: boolean }>();
108
+ // @ts-expect-error - invalid method
109
+ rootBuilder.$route({ method: "INVALID" });
110
+ // @ts-expect-error - invalid schema
111
+ rootBuilder.$input<"invalid">();
112
+ });
113
+
114
+ it(".middleware", () => {
115
+ expectTypeOf(
116
+ rootBuilder.middleware(
117
+ ({ next }, input: "input", output: MiddlewareOutputFn<"output">) => {
118
+ expectTypeOf(input).toEqualTypeOf<"input">();
119
+ expectTypeOf(output).toEqualTypeOf<MiddlewareOutputFn<"output">>();
120
+ return next({ context: { extra: true } });
121
+ },
122
+ ),
123
+ ).toExtend<
124
+ DecoratedMiddleware<
125
+ InitialContext,
126
+ { extra: boolean },
127
+ "input",
128
+ "output",
129
+ any,
130
+ BaseMeta
131
+ >
132
+ >();
133
+ });
134
+
135
+ it(".errors / .use / .meta / .route / .input / .output", () => {
136
+ expectTypeOf(
137
+ rootBuilder.errors({ BAD_GATEWAY: { message: "BAD" } }),
138
+ ).toBeObject();
139
+ expectTypeOf(withMiddlewares.use).toBeFunction();
140
+ expectTypeOf(withMiddlewares.meta).toBeFunction();
141
+ expectTypeOf(withMiddlewares.route).toBeFunction();
142
+ expectTypeOf(withMiddlewares.input).toBeFunction();
143
+ expectTypeOf(withMiddlewares.output).toBeFunction();
144
+
145
+ const mid = {} as Middleware<
146
+ { cacheable?: boolean } & Record<never, never>,
147
+ Record<never, never>,
148
+ unknown,
149
+ unknown,
150
+ any,
151
+ BaseMeta
152
+ >;
153
+ expectTypeOf(withMiddlewares.use(mid)).toBeObject();
154
+ });
155
+
156
+ it(".handler / .effect / .prefix / .tag / .router / .lazy", () => {
157
+ expectTypeOf(withOutput.handler(() => ({ output: 456 }))).toExtend<
158
+ EffectDecoratedProcedure<
159
+ InitialContext & Record<never, never>,
160
+ CurrentContext,
161
+ typeof inputSchema,
162
+ typeof outputSchema,
163
+ typeof baseErrorMap,
164
+ BaseMeta,
165
+ never,
166
+ never
167
+ >
168
+ >();
169
+
170
+ expectTypeOf(
171
+ withOutput.effect(function* () {
172
+ return { output: 456 };
173
+ }),
174
+ ).toExtend<
175
+ EffectDecoratedProcedure<
176
+ InitialContext & Record<never, never>,
177
+ CurrentContext,
178
+ typeof inputSchema,
179
+ typeof outputSchema,
180
+ typeof baseErrorMap,
181
+ BaseMeta,
182
+ never,
183
+ never
184
+ >
185
+ >();
186
+
187
+ expectTypeOf(rootBuilder.prefix("/api")).toBeObject();
188
+ expectTypeOf(rootBuilder.tag("tag1", "tag2")).toBeObject();
189
+ });
190
+ });
191
+
192
+ describe("parity: @orpc/server builder-variants.test-d.ts", () => {
193
+ it("keeps variant method surface aligned with upstream", () => {
194
+ void ({} as OmitChainMethodDeep<
195
+ typeof typedBuilder,
196
+ "$config" | "$context" | "$meta" | "$route" | "$input" | "middleware"
197
+ >);
198
+
199
+ expectTypeOf(withMiddlewares.errors).toBeFunction();
200
+ expectTypeOf(withMiddlewares.use).toBeFunction();
201
+ expectTypeOf(withMiddlewares.handler).toBeFunction();
202
+ expectTypeOf(withMiddlewares.effect).toBeFunction();
203
+
204
+ expectTypeOf(withMiddlewares.handler).toBeFunction();
205
+ expectTypeOf(procedureBuilder.traced).toBeFunction();
206
+ expectTypeOf(withInput.output).toBeFunction();
207
+ expectTypeOf(withOutput.input).toBeFunction();
208
+ expectTypeOf(withInputOutput.effect).toBeFunction();
209
+ });
210
+ });