@umijs/plugins 4.0.0-canary.20220729.2 → 4.0.0-canary.20220819.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.
- package/dist/dva.js +23 -0
- package/dist/initial-state.js +9 -0
- package/dist/layout.js +19 -6
- package/dist/locale.js +1 -1
- package/dist/qiankun/master.js +16 -0
- package/dist/qiankun/slave.js +25 -0
- package/dist/request.js +11 -0
- package/dist/tailwindcss.js +5 -1
- package/libs/qiankun/master/MicroApp.tsx +1 -2
- package/libs/qiankun/master/common.ts +55 -19
- package/libs/qiankun/master/masterRuntimePlugin.tsx +10 -2
- package/libs/qiankun/master/types.ts +1 -1
- package/package.json +3 -3
package/dist/dva.js
CHANGED
|
@@ -30,6 +30,7 @@ module.exports = __toCommonJS(dva_exports);
|
|
|
30
30
|
var t = __toESM(require("@umijs/bundler-utils/compiled/babel/types"));
|
|
31
31
|
var import_utils = require("@umijs/utils");
|
|
32
32
|
var import_path = require("path");
|
|
33
|
+
var import_umi = require("umi");
|
|
33
34
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
34
35
|
var import_modelUtils = require("./utils/modelUtils");
|
|
35
36
|
var import_withTmpPath = require("./utils/withTmpPath");
|
|
@@ -65,6 +66,28 @@ var dva_default = (api) => {
|
|
|
65
66
|
path: "models.ts",
|
|
66
67
|
content: import_modelUtils.ModelUtils.getModelsContent(models)
|
|
67
68
|
});
|
|
69
|
+
api.writeTmpFile({
|
|
70
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
71
|
+
content: `
|
|
72
|
+
export interface IRuntimeConfig {
|
|
73
|
+
dva?: {
|
|
74
|
+
config?: {
|
|
75
|
+
initialState?: Record<string, any>;
|
|
76
|
+
onError?: any;
|
|
77
|
+
onStateChange?: any;
|
|
78
|
+
onAction?: any;
|
|
79
|
+
onHmr?: any;
|
|
80
|
+
onReducer?: any;
|
|
81
|
+
onEffect?: any;
|
|
82
|
+
extraReducers?: any;
|
|
83
|
+
extraEnhancers?: any;
|
|
84
|
+
[key: string]: any;
|
|
85
|
+
},
|
|
86
|
+
plugins?: string[];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
`
|
|
90
|
+
});
|
|
68
91
|
api.writeTmpFile({
|
|
69
92
|
path: "dva.tsx",
|
|
70
93
|
tpl: `
|
package/dist/initial-state.js
CHANGED
|
@@ -22,6 +22,7 @@ __export(initial_state_exports, {
|
|
|
22
22
|
default: () => initial_state_default
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(initial_state_exports);
|
|
25
|
+
var import_umi = require("umi");
|
|
25
26
|
var import_withTmpPath = require("./utils/withTmpPath");
|
|
26
27
|
var initial_state_default = (api) => {
|
|
27
28
|
api.describe({
|
|
@@ -132,6 +133,14 @@ import React from 'react';
|
|
|
132
133
|
import Provider from './Provider';
|
|
133
134
|
export function dataflowProvider(container) {
|
|
134
135
|
return <Provider>{ container }</Provider>;
|
|
136
|
+
}
|
|
137
|
+
`
|
|
138
|
+
});
|
|
139
|
+
api.writeTmpFile({
|
|
140
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
141
|
+
content: `
|
|
142
|
+
export interface IRuntimeConfig {
|
|
143
|
+
getInitialState?: () => Promise<Record<string, any>>
|
|
135
144
|
}
|
|
136
145
|
`
|
|
137
146
|
});
|
package/dist/layout.js
CHANGED
|
@@ -28,6 +28,7 @@ module.exports = __toCommonJS(layout_exports);
|
|
|
28
28
|
var allIcons = __toESM(require("@ant-design/icons"));
|
|
29
29
|
var import_fs = require("fs");
|
|
30
30
|
var import_path = require("path");
|
|
31
|
+
var import_umi = require("umi");
|
|
31
32
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
32
33
|
var import_withTmpPath = require("./utils/withTmpPath");
|
|
33
34
|
var layout_default = (api) => {
|
|
@@ -251,15 +252,16 @@ const { formatMessage } = useIntl();
|
|
|
251
252
|
${hasInitialStatePlugin ? `import type InitialStateType from '@@/plugin-initialState/@@initialState';
|
|
252
253
|
type InitDataType = ReturnType<typeof InitialStateType>;
|
|
253
254
|
` : "type InitDataType = any;"}
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
|
|
256
|
+
import type { IConfigFromPlugins } from '@@/core/pluginConfig';
|
|
257
|
+
|
|
256
258
|
export type RunTimeLayoutConfig = (initData: InitDataType) => Omit<
|
|
257
259
|
ProLayoutProps,
|
|
258
260
|
'rightContentRender'
|
|
259
261
|
> & {
|
|
260
262
|
childrenRender?: (dom: JSX.Element, props: ProLayoutProps) => React.ReactNode;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
+
unAccessible?: JSX.Element;
|
|
264
|
+
noFound?: JSX.Element;
|
|
263
265
|
logout?: (initialState: InitDataType['initialState']) => Promise<void> | void;
|
|
264
266
|
rightContentRender?: (
|
|
265
267
|
headerProps: HeaderProps,
|
|
@@ -280,6 +282,15 @@ const { formatMessage } = useIntl();
|
|
|
280
282
|
};
|
|
281
283
|
`
|
|
282
284
|
});
|
|
285
|
+
api.writeTmpFile({
|
|
286
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
287
|
+
content: `
|
|
288
|
+
import type { RunTimeLayoutConfig } from './types.d';
|
|
289
|
+
export interface IRuntimeConfig {
|
|
290
|
+
layout?: RunTimeLayoutConfig
|
|
291
|
+
}
|
|
292
|
+
`
|
|
293
|
+
});
|
|
283
294
|
const iconsMap = Object.keys(api.appData.routes).reduce((memo, id) => {
|
|
284
295
|
const { icon } = api.appData.routes[id];
|
|
285
296
|
if (icon) {
|
|
@@ -579,11 +590,13 @@ const Exception: React.FC<{
|
|
|
579
590
|
route?: IRoute;
|
|
580
591
|
notFound?: React.ReactNode;
|
|
581
592
|
noAccessible?: React.ReactNode;
|
|
593
|
+
unAccessible?: React.ReactNode;
|
|
594
|
+
noFound?: React.ReactNode;
|
|
582
595
|
}> = (props) => (
|
|
583
596
|
// render custom 404
|
|
584
|
-
(!props.route && props.notFound) ||
|
|
597
|
+
(!props.route && (props.noFound || props.notFound)) ||
|
|
585
598
|
// render custom 403
|
|
586
|
-
(props.route.unaccessible && props.noAccessible) ||
|
|
599
|
+
(props.route.unaccessible && (props.unAccessible || props.noAccessible)) ||
|
|
587
600
|
// render default exception
|
|
588
601
|
((!props.route || props.route.unaccessible) && (
|
|
589
602
|
<Result
|
package/dist/locale.js
CHANGED
|
@@ -202,7 +202,7 @@ var locale_default = (api) => {
|
|
|
202
202
|
api.writeTmpFile({
|
|
203
203
|
path: "index.ts",
|
|
204
204
|
content: `
|
|
205
|
-
export { addLocale, setLocale, getLocale, getIntl, useIntl, injectIntl, formatMessage, FormattedMessage, getAllLocales } from './localeExports';
|
|
205
|
+
export { addLocale, setLocale, getLocale, getIntl, useIntl, injectIntl, formatMessage, FormattedMessage, getAllLocales, FormattedDate, FormattedDateParts, FormattedDisplayName, FormattedHTMLMessage, FormattedList, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, IntlProvider, RawIntlProvider } from './localeExports';
|
|
206
206
|
export { SelectLang } from './SelectLang';
|
|
207
207
|
`
|
|
208
208
|
});
|
package/dist/qiankun/master.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(master_exports, {
|
|
|
45
45
|
module.exports = __toCommonJS(master_exports);
|
|
46
46
|
var import_fs = require("fs");
|
|
47
47
|
var import_path = require("path");
|
|
48
|
+
var import_umi = require("umi");
|
|
48
49
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
49
50
|
var import_withTmpPath = require("../utils/withTmpPath");
|
|
50
51
|
var import_constants = require("./constants");
|
|
@@ -103,6 +104,21 @@ var master_default = (api) => {
|
|
|
103
104
|
}
|
|
104
105
|
api.onGenerateFiles(() => {
|
|
105
106
|
var _a;
|
|
107
|
+
api.writeTmpFile({
|
|
108
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
109
|
+
content: `
|
|
110
|
+
import { MasterOptions } from './types'
|
|
111
|
+
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
|
112
|
+
type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
|
|
113
|
+
interface Config {
|
|
114
|
+
master?: MasterOptions;
|
|
115
|
+
}
|
|
116
|
+
export interface IRuntimeConfig {
|
|
117
|
+
qiankun?: XOR<MasterOptions, Config>;
|
|
118
|
+
${import_constants.MODEL_EXPORT_NAME}?: () => Record<string, any>;
|
|
119
|
+
}
|
|
120
|
+
`
|
|
121
|
+
});
|
|
106
122
|
api.writeTmpFile({
|
|
107
123
|
path: "masterOptions.ts",
|
|
108
124
|
content: `
|
package/dist/qiankun/slave.js
CHANGED
|
@@ -45,6 +45,7 @@ module.exports = __toCommonJS(slave_exports);
|
|
|
45
45
|
var import_assert = __toESM(require("assert"));
|
|
46
46
|
var import_fs = require("fs");
|
|
47
47
|
var import_path = require("path");
|
|
48
|
+
var import_umi = require("umi");
|
|
48
49
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
49
50
|
var import_withTmpPath = require("../utils/withTmpPath");
|
|
50
51
|
var import_constants = require("./constants");
|
|
@@ -75,6 +76,30 @@ var slave_default = (api) => {
|
|
|
75
76
|
];
|
|
76
77
|
}
|
|
77
78
|
});
|
|
79
|
+
api.onGenerateFiles(() => {
|
|
80
|
+
api.writeTmpFile({
|
|
81
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
82
|
+
content: `
|
|
83
|
+
interface LifeCycles {
|
|
84
|
+
bootstrap?: (props?: any) => Promise<any>;
|
|
85
|
+
mount?: (props?: any) => Promise<any>;
|
|
86
|
+
unmount?: (props?: any) => Promise<any>;
|
|
87
|
+
update?: (props?: any) => Promise<any>;
|
|
88
|
+
}
|
|
89
|
+
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
|
90
|
+
type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
|
|
91
|
+
interface SlaveOption extends LifeCycles {
|
|
92
|
+
enable?: boolean;
|
|
93
|
+
}
|
|
94
|
+
interface Config {
|
|
95
|
+
slave?: SlaveOption;
|
|
96
|
+
}
|
|
97
|
+
export interface IRuntimeConfig {
|
|
98
|
+
qiankun?: XOR<Config, LifeCycles>
|
|
99
|
+
}
|
|
100
|
+
`
|
|
101
|
+
});
|
|
102
|
+
});
|
|
78
103
|
api.modifyDefaultConfig((memo) => {
|
|
79
104
|
var _a, _b, _c;
|
|
80
105
|
const initialSlaveOptions = __spreadValues(__spreadValues({
|
package/dist/request.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(request_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(request_exports);
|
|
28
28
|
var import_path = require("path");
|
|
29
|
+
var import_umi = require("umi");
|
|
29
30
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
30
31
|
var request_default = (api) => {
|
|
31
32
|
api.describe({
|
|
@@ -341,9 +342,19 @@ export {
|
|
|
341
342
|
useRequest,
|
|
342
343
|
UseRequestProvider,
|
|
343
344
|
request,
|
|
345
|
+
getRequestInstance,
|
|
344
346
|
} from './request';
|
|
345
347
|
`
|
|
346
348
|
});
|
|
349
|
+
api.writeTmpFile({
|
|
350
|
+
path: import_umi.RUNTIME_TYPE_FILE_NAME,
|
|
351
|
+
content: `
|
|
352
|
+
import type { RequestConfig } from './types.d'
|
|
353
|
+
export type IRuntimeConfig = {
|
|
354
|
+
request?: RequestConfig
|
|
355
|
+
};
|
|
356
|
+
`
|
|
357
|
+
});
|
|
347
358
|
});
|
|
348
359
|
};
|
|
349
360
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/tailwindcss.js
CHANGED
|
@@ -40,15 +40,19 @@ var tailwindcss_default = (api) => {
|
|
|
40
40
|
const inputPath = (0, import_path.join)(api.cwd, "tailwind.css");
|
|
41
41
|
const generatedPath = (0, import_path.join)(api.paths.absTmpPath, outputPath);
|
|
42
42
|
const binPath = (0, import_path.join)(api.cwd, "node_modules/.bin/tailwind");
|
|
43
|
+
const configPath = (0, import_path.join)(process.env.APP_ROOT || api.cwd, "tailwind.config.js");
|
|
43
44
|
return new Promise((resolve) => {
|
|
44
45
|
tailwind = (0, import_plugin_utils.crossSpawn)(`${binPath}`, [
|
|
46
|
+
"-c",
|
|
47
|
+
configPath,
|
|
45
48
|
"-i",
|
|
46
49
|
inputPath,
|
|
47
50
|
"-o",
|
|
48
51
|
generatedPath,
|
|
49
52
|
api.env === "development" ? "--watch" : ""
|
|
50
53
|
], {
|
|
51
|
-
stdio: "inherit"
|
|
54
|
+
stdio: "inherit",
|
|
55
|
+
cwd: process.env.APP_ROOT || api.cwd
|
|
52
56
|
});
|
|
53
57
|
tailwind.on("error", (m) => {
|
|
54
58
|
api.logger.error("tailwindcss service encounter an error: " + m);
|
|
@@ -18,13 +18,12 @@ import React, {
|
|
|
18
18
|
useRef,
|
|
19
19
|
useState,
|
|
20
20
|
} from 'react';
|
|
21
|
+
import { qiankunStateForSlaveModelNamespace } from './constants';
|
|
21
22
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
22
23
|
import { getMasterOptions } from './masterOptions';
|
|
23
24
|
import MicroAppLoader from './MicroAppLoader';
|
|
24
25
|
import { MasterOptions } from './types';
|
|
25
26
|
|
|
26
|
-
const qiankunStateForSlaveModelNamespace = '@@qiankunStateForSlave';
|
|
27
|
-
|
|
28
27
|
type HashHistory = {
|
|
29
28
|
type?: 'hash';
|
|
30
29
|
} & any;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import React, { ReactComponentElement } from 'react';
|
|
9
|
-
import type
|
|
9
|
+
import { Navigate, type IRouteProps } from 'umi';
|
|
10
10
|
|
|
11
11
|
export const defaultMountContainerId = 'root-subapp';
|
|
12
12
|
|
|
@@ -94,19 +94,30 @@ export function patchMicroAppRoute(
|
|
|
94
94
|
routeProps,
|
|
95
95
|
};
|
|
96
96
|
route.element = React.createElement(getMicroAppRouteComponent(opts), null);
|
|
97
|
+
} else if (route.redirect) {
|
|
98
|
+
// patchClientRoutes 插入的 redirect 不会被转换,所以这里需要手动处理成重定向组件
|
|
99
|
+
route.element = React.createElement(Navigate, {
|
|
100
|
+
to: route.redirect,
|
|
101
|
+
replace: true,
|
|
102
|
+
});
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
const recursiveSearch = (
|
|
101
107
|
routes: IRouteProps[],
|
|
102
108
|
path: string,
|
|
103
|
-
|
|
109
|
+
parentPath: string,
|
|
110
|
+
): [IRouteProps, IRouteProps[], number, string] | null => {
|
|
104
111
|
for (let i = 0; i < routes.length; i++) {
|
|
105
112
|
if (routes[i].path === path) {
|
|
106
|
-
return routes[i];
|
|
113
|
+
return [routes[i], routes, i, parentPath];
|
|
107
114
|
}
|
|
108
115
|
if (routes[i].children && routes[i].children?.length) {
|
|
109
|
-
const found = recursiveSearch(
|
|
116
|
+
const found = recursiveSearch(
|
|
117
|
+
routes[i].children || [],
|
|
118
|
+
path,
|
|
119
|
+
routes[i].path,
|
|
120
|
+
);
|
|
110
121
|
if (found) {
|
|
111
122
|
return found;
|
|
112
123
|
}
|
|
@@ -116,23 +127,48 @@ const recursiveSearch = (
|
|
|
116
127
|
};
|
|
117
128
|
|
|
118
129
|
export function insertRoute(routes: IRouteProps[], microAppRoute: IRouteProps) {
|
|
119
|
-
const
|
|
130
|
+
const mod =
|
|
131
|
+
microAppRoute.appendChildTo || microAppRoute.insert
|
|
132
|
+
? 'appendChildTo'
|
|
133
|
+
: microAppRoute.insertBefore
|
|
134
|
+
? 'insertBefore'
|
|
135
|
+
: undefined;
|
|
136
|
+
const target =
|
|
137
|
+
microAppRoute.appendChildTo ||
|
|
138
|
+
microAppRoute.insert ||
|
|
139
|
+
microAppRoute.insertBefore;
|
|
140
|
+
const [found, foundParentRoutes = [], index = 0, parentPath] =
|
|
141
|
+
recursiveSearch(routes, target, '/') || [];
|
|
120
142
|
if (found) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
143
|
+
switch (mod) {
|
|
144
|
+
case 'appendChildTo':
|
|
145
|
+
if (
|
|
146
|
+
!microAppRoute.path ||
|
|
147
|
+
!found.path ||
|
|
148
|
+
!microAppRoute.path.startsWith(found.path)
|
|
149
|
+
) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`[plugin-qiankun]: path "${microAppRoute.path}" need to starts with "${found.path}"`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
found.exact = false;
|
|
155
|
+
found.children = found.children || [];
|
|
156
|
+
found.children.push(microAppRoute);
|
|
157
|
+
break;
|
|
158
|
+
case 'insertBefore':
|
|
159
|
+
if (
|
|
160
|
+
!microAppRoute.path ||
|
|
161
|
+
!found.path ||
|
|
162
|
+
!microAppRoute.path.startsWith(parentPath)
|
|
163
|
+
) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`[plugin-qiankun]: path "${microAppRoute.path}" need to starts with "${parentPath}"`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
foundParentRoutes.splice(index, 0, microAppRoute);
|
|
169
|
+
break;
|
|
129
170
|
}
|
|
130
|
-
found.exact = false;
|
|
131
|
-
found.children = found.children || [];
|
|
132
|
-
found.children.push(microAppRoute);
|
|
133
171
|
} else {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`[plugin-qiankun]: path "${microAppRoute.insert}" not found`,
|
|
136
|
-
);
|
|
172
|
+
throw new Error(`[plugin-qiankun]: path "${target}" not found`);
|
|
137
173
|
}
|
|
138
174
|
}
|
|
@@ -24,7 +24,9 @@ async function getMasterRuntime() {
|
|
|
24
24
|
|
|
25
25
|
// modify route with "microApp" attribute to use real component
|
|
26
26
|
function patchMicroAppRouteComponent(routes: any[]) {
|
|
27
|
-
const insertRoutes = microAppRuntimeRoutes.filter(
|
|
27
|
+
const insertRoutes = microAppRuntimeRoutes.filter(
|
|
28
|
+
(r) => r.insert || r.insertBefore || r.appendChildTo,
|
|
29
|
+
);
|
|
28
30
|
// 先处理 insert 配置
|
|
29
31
|
insertRoutes.forEach((route) => {
|
|
30
32
|
insertRoute(routes, route);
|
|
@@ -60,7 +62,13 @@ function patchMicroAppRouteComponent(routes: any[]) {
|
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
patchRoute(microAppRoute);
|
|
63
|
-
|
|
65
|
+
if (
|
|
66
|
+
!microAppRoute.insert &&
|
|
67
|
+
!microAppRoute.insertBefore &&
|
|
68
|
+
!microAppRoute.appendChildTo
|
|
69
|
+
) {
|
|
70
|
+
rootRoutes.unshift(microAppRoute);
|
|
71
|
+
}
|
|
64
72
|
});
|
|
65
73
|
}
|
|
66
74
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umijs/plugins",
|
|
3
|
-
"version": "4.0.0-canary.
|
|
3
|
+
"version": "4.0.0-canary.20220819.1",
|
|
4
4
|
"description": "@umijs/plugins",
|
|
5
5
|
"homepage": "https://github.com/umijs/umi/tree/master/packages/plugins#readme",
|
|
6
6
|
"bugs": "https://github.com/umijs/umi/issues",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@ahooksjs/use-request": "^2.0.0",
|
|
26
26
|
"@ant-design/icons": "^4.7.0",
|
|
27
27
|
"@ant-design/pro-layout": "^7.0.1-beta.28",
|
|
28
|
-
"@umijs/bundler-utils": "4.0.0-canary.
|
|
28
|
+
"@umijs/bundler-utils": "4.0.0-canary.20220819.1",
|
|
29
29
|
"antd-dayjs-webpack-plugin": "^1.0.6",
|
|
30
30
|
"axios": "^0.27.2",
|
|
31
31
|
"babel-plugin-import": "^1.13.5",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"warning": "^4.0.3"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"umi": "4.0.0-canary.
|
|
47
|
+
"umi": "4.0.0-canary.20220819.1"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|