Repository navigation
feat: close the Graphle data-layer parity gaps - #38
Conversation
A sync takes an optional typed filter (states, labels, order field and direction) that narrows and orders what each scope lists on the source's side, and a cursor is valid only under the filter it was issued for. scopes.roots and scopes.children list the scopes a picker offers as typed entries (scope, label, description, URL, archived flag), paged, resumable and abortable like sync, with an unknown parent reported as a gap. A pager supplies them through an optional scopes member; one without it answers NOT_IMPLEMENTED, so existing pagers keep compiling. The fake honours both, and the conformance kit gains filter cases and optional scope listing cases.
An adapter that replays recorded responses has to record the filtered requests the kit makes, so the filter is exported as conformanceFilter.
…s and scope listings Each issue's blocking connection is read beside blockedBy, so work blocked in a repository outside the requested scopes is found from its blocker; both ends give the same transition id, so a dependency read twice is one transition. A sync's filter becomes GitHub's issue listing arguments (states, labels and IssueOrder) and is carried in the cursor. github:owner/projects/number syncs the issues on an organisation's or user's board through the same paging, rate-limit and gap handling, passing over pull requests and draft issues; a filter with a board scope is invalid-scope, since a board cannot be filtered. The pager lists scopes: the viewer's own account and organisations, and an owner's repositories with description, URL and archived flag. The token port takes an undefined owner for the viewer's own listing. The fixture is re-recorded from public repositories and a public board in GitHub's own organisation; the viewer's listing is tested over written responses and live, never recorded.
graphSourceListingConformance takes its own client, so an adapter can exercise the listing at a page size that makes the parent span two pages while syncing at its default.
… page size The demonstration organisation's repositories fit one page at the default size, so the live listing runs on a client at the fixture page size, as the recording does.
storedTokenPort is a token port over tokens a host keeps, each scoped to some owners or to any, ported from Graphle's resolution: a token naming the owner wins, the most specific first and then the most recently used; otherwise the most recently used token for any owner, which is also the only kind a request about the viewer can use. Logins match without regard to case, and no fitting token is unauthorised without naming a token. A browser host gets the same per-owner choice the environment helper gives Node.
The test spread the shared options with an undefined page size, which exactOptionalPropertyTypes refuses; it now builds its own listing and asserts the whole page.
…d-of hierarchy items.upsert takes an optional relations list, the child-of, assigned-to and part-of relations a source already returns, which the store used to drop. Each distinct relation is stored once in first-stored order; an end that names nothing the merged model declares in the space its kind requires is an unknown-reference issue and the write is refused. Saving a model keeps only the relations of what it still declares, and deleting it removes them. relations.list reads them back, and query.children, query.descendants and query.ancestors walk child-of relations, nearest first in model order, ending on a cycle. All are new v1 procedures, so existing clients are unchanged; the fake implements them through the exported reference functions and the conformance kit covers them.
…s in SQL A relations table keyed by model, kind and both ends holds what items.upsert sends, with a position for first-stored order and an index on the parent end for the downward walk; the primary key serves the upward one. The drizzle-kit migration that adds it is committed beside the initial one. Writes rewrite a model's relations with its other rows in the same transaction after the contract's relationIssues check. query.descendants and query.ancestors are WITH RECURSIVE walks over child-of rows, capped at the model's element count like the dependency walks, and query.children a plain query; all answer as the contract's reference functions do, which the conformance kit checks.
…ilter on the fake The message-port run exercises graphSourceListingConformance on its own and a fake test syncs under conformanceFilter, so both exports are used where they are defined.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex security review |
1 similar comment
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
🎉 This PR is included in version 1.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Closes the data-layer gaps between Graphle and process-graph in the source contract, the GitHub adapter and the store.
The source contract's
v1gains a typed syncfilter(states, labels, order field and direction), carried in every cursor, andscopes.rootsandscopes.children, which list the scopes a picker offers as typed entries with paging, resumption, gaps and aborts. Both are additive: a pager withoutscopesstill compiles and its listing answersNOT_IMPLEMENTED. The fake implements both and the conformance kit covers them;graphSourceListingConformanceruns the listing part on its own client.The GitHub adapter reads
blockingbesideblockedBy(one transition per dependency whichever end it is read from), maps the filter to GitHub's issue listing arguments, syncs a Projects v2 board asgithub:owner/projects/numberthrough the same paging, rate-limit and gap handling, and lists the viewer's account and organisations and an owner's repositories. The token port takes an undefined owner for the viewer's own listing, andstoredTokenPortports Graphle's per-owner choice among stored tokens for a browser host. The fixture is re-recorded from public repositories and a public board in GitHub's own organisation; the viewer's listing is tested over written responses and live, never recorded.The store contract keeps the
child-of,assigned-toandpart-ofrelations a sync already returns:items.upserttakes an optionalrelationslist, checked against the model, and newv1proceduresrelations.list,query.children,query.descendantsandquery.ancestorsread them back and walk the hierarchy. The SQLite store persists them in a newrelationstable (committed drizzle-kit migration) and answers the walks withWITH RECURSIVE; the fake and conformance kit cover both.Graphle never loaded labels as data on an issue (only as a listing filter) and never linked pull requests to issues, so neither is added here.
Closes #40. The board scope is
github:owner/projects/number; turning a pasted board URL into it is the one-linereadScopeInputchange in graph-web.