@nx/gradle 23.2.0-beta.4 → 23.2.0-beta.5
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/batch-runner/build/libs/gradle-batch-runner-all.jar +0 -0
- package/dist/batch-runner/build/libs/gradle-batch-runner.jar +0 -0
- package/dist/src/executors/gradle/gradle-batch.impl.d.ts +1 -2
- package/dist/src/executors/gradle/gradle.impl.js +2 -3
- package/dist/src/generators/ci-workflow/generator.js +4 -5
- package/dist/src/plugin/dependencies.js +2 -2
- package/dist/src/plugin/nodes.js +3 -6
- package/dist/src/plugin/utils/get-project-graph-from-gradle-plugin.js +4 -6
- package/dist/src/plugin/utils/get-project-graph-lines.js +2 -2
- package/dist/src/plugin-v1/nodes.d.ts +1 -1
- package/dist/src/plugin-v1/nodes.js +4 -8
- package/dist/src/plugin-v1/utils/get-gradle-report.js +3 -4
- package/dist/src/utils/exec-gradle.js +3 -4
- package/dist/src/utils/split-config-files.js +3 -3
- package/package.json +3 -3
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ExecutorContext, ProjectGraphProjectNode, TaskGraph } from '@nx/devkit';
|
|
2
|
-
import { RunCommandsOptions } from 'nx/src/executors/run-commands/run-commands.impl';
|
|
3
|
-
import { TaskResult } from 'nx/src/config/misc-interfaces';
|
|
4
2
|
import { GradleExecutorSchema } from './schema';
|
|
3
|
+
import { RunCommandsOptions, TaskResult } from '@nx/devkit/internal';
|
|
5
4
|
export declare const batchRunnerPath: string;
|
|
6
5
|
export default function gradleBatch(taskGraph: TaskGraph, inputs: Record<string, GradleExecutorSchema>, overrides: RunCommandsOptions, context: ExecutorContext): AsyncGenerator<{
|
|
7
6
|
task: string;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = gradleExecutor;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
4
|
const devkit_1 = require("@nx/devkit");
|
|
6
5
|
const exec_gradle_1 = require("../../utils/exec-gradle");
|
|
7
6
|
const node_path_1 = require("node:path");
|
|
8
|
-
const
|
|
7
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
9
8
|
const get_exclude_task_1 = require("./get-exclude-task");
|
|
10
9
|
async function gradleExecutor(options, context) {
|
|
11
10
|
let projectRoot = context.projectGraph.nodes[context.projectName]?.data?.root ?? context.root;
|
|
@@ -56,7 +55,7 @@ async function gradleExecutor(options, context) {
|
|
|
56
55
|
});
|
|
57
56
|
}
|
|
58
57
|
try {
|
|
59
|
-
const { success } = await (0,
|
|
58
|
+
const { success } = await (0, internal_1.runCommandsExecutor)({
|
|
60
59
|
command: `${gradlewPath} ${options.taskName}`,
|
|
61
60
|
cwd: (0, node_path_1.dirname)(gradlewPath),
|
|
62
61
|
args: args,
|
|
@@ -3,8 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ciWorkflowGenerator = ciWorkflowGenerator;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
-
const
|
|
7
|
-
const default_base_1 = require("nx/src/utils/default-base");
|
|
6
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
8
7
|
function getCiCommands(ci) {
|
|
9
8
|
switch (ci) {
|
|
10
9
|
case 'circleci': {
|
|
@@ -54,13 +53,13 @@ function getTemplateData(tree, options) {
|
|
|
54
53
|
const { name: workflowName, fileName: workflowFileName } = (0, devkit_1.names)(options.name);
|
|
55
54
|
let nxCloudHost = 'nx.app';
|
|
56
55
|
try {
|
|
57
|
-
const nxCloudUrl = (0,
|
|
56
|
+
const nxCloudUrl = (0, internal_1.getNxCloudUrl)((0, devkit_1.readNxJson)(tree));
|
|
58
57
|
nxCloudHost = new URL(nxCloudUrl).host;
|
|
59
58
|
}
|
|
60
59
|
catch { }
|
|
61
|
-
const mainBranch = (0,
|
|
60
|
+
const mainBranch = (0, internal_1.deduceDefaultBase)();
|
|
62
61
|
const commands = options.commands ?? getCiCommands(options.ci);
|
|
63
|
-
const connectedToCloud = (0,
|
|
62
|
+
const connectedToCloud = (0, internal_1.isNxCloudUsed)((0, devkit_1.readNxJson)(tree));
|
|
64
63
|
return {
|
|
65
64
|
workflowName,
|
|
66
65
|
workflowFileName,
|
|
@@ -5,10 +5,10 @@ const devkit_1 = require("@nx/devkit");
|
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
6
|
const get_project_graph_from_gradle_plugin_1 = require("./utils/get-project-graph-from-gradle-plugin");
|
|
7
7
|
const split_config_files_1 = require("../utils/split-config-files");
|
|
8
|
-
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
|
9
8
|
const node_fs_1 = require("node:fs");
|
|
9
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
10
10
|
const createDependencies = async (options, context) => {
|
|
11
|
-
const files = await (0,
|
|
11
|
+
const files = await (0, internal_1.globWithWorkspaceContext)(devkit_1.workspaceRoot, Array.from(split_config_files_1.GRADLEW_FILES));
|
|
12
12
|
const { gradlewFiles } = (0, split_config_files_1.splitConfigFiles)(files);
|
|
13
13
|
await (0, get_project_graph_from_gradle_plugin_1.populateProjectGraph)(context.workspaceRoot, gradlewFiles.map((file) => (0, node_path_1.join)(devkit_1.workspaceRoot, file)), options);
|
|
14
14
|
const { dependencies: dependenciesFromReport } = (0, get_project_graph_from_gradle_plugin_1.getCurrentProjectGraphReport)();
|
package/dist/src/plugin/nodes.js
CHANGED
|
@@ -4,9 +4,6 @@ exports.makeCreateNodesForGradleConfigFile = exports.createNodesV2 = exports.cre
|
|
|
4
4
|
const internal_1 = require("@nx/devkit/internal");
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
const node_path_1 = require("node:path");
|
|
7
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
8
|
-
const plugin_cache_utils_1 = require("nx/src/utils/plugin-cache-utils");
|
|
9
|
-
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
|
10
7
|
const split_config_files_1 = require("../utils/split-config-files");
|
|
11
8
|
const get_project_graph_from_gradle_plugin_1 = require("./utils/get-project-graph-from-gradle-plugin");
|
|
12
9
|
const gradle_plugin_options_1 = require("./utils/gradle-plugin-options");
|
|
@@ -71,9 +68,9 @@ exports.createNodes = [
|
|
|
71
68
|
split_config_files_1.gradleConfigAndTestGlob,
|
|
72
69
|
async (files, options, context) => {
|
|
73
70
|
const { buildFiles: buildFilesFromSplitConfigFiles, gradlewFiles } = (0, split_config_files_1.splitConfigFiles)(files);
|
|
74
|
-
const optionsHash = (0,
|
|
75
|
-
const cachePath = (0, node_path_1.join)(
|
|
76
|
-
const pluginCache = new
|
|
71
|
+
const optionsHash = (0, internal_1.hashObject)(options);
|
|
72
|
+
const cachePath = (0, node_path_1.join)(internal_1.workspaceDataDirectory, `gradle-${optionsHash}.hash`);
|
|
73
|
+
const pluginCache = new internal_1.PluginCache(cachePath);
|
|
77
74
|
await (0, get_project_graph_from_gradle_plugin_1.populateProjectGraph)(context.workspaceRoot, gradlewFiles.map((f) => (0, node_path_1.join)(context.workspaceRoot, f)), options);
|
|
78
75
|
const report = (0, get_project_graph_from_gradle_plugin_1.getCurrentProjectGraphReport)();
|
|
79
76
|
const { nodes, externalNodes = {}, buildFiles = [] } = report;
|
|
@@ -8,13 +8,11 @@ exports.processNxProjectGraph = processNxProjectGraph;
|
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_path_1 = require("node:path");
|
|
10
10
|
const devkit_1 = require("@nx/devkit");
|
|
11
|
-
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
|
12
11
|
const split_config_files_1 = require("../../utils/split-config-files");
|
|
13
12
|
const versions_1 = require("../../utils/versions");
|
|
14
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
15
13
|
const get_project_graph_lines_1 = require("./get-project-graph-lines");
|
|
16
14
|
const gradle_plugin_options_1 = require("./gradle-plugin-options");
|
|
17
|
-
const
|
|
15
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
18
16
|
function readProjectGraphReportCache(cachePath, hash) {
|
|
19
17
|
const projectGraphReportCache = (0, node_fs_1.existsSync)(cachePath)
|
|
20
18
|
? (0, devkit_1.readJsonFile)(cachePath)
|
|
@@ -43,7 +41,7 @@ function writeProjectGraphReportToCache(cachePath, results, hash) {
|
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
43
|
let projectGraphReportCache;
|
|
46
|
-
let projectGraphReportCachePath = (0, node_path_1.join)(
|
|
44
|
+
let projectGraphReportCachePath = (0, node_path_1.join)(internal_1.workspaceDataDirectory, 'gradle-nodes.hash');
|
|
47
45
|
function getCurrentProjectGraphReport() {
|
|
48
46
|
if (!projectGraphReportCache) {
|
|
49
47
|
throw new devkit_1.AggregateCreateNodesError([
|
|
@@ -72,8 +70,8 @@ function getCurrentBuildFiles() {
|
|
|
72
70
|
async function populateProjectGraph(workspaceRoot, gradlewFiles, options) {
|
|
73
71
|
const normalizedOptions = (0, gradle_plugin_options_1.normalizeOptions)(options);
|
|
74
72
|
const gradleConfigHash = (0, devkit_1.hashArray)([
|
|
75
|
-
await (0,
|
|
76
|
-
(0,
|
|
73
|
+
await (0, internal_1.hashWithWorkspaceContext)(workspaceRoot, [split_config_files_1.gradleConfigAndTestGlob]),
|
|
74
|
+
(0, internal_1.hashObject)(normalizedOptions),
|
|
77
75
|
process.env.CI,
|
|
78
76
|
]);
|
|
79
77
|
const cached = readProjectGraphReportCache(projectGraphReportCachePath, gradleConfigHash);
|
|
@@ -4,9 +4,9 @@ exports.cancelPendingProjectGraphRequest = cancelPendingProjectGraphRequest;
|
|
|
4
4
|
exports.getGraphTimeoutMs = getGraphTimeoutMs;
|
|
5
5
|
exports.getNxProjectGraphLines = getNxProjectGraphLines;
|
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
|
7
|
-
const devkit_internals_1 = require("nx/src/devkit-internals");
|
|
8
7
|
const exec_gradle_1 = require("../../utils/exec-gradle");
|
|
9
|
-
const
|
|
8
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
9
|
+
const DEFAULT_GRAPH_TIMEOUT_SECONDS = (0, internal_1.isCI)() ? 600 : 120;
|
|
10
10
|
let currentAbortController;
|
|
11
11
|
/**
|
|
12
12
|
* Cancel any in-flight Gradle project graph process.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { PluginCache } from '@nx/devkit/internal';
|
|
1
2
|
import { CreateNodes, CreateNodesContext, ProjectConfiguration } from '@nx/devkit';
|
|
2
|
-
import { PluginCache } from 'nx/src/utils/plugin-cache-utils';
|
|
3
3
|
import { GradleReport } from './utils/get-gradle-report';
|
|
4
4
|
export interface GradlePluginOptions {
|
|
5
5
|
includeSubprojectsTasks?: boolean;
|
|
@@ -4,11 +4,7 @@ exports.createNodes = exports.makeCreateNodesForGradleConfigFile = exports.creat
|
|
|
4
4
|
const internal_1 = require("@nx/devkit/internal");
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
const node_path_1 = require("node:path");
|
|
7
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
8
|
-
const plugin_cache_utils_1 = require("nx/src/utils/plugin-cache-utils");
|
|
9
|
-
const devkit_internals_1 = require("nx/src/devkit-internals");
|
|
10
7
|
const get_gradle_report_1 = require("./utils/get-gradle-report");
|
|
11
|
-
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
|
12
8
|
const split_config_files_1 = require("../utils/split-config-files");
|
|
13
9
|
const exec_gradle_1 = require("../utils/exec-gradle");
|
|
14
10
|
const cacheableTaskType = new Set(['Build', 'Verification']);
|
|
@@ -33,9 +29,9 @@ exports.createNodesV2 = [
|
|
|
33
29
|
split_config_files_1.gradleConfigAndTestGlob,
|
|
34
30
|
async (files, options, context) => {
|
|
35
31
|
const { buildFiles, projectRoots, gradlewFiles, testFiles } = (0, split_config_files_1.splitConfigFiles)(files);
|
|
36
|
-
const optionsHash = (0,
|
|
37
|
-
const cachePath = (0, node_path_1.join)(
|
|
38
|
-
const pluginCache = new
|
|
32
|
+
const optionsHash = (0, internal_1.hashObject)(options);
|
|
33
|
+
const cachePath = (0, node_path_1.join)(internal_1.workspaceDataDirectory, `gradle-${optionsHash}.hash`);
|
|
34
|
+
const pluginCache = new internal_1.PluginCache(cachePath);
|
|
39
35
|
await (0, get_gradle_report_1.populateGradleReport)(context.workspaceRoot, gradlewFiles.map((f) => (0, node_path_1.join)(context.workspaceRoot, f)));
|
|
40
36
|
const gradleReport = (0, get_gradle_report_1.getCurrentGradleReport)();
|
|
41
37
|
const gradleProjectRootToTestFilesMap = getGradleProjectRootToTestFilesMap(testFiles, projectRoots);
|
|
@@ -257,7 +253,7 @@ function getGradleProjectRootToTestFilesMap(testFiles, projectRoots) {
|
|
|
257
253
|
const roots = new Map(projectRoots.map((root) => [root, root]));
|
|
258
254
|
const testFilesToGradleProjectMap = {};
|
|
259
255
|
testFiles.forEach((testFile) => {
|
|
260
|
-
const projectRoot = (0,
|
|
256
|
+
const projectRoot = (0, internal_1.findProjectForPath)(testFile, roots);
|
|
261
257
|
if (projectRoot) {
|
|
262
258
|
if (!testFilesToGradleProjectMap[projectRoot]) {
|
|
263
259
|
testFilesToGradleProjectMap[projectRoot] = [];
|
|
@@ -8,12 +8,11 @@ exports.processGradleDependencies = processGradleDependencies;
|
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_path_1 = require("node:path");
|
|
10
10
|
const devkit_1 = require("@nx/devkit");
|
|
11
|
-
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
|
12
11
|
const path_1 = require("path");
|
|
13
12
|
const split_config_files_1 = require("../../utils/split-config-files");
|
|
14
13
|
const get_project_report_lines_1 = require("./get-project-report-lines");
|
|
15
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
16
14
|
const exec_gradle_1 = require("../../utils/exec-gradle");
|
|
15
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
17
16
|
function readGradleReportCache(cachePath, hash) {
|
|
18
17
|
const gradleReportJson = (0, node_fs_1.existsSync)(cachePath)
|
|
19
18
|
? (0, devkit_1.readJsonFile)(cachePath)
|
|
@@ -65,7 +64,7 @@ function writeGradleReportToCache(cachePath, results, hash) {
|
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
let gradleReportCache;
|
|
68
|
-
let gradleReportCachePath = (0, node_path_1.join)(
|
|
67
|
+
let gradleReportCachePath = (0, node_path_1.join)(internal_1.workspaceDataDirectory, 'gradle-report-v1.hash');
|
|
69
68
|
function getCurrentGradleReport() {
|
|
70
69
|
if (!gradleReportCache) {
|
|
71
70
|
throw new devkit_1.AggregateCreateNodesError([
|
|
@@ -88,7 +87,7 @@ function getCurrentGradleReport() {
|
|
|
88
87
|
* @returns Promise<void>
|
|
89
88
|
*/
|
|
90
89
|
async function populateGradleReport(workspaceRoot, gradlewFiles) {
|
|
91
|
-
const gradleConfigHash = await (0,
|
|
90
|
+
const gradleConfigHash = await (0, internal_1.hashWithWorkspaceContext)(workspaceRoot, [
|
|
92
91
|
split_config_files_1.gradleConfigAndTestGlob,
|
|
93
92
|
]);
|
|
94
93
|
const cached = readGradleReportCache(gradleReportCachePath, gradleConfigHash);
|
|
@@ -12,9 +12,8 @@ const devkit_1 = require("@nx/devkit");
|
|
|
12
12
|
const node_child_process_1 = require("node:child_process");
|
|
13
13
|
const node_fs_1 = require("node:fs");
|
|
14
14
|
const node_path_1 = require("node:path");
|
|
15
|
-
const run_commands_impl_1 = require("nx/src/executors/run-commands/run-commands.impl");
|
|
16
|
-
const exit_codes_1 = require("nx/src/utils/exit-codes");
|
|
17
15
|
const tree_kill_1 = tslib_1.__importDefault(require("tree-kill"));
|
|
16
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
18
17
|
exports.fileSeparator = process.platform.startsWith('win')
|
|
19
18
|
? 'file:///'
|
|
20
19
|
: 'file://';
|
|
@@ -45,7 +44,7 @@ function execGradleAsync(gradleBinaryPath, args, execOptions = {}) {
|
|
|
45
44
|
shell: true,
|
|
46
45
|
windowsHide: true,
|
|
47
46
|
env: process.env,
|
|
48
|
-
maxBuffer:
|
|
47
|
+
maxBuffer: internal_1.LARGE_BUFFER,
|
|
49
48
|
...restOptions,
|
|
50
49
|
}, undefined);
|
|
51
50
|
// Use tree-kill on abort to kill the entire process tree
|
|
@@ -66,7 +65,7 @@ function execGradleAsync(gradleBinaryPath, args, execOptions = {}) {
|
|
|
66
65
|
cp.on('exit', (code, s) => {
|
|
67
66
|
signal?.removeEventListener('abort', onAbort);
|
|
68
67
|
if (code === null)
|
|
69
|
-
code = (0,
|
|
68
|
+
code = (0, internal_1.signalToCode)(s);
|
|
70
69
|
if (code === 0) {
|
|
71
70
|
res(stdout);
|
|
72
71
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.gradleConfigAndTestGlob = exports.gradleConfigGlob = exports.GRADLE_TEST_FILES = exports.GRADLE_VERSION_CATALOG_GLOB = exports.GRADLEW_FILES = exports.GRADLE_BUILD_FILES = void 0;
|
|
4
4
|
exports.splitConfigFiles = splitConfigFiles;
|
|
5
|
-
const globs_1 = require("nx/src/utils/globs");
|
|
6
5
|
const node_path_1 = require("node:path");
|
|
6
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
7
7
|
exports.GRADLE_BUILD_FILES = new Set(['build.gradle', 'build.gradle.kts']);
|
|
8
8
|
exports.GRADLEW_FILES = new Set(['gradlew', 'gradlew.bat']);
|
|
9
9
|
exports.GRADLE_VERSION_CATALOG_GLOB = '**/gradle/*.versions.toml';
|
|
@@ -15,7 +15,7 @@ exports.GRADLE_TEST_FILES = [
|
|
|
15
15
|
'**/src/test/groovy/**/*Test.groovy',
|
|
16
16
|
'**/src/test/groovy/**/*Tests.groovy',
|
|
17
17
|
];
|
|
18
|
-
exports.gradleConfigGlob = (0,
|
|
18
|
+
exports.gradleConfigGlob = (0, internal_1.combineGlobPatterns)(...Array.from(exports.GRADLE_BUILD_FILES).map((file) => `**/${file}`));
|
|
19
19
|
// Files that influence Gradle's configuration phase and therefore the project
|
|
20
20
|
// graph report: any *.gradle(.kts) script (build, settings, script plugins),
|
|
21
21
|
// gradle.properties, the wrapper pin, and buildSrc build logic.
|
|
@@ -28,7 +28,7 @@ const GRADLE_CONFIG_FILE_PATTERNS = [
|
|
|
28
28
|
'buildSrc/**/*.java',
|
|
29
29
|
'buildSrc/**/*.groovy',
|
|
30
30
|
];
|
|
31
|
-
exports.gradleConfigAndTestGlob = (0,
|
|
31
|
+
exports.gradleConfigAndTestGlob = (0, internal_1.combineGlobPatterns)(...GRADLE_CONFIG_FILE_PATTERNS, ...GRADLE_CONFIG_FILE_PATTERNS.map((pattern) => `**/${pattern}`), ...Array.from(exports.GRADLEW_FILES), ...Array.from(exports.GRADLEW_FILES).map((file) => `**/${file}`), ...exports.GRADLE_TEST_FILES, exports.GRADLE_VERSION_CATALOG_GLOB);
|
|
32
32
|
/**
|
|
33
33
|
* This function split config files into build files, settings files, test files and project roots
|
|
34
34
|
* @param files list of files to split
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/gradle",
|
|
3
|
-
"version": "23.2.0-beta.
|
|
3
|
+
"version": "23.2.0-beta.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -78,10 +78,10 @@
|
|
|
78
78
|
"toml-eslint-parser": "^0.10.0",
|
|
79
79
|
"tree-kill": "^1.2.2",
|
|
80
80
|
"tslib": "^2.3.0",
|
|
81
|
-
"@nx/devkit": "23.2.0-beta.
|
|
81
|
+
"@nx/devkit": "23.2.0-beta.5"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"nx": "23.2.0-beta.
|
|
84
|
+
"nx": "23.2.0-beta.5"
|
|
85
85
|
},
|
|
86
86
|
"publishConfig": {
|
|
87
87
|
"access": "public"
|