plutonium 0.42.0 → 0.43.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.
- checksums.yaml +4 -4
- data/.claude/skills/plutonium-controller/SKILL.md +38 -1
- data/.claude/skills/plutonium-definition/SKILL.md +14 -0
- data/.claude/skills/plutonium-forms/SKILL.md +16 -1
- data/.claude/skills/plutonium-profile/SKILL.md +276 -0
- data/.claude/skills/plutonium-views/SKILL.md +23 -1
- data/CHANGELOG.md +42 -0
- data/app/assets/plutonium.css +2 -2
- data/app/views/plutonium/_resource_header.html.erb +6 -27
- data/app/views/plutonium/_resource_sidebar.html.erb +1 -2
- data/app/views/resource/_resource_details.rabl +3 -2
- data/app/views/resource/index.rabl +3 -2
- data/app/views/resource/show.rabl +3 -2
- data/docs/guides/user-profile.md +322 -0
- data/docs/reference/controller/index.md +38 -1
- data/docs/reference/definition/index.md +16 -0
- data/docs/reference/views/forms.md +15 -0
- data/docs/reference/views/index.md +23 -1
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/core/assets/assets_generator.rb +12 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +11 -0
- data/lib/generators/pu/core/typespec/templates/common.tsp.tt +95 -0
- data/lib/generators/pu/core/typespec/templates/main.tsp.tt +27 -0
- data/lib/generators/pu/core/typespec/templates/main_multi.tsp.tt +25 -0
- data/lib/generators/pu/core/typespec/templates/model.tsp.tt +226 -0
- data/lib/generators/pu/core/typespec/typespec_generator.rb +342 -0
- data/lib/generators/pu/invites/USAGE +0 -1
- data/lib/generators/pu/invites/install_generator.rb +62 -15
- data/lib/generators/pu/invites/templates/db/migrate/create_user_invites.rb.tt +2 -2
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +2 -0
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/welcome_controller.rb.tt +1 -0
- data/lib/generators/pu/invites/templates/packages/invites/app/models/invites/user_invite.rb.tt +5 -5
- data/lib/generators/pu/invites/templates/packages/invites/app/views/invites/user_invitations/signup.html.erb.tt +4 -4
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +1 -1
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +29 -0
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +6 -23
- data/lib/generators/pu/pkg/portal/portal_generator.rb +5 -1
- data/lib/generators/pu/profile/USAGE +59 -0
- data/lib/generators/pu/profile/concerns/profile_arguments.rb +27 -0
- data/lib/generators/pu/profile/conn/USAGE +33 -0
- data/lib/generators/pu/profile/conn_generator.rb +167 -0
- data/lib/generators/pu/profile/install_generator.rb +119 -0
- data/lib/generators/pu/profile/setup/USAGE +42 -0
- data/lib/generators/pu/profile/setup_generator.rb +73 -0
- data/lib/generators/pu/rodauth/account_generator.rb +2 -4
- data/lib/generators/pu/rodauth/install_generator.rb +2 -2
- data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +3 -0
- data/lib/generators/pu/saas/api_client_generator.rb +0 -2
- data/lib/generators/pu/saas/membership_generator.rb +68 -19
- data/lib/generators/pu/saas/setup_generator.rb +7 -2
- data/lib/generators/pu/saas/user_generator.rb +0 -2
- data/lib/plutonium/auth/rodauth.rb +8 -0
- data/lib/plutonium/core/controller.rb +7 -4
- data/lib/plutonium/core/controllers/authorizable.rb +5 -1
- data/lib/plutonium/definition/base.rb +7 -0
- data/lib/plutonium/helpers/display_helper.rb +6 -0
- data/lib/plutonium/profile/security_section.rb +118 -0
- data/lib/plutonium/resource/controller.rb +17 -7
- data/lib/plutonium/resource/controllers/interactive_actions.rb +11 -25
- data/lib/plutonium/resource/controllers/presentable.rb +46 -3
- data/lib/plutonium/resource/record/associated_with.rb +7 -1
- data/lib/plutonium/routing/mapper_extensions.rb +18 -18
- data/lib/plutonium/routing/route_set_extensions.rb +23 -2
- data/lib/plutonium/ui/breadcrumbs.rb +111 -131
- data/lib/plutonium/ui/dyna_frame/content.rb +12 -2
- data/lib/plutonium/ui/form/resource.rb +26 -19
- data/lib/plutonium/ui/page/base.rb +14 -14
- data/lib/plutonium/ui/table/components/scopes_bar.rb +2 -74
- data/lib/plutonium/ui/table/components/selection_column.rb +6 -2
- data/lib/plutonium/ui/table/resource.rb +3 -2
- data/lib/plutonium/version.rb +1 -1
- data/lib/tasks/release.rake +6 -6
- data/package.json +1 -1
- metadata +17 -3
- data/lib/generators/pu/rodauth/concerns/gem_helpers.rb +0 -19
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common TypeSpec definitions for <%= Rails.application.class.module_parent_name %> API
|
|
3
|
+
* Generated by Plutonium TypeSpec Generator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "@typespec/http";
|
|
7
|
+
|
|
8
|
+
using TypeSpec.Http;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Signed Global ID - cryptographically signed resource identifier
|
|
12
|
+
* Format: gid://app/Model/id--signature
|
|
13
|
+
*/
|
|
14
|
+
@pattern("gid://.*--.*")
|
|
15
|
+
@doc("Signed Global ID for secure resource identification")
|
|
16
|
+
scalar SignedGlobalId extends string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base fields included in all resource responses
|
|
20
|
+
*/
|
|
21
|
+
@doc("Common fields present in all API resource responses")
|
|
22
|
+
model ResourceBase {
|
|
23
|
+
@doc("Signed Global ID for secure references")
|
|
24
|
+
sgid: SignedGlobalId;
|
|
25
|
+
|
|
26
|
+
@doc("API URL for this resource")
|
|
27
|
+
url: url;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Validation error detail
|
|
32
|
+
*/
|
|
33
|
+
model ValidationError {
|
|
34
|
+
@doc("Attribute that failed validation")
|
|
35
|
+
attribute: string;
|
|
36
|
+
|
|
37
|
+
@doc("Error detail/code")
|
|
38
|
+
detail: string;
|
|
39
|
+
|
|
40
|
+
@doc("Human-readable error message")
|
|
41
|
+
message: string;
|
|
42
|
+
|
|
43
|
+
@doc("Full error message including attribute name")
|
|
44
|
+
full_message: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Error response wrapper
|
|
49
|
+
*/
|
|
50
|
+
model ErrorResponse {
|
|
51
|
+
@doc("List of validation errors")
|
|
52
|
+
errors: ValidationError[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Pagination metadata
|
|
57
|
+
*/
|
|
58
|
+
model PaginationMeta {
|
|
59
|
+
@doc("Current page number")
|
|
60
|
+
current_page: int32;
|
|
61
|
+
|
|
62
|
+
@doc("Total number of pages")
|
|
63
|
+
total_pages: int32;
|
|
64
|
+
|
|
65
|
+
@doc("Total number of records")
|
|
66
|
+
total_count: int64;
|
|
67
|
+
|
|
68
|
+
@doc("Number of records per page")
|
|
69
|
+
per_page: int32;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Standard list query parameters
|
|
74
|
+
*/
|
|
75
|
+
model ListQueryParams {
|
|
76
|
+
@query
|
|
77
|
+
@doc("Page number for pagination")
|
|
78
|
+
page?: int32 = 1;
|
|
79
|
+
|
|
80
|
+
@query
|
|
81
|
+
@doc("Number of items per page")
|
|
82
|
+
per_page?: int32 = 25;
|
|
83
|
+
|
|
84
|
+
@query
|
|
85
|
+
@doc("Sort field")
|
|
86
|
+
sort?: string;
|
|
87
|
+
|
|
88
|
+
@query
|
|
89
|
+
@doc("Sort direction")
|
|
90
|
+
direction?: "asc" | "desc";
|
|
91
|
+
|
|
92
|
+
@query
|
|
93
|
+
@doc("Search query")
|
|
94
|
+
q?: string;
|
|
95
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <%= @current_portal[:name] %> API Specification
|
|
3
|
+
* Generated by Plutonium TypeSpec Generator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import "@typespec/http";
|
|
7
|
+
import "@typespec/rest";
|
|
8
|
+
import "@typespec/openapi3";
|
|
9
|
+
|
|
10
|
+
<%- if @single_portal -%>
|
|
11
|
+
import "./common.tsp";
|
|
12
|
+
<%- else -%>
|
|
13
|
+
import "../common.tsp";
|
|
14
|
+
<%- end -%>
|
|
15
|
+
<%- @current_portal[:resources].each do |resource| -%>
|
|
16
|
+
import "./models/<%= resource[:file_name] %>.tsp";
|
|
17
|
+
<%- end -%>
|
|
18
|
+
|
|
19
|
+
using TypeSpec.Http;
|
|
20
|
+
using TypeSpec.Rest;
|
|
21
|
+
|
|
22
|
+
@service({
|
|
23
|
+
title: "<%= @current_portal[:name] %> API",
|
|
24
|
+
version: "1.0.0",
|
|
25
|
+
})
|
|
26
|
+
@server("http://localhost:3000<%= @current_portal[:route_path] %>", "Development server")
|
|
27
|
+
namespace <%= @current_portal[:name].gsub('::', '') %>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <%= Rails.application.class.module_parent_name %> API Specification
|
|
3
|
+
* Generated by Plutonium TypeSpec Generator
|
|
4
|
+
*
|
|
5
|
+
* This file imports all portal APIs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import "@typespec/http";
|
|
9
|
+
import "@typespec/rest";
|
|
10
|
+
import "@typespec/openapi3";
|
|
11
|
+
|
|
12
|
+
import "./common.tsp";
|
|
13
|
+
<%- @portals.each do |portal| -%>
|
|
14
|
+
import "./<%= portal[:file_name] %>/main.tsp";
|
|
15
|
+
<%- end -%>
|
|
16
|
+
|
|
17
|
+
using TypeSpec.Http;
|
|
18
|
+
using TypeSpec.Rest;
|
|
19
|
+
|
|
20
|
+
@service({
|
|
21
|
+
title: "<%= Rails.application.class.module_parent_name %> API",
|
|
22
|
+
version: "1.0.0",
|
|
23
|
+
})
|
|
24
|
+
@server("http://localhost:3000", "Development server")
|
|
25
|
+
namespace <%= Rails.application.class.module_parent_name %>;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<%-
|
|
2
|
+
# Helper methods for template
|
|
3
|
+
def optional_marker(column)
|
|
4
|
+
column[:null] ? '?' : ''
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
resource = @current_resource
|
|
8
|
+
model_name = resource[:typespec_name]
|
|
9
|
+
all_columns = resource[:columns]
|
|
10
|
+
all_column_names = all_columns.map { |c| c[:name] }
|
|
11
|
+
|
|
12
|
+
# Extract special columns if they exist
|
|
13
|
+
primary_key_column = all_columns.find { |c| c[:name] == resource[:primary_key] }
|
|
14
|
+
created_at_column = all_columns.find { |c| c[:name] == 'created_at' }
|
|
15
|
+
updated_at_column = all_columns.find { |c| c[:name] == 'updated_at' }
|
|
16
|
+
|
|
17
|
+
# Regular columns exclude primary key and timestamps
|
|
18
|
+
columns = all_columns.reject { |c| [resource[:primary_key], 'created_at', 'updated_at'].include?(c[:name]) }
|
|
19
|
+
associations = resource[:associations]
|
|
20
|
+
enums = resource[:enums] || {}
|
|
21
|
+
definition = resource[:definition]
|
|
22
|
+
inputs = definition ? definition[:inputs] : []
|
|
23
|
+
|
|
24
|
+
# Separate association columns (foreign keys) from regular columns
|
|
25
|
+
belongs_to_assocs = associations.select { |a| a[:macro] == 'belongs_to' }
|
|
26
|
+
has_many_assocs = associations.select { |a| a[:macro] == 'has_many' }
|
|
27
|
+
has_one_assocs = associations.select { |a| a[:macro] == 'has_one' }
|
|
28
|
+
|
|
29
|
+
# Foreign key columns to exclude from regular attributes
|
|
30
|
+
fk_columns = belongs_to_assocs.map { |a| a[:foreign_key] }.compact
|
|
31
|
+
regular_columns = columns.reject { |c| fk_columns.include?(c[:name]) }
|
|
32
|
+
|
|
33
|
+
# Check if we have definition-based inputs
|
|
34
|
+
has_definition_inputs = inputs.any?
|
|
35
|
+
-%>
|
|
36
|
+
/**
|
|
37
|
+
* <%= model_name %> resource
|
|
38
|
+
* Table: <%= resource[:table_name] %>
|
|
39
|
+
* Route: <%= resource[:route_path] %>
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
<%- if @single_portal -%>
|
|
43
|
+
import "../common.tsp";
|
|
44
|
+
<%- else -%>
|
|
45
|
+
import "../../common.tsp";
|
|
46
|
+
<%- end -%>
|
|
47
|
+
|
|
48
|
+
using TypeSpec.Http;
|
|
49
|
+
|
|
50
|
+
<%- enums.each do |enum_name, values| -%>
|
|
51
|
+
/** <%= enum_name.humanize %> options */
|
|
52
|
+
enum <%= model_name %><%= enum_name.camelize %> {
|
|
53
|
+
<%- values.each do |value| -%>
|
|
54
|
+
<%= value %>,
|
|
55
|
+
<%- end -%>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
<%- end -%>
|
|
59
|
+
/**
|
|
60
|
+
* <%= model_name %> response model
|
|
61
|
+
*/
|
|
62
|
+
model <%= model_name %> extends ResourceBase {
|
|
63
|
+
<%- if primary_key_column -%>
|
|
64
|
+
@doc("Unique identifier")
|
|
65
|
+
<%= resource[:primary_key] %>: <%= resource[:primary_key_type] %>;
|
|
66
|
+
<%- end -%>
|
|
67
|
+
<%- if created_at_column -%>
|
|
68
|
+
@doc("Creation timestamp")
|
|
69
|
+
created_at: utcDateTime;
|
|
70
|
+
<%- end -%>
|
|
71
|
+
<%- if updated_at_column -%>
|
|
72
|
+
@doc("Last update timestamp")
|
|
73
|
+
updated_at: utcDateTime;
|
|
74
|
+
<%- end -%>
|
|
75
|
+
<%- if (primary_key_column || created_at_column || updated_at_column) && regular_columns.any? -%>
|
|
76
|
+
|
|
77
|
+
<%- end -%>
|
|
78
|
+
<%- regular_columns.each do |column| -%>
|
|
79
|
+
<%- if enums.key?(column[:name]) -%>
|
|
80
|
+
<%= column[:name] %><%= optional_marker(column) %>: <%= model_name %><%= column[:name].camelize %>;
|
|
81
|
+
<%- else -%>
|
|
82
|
+
<%= column[:name] %><%= optional_marker(column) %>: <%= column[:typespec_type] %>;
|
|
83
|
+
<%- end -%>
|
|
84
|
+
<%- end -%>
|
|
85
|
+
|
|
86
|
+
<%- belongs_to_assocs.each do |assoc| -%>
|
|
87
|
+
<%- if assoc[:polymorphic] -%>
|
|
88
|
+
/** Polymorphic association type */
|
|
89
|
+
<%= assoc[:name] %>_type?: string;
|
|
90
|
+
/** Polymorphic association ID */
|
|
91
|
+
<%= assoc[:name] %>_id?: <%= assoc[:foreign_key_type] %>;
|
|
92
|
+
/** Polymorphic association SGID */
|
|
93
|
+
<%= assoc[:name] %>_sgid?: SignedGlobalId;
|
|
94
|
+
<%- else -%>
|
|
95
|
+
/** <%= assoc[:name].humanize %> ID */
|
|
96
|
+
<%= assoc[:foreign_key] || "#{assoc[:name]}_id" %>?: <%= assoc[:foreign_key_type] %>;
|
|
97
|
+
/** <%= assoc[:name].humanize %> SGID */
|
|
98
|
+
<%= assoc[:name] %>_sgid?: SignedGlobalId;
|
|
99
|
+
<%- end -%>
|
|
100
|
+
<%- end -%>
|
|
101
|
+
|
|
102
|
+
<%- has_many_assocs.each do |assoc| -%>
|
|
103
|
+
/** <%= assoc[:name].to_s.singularize.humanize %> IDs */
|
|
104
|
+
<%= assoc[:name].to_s.singularize %>_ids?: <%= assoc[:foreign_key_type] %>[];
|
|
105
|
+
/** <%= assoc[:name].to_s.singularize.humanize %> SGIDs */
|
|
106
|
+
<%= assoc[:name].to_s.singularize %>_sgids?: SignedGlobalId[];
|
|
107
|
+
<%- end -%>
|
|
108
|
+
<%- has_one_assocs.each do |assoc| -%>
|
|
109
|
+
/** <%= assoc[:name].humanize %> ID */
|
|
110
|
+
<%= assoc[:name] %>_id?: <%= assoc[:foreign_key_type] %>;
|
|
111
|
+
/** <%= assoc[:name].humanize %> SGID */
|
|
112
|
+
<%= assoc[:name] %>_sgid?: SignedGlobalId;
|
|
113
|
+
<%- end -%>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* <%= model_name %> input model for create/update operations
|
|
118
|
+
<%- if has_definition_inputs -%>
|
|
119
|
+
* Based on definition: <%= definition[:class_name] %>
|
|
120
|
+
<%- end -%>
|
|
121
|
+
*/
|
|
122
|
+
model <%= model_name %>Input {
|
|
123
|
+
<%- if has_definition_inputs -%>
|
|
124
|
+
<%# Use definition inputs -%>
|
|
125
|
+
<%- inputs.each do |input| -%>
|
|
126
|
+
<%- next if input[:nested] # Skip nested inputs for now -%>
|
|
127
|
+
<%- if input[:is_association] -%>
|
|
128
|
+
<%- if input[:is_polymorphic] -%>
|
|
129
|
+
/** Polymorphic <%= input[:name] %> (SGID) */
|
|
130
|
+
<%= input[:name] %>_sgid<%= input[:required] ? '' : '?' %>: SignedGlobalId;
|
|
131
|
+
<%- elsif input[:association_macro] == 'has_many' || input[:association_macro] == 'has_and_belongs_to_many' -%>
|
|
132
|
+
/** <%= input[:name].singularize.humanize %> SGIDs */
|
|
133
|
+
<%= input[:name].singularize %>_sgids<%= input[:required] ? '' : '?' %>: SignedGlobalId[];
|
|
134
|
+
<%- else -%>
|
|
135
|
+
/** <%= input[:name].humanize %> (SGID) */
|
|
136
|
+
<%= input[:name] %>_sgid<%= input[:required] ? '' : '?' %>: SignedGlobalId;
|
|
137
|
+
<%- end -%>
|
|
138
|
+
<%- else -%>
|
|
139
|
+
<%= input[:name] %><%= input[:required] ? '' : '?' %>: <%= input[:typespec_type] %>;
|
|
140
|
+
<%- end -%>
|
|
141
|
+
<%- end -%>
|
|
142
|
+
<%- else -%>
|
|
143
|
+
<%# Fallback to column-based inputs -%>
|
|
144
|
+
<%- regular_columns.each do |column| -%>
|
|
145
|
+
<%- next if column[:name].end_with?('_count') # skip counter caches -%>
|
|
146
|
+
<%- if enums.key?(column[:name]) -%>
|
|
147
|
+
<%= column[:name] %><%= optional_marker(column) %>: <%= model_name %><%= column[:name].camelize %>;
|
|
148
|
+
<%- else -%>
|
|
149
|
+
<%= column[:name] %><%= optional_marker(column) %>: <%= column[:typespec_type] %>;
|
|
150
|
+
<%- end -%>
|
|
151
|
+
<%- end -%>
|
|
152
|
+
|
|
153
|
+
<%- belongs_to_assocs.each do |assoc| -%>
|
|
154
|
+
<%- if assoc[:polymorphic] -%>
|
|
155
|
+
/** Polymorphic <%= assoc[:name] %> (SGID) */
|
|
156
|
+
<%= assoc[:name] %>_sgid?: SignedGlobalId;
|
|
157
|
+
<%- else -%>
|
|
158
|
+
/** <%= assoc[:name].humanize %> (SGID) */
|
|
159
|
+
<%= assoc[:name] %>_sgid?: SignedGlobalId;
|
|
160
|
+
<%- end -%>
|
|
161
|
+
<%- end -%>
|
|
162
|
+
|
|
163
|
+
<%- has_many_assocs.each do |assoc| -%>
|
|
164
|
+
/** <%= assoc[:name].to_s.singularize.humanize %> SGIDs */
|
|
165
|
+
<%= assoc[:name].to_s.singularize %>_sgids?: SignedGlobalId[];
|
|
166
|
+
<%- end -%>
|
|
167
|
+
<%- end -%>
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* <%= model_name %> list response
|
|
172
|
+
*/
|
|
173
|
+
model <%= model_name %>ListResponse {
|
|
174
|
+
<%= model_name.underscore.pluralize %>: <%= model_name %>[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* <%= model_name %> CRUD operations
|
|
179
|
+
*/
|
|
180
|
+
@route("<%= resource[:route_path] %>")
|
|
181
|
+
@tag("<%= model_name.pluralize %>")
|
|
182
|
+
interface <%= model_name %>Operations {
|
|
183
|
+
/**
|
|
184
|
+
* List all <%= model_name.underscore.humanize.pluralize.downcase %>
|
|
185
|
+
*/
|
|
186
|
+
@get
|
|
187
|
+
list(...ListQueryParams): <%= model_name %>ListResponse;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get a single <%= model_name.underscore.humanize.downcase %>
|
|
191
|
+
*/
|
|
192
|
+
@route("{id}")
|
|
193
|
+
@get
|
|
194
|
+
show(@path id: <%= resource[:primary_key_type] %>): <%= model_name %>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Create a new <%= model_name.underscore.humanize.downcase %>
|
|
198
|
+
*/
|
|
199
|
+
@post
|
|
200
|
+
create(@body input: <%= model_name %>Input): {
|
|
201
|
+
@statusCode statusCode: 201;
|
|
202
|
+
@body body: <%= model_name %>;
|
|
203
|
+
} | {
|
|
204
|
+
@statusCode statusCode: 422;
|
|
205
|
+
@body body: ErrorResponse;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Update a <%= model_name.underscore.humanize.downcase %>
|
|
210
|
+
*/
|
|
211
|
+
@route("{id}")
|
|
212
|
+
@patch
|
|
213
|
+
update(@path id: <%= resource[:primary_key_type] %>, @body input: <%= model_name %>Input): <%= model_name %> | {
|
|
214
|
+
@statusCode statusCode: 422;
|
|
215
|
+
@body body: ErrorResponse;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Delete a <%= model_name.underscore.humanize.downcase %>
|
|
220
|
+
*/
|
|
221
|
+
@route("{id}")
|
|
222
|
+
@delete
|
|
223
|
+
destroy(@path id: <%= resource[:primary_key_type] %>): {
|
|
224
|
+
@statusCode statusCode: 204;
|
|
225
|
+
};
|
|
226
|
+
}
|