55# '
66# ' @param ... plumber files or directories containing plumber files to be parsed
77# ' in the given order. The order of parsing determines the final order of the
8- # ' routes in the stack
8+ # ' routes in the stack. If `...` contains a `_server.yml` file then all other
9+ # ' files in `...` will be ignored and the `_server.yml` file will be used as the
10+ # ' basis for the API
911# ' @param host A string that is a valid IPv4 address that is owned by this
1012# ' server
1113# ' @param port A number or integer that indicates the server port that should be
@@ -61,19 +63,59 @@ api <- function(
6163 compression_limit = get_opts(" compressionLimit" , 1e3 ),
6264 env = caller_env()
6365) {
64- api <- Plumber $ new(
65- host = host ,
66- port = port ,
67- doc_type = doc_type ,
68- doc_path = doc_path ,
69- reject_missing_methods = reject_missing_methods ,
70- ignore_trailing_slash = ignore_trailing_slash ,
71- max_request_size = max_request_size ,
72- shared_secret = shared_secret ,
73- compression_limit = compression_limit ,
74- env = env
75- )
76- api_parse(api , ... )
66+ locations <- dots_to_plumber_files(... )
67+ if (isTRUE(is_plumber2_server_yml(locations ))) {
68+ server_yml <- yaml :: read_yaml(locations )
69+ if (! is.null(server_yml $ constructor )) {
70+ api <- source(
71+ fs :: path(
72+ fs :: path_dir(locations ),
73+ server_yml $ constructor
74+ ),
75+ verbose = FALSE
76+ )
77+ if (! is_plumber_api(api )) {
78+ cli :: cli_abort(
79+ " The constructor file in {.file {locations}} did not produce a plumber2 API"
80+ )
81+ }
82+ } else {
83+ api <- Plumber $ new(
84+ host = server_yml $ options $ host %|| % host ,
85+ port = server_yml $ options $ port %|| % port ,
86+ doc_type = server_yml $ options $ docType %|| % doc_type ,
87+ doc_path = server_yml $ options $ docPath %|| % doc_path ,
88+ reject_missing_methods = server_yml $ options $ methodNotAllowed %|| %
89+ reject_missing_methods ,
90+ ignore_trailing_slash = server_yml $ options $ ignoreTrailingSlash %|| %
91+ ignore_trailing_slash ,
92+ max_request_size = server_yml $ options $ maxRequestSize %|| %
93+ max_request_size ,
94+ shared_secret = shared_secret ,
95+ compression_limit = server_yml $ options $ compressionLimit %|| %
96+ compression_limit ,
97+ env = env
98+ )
99+ }
100+ locations <- fs :: path(
101+ fs :: path_dir(locations ),
102+ server_yml $ routes
103+ )
104+ } else {
105+ api <- Plumber $ new(
106+ host = host ,
107+ port = port ,
108+ doc_type = doc_type ,
109+ doc_path = doc_path ,
110+ reject_missing_methods = reject_missing_methods ,
111+ ignore_trailing_slash = ignore_trailing_slash ,
112+ max_request_size = max_request_size ,
113+ shared_secret = shared_secret ,
114+ compression_limit = compression_limit ,
115+ env = env
116+ )
117+ }
118+ api_parse(api , locations )
77119}
78120# ' @rdname api
79121# ' @param x An object to test for whether it is a plumber api
@@ -85,14 +127,55 @@ is_plumber_api <- function(x) inherits(x, "Plumber")
85127# ' @param api A plumber2 api object to parse files into
86128# ' @export
87129api_parse <- function (api , ... ) {
88- locations <- list2(... )
89- lapply(locations , function (loc ) {
130+ locations <- dots_to_plumber_files(... , prefer_yml = FALSE )
131+ for (loc in locations ) {
132+ api $ parse_file(file )
133+ }
134+ api
135+ }
136+
137+ dots_to_plumber_files <- function (... , prefer_yml = TRUE , call = caller_env()) {
138+ locations <- unlist(lapply(list2(... ), function (loc ) {
90139 if (fs :: is_dir(loc )) {
91- loc <- fs :: dir_ls(loc )
140+ loc <- fs :: dir_ls(loc , all = TRUE , recurse = TRUE )
141+ server_yml <- is_plumber2_server_yml(loc )
142+ if (prefer_yml && any(server_yml )) {
143+ loc <- loc [server_yml ]
144+ } else {
145+ loc <- loc [fs :: path_ext(loc ) %in% c(" R" , " r" )]
146+ }
92147 }
93- for (file in loc ) {
94- api $ parse_file(file )
148+ loc
149+ }))
150+ if (length(locations ) == 0 ) return (character ())
151+ if (! all(fs :: file_exists(locations ))) {
152+ cli :: cli_abort(" {.arg ...} must point to existing files" , call = call )
153+ }
154+ server_yml <- is_plumber2_server_yml(locations )
155+ if (prefer_yml && any(server_yml )) {
156+ if (sum(server_yml ) != 1 ) {
157+ cli :: cli_abort(
158+ " You can at most use one {.file _server.yml} file to specify your API" ,
159+ call = call
160+ )
95161 }
96- })
97- api
162+ if (length(locations ) != 1 ) {
163+ cli :: cli_warn(
164+ " {.file _server.yml} found. Ignoring all other files provided in {.arg ...}" ,
165+ call = call
166+ )
167+ }
168+ locations [server_yml ]
169+ } else {
170+ if (any(server_yml )) {
171+ cli :: cli_warn(
172+ " Ignoring {.file _server.yml} files in {.arg ...}" ,
173+ call = call
174+ )
175+ }
176+ locations [! server_yml ]
177+ }
98178}
179+
180+ # For use by connect etc
181+ create_server <- api
0 commit comments