Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,14 @@
const endpoint = getApiEndpoint();
const hasPaymentError = $derived(invoiceList?.invoices.some((invoice) => invoice?.lastError));
/**
* Special case handling for the first page!
*
* As per Damodar - `there is some logic to **hide current cycle invoice** in the endpoint`.
*
* Due to this, the first page always loads `limit - 1` invoices which is inconsistent!
* Therefore, we load `limit + 1` to counter that so the returned invoices are consistent.
*/
onMount(() => request(true));
onMount(loadInvoices);
async function request(patchQuery: boolean = false) {
async function loadInvoices() {
isLoadingInvoices = true;
invoiceList = await sdk.forConsole.billing.listInvoices(page.params.organization, [
Query.orderDesc('$createdAt'),
// first page extra must have an extra limit!
Query.limit(patchQuery ? limit + 1 : limit),
// so an invoice isn't repeated on 2nd page!
Query.offset(patchQuery ? offset : offset + 1)
Query.limit(limit),
Query.offset(offset + 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need offset + 1 right?

]);
Comment on lines +45 to 51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Appwrite Console SDK billing listInvoices offset parameter semantics

💡 Result:

Short answer: offset is the number of records to skip (not a 1-based page number). Pass offset = how many items to skip (e.g. 0 for start, limit for second page, limit*2 for third page). See Appwrite pagination docs. [1][2][3]

Sources:

  • Appwrite pagination docs (offset = number of rows/documents to skip). [1]
  • Community example + explanation showing offset used as skip (and an alternate description where some SDK examples treat it as page index by incrementing offset by 1 when limit is fixed). [2]
  • Appwrite Console SDK repo (SDK surface for Console). [3]

🌐 Web query:

Appwrite Query.offset definition documentation

💡 Result:

Query.offset — skips a number of records before returning results (used with Query.limit for offset-style pagination). Example: Query.offset(25) skips the first 25 records. Use Query.offset when you want page-based pagination (but prefer cursor pagination for frequently changing or large datasets). [1][2]

Sources:

  • Appwrite Pagination docs. [1]
  • Appwrite Queries reference. [2]

🌐 Web query:

@appwrite.io/pink-svelte PaginationInline offset behavior

💡 Result:

Short answer: PaginationInline's offset is a page index (integer pages, 0-based) used to compute the record skip as offset * limit — so to get items starting at record R you set offset = floor(R / limit). See Appwrite docs on offset pagination (offset = number of pages to skip / integer page index) and Pink design docs for the Pink pagination components. [1][2]

Sources:

  • Appwrite pagination (offset explanation). [1]
  • Pink Design (Appwrite Pink design system / components). [2]

🏁 Script executed:

# Check the codebase for related files and usage patterns
fd -e svelte -e ts -e js | grep -i "pagination\|invoice" | head -20

Repository: appwrite/console

Length of output: 971


🏁 Script executed:

# Look for package.json to check installed versions
cat package.json | grep -A 5 -B 5 "@appwrite"

Repository: appwrite/console

Length of output: 923


🏁 Script executed:

cat -n src/routes/\(console\)/organization-\[organization\]/billing/paymentHistory.svelte | sed -n '40,60p'

Repository: appwrite/console

Length of output: 823


🏁 Script executed:

# Also check what the limit variable is and how offset is being passed
cat -n src/routes/\(console\)/organization-\[organization\]/billing/paymentHistory.svelte | sed -n '1,100p' | grep -E "(limit|offset|let )"

Repository: appwrite/console

Length of output: 312


🏁 Script executed:

# Let me check the PaginationInline component to understand what offset value it provides
cat -n src/lib/components/paginationInline.svelte | head -150

Repository: appwrite/console

Length of output: 3287


🏁 Script executed:

# Also check how the offset is being used in the on:change handler
cat -n src/routes/\(console\)/organization-\[organization\]/billing/paymentHistory.svelte | sed -n '180,195p'

Repository: appwrite/console

Length of output: 838


Remove the + 1 from Query.offset() — it causes the first invoice to be skipped and misaligns all subsequent pages.

PaginationInline already computes offset as the actual record skip count (0, 5, 10, etc.). Calling Query.offset(offset + 1) skips one extra record on every page. Use Query.offset(offset) instead.

Additionally, wrap the listInvoices call in a try/finally to reset isLoadingInvoices on error:

Suggested fix
async function loadInvoices() {
    isLoadingInvoices = true;
    try {
        invoiceList = await sdk.forConsole.billing.listInvoices(page.params.organization, [
            Query.orderDesc('$createdAt'),
            Query.limit(limit),
            Query.offset(offset)
        ]);
    } finally {
        isLoadingInvoices = false;
    }
}
🤖 Prompt for AI Agents
In
`@src/routes/`(console)/organization-[organization]/billing/paymentHistory.svelte
around lines 45 - 51, In loadInvoices(), remove the extra "+ 1" so
Query.offset(offset) is used (the +1 causes the first invoice to be skipped and
misaligns pagination), and wrap the sdk.forConsole.billing.listInvoices(...)
call in a try/finally that sets isLoadingInvoices = false in the finally block
so isLoadingInvoices is always reset on error; update references to invoiceList
and Query.orderDesc/Query.limit as needed inside the same try block.

isLoadingInvoices = false;
Expand All @@ -73,7 +61,7 @@
$effect(() => {
if (page.url.searchParams.get('type') === 'validate-invoice') {
window.history.replaceState({}, '', page.url.pathname);
request();
loadInvoices();
}
});
Expand Down Expand Up @@ -197,7 +185,7 @@
hidePages
bind:offset
total={invoiceList.total}
on:change={() => request()} />
on:change={loadInvoices} />
</Layout.Stack>
{/if}
{:else}
Expand Down
Loading