wefunder 0.1.0.beta3 → 0.1.0.beta4

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: a3ac10a62a698ee6cb163f3ec6e100248d461dc6c55bf97caeb1bac349b44af6
4
- data.tar.gz: 26d0e08433a88d288942da627f8d509ffa196e6e2ed3cc347bae43beadaf84bf
3
+ metadata.gz: 5debc49eda9f51f36042922d2fa820f891d2c847e20f83409d7e61fa1ff2e95a
4
+ data.tar.gz: d8f9889dc16fb317efd3900b5dafc881807e60a4822b4dcab8a7ded46a2f4d39
5
5
  SHA512:
6
- metadata.gz: 4ee97ef8052e3e7a9476a8b0243b52a706bfd2c6a5911e1b9362c07e5d5d6290529615ed6daace3d953769d126a492440692ebef5191cd7846c418a70f6a54b5
7
- data.tar.gz: 535800baceafa25b8fcb744d2a1fc16a0596e14d80db5fba6f0c83772ee371c16a361335f82819b5a5e664bf016d17b008d3ff46a3f07f527eab491d8aa36bdd
6
+ metadata.gz: 9b7c81d6afb161eacc9a727aaa4bcca3720a6b6bc77e3c8efc332ac594e5e35581680d4ad847c6dd6fb3df5d7382eb2149fcff0f072e0b75d189b96281cee6bc
7
+ data.tar.gz: 85613d6d2be67d40039f2a9a953682ee180d45811076f4e477629f9a2effce804274e1726c4bbf098b1d8d59ef7fc4fbf5a9fab358a1d656c23088265ea1ff87
data/README.md CHANGED
@@ -103,8 +103,12 @@ portfolio = wf.portfolio.get
103
103
  ```
104
104
 
105
105
  Namespaces: `users`, `offerings`, `investments`, `portfolio`, `campaigns`, `syndicates`, `intents`,
106
- `attribution`, and `webhook_endpoints`. Query parameters are keyword arguments; enum-typed ones take
107
- plain strings, and `Time` / `DateTime` / `Date` values are sent as ISO 8601.
106
+ `attribution`, `installations`, and `webhook_endpoints`. Query parameters are keyword arguments;
107
+ enum-typed ones take plain strings, and `Time` / `DateTime` / `Date` values are sent as ISO 8601.
108
+
109
+ `wf.installations` lets your app act as a company or syndicate: `eligible_targets`, `create`,
110
+ `mint_token`, `list`, `get`, `revoke`, and `install_or_mint_token`, which handles the API's 409
111
+ `already_installed` answer by minting a token for the existing install with the same scopes.
108
112
 
109
113
  `wf.investments` is the Investment Delta API. `list` without a cursor bootstraps; pass `updated_since:`
110
114
  or the `meta.next_cursor` you saved from your last page to receive only records that changed since then.
@@ -26,7 +26,7 @@ module Wefunder
26
26
  # typed-error unwrapping, and lazy auto-pagination. +raw+ exposes every generated API.
27
27
  class Client
28
28
  attr_reader :mode, :users, :offerings, :investments, :portfolio, :campaigns, :syndicates, :intents,
29
- :attribution, :webhook_endpoints
29
+ :attribution, :installations, :webhook_endpoints
30
30
 
31
31
  def initialize(access_token: nil, tokens: nil, client_id: nil, client_secret: nil, client_credentials: nil,
32
32
  api_version: DEFAULT_API_VERSION, base_url: DEFAULT_API_BASE_URL, authorize_base_url: nil,
@@ -53,6 +53,7 @@ module Wefunder
53
53
  @syndicates = Syndicates.new(self)
54
54
  @intents = Intents.new(self)
55
55
  @attribution = Attribution.new(self)
56
+ @installations = Installations.new(self)
56
57
  @webhook_endpoints = WebhookEndpoints.new(self)
57
58
  end
58
59
 
@@ -275,6 +276,58 @@ module Wefunder
275
276
  def me = data_of(wrap { raw.attribution_partners.get_attribution_me })
276
277
  end
277
278
 
279
+ # /installations (read:installations / write:installations; write does not imply read). An
280
+ # install lets your app act AS a company or syndicate: +create+ and +mint_token+ return the
281
+ # envelope whose +token.access_token+ is a company-owned token (shown once, no expiry, no
282
+ # refresh) — build a second client with it. Installing is also what makes a company or
283
+ # syndicate an audience for your webhooks.
284
+ class Installations < Namespace
285
+ # Companies / syndicates the token's user may install your app on (empty for an investor).
286
+ def eligible_targets(target_type: nil)
287
+ opts = target_type ? { target_type: target_type } : {}
288
+ data_of(wrap { raw.installations.list_eligible_install_targets(opts) }) || []
289
+ end
290
+
291
+ # Every install of your app; the envelope (+meta.count+).
292
+ def list = wrap { raw.installations.list_installations }
293
+ def get(installation_id) = data_of(wrap { raw.installations.get_installation(installation_id) })
294
+
295
+ # Install on a target (+target_type:+, +target_id:+, optional +scopes:+ / +tier:+). Returns the
296
+ # envelope: +data+ is the install, +token.access_token+ the one-time token. If the app is
297
+ # already installed there the API answers 409 +already_installed+ with
298
+ # +details["installation"]+ = the existing id; see +install_or_mint_token+.
299
+ def create(**attrs)
300
+ attrs = attrs.transform_keys(&:to_sym)
301
+ wrap { raw.installations.create_installation(WefunderGenerated::CreateInstallationRequest.new(attrs)) }
302
+ end
303
+
304
+ # A fresh company-owned token for an existing install. +scopes+ narrows within the install's
305
+ # ceiling; omit for the ceiling. An explicit +[]+ grants nothing, so only nil omits the body.
306
+ def mint_token(installation_id, scopes = nil)
307
+ opts = {}
308
+ opts[:create_installation_token_request] = WefunderGenerated::CreateInstallationTokenRequest.new(scopes: scopes) if scopes
309
+ wrap { raw.installations.create_installation_token(installation_id, opts) }
310
+ end
311
+
312
+ # +create+, falling back to +mint_token+ for the existing install on 409 +already_installed+.
313
+ # The mint re-requests +scopes+ so a retry never widens the grant. Any other error (revoked
314
+ # install, missing scope) still raises.
315
+ def install_or_mint_token(**attrs)
316
+ # Normalize once so the fallback re-requests exactly what create sent — string-keyed
317
+ # attrs (e.g. from JSON.parse) must not turn a restricted or empty grant into the ceiling.
318
+ attrs = attrs.transform_keys(&:to_sym)
319
+ create(**attrs)
320
+ rescue Wefunder::Error => e
321
+ existing_id = e.details["installation"] if e.type == "already_installed" && e.details.is_a?(Hash)
322
+ raise unless existing_id.is_a?(String) && !existing_id.empty?
323
+
324
+ mint_token(existing_id, attrs[:scopes])
325
+ end
326
+
327
+ # Revoke an install: its tokens stop working at once. Returns the install, now +revoked+.
328
+ def revoke(installation_id) = data_of(wrap { raw.installations.revoke_installation(installation_id) })
329
+ end
330
+
278
331
  # Endpoints belong to your application and are managed through the LIVE API
279
332
  # (write:webhooks). The signing secret is returned only on create and rotate.
280
333
  class WebhookEndpoints < Namespace
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wefunder
4
- VERSION = "0.1.0.beta3"
4
+ VERSION = "0.1.0.beta4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wefunder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.beta3
4
+ version: 0.1.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wefunder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-02 00:00:00.000000000 Z
11
+ date: 2026-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday