elasticgraph 0.19.0.0 → 0.19.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8eca32e62a4248d2e0af28f5fc55387b041730fab33f333393681f2ce4c8b7d4
4
- data.tar.gz: 885c292bd452fd17ccd495478097c3e3fbbe60214f56f4c75a9371e40cf0392a
3
+ metadata.gz: 2bc0f43e12d65d88384972b991179c77c5ec7856c86c85f151138e0af2d99f2f
4
+ data.tar.gz: f12ed7e628eba142a6299f5878a97d8d80de3068fbff13606fe6ffbc7e181acd
5
5
  SHA512:
6
- metadata.gz: 753d971644015e750ff3a23f639059a14b70794c8cff317609d405861c5e602230be5e0ed911baf9860a627c304aaaba77a80f4acb552f9a38fe9acc58887439
7
- data.tar.gz: 712cd194f44ecb3cc412811214a761150936ea166611a2bc901f862108cc830d7db531e4fd9ab683e8039b5c845a07b933610a8d98f22d4dc8eb50692b718418
6
+ metadata.gz: 276bb3d1e4e9aa8180c01031468d60115ec05567bfbc02d39fbd65e8777dec65f874a19f6e46a5bbeb20aca56d0855c66ba0dd1a989462804ba01cddf6ba81e5
7
+ data.tar.gz: c191d95111cf81157ef2777bea143d12a0f71aa095b9df0da9bccf27ede6b3f53f250e01bc1bf0d20ab911840dbe33534c9c5fb7557cc521f08496eb8bc2a49f
data/README.md CHANGED
@@ -2,3 +2,11 @@
2
2
 
3
3
  ElasticGraph meta-gem that pulls in all the core ElasticGraph gems. Intended for use when all
4
4
  parts of ElasticGraph are used from the same deployed app.
5
+
6
+ ## Getting Started
7
+
8
+ Run this command to bootstrap a new local project:
9
+
10
+ ```bash
11
+ elasticgraph new my_app
12
+ ```
data/exe/elasticgraph ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2024 Block, Inc.
3
+ #
4
+ # Use of this source code is governed by an MIT-style
5
+ # license that can be found in the LICENSE file or at
6
+ # https://opensource.org/licenses/MIT.
7
+ #
8
+ # frozen_string_literal: true
9
+
10
+ require "elastic_graph/cli"
11
+ ElasticGraph::CLI.start(ARGV)
@@ -0,0 +1,106 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "bundler"
10
+ require "elastic_graph/version"
11
+ require "thor"
12
+
13
+ module ElasticGraph
14
+ class CLI < ::Thor
15
+ include ::Thor::Actions
16
+
17
+ # Tell Thor where our template files live
18
+ def self.source_root
19
+ ::File.expand_path("project_template", __dir__)
20
+ end
21
+
22
+ def self.exit_on_failure?
23
+ true
24
+ end
25
+
26
+ VALID_DATASTORES = %w[elasticsearch opensearch]
27
+
28
+ option :datastore, desc: "elasticsearch or opensearch", type: :string, default: "opensearch"
29
+ desc "new APP_NAME", "Generate a new ElasticGraph project in APP_NAME."
30
+ def new(app_path)
31
+ new_app_path = ::File.join(::Dir.pwd, app_path)
32
+ app_name = ::File.basename(new_app_path)
33
+
34
+ unless app_name.match?(/\A[a-z_]+\z/)
35
+ raise ::Thor::Error, "App name must be in `snake_case` form but was not: `#{app_name}`."
36
+ end
37
+
38
+ unless VALID_DATASTORES.include?(options[:datastore])
39
+ raise ::Thor::Error, "Invalid datastore option: #{options[:datastore]}. Must be #{VALID_DATASTORES.join(" or ")}."
40
+ end
41
+
42
+ setup_env = SetupEnv.new(
43
+ app_name: app_name,
44
+ app_module: app_name.split("_").map(&:capitalize).join,
45
+ datastore: options.fetch(:datastore),
46
+ gemfile_elasticgraph_details_code_snippet: %(["#{VERSION}"])
47
+ )
48
+
49
+ say "Creating a new #{setup_env.datastore_name} ElasticGraph project called '#{app_name}' at: #{new_app_path}", :green
50
+
51
+ ElasticGraph.with_setup_env(setup_env) do
52
+ # Recursively copy all files from project_template into the new_app_path
53
+ directory ".", new_app_path, exclude_pattern: %r{/lib/app_name/}
54
+ directory "lib/app_name", ::File.join(new_app_path, "lib", app_name)
55
+ end
56
+
57
+ inside new_app_path do
58
+ ::Bundler.with_unbundled_env do
59
+ run "bundle install"
60
+ run "bundle exec rake schema_artifacts:dump query_registry:dump_variables:all build"
61
+ end
62
+
63
+ run "git init"
64
+ run "git add ."
65
+ run "git commit -m 'Bootstrapped ElasticGraph with `elasticgraph new`.'"
66
+ end
67
+
68
+ say "Successfully bootstrapped '#{app_name}' as a new #{setup_env.datastore_name} ElasticGraph project.", :green
69
+
70
+ say <<~INSTRUCTIONS, :yellow
71
+ Next steps:
72
+ 1. cd #{app_path}
73
+ 2. Run `bundle exec rake boot_locally` to try it out in your browser.
74
+ 3. Run `bundle exec rake -T` to view other available tasks.
75
+ 4. Customize your new project as needed. (Search for `TODO` to find things that need updating.)
76
+ INSTRUCTIONS
77
+ end
78
+ end
79
+
80
+ class SetupEnv < ::Data.define(:app_name, :app_module, :datastore, :gemfile_elasticgraph_details_code_snippet)
81
+ DATASTORE_NAMES = {"elasticsearch" => "Elasticsearch", "opensearch" => "OpenSearch"}
82
+ DATASTORE_UI_NAMES = {"elasticsearch" => "Kibana", "opensearch" => "OpenSearch Dashboards"}
83
+
84
+ def datastore_name
85
+ DATASTORE_NAMES.fetch(datastore)
86
+ end
87
+
88
+ def datastore_ui_name
89
+ DATASTORE_UI_NAMES.fetch(datastore)
90
+ end
91
+
92
+ def ruby_major_minor
93
+ "3.4"
94
+ end
95
+ end
96
+
97
+ singleton_class.attr_reader :setup_env
98
+
99
+ def self.with_setup_env(setup_env)
100
+ original_setup_env = self.setup_env
101
+ @setup_env = setup_env
102
+ yield
103
+ ensure
104
+ @setup_env = original_setup_env
105
+ end
106
+ end
@@ -0,0 +1,5 @@
1
+ bin/*
2
+ bundle/*
3
+ .bundle/*
4
+ tmp/*
5
+ log/*
@@ -0,0 +1,8 @@
1
+ ruby_version: <%= ElasticGraph.setup_env.ruby_major_minor %>
2
+ format: progress
3
+ ignore:
4
+ - bin/**/*
5
+ - bundle/**/*
6
+ - .bundle/**/*
7
+ - log/**/*
8
+ - tmp/**/*
@@ -0,0 +1,17 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Gem details for the elasticgraph gems.
4
+ elasticgraph_details = <%= ElasticGraph.setup_env.gemfile_elasticgraph_details_code_snippet %>
5
+
6
+ gem "elasticgraph-local", *elasticgraph_details
7
+ gem "elasticgraph-<%= ElasticGraph.setup_env.datastore %>", *elasticgraph_details
8
+ gem "elasticgraph-query_registry", *elasticgraph_details
9
+
10
+ gem "httpx", "~> 1.3"
11
+
12
+ group :development do
13
+ gem "factory_bot"
14
+ gem "faker"
15
+ gem "rspec"
16
+ gem "standard"
17
+ end
@@ -0,0 +1,176 @@
1
+ # <%= ElasticGraph.setup_env.app_module %> ElasticGraph Project
2
+
3
+ This repository contains the files for creating and maintaining the <%= ElasticGraph.setup_env.app_module %> ElasticGraph Project.
4
+
5
+ ## Development Environment
6
+
7
+ Here's what you need:
8
+
9
+ | Requirement | Version | Installation Instructions |
10
+ |----------------|---------|---------------------------------------------------------------------------|
11
+ | Ruby | <%= ElasticGraph.setup_env.ruby_major_minor %>.x | [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/) |
12
+ | Docker Engine | 27.x | [docker.com](https://docs.docker.com/engine/install/) |
13
+ | Docker Compose | 2.29.x | [docker.com](https://docs.docker.com/compose/install/) |
14
+
15
+ ### Ruby
16
+
17
+ This project is written in Ruby, a dynamic, open source programming language with a focus on simplicity and productivity.
18
+
19
+ You may verify your `ruby` installation via the terminal:
20
+
21
+ ```bash
22
+ $ ruby -v
23
+ ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
24
+ ```
25
+
26
+ If you do not have Ruby, we recommend installing it using one of the following:
27
+
28
+ * [RVM](https://rvm.io/)
29
+ * [asdf](https://asdf-vm.com/)
30
+ * [rbenv](https://rbenv.org/)
31
+ * [ruby-install](https://github.com/postmodern/ruby-install)
32
+
33
+ ### Ruby Dependencies
34
+
35
+ Ruby dependencies are managed using [bundler](https://bundler.io/), which comes installed with Ruby.
36
+ To install Ruby dependencies, run:
37
+
38
+ ```bash
39
+ $ bundle install
40
+ ```
41
+
42
+ Once that is done, prefix Ruby commands with `bundle exec` in order to run them in the context of the project bundle.
43
+
44
+ ### Docker and Docker Compose
45
+
46
+ This project uses Docker Engine and Docker Compose to run <%= ElasticGraph.setup_env.datastore_name %> locally. We recommend installing
47
+ [Docker Desktop](https://docs.docker.com/desktop/) to get both Docker dependencies.
48
+
49
+ ## Local Development
50
+
51
+ Some useful commands to try:
52
+
53
+ ```bash
54
+ # The build rake task can be used after making changes to rebuild everything
55
+ bundle exec rake build
56
+
57
+ # See all tasks available for managing your project and schemas
58
+ bundle exec rake -T
59
+
60
+ # Boot a local instance prepopulated with fake data, useful for experimenting
61
+ bundle exec rake boot_locally
62
+
63
+ # The GraphiQL UI should open automatically
64
+ open http://localhost:9393/
65
+
66
+ # You can also visit <%= ElasticGraph.setup_env.datastore_ui_name %> via:
67
+ open http://localhost:19293/
68
+ ```
69
+
70
+ ### Run Build Tasks
71
+
72
+ Run a complete suite of build tasks with the build `rake` task:
73
+
74
+ ```bash
75
+ bundle exec rake build
76
+ ```
77
+
78
+ This will:
79
+ 1. (Re)generate your schema artifacts
80
+ 2. Validate all registered queries against the latest schema
81
+ 3. Lint everything (use `bundle exec standardrb --fix` to fix most issues)
82
+ 4. Run tests (including the common shared ElasticGraph tests)
83
+
84
+ Note: on CI, you'll want to use `bundle exec rake check` instead of `bundle exec rake build`,
85
+ so that it verifies that schema artifacts are up-to-date (rather than dumping them).
86
+
87
+ ### Upgrading ElasticGraph
88
+
89
+ Upgrades to the ElasticGraph gems will come with [release notes](https://github.com/block/elasticgraph/releases/tag/v0.19.0.0) that include upgrade instructions, if necessary.
90
+
91
+ Here's the bare minimum upgrade process:
92
+
93
+ 1. Modify `elasticgraph_details` in the root `Gemfile` and run `bundle install`.
94
+ 2. Run `bundle exec rake`.
95
+ 3. Commit the results.
96
+
97
+ ### Managing <%= ElasticGraph.setup_env.datastore_name %>
98
+
99
+ The `<%= ElasticGraph.setup_env.datastore %>:` tasks will boot the desired <%= ElasticGraph.setup_env.datastore_name %> version using docker. You can
100
+ use either the `:boot` or `:daemon` tasks:
101
+
102
+ * The `:boot` task will keep <%= ElasticGraph.setup_env.datastore_name %> in the foreground, allowing you to see the logs.
103
+ * The `:daemon` task runs <%= ElasticGraph.setup_env.datastore_name %> as a background daemon task. Notably, it waits to return
104
+ until <%= ElasticGraph.setup_env.datastore_name %> is ready to receive traffic.
105
+
106
+ If you use a `:daemon` task, you can later use the corresponding `:halt` task to stop the daemon.
107
+
108
+ ### Using the GraphiQL interactive GraphQL query editor
109
+
110
+ When running `bundle exec rake boot_locally` the GraphiQL editor should open automatically
111
+ (`open http://localhost:9393/`). Using it you can query your ElasticGraph cluster using GraphQL.
112
+
113
+ ### Seeding Fake Data
114
+
115
+ The `bundle exec rake index_fake_data:<type_name>` tasks generate and index a batch of fake data.
116
+ You can pass an arg (note quotes) to seed more batches of data:
117
+ `bundle exec rake "index_fake_data:<type_name>[10]"`.
118
+
119
+ ### Using <%= ElasticGraph.setup_env.datastore_ui_name %>
120
+
121
+ After running `bundle exec rake boot_locally` and opening <%= ElasticGraph.setup_env.datastore_ui_name %>
122
+ `open http://localhost:19293/` click "Dev Tools" to open the <%= ElasticGraph.setup_env.datastore_name %> console.
123
+
124
+ Here are some queries to get you started:
125
+
126
+ ```
127
+ # Cluster info
128
+ GET /_cat/indices?v
129
+ GET /_cat/shards?v
130
+ GET /_cat/templates?v
131
+ GET /_cat/nodes?v
132
+ GET /_cat/allocation?v
133
+
134
+ # Or with a pattern
135
+ GET /_cat/shards/*_rollover__202*?v
136
+
137
+ # More cluster info
138
+ GET /_cluster/health
139
+ GET /_cluster/settings
140
+
141
+ # Test queries (change from `artists` to your index name)
142
+ GET /artists/_search
143
+ {
144
+ "from": 0,
145
+ "size": 1
146
+ }
147
+
148
+ GET /artists/_search
149
+ {
150
+ "from": 0,
151
+ "size": 1,
152
+ "query": {
153
+ "bool": {
154
+ "must": [
155
+ {
156
+ "match": {
157
+ "bio": "accordion"
158
+ }
159
+ }
160
+ ]
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ ### Query Registry
167
+
168
+ This project uses the ElasticGraph query registry extension. This is an optional piece you can choose to remove,
169
+ but provides many benefits--see the [elasticgraph-query_registry
170
+ README](https://github.com/block/elasticgraph/tree/main/elasticgraph-query_registry#elasticgraphqueryregistry)
171
+ for details.
172
+
173
+ With the registry in place, clients must register their queries in a directory under
174
+ [config/queries](config/queries) that matches their resolved application name.
175
+ The CI build will validate that all schema changes are compatible with all registered queries, and
176
+ your deployed GraphQL endpoints will reject any unregistered queries.
@@ -0,0 +1,64 @@
1
+ project_root = File.expand_path(__dir__)
2
+
3
+ require "elastic_graph/local/rake_tasks"
4
+ require "elastic_graph/query_registry/rake_tasks"
5
+ require "rspec/core/rake_task"
6
+ require "standard/rake"
7
+ require_relative "lib/<%= ElasticGraph.setup_env.app_name %>/fake_data_batch_generator"
8
+
9
+ settings_file = "#{project_root}/config/settings/local.yaml"
10
+
11
+ ElasticGraph::Local::RakeTasks.new(
12
+ local_config_yaml: settings_file,
13
+ path_to_schema: "#{project_root}/config/schema.rb"
14
+ ) do |tasks|
15
+ # Set this to true once you're beyond the prototyping stage.
16
+ tasks.enforce_json_schema_version = false
17
+
18
+ # Determines casing of field names. Can be either `:camelCase` or `:snake_case`.
19
+ tasks.schema_element_name_form = :camelCase
20
+
21
+ # Customizes the names of fields generated by ElasticGraph.
22
+ tasks.schema_element_name_overrides = {
23
+ # Example: force inequality operators to be spelled out.
24
+ # gt: "greaterThan",
25
+ # gte: "greaterThanOrEqualTo",
26
+ # lt: "lessThan",
27
+ # lte: "lessThanOrEqualTo"
28
+ }
29
+
30
+ # Customizes the naming format used by derived types.
31
+ tasks.derived_type_name_formats = {
32
+ # Example: change suffix used for filter inputs from `FilterInput` to just `Filter`.
33
+ # FilterInput: "%{base}Filter",
34
+ }
35
+
36
+ # Use this to override type names generated by ElasticGraph. We generally recommend sticking
37
+ # with the defaults, but to align with conventions in your organization you may need to override
38
+ # some type names.
39
+ tasks.type_name_overrides = {
40
+ # Example: this would make your ElasticGraph schema use `IDFilter` in place of the standard `IDFilterInput`.
41
+ # IDFilterInput: "IDFilter"
42
+ }
43
+
44
+ # TODO: replace this with a fake data generator for your own dataset.
45
+ tasks.define_fake_data_batch_for :artists do
46
+ <%= ElasticGraph.setup_env.app_module %>::FakeDataBatchGenerator.generate(artists: 100, venues: 10)
47
+ end
48
+ end
49
+
50
+ ElasticGraph::QueryRegistry::RakeTasks.from_yaml_file(
51
+ settings_file,
52
+ "config/queries",
53
+ require_eg_latency_slo_directive: false
54
+ )
55
+
56
+ ::RSpec::Core::RakeTask.new
57
+
58
+ standard_checks = ["standard", "query_registry:validate_queries", "spec"]
59
+
60
+ desc "Rebuild everything. Intended to be run locally as you iterate on the schema"
61
+ task build: ["schema_artifacts:dump", *standard_checks]
62
+
63
+ desc "Check everything. Intended to be run on CI to check your project."
64
+ task check: ["schema_artifacts:check", *standard_checks]
@@ -0,0 +1,24 @@
1
+ # TODO: remove or replace this query when you replace the artist schema.
2
+ query FindArtist {
3
+ byName: artists(filter: {
4
+ name: {equalToAnyOf: ["U2"]}
5
+ }) {
6
+ nodes {
7
+ name
8
+ bio {
9
+ yearFormed
10
+ }
11
+ }
12
+ }
13
+
14
+ byBioYearFounded: artists(filter: {
15
+ bio: {yearFormed: {gt: 2000}}
16
+ }) {
17
+ nodes {
18
+ name
19
+ bio {
20
+ yearFormed
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,16 @@
1
+ # TODO: remove or replace this query when you replace the artist schema.
2
+ query ListArtistAlbums {
3
+ artists {
4
+ nodes {
5
+ name
6
+ albums {
7
+ name
8
+ releasedOn
9
+
10
+ tracks {
11
+ name
12
+ }
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,65 @@
1
+ # TODO: replace this file with one that defines the schema for your own dataset.
2
+ ElasticGraph.define_schema do |schema|
3
+ schema.object_type "Artist" do |t|
4
+ t.field "id", "ID"
5
+ t.field "name", "String"
6
+ t.field "lifetimeSales", "JsonSafeLong"
7
+ t.field "bio", "ArtistBio"
8
+
9
+ t.field "albums", "[Album!]!" do |f|
10
+ f.mapping type: "nested"
11
+ end
12
+
13
+ t.field "tours", "[Tour!]!" do |f|
14
+ f.mapping type: "nested"
15
+ end
16
+
17
+ t.index "artists"
18
+ end
19
+
20
+ schema.object_type "ArtistBio" do |t|
21
+ t.field "yearFormed", "Int"
22
+ t.field "homeCountry", "String"
23
+ t.field "description", "String" do |f|
24
+ f.mapping type: "text"
25
+ end
26
+ end
27
+
28
+ schema.object_type "Album" do |t|
29
+ t.field "name", "String"
30
+ t.field "releasedOn", "Date"
31
+ t.field "soldUnits", "Int"
32
+ t.field "tracks", "[AlbumTrack!]!" do |f|
33
+ f.mapping type: "nested"
34
+ end
35
+ end
36
+
37
+ schema.object_type "AlbumTrack" do |t|
38
+ t.field "name", "String"
39
+ t.field "trackNumber", "Int"
40
+ t.field "lengthInSeconds", "Int"
41
+ end
42
+
43
+ schema.object_type "Tour" do |t|
44
+ t.field "name", "String"
45
+ t.field "shows", "[Show!]!" do |f|
46
+ f.mapping type: "nested"
47
+ end
48
+ end
49
+
50
+ schema.object_type "Show" do |t|
51
+ t.relates_to_one "venue", "Venue", via: "venueId", dir: :out
52
+ t.field "attendance", "Int"
53
+ t.field "startedAt", "DateTime"
54
+ end
55
+
56
+ schema.object_type "Venue" do |t|
57
+ t.field "id", "ID"
58
+ t.field "name", "String"
59
+ t.field "location", "GeoLocation"
60
+ t.field "capacity", "Int"
61
+ t.relates_to_many "featuredArtists", "Artist", via: "tours.shows.venueId", dir: :in, singular: "featuredArtist"
62
+
63
+ t.index "venues"
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ require "pathname"
2
+
3
+ ElasticGraph.define_schema do |schema|
4
+ # ElasticGraph will tell you when you need to bump this.
5
+ schema.json_schema_version 1
6
+
7
+ # This registers the elasticgraph-query_registry extension, which can be used to reject queries that
8
+ # clients have not registered (and to reject queries that differ from what a client has registered).
9
+ # In addition, every registered query is validated against the schema in the CI build, giving you
10
+ # confidence as you evolve your schema that you're not breaking client queries.
11
+ #
12
+ # If you don't want to use this extension, you can remove these lines.
13
+ require(query_registry_path = "elastic_graph/query_registry/graphql_extension")
14
+ schema.register_graphql_extension ElasticGraph::QueryRegistry::GraphQLExtension, defined_at: query_registry_path
15
+ end
16
+
17
+ # Load the rest of the schema from files at config/schema/**/*.rb.
18
+ Dir["#{__dir__}/schema/**/*.rb"].each do |schema_def_file|
19
+ # Must use `load`, not `require` so that if the schema is evaluated multiple times it works.
20
+ load Pathname(schema_def_file).expand_path
21
+ end
@@ -0,0 +1,36 @@
1
+ datastore:
2
+ client_faraday_adapter:
3
+ name: httpx
4
+ require: httpx/adapters/faraday
5
+ clusters:
6
+ main:
7
+ backend: <%= ElasticGraph.setup_env.datastore %>
8
+ url: http://localhost:9293
9
+ settings: {}
10
+ index_definitions:
11
+ # TODO: replace the `artists:` and `venues:` keys with the indices from your dataset
12
+ artists: &main_index_settings
13
+ # elasticgraph-local relies on the cluster being named "main".
14
+ query_cluster: "main"
15
+ index_into_clusters: ["main"]
16
+ ignore_routing_values: []
17
+ custom_timestamp_ranges: []
18
+ setting_overrides:
19
+ number_of_shards: 10
20
+ setting_overrides_by_timestamp: {}
21
+ venues: *main_index_settings
22
+ max_client_retries: 3
23
+ graphql:
24
+ default_page_size: 50
25
+ max_page_size: 500
26
+ logger:
27
+ device: stderr
28
+ indexer:
29
+ latency_slo_thresholds_by_timestamp_in_ms: {}
30
+ schema_artifacts:
31
+ directory: config/schema/artifacts
32
+ query_registry:
33
+ # Allow any query by any client since this is for local use.
34
+ allow_unregistered_clients: true
35
+ allow_any_query_for_clients: []
36
+ path_to_registry: config/queries
@@ -0,0 +1,107 @@
1
+ require "factory_bot"
2
+ require "faker"
3
+ require_relative "shared_factories"
4
+
5
+ # TODO: replace the artist/album/tour/venue factories with your own.
6
+ FactoryBot.define do
7
+ factory :artist, parent: :indexed_type_base do
8
+ __typename { "Artist" }
9
+ name { Faker::Music.band }
10
+
11
+ lifetimeSales do
12
+ albums.map { |a| a.fetch(:soldUnits) }.sum
13
+ end
14
+
15
+ bio { build(:artist_bio) }
16
+
17
+ albums do
18
+ Faker::Number.between(from: 1, to: 10).times.map { build(:album) }
19
+ end
20
+
21
+ tours do
22
+ Faker::Number.between(from: 0, to: 8).times.map { build(:tour, venueIds: venueIds) }
23
+ end
24
+
25
+ transient do
26
+ venueIds { [] }
27
+ end
28
+ end
29
+
30
+ factory :artist_bio, parent: :hash_base do
31
+ __typename { "ArtistBio" }
32
+ yearFormed { Faker::Number.between(from: 1900, to: 2025) }
33
+ homeCountry { Faker::Address.country }
34
+ description { Faker::Lorem.paragraphs(number: 3).join("\n\n") }
35
+ end
36
+
37
+ factory :album, parent: :hash_base do
38
+ __typename { "Album" }
39
+ name { Faker::Music.album }
40
+ releasedOn { Faker::Date.between(from: "1900-01-01", to: "2025-12-31").iso8601 }
41
+ soldUnits { Faker::Number.between(from: 10000, to: 100_000_000) }
42
+ tracks do
43
+ Faker::Number.between(from: 1, to: 20).times.map do |index|
44
+ build(:album_track, trackNumber: index + 1)
45
+ end
46
+ end
47
+ end
48
+
49
+ factory :album_track, parent: :hash_base do
50
+ __typename { "AlbumTrack" }
51
+ name { Faker::Music::RockBand.song }
52
+ trackNumber { Faker::Number.between(from: 1, to: 20) }
53
+ lengthInSeconds { Faker::Number.between(from: 30, to: 1200) }
54
+ end
55
+
56
+ factory :tour, parent: :hash_base do
57
+ __typename { "Tour" }
58
+ name { "#{Faker::Music::RockBand.song} Tour" }
59
+ shows do
60
+ start_date = Faker::Date.between(from: "1900-01-01", to: "2025-12-31")
61
+
62
+ Faker::Number.between(from: 3, to: 200).times.map do |index|
63
+ venue_id = Faker::Base.sample(venueIds)
64
+ build(:show, date: start_date + index, venueId: venue_id)
65
+ end
66
+ end
67
+
68
+ transient do
69
+ venueIds { [] }
70
+ end
71
+ end
72
+
73
+ factory :show, parent: :hash_base do
74
+ __typename { "Show" }
75
+ attendance { Faker::Number.between(from: 200, to: 100_000) }
76
+ startedAt { "#{date.iso8601}T#{startTime}" }
77
+ venueId { nil }
78
+
79
+ transient do
80
+ date { Faker::Date.between(from: "1900-01-01", to: "2025-12-31") }
81
+ startTime { Faker::Base.sample(%w[19:00:00Z 19:30:00Z 20:00:00Z 20:30:00Z]) }
82
+ end
83
+ end
84
+
85
+ factory :venue, parent: :indexed_type_base do
86
+ __typename { "Venue" }
87
+
88
+ name do
89
+ # Some common music venue types
90
+ venue_types = ["Theater", "Arena", "Music Hall", "Stadium", "Opera House", "Amphitheater"]
91
+
92
+ city_name = Faker::Address.city
93
+ venue_type = Faker::Base.sample(venue_types)
94
+
95
+ "#{city_name} #{venue_type}"
96
+ end
97
+
98
+ location { build(:geo_location) }
99
+ capacity { Faker::Number.between(from: 200, to: 100_000) }
100
+ end
101
+
102
+ factory :geo_location, parent: :hash_base do
103
+ __typename { "GeoLocation" }
104
+ latitude { Faker::Number.between(from: -90.0, to: 90.0) }
105
+ longitude { Faker::Number.between(from: -180.0, to: 180.0) }
106
+ end
107
+ end
@@ -0,0 +1,14 @@
1
+ require_relative "factories"
2
+
3
+ module <%= ElasticGraph.setup_env.app_module %>
4
+ module FakeDataBatchGenerator
5
+ def self.generate(artists:, venues:)
6
+ venue_list = FactoryBot.build_list(:venue, venues)
7
+ venue_ids = venue_list.map { |v| v.fetch(:id) }
8
+
9
+ artist_list = FactoryBot.build_list(:artist, artists, venueIds: venue_ids)
10
+
11
+ venue_list + artist_list
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ require "date"
2
+ require "factory_bot"
3
+ require "faker"
4
+
5
+ FactoryBot.define do
6
+ factory :hash_base, class: Hash do
7
+ initialize_with { attributes }
8
+ end
9
+
10
+ trait :uuid_id do
11
+ id { Faker::Internet.uuid }
12
+ end
13
+
14
+ trait :versioned do
15
+ __version { Faker::Number.between(from: 1, to: 10) }
16
+ end
17
+
18
+ current_json_schema_version = nil
19
+
20
+ factory :indexed_type_base, parent: :hash_base, traits: [:uuid_id, :versioned] do
21
+ __typename { raise NotImplementedError, "You must supply __typename" }
22
+ __json_schema_version do
23
+ current_json_schema_version ||= begin
24
+ json_schema_file = File.expand_path("../../config/schema/artifacts/json_schemas.yaml", __dir__)
25
+ YAML.safe_load_file(json_schema_file).fetch("json_schema_version")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ require "elastic_graph/local/spec_support/common_project_specs"
2
+ require "<%= ElasticGraph.setup_env.app_name %>/factories"
3
+ require "<%= ElasticGraph.setup_env.app_name %>/fake_data_batch_generator"
4
+
5
+ RSpec.describe "ElasticGraph project" do
6
+ ignored_factories = [
7
+ # List any factories to ignore
8
+ ]
9
+
10
+ include_examples "an ElasticGraph project",
11
+ use_settings_yaml: "local.yaml",
12
+ ignored_factories: ignored_factories
13
+
14
+ # TODO: update this spec as needed to generate example fake data for your dataset.
15
+ it "generates a batch of valid records from `FakeDataBatchGenerator`" do
16
+ batch = <%= ElasticGraph.setup_env.app_module %>::FakeDataBatchGenerator.generate(artists: 20, venues: 5)
17
+ expect(batch.size).to eq(25)
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticgraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0.0
4
+ version: 0.19.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Myron Marston
@@ -10,139 +10,71 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-12-10 00:00:00.000000000 Z
13
+ date: 2025-02-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: rubocop-factory_bot
17
- requirement: !ruby/object:Gem::Requirement
18
- requirements:
19
- - - "~>"
20
- - !ruby/object:Gem::Version
21
- version: '2.26'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- requirements:
26
- - - "~>"
27
- - !ruby/object:Gem::Version
28
- version: '2.26'
29
- - !ruby/object:Gem::Dependency
30
- name: rubocop-rake
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - "~>"
34
- - !ruby/object:Gem::Version
35
- version: '0.6'
36
- type: :development
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - "~>"
41
- - !ruby/object:Gem::Version
42
- version: '0.6'
43
- - !ruby/object:Gem::Dependency
44
- name: rubocop-rspec
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '3.1'
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - "~>"
55
- - !ruby/object:Gem::Version
56
- version: '3.1'
57
- - !ruby/object:Gem::Dependency
58
- name: standard
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - "~>"
62
- - !ruby/object:Gem::Version
63
- version: 1.41.0
64
- type: :development
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - "~>"
69
- - !ruby/object:Gem::Version
70
- version: 1.41.0
71
- - !ruby/object:Gem::Dependency
72
- name: elasticgraph-admin
73
- requirement: !ruby/object:Gem::Requirement
74
- requirements:
75
- - - '='
76
- - !ruby/object:Gem::Version
77
- version: 0.19.0.0
78
- type: :runtime
79
- prerelease: false
80
- version_requirements: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - '='
83
- - !ruby/object:Gem::Version
84
- version: 0.19.0.0
85
- - !ruby/object:Gem::Dependency
86
- name: elasticgraph-graphql
16
+ name: elasticgraph-support
87
17
  requirement: !ruby/object:Gem::Requirement
88
18
  requirements:
89
19
  - - '='
90
20
  - !ruby/object:Gem::Version
91
- version: 0.19.0.0
21
+ version: 0.19.1.0
92
22
  type: :runtime
93
23
  prerelease: false
94
24
  version_requirements: !ruby/object:Gem::Requirement
95
25
  requirements:
96
26
  - - '='
97
27
  - !ruby/object:Gem::Version
98
- version: 0.19.0.0
28
+ version: 0.19.1.0
99
29
  - !ruby/object:Gem::Dependency
100
- name: elasticgraph-indexer
30
+ name: thor
101
31
  requirement: !ruby/object:Gem::Requirement
102
32
  requirements:
103
- - - '='
104
- - !ruby/object:Gem::Version
105
- version: 0.19.0.0
106
- type: :runtime
107
- prerelease: false
108
- version_requirements: !ruby/object:Gem::Requirement
109
- requirements:
110
- - - '='
111
- - !ruby/object:Gem::Version
112
- version: 0.19.0.0
113
- - !ruby/object:Gem::Dependency
114
- name: elasticgraph-local
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - '='
33
+ - - "~>"
118
34
  - !ruby/object:Gem::Version
119
- version: 0.19.0.0
35
+ version: '1.3'
120
36
  type: :runtime
121
37
  prerelease: false
122
38
  version_requirements: !ruby/object:Gem::Requirement
123
39
  requirements:
124
- - - '='
40
+ - - "~>"
125
41
  - !ruby/object:Gem::Version
126
- version: 0.19.0.0
42
+ version: '1.3'
127
43
  description:
128
44
  email:
129
45
  - myron@squareup.com
130
- executables: []
46
+ executables:
47
+ - elasticgraph
131
48
  extensions: []
132
49
  extra_rdoc_files: []
133
50
  files:
134
51
  - LICENSE.txt
135
52
  - README.md
136
- - elasticgraph.gemspec
53
+ - exe/elasticgraph
54
+ - lib/elastic_graph/cli.rb
55
+ - lib/elastic_graph/project_template/.gitignore
56
+ - lib/elastic_graph/project_template/.standard.yml.tt
57
+ - lib/elastic_graph/project_template/Gemfile.tt
58
+ - lib/elastic_graph/project_template/README.md.tt
59
+ - lib/elastic_graph/project_template/Rakefile.tt
60
+ - lib/elastic_graph/project_template/config/queries/example_client/FindArtist.graphql
61
+ - lib/elastic_graph/project_template/config/queries/example_client/ListArtistAlbums.graphql
62
+ - lib/elastic_graph/project_template/config/schema.rb.tt
63
+ - lib/elastic_graph/project_template/config/schema/artists.rb.tt
64
+ - lib/elastic_graph/project_template/config/settings/local.yaml.tt
65
+ - lib/elastic_graph/project_template/lib/app_name/factories.rb
66
+ - lib/elastic_graph/project_template/lib/app_name/fake_data_batch_generator.rb.tt
67
+ - lib/elastic_graph/project_template/lib/app_name/shared_factories.rb
68
+ - lib/elastic_graph/project_template/spec/project_spec.rb.tt
137
69
  homepage: https://block.github.io/elasticgraph/
138
70
  licenses:
139
71
  - MIT
140
72
  metadata:
141
73
  bug_tracker_uri: https://github.com/block/elasticgraph/issues
142
- changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.0.0
74
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.1.0
143
75
  documentation_uri: https://block.github.io/elasticgraph/docs/main/
144
76
  homepage_uri: https://block.github.io/elasticgraph/
145
- source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.0.0/elasticgraph
77
+ source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.1.0/elasticgraph
146
78
  gem_category: core
147
79
  post_install_message:
148
80
  rdoc_options: []
@@ -150,9 +82,12 @@ require_paths:
150
82
  - lib
151
83
  required_ruby_version: !ruby/object:Gem::Requirement
152
84
  requirements:
153
- - - "~>"
85
+ - - ">="
154
86
  - !ruby/object:Gem::Version
155
87
  version: '3.2'
88
+ - - "<"
89
+ - !ruby/object:Gem::Version
90
+ version: '3.5'
156
91
  required_rubygems_version: !ruby/object:Gem::Requirement
157
92
  requirements:
158
93
  - - ">="
@@ -162,5 +97,5 @@ requirements: []
162
97
  rubygems_version: 3.5.22
163
98
  signing_key:
164
99
  specification_version: 4
165
- summary: ElasticGraph meta-gem that pulls in all the core ElasticGraph gems.
100
+ summary: Bootstraps ElasticGraph projects.
166
101
  test_files: []
data/elasticgraph.gemspec DELETED
@@ -1,18 +0,0 @@
1
- # Copyright 2024 Block, Inc.
2
- #
3
- # Use of this source code is governed by an MIT-style
4
- # license that can be found in the LICENSE file or at
5
- # https://opensource.org/licenses/MIT.
6
- #
7
- # frozen_string_literal: true
8
-
9
- require_relative "../gemspec_helper"
10
-
11
- ElasticGraphGemspecHelper.define_elasticgraph_gem(gemspec_file: __FILE__, category: :core) do |spec, eg_version|
12
- spec.summary = "ElasticGraph meta-gem that pulls in all the core ElasticGraph gems."
13
-
14
- spec.add_dependency "elasticgraph-admin", eg_version
15
- spec.add_dependency "elasticgraph-graphql", eg_version
16
- spec.add_dependency "elasticgraph-indexer", eg_version
17
- spec.add_dependency "elasticgraph-local", eg_version
18
- end