@modern-js/utils 1.1.2 → 1.1.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @modern-js/utils
2
2
 
3
+ ## 1.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 085a6a58: refactor server plugin
8
+ - 085a6a58: refactor server plugin
9
+ - 085a6a58: refactor server conifg
10
+ - d280ea33: chore: runtime exports can choose to generate d.ts file
11
+ - 085a6a58: support server runtime
12
+ - 085a6a58: feat: refactor server plugin
13
+
3
14
  ## 1.1.2
4
15
 
5
16
  ### Patch Changes
@@ -1,10 +1,21 @@
1
+ import { findExists } from "./findExists";
1
2
  /**
2
3
  * Require function compatible with esm and cjs module.
3
4
  * @param filePath - File to required.
4
5
  * @returns module export object.
5
6
  */
7
+
6
8
  export const compatRequire = filePath => {
7
9
  const mod = require(filePath);
8
10
 
9
11
  return mod !== null && mod !== void 0 && mod.__esModule ? mod.default : mod;
12
+ };
13
+ export const requireExistModule = (filename, extensions = ['.ts', '.js']) => {
14
+ const exist = findExists(extensions.map(ext => `${filename}${ext}`));
15
+
16
+ if (!exist) {
17
+ return null;
18
+ }
19
+
20
+ return compatRequire(exist);
10
21
  };
@@ -47,7 +47,18 @@ export const SERVER_RENDER_FUNCTION_NAME = 'serverRender';
47
47
  */
48
48
 
49
49
  export const LOADABLE_STATS_FILE = 'loadable-stats.json';
50
+ /**
51
+ * real entry generate by modern.js
52
+ */
53
+
50
54
  export const HIDE_MODERN_JS_DIR = './node_modules/.modern-js';
55
+ /**
56
+ * internal specified folder
57
+ */
58
+
59
+ export const API_DIR = 'api';
60
+ export const SERVER_DIR = 'server';
61
+ export const SHARED_DIR = 'shared';
51
62
  /**
52
63
  * Internal plugins that work as soon as they are installed.
53
64
  */
@@ -118,6 +129,10 @@ export const INTERNAL_PLUGINS = {
118
129
  '@modern-js/plugin-server-build': {
119
130
  cli: '@modern-js/plugin-server-build'
120
131
  },
132
+ '@modern-js/plugin-server': {
133
+ cli: '@modern-js/plugin-server/cli',
134
+ server: '@modern-js/plugin-server/server'
135
+ },
121
136
  '@modern-js/plugin-micro-frontend': {
122
137
  cli: '@modern-js/plugin-micro-frontend/cli'
123
138
  },
@@ -175,7 +190,10 @@ export const PLUGIN_SCHEMAS = {
175
190
  type: 'object',
176
191
  properties: {
177
192
  prefix: {
178
- type: 'string'
193
+ type: ['string', 'array'],
194
+ items: {
195
+ type: 'string'
196
+ }
179
197
  },
180
198
  fetcher: {
181
199
  type: 'string'
@@ -183,7 +201,7 @@ export const PLUGIN_SCHEMAS = {
183
201
  proxy: {
184
202
  type: 'object'
185
203
  },
186
- requestCreater: {
204
+ requestCreator: {
187
205
  type: 'string'
188
206
  }
189
207
  }
@@ -18,8 +18,9 @@ const memo = fn => {
18
18
  };
19
19
  };
20
20
 
21
- export const createRuntimeExportsUtils = memo((pwd = '', namespace) => {
22
- const entryExportFile = path.join(pwd, `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`); // const ensure = () => {
21
+ export const createRuntimeExportsUtils = memo((pwd = '', namespace, ts = false) => {
22
+ const entryExportFile = path.join(pwd, `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`);
23
+ const entryExportTsFile = path.join(pwd, `.runtime-exports/${namespace ? `${namespace}.d.ts` : 'index.d.ts'}`); // const ensure = () => {
23
24
  // if (!fs.existsSync(entryExportFile)) {
24
25
  // fs.outputFileSync(entryExportFile, '');
25
26
  // }
@@ -32,9 +33,11 @@ export const createRuntimeExportsUtils = memo((pwd = '', namespace) => {
32
33
 
33
34
  try {
34
35
  fs.ensureFileSync(entryExportFile);
36
+ fs.ensureFileSync(entryExportTsFile);
35
37
 
36
38
  if (!fs.readFileSync(entryExportFile, 'utf8').includes(statement)) {
37
39
  fs.appendFileSync(entryExportFile, `${statement}\n`);
40
+ ts && fs.appendFileSync(entryExportTsFile, `${statement.replace('.js', '.d')}\n`);
38
41
  }
39
42
  } catch (_unused) {// FIXME:
40
43
  }
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.compatRequire = void 0;
6
+ exports.requireExistModule = exports.compatRequire = void 0;
7
+
8
+ var _findExists = require("./findExists");
7
9
 
8
10
  /**
9
11
  * Require function compatible with esm and cjs module.
@@ -16,4 +18,16 @@ const compatRequire = filePath => {
16
18
  return mod !== null && mod !== void 0 && mod.__esModule ? mod.default : mod;
17
19
  };
18
20
 
19
- exports.compatRequire = compatRequire;
21
+ exports.compatRequire = compatRequire;
22
+
23
+ const requireExistModule = (filename, extensions = ['.ts', '.js']) => {
24
+ const exist = (0, _findExists.findExists)(extensions.map(ext => `${filename}${ext}`));
25
+
26
+ if (!exist) {
27
+ return null;
28
+ }
29
+
30
+ return compatRequire(exist);
31
+ };
32
+
33
+ exports.requireExistModule = requireExistModule;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SERVER_RENDER_FUNCTION_NAME = exports.SERVER_BUNDLE_DIRECTORY = exports.ROUTE_SPEC_FILE = exports.PLUGIN_SCHEMAS = exports.MAIN_ENTRY_NAME = exports.LOADABLE_STATS_FILE = exports.LAUNCH_EDITOR_ENDPOINT = exports.INTERNAL_SRC_ALIAS = exports.INTERNAL_PLUGINS = exports.INTERNAL_DIR_ALAIS = exports.HMR_SOCK_PATH = exports.HIDE_MODERN_JS_DIR = exports.ENTRY_NAME_PATTERN = void 0;
6
+ exports.SHARED_DIR = exports.SERVER_RENDER_FUNCTION_NAME = exports.SERVER_DIR = exports.SERVER_BUNDLE_DIRECTORY = exports.ROUTE_SPEC_FILE = exports.PLUGIN_SCHEMAS = exports.MAIN_ENTRY_NAME = exports.LOADABLE_STATS_FILE = exports.LAUNCH_EDITOR_ENDPOINT = exports.INTERNAL_SRC_ALIAS = exports.INTERNAL_PLUGINS = exports.INTERNAL_DIR_ALAIS = exports.HMR_SOCK_PATH = exports.HIDE_MODERN_JS_DIR = exports.ENTRY_NAME_PATTERN = exports.API_DIR = void 0;
7
7
 
8
8
  /**
9
9
  * alias to src directory
@@ -63,13 +63,27 @@ const SERVER_RENDER_FUNCTION_NAME = 'serverRender';
63
63
 
64
64
  exports.SERVER_RENDER_FUNCTION_NAME = SERVER_RENDER_FUNCTION_NAME;
65
65
  const LOADABLE_STATS_FILE = 'loadable-stats.json';
66
+ /**
67
+ * real entry generate by modern.js
68
+ */
69
+
66
70
  exports.LOADABLE_STATS_FILE = LOADABLE_STATS_FILE;
67
71
  const HIDE_MODERN_JS_DIR = './node_modules/.modern-js';
68
72
  /**
69
- * Internal plugins that work as soon as they are installed.
73
+ * internal specified folder
70
74
  */
71
75
 
72
76
  exports.HIDE_MODERN_JS_DIR = HIDE_MODERN_JS_DIR;
77
+ const API_DIR = 'api';
78
+ exports.API_DIR = API_DIR;
79
+ const SERVER_DIR = 'server';
80
+ exports.SERVER_DIR = SERVER_DIR;
81
+ const SHARED_DIR = 'shared';
82
+ /**
83
+ * Internal plugins that work as soon as they are installed.
84
+ */
85
+
86
+ exports.SHARED_DIR = SHARED_DIR;
73
87
  const INTERNAL_PLUGINS = {
74
88
  '@modern-js/app-tools': {
75
89
  cli: '@modern-js/app-tools/cli'
@@ -136,6 +150,10 @@ const INTERNAL_PLUGINS = {
136
150
  '@modern-js/plugin-server-build': {
137
151
  cli: '@modern-js/plugin-server-build'
138
152
  },
153
+ '@modern-js/plugin-server': {
154
+ cli: '@modern-js/plugin-server/cli',
155
+ server: '@modern-js/plugin-server/server'
156
+ },
139
157
  '@modern-js/plugin-micro-frontend': {
140
158
  cli: '@modern-js/plugin-micro-frontend/cli'
141
159
  },
@@ -194,7 +212,10 @@ const PLUGIN_SCHEMAS = {
194
212
  type: 'object',
195
213
  properties: {
196
214
  prefix: {
197
- type: 'string'
215
+ type: ['string', 'array'],
216
+ items: {
217
+ type: 'string'
218
+ }
198
219
  },
199
220
  fetcher: {
200
221
  type: 'string'
@@ -202,7 +223,7 @@ const PLUGIN_SCHEMAS = {
202
223
  proxy: {
203
224
  type: 'object'
204
225
  },
205
- requestCreater: {
226
+ requestCreator: {
206
227
  type: 'string'
207
228
  }
208
229
  }
@@ -29,8 +29,10 @@ const memo = fn => {
29
29
  };
30
30
  };
31
31
 
32
- const createRuntimeExportsUtils = memo((pwd = '', namespace) => {
33
- const entryExportFile = _path.default.join(pwd, `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`); // const ensure = () => {
32
+ const createRuntimeExportsUtils = memo((pwd = '', namespace, ts = false) => {
33
+ const entryExportFile = _path.default.join(pwd, `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`);
34
+
35
+ const entryExportTsFile = _path.default.join(pwd, `.runtime-exports/${namespace ? `${namespace}.d.ts` : 'index.d.ts'}`); // const ensure = () => {
34
36
  // if (!fs.existsSync(entryExportFile)) {
35
37
  // fs.outputFileSync(entryExportFile, '');
36
38
  // }
@@ -45,8 +47,12 @@ const createRuntimeExportsUtils = memo((pwd = '', namespace) => {
45
47
  try {
46
48
  _fsExtra.default.ensureFileSync(entryExportFile);
47
49
 
50
+ _fsExtra.default.ensureFileSync(entryExportTsFile);
51
+
48
52
  if (!_fsExtra.default.readFileSync(entryExportFile, 'utf8').includes(statement)) {
49
53
  _fsExtra.default.appendFileSync(entryExportFile, `${statement}\n`);
54
+
55
+ ts && _fsExtra.default.appendFileSync(entryExportTsFile, `${statement.replace('.js', '.d')}\n`);
50
56
  }
51
57
  } catch (_unused) {// FIXME:
52
58
  }
@@ -1,10 +1,24 @@
1
+ import { findExists } from "./findExists";
1
2
  /**
2
3
  * Require function compatible with esm and cjs module.
3
4
  * @param filePath - File to required.
4
5
  * @returns module export object.
5
6
  */
7
+
6
8
  export var compatRequire = function compatRequire(filePath) {
7
9
  var mod = require(filePath);
8
10
 
9
11
  return mod !== null && mod !== void 0 && mod.__esModule ? mod["default"] : mod;
12
+ };
13
+ export var requireExistModule = function requireExistModule(filename) {
14
+ var extensions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ['.ts', '.js'];
15
+ var exist = findExists(extensions.map(function (ext) {
16
+ return "".concat(filename).concat(ext);
17
+ }));
18
+
19
+ if (!exist) {
20
+ return null;
21
+ }
22
+
23
+ return compatRequire(exist);
10
24
  };
@@ -49,7 +49,18 @@ export var SERVER_RENDER_FUNCTION_NAME = 'serverRender';
49
49
  */
50
50
 
51
51
  export var LOADABLE_STATS_FILE = 'loadable-stats.json';
52
+ /**
53
+ * real entry generate by modern.js
54
+ */
55
+
52
56
  export var HIDE_MODERN_JS_DIR = './node_modules/.modern-js';
57
+ /**
58
+ * internal specified folder
59
+ */
60
+
61
+ export var API_DIR = 'api';
62
+ export var SERVER_DIR = 'server';
63
+ export var SHARED_DIR = 'shared';
53
64
  /**
54
65
  * Internal plugins that work as soon as they are installed.
55
66
  */
@@ -120,6 +131,10 @@ export var INTERNAL_PLUGINS = {
120
131
  '@modern-js/plugin-server-build': {
121
132
  cli: '@modern-js/plugin-server-build'
122
133
  },
134
+ '@modern-js/plugin-server': {
135
+ cli: '@modern-js/plugin-server/cli',
136
+ server: '@modern-js/plugin-server/server'
137
+ },
123
138
  '@modern-js/plugin-micro-frontend': {
124
139
  cli: '@modern-js/plugin-micro-frontend/cli'
125
140
  },
@@ -175,7 +190,10 @@ export var PLUGIN_SCHEMAS = {
175
190
  type: 'object',
176
191
  properties: {
177
192
  prefix: {
178
- type: 'string'
193
+ type: ['string', 'array'],
194
+ items: {
195
+ type: 'string'
196
+ }
179
197
  },
180
198
  fetcher: {
181
199
  type: 'string'
@@ -183,7 +201,7 @@ export var PLUGIN_SCHEMAS = {
183
201
  proxy: {
184
202
  type: 'object'
185
203
  },
186
- requestCreater: {
204
+ requestCreator: {
187
205
  type: 'string'
188
206
  }
189
207
  }
@@ -25,7 +25,9 @@ var memo = function memo(fn) {
25
25
  export var createRuntimeExportsUtils = memo(function () {
26
26
  var pwd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
27
27
  var namespace = arguments.length > 1 ? arguments[1] : undefined;
28
- var entryExportFile = path.join(pwd, ".runtime-exports/".concat(namespace ? "".concat(namespace, ".js") : 'index.js')); // const ensure = () => {
28
+ var ts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
29
+ var entryExportFile = path.join(pwd, ".runtime-exports/".concat(namespace ? "".concat(namespace, ".js") : 'index.js'));
30
+ var entryExportTsFile = path.join(pwd, ".runtime-exports/".concat(namespace ? "".concat(namespace, ".d.ts") : 'index.d.ts')); // const ensure = () => {
29
31
  // if (!fs.existsSync(entryExportFile)) {
30
32
  // fs.outputFileSync(entryExportFile, '');
31
33
  // }
@@ -38,9 +40,11 @@ export var createRuntimeExportsUtils = memo(function () {
38
40
 
39
41
  try {
40
42
  fs.ensureFileSync(entryExportFile);
43
+ fs.ensureFileSync(entryExportTsFile);
41
44
 
42
45
  if (!fs.readFileSync(entryExportFile, 'utf8').includes(statement)) {
43
46
  fs.appendFileSync(entryExportFile, "".concat(statement, "\n"));
47
+ ts && fs.appendFileSync(entryExportTsFile, "".concat(statement.replace('.js', '.d'), "\n"));
44
48
  }
45
49
  } catch (_unused) {// FIXME:
46
50
  }
@@ -3,4 +3,5 @@
3
3
  * @param filePath - File to required.
4
4
  * @returns module export object.
5
5
  */
6
- export declare const compatRequire: (filePath: string) => any;
6
+ export declare const compatRequire: (filePath: string) => any;
7
+ export declare const requireExistModule: (filename: string, extensions?: string[]) => any;
@@ -47,7 +47,18 @@ export declare const SERVER_RENDER_FUNCTION_NAME = "serverRender";
47
47
  */
48
48
 
49
49
  export declare const LOADABLE_STATS_FILE = "loadable-stats.json";
50
+ /**
51
+ * real entry generate by modern.js
52
+ */
53
+
50
54
  export declare const HIDE_MODERN_JS_DIR = "./node_modules/.modern-js";
55
+ /**
56
+ * internal specified folder
57
+ */
58
+
59
+ export declare const API_DIR = "api";
60
+ export declare const SERVER_DIR = "server";
61
+ export declare const SHARED_DIR = "shared";
51
62
  /**
52
63
  * Internal plugins that work as soon as they are installed.
53
64
  */
@@ -88,7 +99,10 @@ export declare const PLUGIN_SCHEMAS: {
88
99
  type: string;
89
100
  properties: {
90
101
  prefix: {
91
- type: string;
102
+ type: string[];
103
+ items: {
104
+ type: string;
105
+ };
92
106
  };
93
107
  fetcher: {
94
108
  type: string;
@@ -96,7 +110,7 @@ export declare const PLUGIN_SCHEMAS: {
96
110
  proxy: {
97
111
  type: string;
98
112
  };
99
- requestCreater: {
113
+ requestCreator: {
100
114
  type: string;
101
115
  };
102
116
  };
@@ -1,4 +1,4 @@
1
- export declare const createRuntimeExportsUtils: (pwd: any, namespace: string) => {
1
+ export declare const createRuntimeExportsUtils: (pwd: any, namespace: string, ts?: any) => {
2
2
  addExport: (statement: string) => void;
3
3
  getPath: () => string;
4
4
  };
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.1.2",
14
+ "version": "1.1.3",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -65,8 +65,8 @@
65
65
  "@types/recursive-readdir": "^2.2.0",
66
66
  "typescript": "^4",
67
67
  "webpack": "^5.54.0",
68
- "@modern-js/plugin-testing": "^1.1.0",
69
- "@modern-js/module-tools": "^1.1.0"
68
+ "@modern-js/plugin-testing": "^1.1.1",
69
+ "@modern-js/module-tools": "^1.1.1"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "typescript": "^4.4.3"
@@ -1,3 +1,5 @@
1
+ import { findExists } from './findExists';
2
+
1
3
  /**
2
4
  * Require function compatible with esm and cjs module.
3
5
  * @param filePath - File to required.
@@ -8,3 +10,16 @@ export const compatRequire = (filePath: string) => {
8
10
 
9
11
  return mod?.__esModule ? mod.default : mod;
10
12
  };
13
+
14
+ export const requireExistModule = (
15
+ filename: string,
16
+ extensions = ['.ts', '.js'],
17
+ ) => {
18
+ const exist = findExists(extensions.map(ext => `${filename}${ext}`));
19
+
20
+ if (!exist) {
21
+ return null;
22
+ }
23
+
24
+ return compatRequire(exist);
25
+ };
package/src/constants.ts CHANGED
@@ -48,8 +48,20 @@ export const SERVER_RENDER_FUNCTION_NAME = 'serverRender';
48
48
  */
49
49
  export const LOADABLE_STATS_FILE = 'loadable-stats.json';
50
50
 
51
+ /**
52
+ * real entry generate by modern.js
53
+ */
51
54
  export const HIDE_MODERN_JS_DIR = './node_modules/.modern-js';
52
55
 
56
+ /**
57
+ * internal specified folder
58
+ */
59
+ export const API_DIR = 'api';
60
+
61
+ export const SERVER_DIR = 'server';
62
+
63
+ export const SHARED_DIR = 'shared';
64
+
53
65
  /**
54
66
  * Internal plugins that work as soon as they are installed.
55
67
  */
@@ -91,6 +103,10 @@ export const INTERNAL_PLUGINS: {
91
103
  },
92
104
  '@modern-js/plugin-unbundle': { cli: '@modern-js/plugin-unbundle' },
93
105
  '@modern-js/plugin-server-build': { cli: '@modern-js/plugin-server-build' },
106
+ '@modern-js/plugin-server': {
107
+ cli: '@modern-js/plugin-server/cli',
108
+ server: '@modern-js/plugin-server/server',
109
+ },
94
110
  '@modern-js/plugin-micro-frontend': {
95
111
  cli: '@modern-js/plugin-micro-frontend/cli',
96
112
  },
@@ -133,10 +149,13 @@ export const PLUGIN_SCHEMAS = {
133
149
  schema: {
134
150
  type: 'object',
135
151
  properties: {
136
- prefix: { type: 'string' },
152
+ prefix: {
153
+ type: ['string', 'array'],
154
+ items: { type: 'string' },
155
+ },
137
156
  fetcher: { type: 'string' },
138
157
  proxy: { type: 'object' },
139
- requestCreater: { type: 'string' },
158
+ requestCreator: { type: 'string' },
140
159
  },
141
160
  },
142
161
  },
@@ -20,36 +20,49 @@ const memo = <T extends (...args: any[]) => any>(fn: T) => {
20
20
  };
21
21
  };
22
22
 
23
- export const createRuntimeExportsUtils = memo((pwd = '', namespace: string) => {
24
- const entryExportFile = path.join(
25
- pwd,
26
- `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`,
27
- );
28
-
29
- // const ensure = () => {
30
- // if (!fs.existsSync(entryExportFile)) {
31
- // fs.outputFileSync(entryExportFile, '');
32
- // }
33
- // fs.ensureFileSync(entryExportFile);
34
- // };
35
-
36
- const addExport = (statement: string) => {
37
- // eslint-disable-next-line no-param-reassign
38
- statement = normalizeOutputPath(statement);
39
- try {
40
- fs.ensureFileSync(entryExportFile);
41
- if (!fs.readFileSync(entryExportFile, 'utf8').includes(statement)) {
42
- fs.appendFileSync(entryExportFile, `${statement}\n`);
23
+ export const createRuntimeExportsUtils = memo(
24
+ (pwd = '', namespace: string, ts = false) => {
25
+ const entryExportFile = path.join(
26
+ pwd,
27
+ `.runtime-exports/${namespace ? `${namespace}.js` : 'index.js'}`,
28
+ );
29
+ const entryExportTsFile = path.join(
30
+ pwd,
31
+ `.runtime-exports/${namespace ? `${namespace}.d.ts` : 'index.d.ts'}`,
32
+ );
33
+
34
+ // const ensure = () => {
35
+ // if (!fs.existsSync(entryExportFile)) {
36
+ // fs.outputFileSync(entryExportFile, '');
37
+ // }
38
+ // fs.ensureFileSync(entryExportFile);
39
+ // };
40
+
41
+ const addExport = (statement: string) => {
42
+ // eslint-disable-next-line no-param-reassign
43
+ statement = normalizeOutputPath(statement);
44
+ try {
45
+ fs.ensureFileSync(entryExportFile);
46
+ fs.ensureFileSync(entryExportTsFile);
47
+
48
+ if (!fs.readFileSync(entryExportFile, 'utf8').includes(statement)) {
49
+ fs.appendFileSync(entryExportFile, `${statement}\n`);
50
+ ts &&
51
+ fs.appendFileSync(
52
+ entryExportTsFile,
53
+ `${statement.replace('.js', '.d')}\n`,
54
+ );
55
+ }
56
+ } catch {
57
+ // FIXME:
43
58
  }
44
- } catch {
45
- // FIXME:
46
- }
47
- };
59
+ };
48
60
 
49
- const getPath = () => entryExportFile;
61
+ const getPath = () => entryExportFile;
50
62
 
51
- return {
52
- addExport,
53
- getPath,
54
- };
55
- });
63
+ return {
64
+ addExport,
65
+ getPath,
66
+ };
67
+ },
68
+ );