diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 525c94f..621fd4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' diff --git a/.gitignore b/.gitignore index eb81fc6..f395f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log .venv temp/ regress/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3d2ac0b..10f3091 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0" + ".": "0.2.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 2b39be6..75ad795 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-5a8ac7b545c48dc892e5c680303e305254921554dabee848e40a808659dbcf1e.yml -openapi_spec_hash: 0103975601aac1445d3a4ef418c5d17a -config_hash: ca148af6be59ec54295b2c5f852a38d1 +configured_endpoints: 24 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-8b89ffbfeb39b4186328fefd81f7dab1d28c786012201feb8035c7f920c4fbae.yml +openapi_spec_hash: de40e013fcc83fa44d5c51ddecb543c0 +config_hash: 08b781db5f1857ed601d1b2f4b6b45d9 diff --git a/CHANGELOG.md b/CHANGELOG.md index f7634d8..08e828d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,43 @@ # Changelog +## 0.2.0 (2026-05-04) + +Full Changelog: [v0.1.0...v0.2.0](https://github.com/beeper/desktop-api-sql/compare/v0.1.0...v0.2.0) + +### Features + +* **api:** add network, bridge fields to accounts ([41e2829](https://github.com/beeper/desktop-api-sql/commit/41e28294a7fcad3839ea2d3c5c3b48061774776f)) +* **api:** api update ([673f0a1](https://github.com/beeper/desktop-api-sql/commit/673f0a1de2c331b41c8093c7bf7edcd908b3bcb0)) +* support setting headers via env ([d1ebc75](https://github.com/beeper/desktop-api-sql/commit/d1ebc75c6cdaf3421824fc57f4ec85cba613c944)) + + +### Chores + +* **internal:** codegen related update ([836fc21](https://github.com/beeper/desktop-api-sql/commit/836fc2121e4d8bdc5116b39acac969c20a4af775)) +* **internal:** codegen related update ([91994fa](https://github.com/beeper/desktop-api-sql/commit/91994fa8b9e406c674d5245f2da123608e87046b)) +* **internal:** support env vars in `./scripts/repl` ([9183ad1](https://github.com/beeper/desktop-api-sql/commit/9183ad1d77206204a8650471616d1f97b817f024)) +* **internal:** tweak CI branches ([2db5518](https://github.com/beeper/desktop-api-sql/commit/2db5518d6ac525ccd1d753e271f6adcde42398bf)) +* **internal:** update gitignore ([998e1de](https://github.com/beeper/desktop-api-sql/commit/998e1de2a033f9cb44326e681eadc5cbd25d862b)) +* **internal:** update multipart form array serialization ([0af81d8](https://github.com/beeper/desktop-api-sql/commit/0af81d8b40c42ae06bac4d2ee9d9bcf5fb887641)) +* **tests:** bump steady to v0.19.4 ([fe76f5e](https://github.com/beeper/desktop-api-sql/commit/fe76f5e4d60950521215581557cd0453720d7a71)) +* **tests:** bump steady to v0.19.5 ([71cbd2c](https://github.com/beeper/desktop-api-sql/commit/71cbd2c8566c6c466557c8ee7209f6710687cf1a)) +* **tests:** bump steady to v0.19.6 ([827b6a2](https://github.com/beeper/desktop-api-sql/commit/827b6a2c9d2f7db42f469a86f207318e1441a46a)) +* **tests:** bump steady to v0.19.7 ([be70621](https://github.com/beeper/desktop-api-sql/commit/be70621335ade7130eedb59982ff75f36c3ce75a)) +* **tests:** bump steady to v0.20.1 ([1c13343](https://github.com/beeper/desktop-api-sql/commit/1c1334345f7df0ab235018431f6f64026db45332)) +* **tests:** bump steady to v0.20.2 ([60ca024](https://github.com/beeper/desktop-api-sql/commit/60ca0242076c462be6e9da54a39b1138a56b9732)) +* **tests:** bump steady to v0.22.1 ([ad561c9](https://github.com/beeper/desktop-api-sql/commit/ad561c97cdcae8a56ac67bd285e4a4c74f34ac09)) +* update SDK settings ([71dc986](https://github.com/beeper/desktop-api-sql/commit/71dc9866112525943eb11a430cf2505236cc3f46)) + + +### Documentation + +* explain caching ([d84f8a5](https://github.com/beeper/desktop-api-sql/commit/d84f8a50545721a86b7ea48a8af34bd588961c54)) + + +### Refactors + +* **tests:** switch from prism to steady ([ca3c264](https://github.com/beeper/desktop-api-sql/commit/ca3c264cee5d12947269f7fc6f919eb8db071c9b)) + ## 0.1.0 (2026-03-13) Full Changelog: [v0.0.1...v0.1.0](https://github.com/beeper/desktop-api-sql/compare/v0.0.1...v0.1.0) diff --git a/META.json b/META.json index ba92e1b..9311557 100644 --- a/META.json +++ b/META.json @@ -10,7 +10,6 @@ "version": "0.0.1", "release_status": "testing", "maintainer": "Beeper Desktop ", - "generated_by": "Stainless (https://stainless.com)", "license": "mit", "resources": { "homepage": "https://developers.beeper.com/desktop-api/", diff --git a/README.md b/README.md index 0544b3f..d072a4a 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ The Beeper Desktop API PostgreSQL Extension provides convenient access to the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/) from PostgreSQL. -It is generated with [Stainless](https://www.stainless.com/). - The REST API documentation can be found on [developers.beeper.com](https://developers.beeper.com/desktop-api/). ## Installation @@ -70,29 +68,29 @@ FROM beeper_desktop_api_chats.search( Configure the client by setting configuration parameters at the database level: ```sql -ALTER DATABASE my_database SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +ALTER DATABASE my_database SET beeper_desktop_api.access_token = 'My Access Token'; ``` > [!NOTE] > > `ALTER DATABASE` persistently alters the database, but doesn't take effect until the next session. To -> ephemerally modify the current session, use `SET beeper_desktop_api.beeper_access_token TO 'My Access Token';`. +> ephemerally modify the current session, use `SET beeper_desktop_api.access_token TO 'My Access Token';`. See this table for the available configuration parameters: -| Parameter | Required | Default value | -| ---------------------------------------- | -------- | -------------------------- | -| `beeper_desktop_api.beeper_access_token` | true | - | -| `beeper_desktop_api.base_url` | false | `'http://localhost:23373'` | +| Parameter | Required | Default value | +| --------------------------------- | -------- | -------------------------- | +| `beeper_desktop_api.access_token` | true | - | +| `beeper_desktop_api.base_url` | false | `'http://localhost:23373'` | ## Requests and responses To send a request to the Beeper Desktop API, call the relevant SQL function with values corresponding to the parameter types and `SELECT` the columns you need from the returned rows. -To construct [composite type](https://www.postgresql.org/docs/current/rowtypes.html) parameters, use the parameter type's provided `make_*` function. For example, `beeper_desktop_api_chats.create_params_user` may be constructed like so: +To construct [composite type](https://www.postgresql.org/docs/current/rowtypes.html) parameters, use the parameter type's provided `make_*` function. For example, `beeper_desktop_api_chats.start_params_user` may be constructed like so: ```sql -beeper_desktop_api_chats.make_create_params_user( +beeper_desktop_api_chats.make_start_params_user( id := 'id', email := 'email', fullName := 'fullName', @@ -123,6 +121,27 @@ LIMIT 200; > removed, then PostgreSQL may not [push down the condition](https://wiki.postgresql.org/wiki/Inlining_of_SQL_functions), > causing all pages to be requested and buffered. +## Caching + +Sending requests to the Beeper Desktop API for every SQL query can be slow. Combine [materialized views](https://www.postgresql.org/docs/current/rules-materializedviews.html) with [`pg_cron`](https://github.com/citusdata/pg_cron) for scheduled data pulls: + +```sql +CREATE MATERIALIZED VIEW beeper_desktop_api_messages AS +SELECT * +FROM beeper_desktop_api_messages.search( + account_ids := ARRAY['local-telegram_ba_QFrb5lrLPhO3OT5MFBeTWv0x4BI'], + "limit" := 10, + query := 'deployment' +); + +-- Refresh the view every 4 hours. +SELECT cron.schedule( + 'refresh-beeper-desktop-api-messages', + '0 */4 * * *', + 'REFRESH MATERIALIZED VIEW CONCURRENTLY beeper_desktop_api_messages' +); +``` + ## Troubleshooting ### Installation diff --git a/scripts/mock b/scripts/mock index bcf3b39..9c7c439 100755 --- a/scripts/mock +++ b/scripts/mock @@ -19,34 +19,34 @@ fi echo "==> Starting mock server with URL ${URL}" -# Run prism mock on the given spec +# Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stdy/cli@0.22.1 -- steady --version - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & - # Wait for server to come online (max 30s) + # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" attempts=0 - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do + if ! kill -0 $! 2>/dev/null; then + echo + cat .stdy.log + exit 1 + fi attempts=$((attempts + 1)) if [ "$attempts" -ge 300 ]; then echo - echo "Timed out waiting for Prism server to start" - cat .prism.log + echo "Timed out waiting for Steady server to start" + cat .stdy.log exit 1 fi echo -n "." sleep 0.1 done - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - echo else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/repl b/scripts/repl index 21d1eab..30588b5 100755 --- a/scripts/repl +++ b/scripts/repl @@ -1,5 +1,10 @@ #!/usr/bin/env bash +if [ -z "$BEEPER_ACCESS_TOKEN" ]; then + echo 'ERROR: BEEPER_ACCESS_TOKEN environment variable is required but not set' + exit 1 +fi + echo "==> Detecting PostgreSQL Python executable" PYTHON_EXECUTABLE_PATH=$(pg_config --configure | grep -o "PYTHON=[^ ]*" | cut -d= -f2 | tr -d "'") echo "PostgreSQL uses Python $PYTHON_EXECUTABLE_PATH" @@ -29,8 +34,8 @@ if [ "$PG_MAJOR_VERSION" -ge 18 ]; then done POSTGRES_CONFIG=(-c extension_control_path="$(realpath temp/install/share/postgresql)") else - # In PostgreSQL <18 we cannot point `postgres` to our local extensions directory. So we install directly to - # the system. + # In PostgreSQL <18 we cannot point `postgres` to our local extensions directory. So we install + # directly to the system. sudo make install PG_CONFIG="$(command -v pg_config)" fi @@ -61,10 +66,15 @@ done echo "==> Running setup.sql" psql -d postgres -f test/sql/create_extension.sql +psql -d postgres --variable "value='$BEEPER_ACCESS_TOKEN'" -c 'ALTER DATABASE postgres SET beeper_desktop_api.access_token = :value;' +if [ -n "$BEEPER_BASE_URL" ]; then + psql -d postgres --variable "value='$BEEPER_BASE_URL'" -c 'ALTER DATABASE postgres SET beeper_desktop_api.base_url = :value;' +fi + if command -v pgcli &>/dev/null; then echo "==> Starting pgcli REPL" pgcli postgres else echo "==> Starting psql REPL (TIP: Install pgcli for better autocomplete!)" psql -d postgres -fi +fi \ No newline at end of file diff --git a/scripts/test b/scripts/test index 8b23b9c..dc681e7 100755 --- a/scripts/test +++ b/scripts/test @@ -9,8 +9,8 @@ GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 +function steady_is_running() { + curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1 } kill_server_on_port() { @@ -25,7 +25,7 @@ function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } -if ! is_overriding_api_base_url && ! prism_is_running ; then +if ! is_overriding_api_base_url && ! steady_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT @@ -36,19 +36,19 @@ fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" +elif ! steady_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" + echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" echo fi diff --git a/sql/_beeper_desktop_api.sql b/sql/_beeper_desktop_api.sql index 1e703eb..adcbe27 100644 --- a/sql/_beeper_desktop_api.sql +++ b/sql/_beeper_desktop_api.sql @@ -72,12 +72,12 @@ AS $$ # This configuration parameter was not set, but it's optional so ignore the exception. pass try: - value = plpy.execute("SELECT current_setting('beeper_desktop_api.beeper_access_token') AS value")[0]['value'] + value = plpy.execute("SELECT current_setting('beeper_desktop_api.access_token') AS value")[0]['value'] client_options["access_token"] = value except Exception: plpy.warning( - "Required DB config parameter 'beeper_desktop_api.beeper_access_token' is not set", - hint="ALTER DATABASE my_database SET beeper_desktop_api.beeper_access_token = ...;" + "Required DB config parameter 'beeper_desktop_api.access_token' is not set", + hint="ALTER DATABASE my_database SET beeper_desktop_api.access_token = ...;" ) def strip_none(value): @@ -122,6 +122,7 @@ CREATE TYPE beeper_desktop_api.client_search_response_result_message AS (); CREATE SCHEMA IF NOT EXISTS beeper_desktop_api_accounts; CREATE TYPE beeper_desktop_api_accounts.account AS (); +CREATE TYPE beeper_desktop_api_accounts.account_bridge AS (); CREATE SCHEMA IF NOT EXISTS beeper_desktop_api_accounts_contacts; @@ -134,7 +135,8 @@ CREATE TYPE beeper_desktop_api_chats.chat_participant AS (); CREATE TYPE beeper_desktop_api_chats.chat_create_response AS (); CREATE TYPE beeper_desktop_api_chats.chat_list_response AS (); CREATE TYPE beeper_desktop_api_chats.chat_list_response_participant AS (); -CREATE TYPE beeper_desktop_api_chats.create_params_user AS (); +CREATE TYPE beeper_desktop_api_chats.chat_start_response AS (); +CREATE TYPE beeper_desktop_api_chats.start_params_user AS (); CREATE SCHEMA IF NOT EXISTS beeper_desktop_api_chats_reminders; diff --git a/sql/beeper_desktop_api_accounts.sql b/sql/beeper_desktop_api_accounts.sql index 34100ee..5dc05ec 100644 --- a/sql/beeper_desktop_api_accounts.sql +++ b/sql/beeper_desktop_api_accounts.sql @@ -1,14 +1,35 @@ ALTER TYPE beeper_desktop_api_accounts.account - ADD ATTRIBUTE accountID TEXT, ADD ATTRIBUTE "user" beeper_desktop_api.user; + ADD ATTRIBUTE accountID TEXT, + ADD ATTRIBUTE bridge beeper_desktop_api_accounts.account_bridge, + ADD ATTRIBUTE "user" beeper_desktop_api.user, + ADD ATTRIBUTE network TEXT; CREATE OR REPLACE FUNCTION beeper_desktop_api_accounts.make_account( - accountID TEXT, "user" beeper_desktop_api.user + accountID TEXT, + bridge beeper_desktop_api_accounts.account_bridge, + "user" beeper_desktop_api.user, + network TEXT DEFAULT NULL ) RETURNS beeper_desktop_api_accounts.account LANGUAGE SQL IMMUTABLE AS $$ - SELECT ROW(accountID, "user")::beeper_desktop_api_accounts.account; + SELECT ROW( + accountID, bridge, "user", network + )::beeper_desktop_api_accounts.account; +$$; + +ALTER TYPE beeper_desktop_api_accounts.account_bridge + ADD ATTRIBUTE id TEXT, ADD ATTRIBUTE provider TEXT, ADD ATTRIBUTE type TEXT; + +CREATE OR REPLACE FUNCTION beeper_desktop_api_accounts.make_account_bridge( + id TEXT, provider TEXT, type TEXT +) +RETURNS beeper_desktop_api_accounts.account_bridge +LANGUAGE SQL +IMMUTABLE +AS $$ + SELECT ROW(id, provider, type)::beeper_desktop_api_accounts.account_bridge; $$; CREATE OR REPLACE FUNCTION beeper_desktop_api_accounts._list() diff --git a/sql/beeper_desktop_api_assets.sql b/sql/beeper_desktop_api_assets.sql index 3e5ed45..8ed4508 100644 --- a/sql/beeper_desktop_api_assets.sql +++ b/sql/beeper_desktop_api_assets.sql @@ -117,23 +117,30 @@ AS $$ $$; CREATE OR REPLACE FUNCTION beeper_desktop_api_assets._serve(url TEXT) -RETURNS VOID +RETURNS JSONB LANGUAGE plpython3u STABLE AS $$ - GD["__beeper_desktop_api_context__"].client.assets.serve( + response = GD["__beeper_desktop_api_context__"].client.assets.with_raw_response.serve( url=url, ) + + # We don't parse the JSON and let PL/Python perform data mapping because PL/Python errors for omitted + # fields instead of defaulting them to NULL, but we want to be more lenient, which we handle in the + # caller later. + return response.text() $$; CREATE OR REPLACE FUNCTION beeper_desktop_api_assets.serve(url TEXT) -RETURNS VOID +RETURNS BYTEA LANGUAGE plpgsql STABLE AS $$ BEGIN PERFORM beeper_desktop_api_internal.ensure_context(); - PERFORM beeper_desktop_api_assets._serve(url); + RETURN jsonb_populate_record( + NULL::BYTEA, beeper_desktop_api_assets._serve(url) + ); END; $$; diff --git a/sql/beeper_desktop_api_chats.sql b/sql/beeper_desktop_api_chats.sql index f7e06b8..71cd535 100644 --- a/sql/beeper_desktop_api_chats.sql +++ b/sql/beeper_desktop_api_chats.sql @@ -142,38 +142,48 @@ AS $$ )::beeper_desktop_api_chats.chat_list_response_participant; $$; -ALTER TYPE beeper_desktop_api_chats.create_params_user +ALTER TYPE beeper_desktop_api_chats.chat_start_response + ADD ATTRIBUTE chatID TEXT, ADD ATTRIBUTE status TEXT; + +CREATE OR REPLACE FUNCTION beeper_desktop_api_chats.make_chat_start_response( + chatID TEXT, status TEXT DEFAULT NULL +) +RETURNS beeper_desktop_api_chats.chat_start_response +LANGUAGE SQL +IMMUTABLE +AS $$ + SELECT ROW(chatID, status)::beeper_desktop_api_chats.chat_start_response; +$$; + +ALTER TYPE beeper_desktop_api_chats.start_params_user ADD ATTRIBUTE id TEXT, ADD ATTRIBUTE email TEXT, ADD ATTRIBUTE fullName TEXT, ADD ATTRIBUTE phoneNumber TEXT, ADD ATTRIBUTE username TEXT; -CREATE OR REPLACE FUNCTION beeper_desktop_api_chats.make_create_params_user( +CREATE OR REPLACE FUNCTION beeper_desktop_api_chats.make_start_params_user( id TEXT DEFAULT NULL, email TEXT DEFAULT NULL, fullName TEXT DEFAULT NULL, phoneNumber TEXT DEFAULT NULL, username TEXT DEFAULT NULL ) -RETURNS beeper_desktop_api_chats.create_params_user +RETURNS beeper_desktop_api_chats.start_params_user LANGUAGE SQL IMMUTABLE AS $$ SELECT ROW( id, email, fullName, phoneNumber, username - )::beeper_desktop_api_chats.create_params_user; + )::beeper_desktop_api_chats.start_params_user; $$; CREATE OR REPLACE FUNCTION beeper_desktop_api_chats._create( account_id TEXT, - allow_invite BOOLEAN DEFAULT NULL, + participant_ids TEXT[], + type TEXT, message_text TEXT DEFAULT NULL, - mode TEXT DEFAULT NULL, - participant_ids TEXT[] DEFAULT NULL, - title TEXT DEFAULT NULL, - type TEXT DEFAULT NULL, - "user" beeper_desktop_api_chats.create_params_user DEFAULT NULL + title TEXT DEFAULT NULL ) RETURNS JSONB LANGUAGE plpython3u @@ -182,13 +192,10 @@ AS $$ response = GD["__beeper_desktop_api_context__"].client.chats.with_raw_response.create( account_id=account_id, - allow_invite=not_given if allow_invite is None else allow_invite, + participant_ids=participant_ids, + type=type, message_text=not_given if message_text is None else message_text, - mode=not_given if mode is None else mode, - participant_ids=not_given if participant_ids is None else participant_ids, title=not_given if title is None else title, - type=not_given if type is None else type, - user=not_given if user is None else GD["__beeper_desktop_api_context__"].strip_none(user), ) # We don't parse the JSON and let PL/Python perform data mapping because PL/Python errors for omitted @@ -199,13 +206,10 @@ $$; CREATE OR REPLACE FUNCTION beeper_desktop_api_chats.create( account_id TEXT, - allow_invite BOOLEAN DEFAULT NULL, + participant_ids TEXT[], + type TEXT, message_text TEXT DEFAULT NULL, - mode TEXT DEFAULT NULL, - participant_ids TEXT[] DEFAULT NULL, - title TEXT DEFAULT NULL, - type TEXT DEFAULT NULL, - "user" beeper_desktop_api_chats.create_params_user DEFAULT NULL + title TEXT DEFAULT NULL ) RETURNS beeper_desktop_api_chats.chat_create_response LANGUAGE plpgsql @@ -215,14 +219,7 @@ AS $$ RETURN jsonb_populate_record( NULL::beeper_desktop_api_chats.chat_create_response, beeper_desktop_api_chats._create( - account_id, - allow_invite, - message_text, - mode, - participant_ids, - title, - type, - "user" + account_id, participant_ids, type, message_text, title ) ); END; @@ -578,4 +575,48 @@ AS $$ WHERE paginated.next_request_options IS NOT NULL ) SELECT (jsonb_populate_recordset(NULL::beeper_desktop_api_chats.chat, data)).* FROM paginated; +$$; + +CREATE OR REPLACE FUNCTION beeper_desktop_api_chats._start( + account_id TEXT, + "user" beeper_desktop_api_chats.start_params_user, + allow_invite BOOLEAN DEFAULT NULL, + message_text TEXT DEFAULT NULL +) +RETURNS JSONB +LANGUAGE plpython3u +AS $$ + from beeper_desktop_api._types import not_given + + response = GD["__beeper_desktop_api_context__"].client.chats.with_raw_response.start( + account_id=account_id, + user=GD["__beeper_desktop_api_context__"].strip_none(user), + allow_invite=not_given if allow_invite is None else allow_invite, + message_text=not_given if message_text is None else message_text, + ) + + # We don't parse the JSON and let PL/Python perform data mapping because PL/Python errors for omitted + # fields instead of defaulting them to NULL, but we want to be more lenient, which we handle in the + # caller later. + return response.text() +$$; + +CREATE OR REPLACE FUNCTION beeper_desktop_api_chats.start( + account_id TEXT, + "user" beeper_desktop_api_chats.start_params_user, + allow_invite BOOLEAN DEFAULT NULL, + message_text TEXT DEFAULT NULL +) +RETURNS beeper_desktop_api_chats.chat_start_response +LANGUAGE plpgsql +AS $$ + BEGIN + PERFORM beeper_desktop_api_internal.ensure_context(); + RETURN jsonb_populate_record( + NULL::beeper_desktop_api_chats.chat_start_response, + beeper_desktop_api_chats._start( + account_id, "user", allow_invite, message_text + ) + ); + END; $$; \ No newline at end of file diff --git a/sql/beeper_desktop_api_messages.sql b/sql/beeper_desktop_api_messages.sql index 2eae195..36741e6 100644 --- a/sql/beeper_desktop_api_messages.sql +++ b/sql/beeper_desktop_api_messages.sql @@ -161,14 +161,14 @@ STABLE AS $$ import json from beeper_desktop_api.types.shared import Message - from beeper_desktop_api.pagination import SyncCursorSortKey + from beeper_desktop_api.pagination import SyncCursorNoLimit from beeper_desktop_api._models import FinalRequestOptions from pydantic import TypeAdapter from typing import Any page = GD["__beeper_desktop_api_context__"].client._request_api_list( model=Message, - page=SyncCursorSortKey[Message], + page=SyncCursorNoLimit[Message], options=FinalRequestOptions.construct(**json.loads(request_options)) ) next_page_info = page.next_page_info() diff --git a/test/sql/beeper_desktop_api_accounts_contacts_test.sql b/test/sql/beeper_desktop_api_accounts_contacts_test.sql index 3a34024..dc90446 100644 --- a/test/sql/beeper_desktop_api_accounts_contacts_test.sql +++ b/test/sql/beeper_desktop_api_accounts_contacts_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_accounts_contacts.list(account_id := 'accountID') diff --git a/test/sql/beeper_desktop_api_accounts_test.sql b/test/sql/beeper_desktop_api_accounts_test.sql index bee634f..8d462e6 100644 --- a/test/sql/beeper_desktop_api_accounts_test.sql +++ b/test/sql/beeper_desktop_api_accounts_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_accounts.list(); \ No newline at end of file diff --git a/test/sql/beeper_desktop_api_assets_test.sql b/test/sql/beeper_desktop_api_assets_test.sql index b246c23..8d16905 100644 --- a/test/sql/beeper_desktop_api_assets_test.sql +++ b/test/sql/beeper_desktop_api_assets_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_assets.download( diff --git a/test/sql/beeper_desktop_api_chats_messages_reactions_test.sql b/test/sql/beeper_desktop_api_chats_messages_reactions_test.sql index d3f8bee..ce1b811 100644 --- a/test/sql/beeper_desktop_api_chats_messages_reactions_test.sql +++ b/test/sql/beeper_desktop_api_chats_messages_reactions_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_chats_messages_reactions.delete( diff --git a/test/sql/beeper_desktop_api_chats_reminders_test.sql b/test/sql/beeper_desktop_api_chats_reminders_test.sql index db5873b..8a93e16 100644 --- a/test/sql/beeper_desktop_api_chats_reminders_test.sql +++ b/test/sql/beeper_desktop_api_chats_reminders_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_chats_reminders.create( diff --git a/test/sql/beeper_desktop_api_chats_test.sql b/test/sql/beeper_desktop_api_chats_test.sql index c46c02e..cfcfe53 100644 --- a/test/sql/beeper_desktop_api_chats_test.sql +++ b/test/sql/beeper_desktop_api_chats_test.sql @@ -1,8 +1,12 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * -FROM beeper_desktop_api_chats.create(account_id := 'accountID'); +FROM beeper_desktop_api_chats.create( + account_id := 'accountID', + participant_ids := ARRAY['string'], + type := 'single' +); SELECT * FROM beeper_desktop_api_chats.retrieve( @@ -20,4 +24,16 @@ FROM beeper_desktop_api_chats.archive( SELECT * FROM beeper_desktop_api_chats.search() -LIMIT 42; \ No newline at end of file +LIMIT 42; + +SELECT * +FROM beeper_desktop_api_chats.start( + account_id := 'accountID', + "user" := beeper_desktop_api_chats.make_start_params_user( + id := 'id', + email := 'email', + fullName := 'fullName', + phoneNumber := 'phoneNumber', + username := 'username' + ) +); \ No newline at end of file diff --git a/test/sql/beeper_desktop_api_info_test.sql b/test/sql/beeper_desktop_api_info_test.sql index 5598e10..e37887f 100644 --- a/test/sql/beeper_desktop_api_info_test.sql +++ b/test/sql/beeper_desktop_api_info_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_info.retrieve(); \ No newline at end of file diff --git a/test/sql/beeper_desktop_api_messages_test.sql b/test/sql/beeper_desktop_api_messages_test.sql index 0872843..a574bd7 100644 --- a/test/sql/beeper_desktop_api_messages_test.sql +++ b/test/sql/beeper_desktop_api_messages_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api_messages.update( diff --git a/test/sql/beeper_desktop_api_test.sql b/test/sql/beeper_desktop_api_test.sql index ddb5b54..05b90fb 100644 --- a/test/sql/beeper_desktop_api_test.sql +++ b/test/sql/beeper_desktop_api_test.sql @@ -1,5 +1,5 @@ SET datestyle = 'ISO'; -SET beeper_desktop_api.beeper_access_token = 'My Access Token'; +SET beeper_desktop_api.access_token = 'My Access Token'; SELECT * FROM beeper_desktop_api.focus(); diff --git a/uv.lock b/uv.lock index 3e068d8..99ade34 100644 --- a/uv.lock +++ b/uv.lock @@ -103,7 +103,7 @@ wheels = [ [[package]] name = "beeper_desktop_api" -version = "0.0.1" +version = "4.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" },