gemstack-cli 0.1.0

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.
Files changed (110) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +24 -0
  5. data/exe/gemstack +6 -0
  6. data/lib/gemstack/cli/add_generator.rb +237 -0
  7. data/lib/gemstack/cli/app_generator.rb +110 -0
  8. data/lib/gemstack/cli/commands/db.rb +134 -0
  9. data/lib/gemstack/cli/commands/jobs.rb +96 -0
  10. data/lib/gemstack/cli/controller_generator.rb +73 -0
  11. data/lib/gemstack/cli/deploy_generator.rb +64 -0
  12. data/lib/gemstack/cli/doctor.rb +277 -0
  13. data/lib/gemstack/cli/generator.rb +122 -0
  14. data/lib/gemstack/cli/job_generator.rb +47 -0
  15. data/lib/gemstack/cli/migration_generator.rb +52 -0
  16. data/lib/gemstack/cli/policy_generator.rb +35 -0
  17. data/lib/gemstack/cli/project.rb +53 -0
  18. data/lib/gemstack/cli/resource_generator.rb +169 -0
  19. data/lib/gemstack/cli/resource_spec.rb +95 -0
  20. data/lib/gemstack/cli.rb +299 -0
  21. data/templates/app/Gemfile.tt +39 -0
  22. data/templates/app/README.md.tt +29 -0
  23. data/templates/app/app/controllers/application_controller.rb +6 -0
  24. data/templates/app/bin/gemstack +7 -0
  25. data/templates/app/config/app.rb.tt +30 -0
  26. data/templates/app/config/environments/development.rb +6 -0
  27. data/templates/app/config/environments/production.rb +8 -0
  28. data/templates/app/config/environments/test.rb +7 -0
  29. data/templates/app/config/puma.rb +21 -0
  30. data/templates/app/config/routes.rb +10 -0
  31. data/templates/app/config.ru +6 -0
  32. data/templates/app/db/migrations/dot_keep +0 -0
  33. data/templates/app/db/seeds.rb +5 -0
  34. data/templates/app/dot_env.example +9 -0
  35. data/templates/app/dot_gitignore +14 -0
  36. data/templates/app/dot_ruby-version.tt +1 -0
  37. data/templates/app/dot_tool-versions.tt +1 -0
  38. data/templates/app/test/health_test.rb +18 -0
  39. data/templates/app/test/test_helper.rb.tt +25 -0
  40. data/templates/auth/app/controllers/api_tokens_controller.rb +35 -0
  41. data/templates/auth/app/controllers/email_verifications_controller.rb +31 -0
  42. data/templates/auth/app/controllers/password_resets_controller.rb +40 -0
  43. data/templates/auth/app/controllers/registrations_controller.rb +19 -0
  44. data/templates/auth/app/controllers/sessions_controller.rb +29 -0
  45. data/templates/auth/app/mailers/auth_mailer.rb +20 -0
  46. data/templates/auth/app/mailers/templates/auth_mailer/email_verification.html.erb +2 -0
  47. data/templates/auth/app/mailers/templates/auth_mailer/email_verification.text.erb +2 -0
  48. data/templates/auth/app/mailers/templates/auth_mailer/password_reset.html.erb +3 -0
  49. data/templates/auth/app/mailers/templates/auth_mailer/password_reset.text.erb +6 -0
  50. data/templates/auth/app/models/auth_token.rb +15 -0
  51. data/templates/auth/app/models/user.rb +12 -0
  52. data/templates/auth/app/policies/application_policy.rb +6 -0
  53. data/templates/auth/app/serializers/api_token_serializer.rb +6 -0
  54. data/templates/auth/app/serializers/new_api_token_serializer.rb +9 -0
  55. data/templates/auth/app/serializers/user_serializer.rb +6 -0
  56. data/templates/auth/db/migrations/%timestamp%_create_auth_tables.rb +41 -0
  57. data/templates/auth/frontend/app/account/page.tsx +116 -0
  58. data/templates/auth/frontend/app/forgot-password/page.tsx +48 -0
  59. data/templates/auth/frontend/app/login/page.tsx +26 -0
  60. data/templates/auth/frontend/app/reset-password/page.tsx +11 -0
  61. data/templates/auth/frontend/app/signup/page.tsx +27 -0
  62. data/templates/auth/frontend/app/verify-email/page.tsx +11 -0
  63. data/templates/auth/frontend/components/auth/CredentialsForm.tsx +58 -0
  64. data/templates/auth/frontend/components/auth/ResetPasswordForm.tsx +43 -0
  65. data/templates/auth/frontend/components/auth/VerifyEmail.tsx +28 -0
  66. data/templates/auth/frontend/lib/auth.ts +113 -0
  67. data/templates/auth/test/controllers/auth_test.rb +108 -0
  68. data/templates/controller/app/controllers/%file_name%_controller.rb.tt +10 -0
  69. data/templates/controller/test/controllers/%file_name%_controller_test.rb.tt +14 -0
  70. data/templates/deploy/Caddyfile.tt +19 -0
  71. data/templates/deploy/Dockerfile.tt +62 -0
  72. data/templates/deploy/Procfile.tt +6 -0
  73. data/templates/deploy/compose.yaml.tt +80 -0
  74. data/templates/deploy/dot_dockerignore +14 -0
  75. data/templates/frontend/app/globals.css +171 -0
  76. data/templates/frontend/app/layout.tsx.tt +19 -0
  77. data/templates/frontend/app/page.tsx.tt +45 -0
  78. data/templates/frontend/app/providers.tsx +24 -0
  79. data/templates/frontend/lib/gemstack/client.ts +125 -0
  80. data/templates/frontend/next-env.d.ts +5 -0
  81. data/templates/frontend/next.config.ts +17 -0
  82. data/templates/frontend/package.json.tt +23 -0
  83. data/templates/frontend/tsconfig.json +21 -0
  84. data/templates/job/app/jobs/%file_name%.rb.tt +15 -0
  85. data/templates/job/test/jobs/%file_name%_test.rb.tt +15 -0
  86. data/templates/migration/db/migrations/%timestamp%_%file_name%.rb.tt +17 -0
  87. data/templates/policy/app/policies/%file_name%_policy.rb.tt +21 -0
  88. data/templates/policy/test/policies/%file_name%_policy_test.rb.tt +9 -0
  89. data/templates/realtime/config/channels.rb +14 -0
  90. data/templates/realtime/frontend/lib/gemstack/realtime.ts +120 -0
  91. data/templates/resource/controller/app/controllers/%plural%_controller.rb.tt +51 -0
  92. data/templates/resource/controller/test/controllers/%plural%_controller_test.rb.tt +74 -0
  93. data/templates/resource/frontend/frontend/app/%url_segment%/[id]/edit/page.tsx.tt +45 -0
  94. data/templates/resource/frontend/frontend/app/%url_segment%/[id]/page.tsx.tt +49 -0
  95. data/templates/resource/frontend/frontend/app/%url_segment%/new/page.tsx.tt +27 -0
  96. data/templates/resource/frontend/frontend/app/%url_segment%/page.tsx.tt +51 -0
  97. data/templates/resource/frontend/frontend/components/%url_segment%/%class_name%Card.tsx.tt +15 -0
  98. data/templates/resource/frontend/frontend/components/%url_segment%/%class_name%Form.tsx.tt +98 -0
  99. data/templates/resource/frontend/frontend/components/%url_segment%/%class_name%Table.tsx.tt +36 -0
  100. data/templates/resource/frontend/frontend/lib/format.ts +12 -0
  101. data/templates/resource/frontend/frontend/lib/queries/%url_segment%.ts.tt +63 -0
  102. data/templates/resource/migration/db/migrations/%timestamp%_create_%table%.rb.tt +18 -0
  103. data/templates/resource/model/app/models/%file_name%.rb.tt +15 -0
  104. data/templates/resource/model/test/models/%file_name%_test.rb.tt +29 -0
  105. data/templates/resource/serializer/app/serializers/%file_name%_serializer.rb.tt +7 -0
  106. data/templates/storage/app/controllers/uploads_controller.rb.tt +33 -0
  107. data/templates/storage/app/serializers/upload_serializer.rb +11 -0
  108. data/templates/storage/frontend/lib/upload.ts +52 -0
  109. data/templates/storage/test/controllers/uploads_test.rb.tt +30 -0
  110. metadata +195 -0
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %> < GemStack::Model
4
+ <% fields.each do |field| -%>
5
+ <%= model_field(field) %>
6
+ <% end -%>
7
+ <% fields.select(&:unique).each do |field| -%>
8
+
9
+ validates :<%= field.column %>, uniqueness: true
10
+ <% end -%>
11
+ <% spec.references.each do |field| -%>
12
+
13
+ belongs_to :<%= field.name %>
14
+ <% end -%>
15
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_helper"
4
+
5
+ class <%= class_name %>Test < GemStack::TestCase
6
+ def sample = GemStack::DB::Testing.sample_attributes(<%= class_name %>)
7
+
8
+ def test_valid_with_sample_attributes
9
+ <%= spec.variable %> = <%= class_name %>.new(sample)
10
+
11
+ assert_predicate <%= spec.variable %>, :valid?, <%= spec.variable %>.errors.to_h.inspect
12
+ end
13
+
14
+ def test_create
15
+ <%= spec.variable %> = <%= class_name %>.create(sample)
16
+
17
+ assert <%= spec.variable %>.id
18
+ assert <%= spec.variable %>.created_at
19
+ end
20
+ <% fields.select(&:required?).each do |field| -%>
21
+
22
+ def test_requires_<%= field.column %>
23
+ <%= spec.variable %> = <%= class_name %>.new(sample.except(:<%= field.column %>))
24
+
25
+ refute_predicate <%= spec.variable %>, :valid?
26
+ assert_includes <%= spec.variable %>.errors[:<%= field.column %>], "is required"
27
+ end
28
+ <% end -%>
29
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # What the API returns for a <%= class_name %>. Only listed attributes are exposed;
4
+ # their types (from <%= class_name %>'s fields) drive the generated TypeScript types.
5
+ class <%= class_name %>Serializer < GemStack::Serializer
6
+ attributes :id, <%= fields.map { |f| ":#{f.column}" }.join(", ") %>, :created_at, :updated_at
7
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # POST /api/uploads — step 1 of a direct upload (frontend/lib/upload.ts):
4
+ # validates the file's type and size and returns a short-lived URL the
5
+ # browser PUTs the file to. Save the returned signed_id on your record:
6
+ #
7
+ # product.update(image_key: GemStack::Storage.key_for_signed_id(input[:image]))
8
+ # GemStack::Storage.url(product.image_key) # signed download URL
9
+ #
10
+ # Allowed types and the size limit: config.storage (docs/storage.md).
11
+ class UploadsController < ApplicationController
12
+ <% if auth? -%>
13
+ before :require_login
14
+ <% else -%>
15
+ # Anyone can upload until you add authentication (gemstack add auth), then:
16
+ # before :require_login
17
+ <% end -%>
18
+ rate_limit to: 60, within: 3600, only: :create if respond_to?(:rate_limit)
19
+
20
+ accepts :create do
21
+ required :filename, :string, max_length: 255
22
+ required :content_type, :string, max_length: 100
23
+ required :byte_size, :integer, gt: 0
24
+ end
25
+ returns :create, UploadSerializer
26
+
27
+ def create
28
+ upload = GemStack::Storage.direct_upload(**input.slice(:filename, :content_type, :byte_size))
29
+ result = UploadSerializer::Result.new(signed_id: upload[:signed_id], url: upload[:url],
30
+ http_method: upload[:method], headers: upload[:headers])
31
+ render result, status: :created, serializer: UploadSerializer
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Where and how the browser sends the file (see UploadsController).
4
+ class UploadSerializer < GemStack::Serializer
5
+ Result = Data.define(:signed_id, :url, :http_method, :headers)
6
+
7
+ attribute :signed_id, :string
8
+ attribute :url, :string
9
+ attribute(:method, :string) { |upload| upload.http_method }
10
+ attribute :headers, :json
11
+ end
@@ -0,0 +1,52 @@
1
+ "use client";
2
+
3
+ // Direct uploads (generated by `gemstack add storage`): the file goes from the
4
+ // browser straight to storage (S3, or the Ruby disk endpoint in development).
5
+ //
6
+ // const { signedId } = await uploadFile(file, { onProgress: (p) => setProgress(p) });
7
+ // await products.update(id, { image: signedId });
8
+ import { useMutation } from "@tanstack/react-query";
9
+ import { uploads } from "@/lib/api/generated";
10
+
11
+ export interface UploadResult {
12
+ /** Send this to the API to attach the file to a record. */
13
+ signedId: string;
14
+ }
15
+
16
+ export interface UploadOptions {
17
+ /** 0–1 while uploading. */
18
+ onProgress?: (fraction: number) => void;
19
+ signal?: AbortSignal;
20
+ }
21
+
22
+ export async function uploadFile(file: File, options: UploadOptions = {}): Promise<UploadResult> {
23
+ const upload = await uploads.create({
24
+ filename: file.name,
25
+ content_type: file.type || "application/octet-stream",
26
+ byte_size: file.size,
27
+ });
28
+ await send(upload.url, upload.method, upload.headers as Record<string, string>, file, options);
29
+ return { signedId: upload.signed_id };
30
+ }
31
+
32
+ // XMLHttpRequest rather than fetch: it reports upload progress.
33
+ function send(url: string, method: string, headers: Record<string, string>, file: File, options: UploadOptions) {
34
+ return new Promise<void>((resolve, reject) => {
35
+ const xhr = new XMLHttpRequest();
36
+ xhr.open(method, url);
37
+ for (const [name, value] of Object.entries(headers)) xhr.setRequestHeader(name, value);
38
+ xhr.upload.onprogress = (event) => {
39
+ if (event.lengthComputable) options.onProgress?.(event.loaded / event.total);
40
+ };
41
+ xhr.onload = () => (xhr.status < 300 ? resolve() : reject(new Error(`Upload failed (HTTP ${xhr.status})`)));
42
+ xhr.onerror = () => reject(new Error("Upload failed: network error"));
43
+ xhr.onabort = () => reject(new DOMException("Upload aborted", "AbortError"));
44
+ options.signal?.addEventListener("abort", () => xhr.abort());
45
+ xhr.send(file);
46
+ });
47
+ }
48
+
49
+ /** uploadFile as a TanStack Query mutation: const upload = useUpload(); upload.mutateAsync(file). */
50
+ export function useUpload(options: Omit<UploadOptions, "signal"> = {}) {
51
+ return useMutation({ mutationFn: (file: File) => uploadFile(file, options) });
52
+ }
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_helper"
4
+
5
+ class UploadsTest < GemStack::TestCase
6
+ <% if auth? -%>
7
+ def setup
8
+ sign_in_as(User.create(email: "uploader@example.com", password: "correct horse battery staple"))
9
+ end
10
+
11
+ <% end -%>
12
+ def test_direct_upload
13
+ post_json "/api/uploads", { filename: "cat.png", content_type: "image/png", byte_size: 4 }
14
+
15
+ assert_status 201
16
+ signed_id = json_body["signed_id"]
17
+ put json_body["url"], "\x89PNG", "CONTENT_TYPE" => "image/png"
18
+
19
+ assert_status 201
20
+ key = GemStack::Storage.key_for_signed_id(signed_id)
21
+ assert_equal "\x89PNG".b, GemStack::Storage.download(key).b
22
+ end
23
+
24
+ def test_refuses_other_types
25
+ post_json "/api/uploads", { filename: "page.html", content_type: "text/html", byte_size: 10 }
26
+
27
+ assert_error 422, "validation_failed"
28
+ assert json_body["errors"]["content_type"]
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemstack-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shoaib Malik
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: gemstack-core
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 0.1.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '='
24
+ - !ruby/object:Gem::Version
25
+ version: 0.1.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: gemstack-dev
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: thor
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
54
+ email:
55
+ - gemstack26@gmail.com
56
+ executables:
57
+ - gemstack
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - CHANGELOG.md
62
+ - LICENSE.txt
63
+ - README.md
64
+ - exe/gemstack
65
+ - lib/gemstack/cli.rb
66
+ - lib/gemstack/cli/add_generator.rb
67
+ - lib/gemstack/cli/app_generator.rb
68
+ - lib/gemstack/cli/commands/db.rb
69
+ - lib/gemstack/cli/commands/jobs.rb
70
+ - lib/gemstack/cli/controller_generator.rb
71
+ - lib/gemstack/cli/deploy_generator.rb
72
+ - lib/gemstack/cli/doctor.rb
73
+ - lib/gemstack/cli/generator.rb
74
+ - lib/gemstack/cli/job_generator.rb
75
+ - lib/gemstack/cli/migration_generator.rb
76
+ - lib/gemstack/cli/policy_generator.rb
77
+ - lib/gemstack/cli/project.rb
78
+ - lib/gemstack/cli/resource_generator.rb
79
+ - lib/gemstack/cli/resource_spec.rb
80
+ - templates/app/Gemfile.tt
81
+ - templates/app/README.md.tt
82
+ - templates/app/app/controllers/application_controller.rb
83
+ - templates/app/bin/gemstack
84
+ - templates/app/config.ru
85
+ - templates/app/config/app.rb.tt
86
+ - templates/app/config/environments/development.rb
87
+ - templates/app/config/environments/production.rb
88
+ - templates/app/config/environments/test.rb
89
+ - templates/app/config/puma.rb
90
+ - templates/app/config/routes.rb
91
+ - templates/app/db/migrations/dot_keep
92
+ - templates/app/db/seeds.rb
93
+ - templates/app/dot_env.example
94
+ - templates/app/dot_gitignore
95
+ - templates/app/dot_ruby-version.tt
96
+ - templates/app/dot_tool-versions.tt
97
+ - templates/app/test/health_test.rb
98
+ - templates/app/test/test_helper.rb.tt
99
+ - templates/auth/app/controllers/api_tokens_controller.rb
100
+ - templates/auth/app/controllers/email_verifications_controller.rb
101
+ - templates/auth/app/controllers/password_resets_controller.rb
102
+ - templates/auth/app/controllers/registrations_controller.rb
103
+ - templates/auth/app/controllers/sessions_controller.rb
104
+ - templates/auth/app/mailers/auth_mailer.rb
105
+ - templates/auth/app/mailers/templates/auth_mailer/email_verification.html.erb
106
+ - templates/auth/app/mailers/templates/auth_mailer/email_verification.text.erb
107
+ - templates/auth/app/mailers/templates/auth_mailer/password_reset.html.erb
108
+ - templates/auth/app/mailers/templates/auth_mailer/password_reset.text.erb
109
+ - templates/auth/app/models/auth_token.rb
110
+ - templates/auth/app/models/user.rb
111
+ - templates/auth/app/policies/application_policy.rb
112
+ - templates/auth/app/serializers/api_token_serializer.rb
113
+ - templates/auth/app/serializers/new_api_token_serializer.rb
114
+ - templates/auth/app/serializers/user_serializer.rb
115
+ - templates/auth/db/migrations/%timestamp%_create_auth_tables.rb
116
+ - templates/auth/frontend/app/account/page.tsx
117
+ - templates/auth/frontend/app/forgot-password/page.tsx
118
+ - templates/auth/frontend/app/login/page.tsx
119
+ - templates/auth/frontend/app/reset-password/page.tsx
120
+ - templates/auth/frontend/app/signup/page.tsx
121
+ - templates/auth/frontend/app/verify-email/page.tsx
122
+ - templates/auth/frontend/components/auth/CredentialsForm.tsx
123
+ - templates/auth/frontend/components/auth/ResetPasswordForm.tsx
124
+ - templates/auth/frontend/components/auth/VerifyEmail.tsx
125
+ - templates/auth/frontend/lib/auth.ts
126
+ - templates/auth/test/controllers/auth_test.rb
127
+ - templates/controller/app/controllers/%file_name%_controller.rb.tt
128
+ - templates/controller/test/controllers/%file_name%_controller_test.rb.tt
129
+ - templates/deploy/Caddyfile.tt
130
+ - templates/deploy/Dockerfile.tt
131
+ - templates/deploy/Procfile.tt
132
+ - templates/deploy/compose.yaml.tt
133
+ - templates/deploy/dot_dockerignore
134
+ - templates/frontend/app/globals.css
135
+ - templates/frontend/app/layout.tsx.tt
136
+ - templates/frontend/app/page.tsx.tt
137
+ - templates/frontend/app/providers.tsx
138
+ - templates/frontend/lib/gemstack/client.ts
139
+ - templates/frontend/next-env.d.ts
140
+ - templates/frontend/next.config.ts
141
+ - templates/frontend/package.json.tt
142
+ - templates/frontend/tsconfig.json
143
+ - templates/job/app/jobs/%file_name%.rb.tt
144
+ - templates/job/test/jobs/%file_name%_test.rb.tt
145
+ - templates/migration/db/migrations/%timestamp%_%file_name%.rb.tt
146
+ - templates/policy/app/policies/%file_name%_policy.rb.tt
147
+ - templates/policy/test/policies/%file_name%_policy_test.rb.tt
148
+ - templates/realtime/config/channels.rb
149
+ - templates/realtime/frontend/lib/gemstack/realtime.ts
150
+ - templates/resource/controller/app/controllers/%plural%_controller.rb.tt
151
+ - templates/resource/controller/test/controllers/%plural%_controller_test.rb.tt
152
+ - templates/resource/frontend/frontend/app/%url_segment%/[id]/edit/page.tsx.tt
153
+ - templates/resource/frontend/frontend/app/%url_segment%/[id]/page.tsx.tt
154
+ - templates/resource/frontend/frontend/app/%url_segment%/new/page.tsx.tt
155
+ - templates/resource/frontend/frontend/app/%url_segment%/page.tsx.tt
156
+ - templates/resource/frontend/frontend/components/%url_segment%/%class_name%Card.tsx.tt
157
+ - templates/resource/frontend/frontend/components/%url_segment%/%class_name%Form.tsx.tt
158
+ - templates/resource/frontend/frontend/components/%url_segment%/%class_name%Table.tsx.tt
159
+ - templates/resource/frontend/frontend/lib/format.ts
160
+ - templates/resource/frontend/frontend/lib/queries/%url_segment%.ts.tt
161
+ - templates/resource/migration/db/migrations/%timestamp%_create_%table%.rb.tt
162
+ - templates/resource/model/app/models/%file_name%.rb.tt
163
+ - templates/resource/model/test/models/%file_name%_test.rb.tt
164
+ - templates/resource/serializer/app/serializers/%file_name%_serializer.rb.tt
165
+ - templates/storage/app/controllers/uploads_controller.rb.tt
166
+ - templates/storage/app/serializers/upload_serializer.rb
167
+ - templates/storage/frontend/lib/upload.ts
168
+ - templates/storage/test/controllers/uploads_test.rb.tt
169
+ homepage: https://github.com/gemstack-rb/gemstack
170
+ licenses:
171
+ - MIT
172
+ metadata:
173
+ rubygems_mfa_required: 'true'
174
+ source_code_uri: https://github.com/gemstack-rb/gemstack/tree/main/gems/gemstack-cli
175
+ changelog_uri: https://github.com/gemstack-rb/gemstack/blob/main/gems/gemstack-cli/CHANGELOG.md
176
+ bug_tracker_uri: https://github.com/gemstack-rb/gemstack/issues
177
+ documentation_uri: https://github.com/gemstack-rb/gemstack/tree/main/docs
178
+ rdoc_options: []
179
+ require_paths:
180
+ - lib
181
+ required_ruby_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '4.0'
186
+ required_rubygems_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ requirements: []
192
+ rubygems_version: 4.0.20
193
+ specification_version: 4
194
+ summary: GemStack command-line interface and generators
195
+ test_files: []