@@ -1286,7 +1286,7 @@ if Code.ensure_loaded?(OpenApiSpex) do
1286
1286
description: action_description ( action , route , resource ) ,
1287
1287
operationId: route . name ,
1288
1288
tags: [ to_string ( AshJsonApi.Resource.Info . type ( resource ) ) ] ,
1289
- parameters: path_parameters ( path_params , action ) ++ query_parameters ( route , resource ) ,
1289
+ parameters: parameters ( route , resource , path_params ) ,
1290
1290
responses: % {
1291
1291
:default => % Reference {
1292
1292
"$ref": "#/components/responses/errors"
@@ -1309,33 +1309,12 @@ if Code.ensure_loaded?(OpenApiSpex) do
1309
1309
end
1310
1310
end
1311
1311
1312
- @ spec path_parameters ( path_params :: [ String . t ( ) ] , action :: Actions . action ( ) ) ::
1313
- [ Parameter . t ( ) ]
1314
- defp path_parameters ( path_params , action ) do
1315
- Enum . map ( path_params , fn param ->
1316
- description =
1317
- action . arguments
1318
- |> Enum . find ( & ( to_string ( & 1 . name ) == param ) )
1319
- |> case do
1320
- % { description: description } when is_binary ( description ) -> description
1321
- _ -> nil
1322
- end
1323
-
1324
- % Parameter {
1325
- name: param ,
1326
- description: description ,
1327
- in: :path ,
1328
- required: true ,
1329
- schema: % Schema { type: :string }
1330
- }
1331
- end )
1332
- end
1333
-
1334
- @ spec query_parameters (
1312
+ @ spec parameters (
1335
1313
Route . t ( ) ,
1336
- resource :: module
1314
+ resource :: module ,
1315
+ route_params :: [ String . t ( ) ]
1337
1316
) :: [ Parameter . t ( ) ]
1338
- defp query_parameters ( % { type: :index } = route , resource ) do
1317
+ defp parameters ( % { type: :index } = route , resource , route_params ) do
1339
1318
Enum . filter (
1340
1319
[
1341
1320
filter_parameter ( resource , route ) ,
@@ -1346,13 +1325,14 @@ if Code.ensure_loaded?(OpenApiSpex) do
1346
1325
] ,
1347
1326
& & 1
1348
1327
)
1349
- |> Enum . concat ( read_argument_parameters ( route , resource ) )
1328
+ |> Enum . concat ( read_argument_parameters ( route , resource , route_params ) )
1350
1329
|> Enum . map ( fn param ->
1351
1330
Map . update! ( param , :name , & to_string / 1 )
1352
1331
end )
1332
+ |> apply_route_params ( route_params )
1353
1333
end
1354
1334
1355
- defp query_parameters ( % { type: type } , _resource )
1335
+ defp parameters ( % { type: type } , _resource , _route_params )
1356
1336
when type in [
1357
1337
:post_to_relationship ,
1358
1338
:patch_relationship ,
@@ -1361,19 +1341,21 @@ if Code.ensure_loaded?(OpenApiSpex) do
1361
1341
[ ]
1362
1342
end
1363
1343
1364
- defp query_parameters ( % { type: type } = route , resource ) when type in [ :get , :related ] do
1344
+ defp parameters ( % { type: type } = route , resource , route_params )
1345
+ when type in [ :get , :related ] do
1365
1346
[ include_parameter ( resource ) , fields_parameter ( resource ) ]
1366
1347
|> Enum . filter ( & & 1 )
1367
- |> Enum . concat ( read_argument_parameters ( route , resource ) )
1348
+ |> Enum . concat ( read_argument_parameters ( route , resource , route_params ) )
1368
1349
|> Enum . reverse ( )
1369
1350
|> Enum . map ( fn param ->
1370
1351
Map . update! ( param , :name , & to_string / 1 )
1371
1352
end )
1372
1353
|> Enum . uniq_by ( & & 1 . name )
1373
1354
|> Enum . reverse ( )
1355
+ |> apply_route_params ( route_params )
1374
1356
end
1375
1357
1376
- defp query_parameters ( route , resource ) do
1358
+ defp parameters ( route , resource , route_params ) do
1377
1359
action = Ash.Resource.Info . action ( resource , route . action )
1378
1360
1379
1361
query_params =
@@ -1384,28 +1366,52 @@ if Code.ensure_loaded?(OpenApiSpex) do
1384
1366
if argument do
1385
1367
argument
1386
1368
else
1387
- if name in action . accept do
1369
+ if name in Map . get ( action , : accept, [ ] ) do
1388
1370
Ash.Resource.Info . attribute ( resource , name )
1389
1371
else
1390
1372
nil
1391
1373
end
1392
1374
end
1393
1375
end )
1376
+ |> Enum . concat (
1377
+ Enum . map ( route_params , fn route_param ->
1378
+ case Enum . find ( action . arguments , & ( to_string ( & 1 . name ) == route_param ) ) do
1379
+ nil ->
1380
+ if Enum . any? ( Map . get ( action , :accept , [ ] ) , & ( to_string ( & 1 ) == route_param ) ) do
1381
+ Ash.Resource.Info . attribute ( resource , route_param )
1382
+ else
1383
+ nil
1384
+ end
1385
+
1386
+ argument ->
1387
+ argument
1388
+ end
1389
+ end )
1390
+ )
1394
1391
|> Enum . filter ( & & 1 )
1395
1392
|> Enum . map ( fn argument_or_attribute ->
1396
1393
schema = resource_write_attribute_type ( argument_or_attribute , resource , action . type )
1397
1394
1395
+ location =
1396
+ if to_string ( argument_or_attribute . name ) in route_params do
1397
+ :path
1398
+ else
1399
+ :query
1400
+ end
1401
+
1402
+ style =
1403
+ if schema . type == :object && location == :query do
1404
+ :deepObject
1405
+ else
1406
+ :form
1407
+ end
1408
+
1398
1409
% Parameter {
1399
1410
name: to_string ( argument_or_attribute . name ) ,
1400
- in: :query ,
1401
- description:
1402
- argument_or_attribute . description || to_string ( argument_or_attribute . name ) ,
1403
- required: ! argument_or_attribute . allow_nil? ,
1404
- style:
1405
- case schema . type do
1406
- :object -> :deepObject
1407
- _ -> :form
1408
- end ,
1411
+ in: location ,
1412
+ description: argument_or_attribute . description ,
1413
+ required: location == :path || ! argument_or_attribute . allow_nil? ,
1414
+ style: style ,
1409
1415
schema: schema
1410
1416
}
1411
1417
end )
@@ -1423,6 +1429,26 @@ if Code.ensure_loaded?(OpenApiSpex) do
1423
1429
end )
1424
1430
|> Enum . uniq_by ( & & 1 . name )
1425
1431
|> Enum . reverse ( )
1432
+ |> apply_route_params ( route_params )
1433
+ end
1434
+
1435
+ defp apply_route_params ( params , route_params ) do
1436
+ param_names = Enum . map ( params , & & 1 . name )
1437
+
1438
+ route_params_to_add =
1439
+ route_params
1440
+ |> Enum . reject ( & ( & 1 in param_names ) )
1441
+ |> Enum . map ( fn name ->
1442
+ % Parameter {
1443
+ name: name ,
1444
+ in: :path ,
1445
+ required: true ,
1446
+ style: :form ,
1447
+ schema: % Schema { type: :string }
1448
+ }
1449
+ end )
1450
+
1451
+ route_params_to_add ++ Enum . sort_by ( params , & ( & 1 . in == :query ) )
1426
1452
end
1427
1453
1428
1454
@ spec filter_parameter ( resource :: module , route :: AshJsonApi.Resource.Route . t ( ) ) ::
@@ -1636,26 +1662,36 @@ if Code.ensure_loaded?(OpenApiSpex) do
1636
1662
}
1637
1663
end
1638
1664
1639
- @ spec read_argument_parameters ( Route . t ( ) , resource :: module ) :: [ Parameter . t ( ) ]
1640
- defp read_argument_parameters ( route , resource ) do
1665
+ @ spec read_argument_parameters ( Route . t ( ) , resource :: module , route_params :: [ String . t ( ) ] ) ::
1666
+ [ Parameter . t ( ) ]
1667
+ defp read_argument_parameters ( route , resource , route_params ) do
1641
1668
action = Ash.Resource.Info . action ( resource , route . action )
1642
1669
1643
1670
action . arguments
1644
1671
|> Enum . filter ( & & 1 . public? )
1645
- |> without_path_arguments ( route )
1646
1672
|> Enum . map ( fn argument ->
1647
1673
schema = resource_attribute_type ( argument , resource )
1648
1674
1675
+ location =
1676
+ if to_string ( argument . name ) in route_params do
1677
+ :path
1678
+ else
1679
+ :query
1680
+ end
1681
+
1682
+ style =
1683
+ if schema . type == :object && location == :query do
1684
+ :deepObject
1685
+ else
1686
+ :form
1687
+ end
1688
+
1649
1689
% Parameter {
1650
1690
name: argument . name ,
1651
- in: :query ,
1652
- description: argument . description || to_string ( argument . name ) ,
1653
- required: ! argument . allow_nil? ,
1654
- style:
1655
- case schema . type do
1656
- :object -> :deepObject
1657
- _ -> :form
1658
- end ,
1691
+ in: location ,
1692
+ description: argument . description ,
1693
+ required: location == :path || ! argument . allow_nil? ,
1694
+ style: style ,
1659
1695
schema: schema
1660
1696
}
1661
1697
end )
0 commit comments