Skip to content
Merged
Show file tree
Hide file tree
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
39 changes: 39 additions & 0 deletions .github/workflows/full-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,45 @@ jobs:
if-no-files-found: ignore
retention-days: 7

js-sdk-live:
name: JS SDK query examples (live server)
needs: gate
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo
uses: useblacksmith/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target/release
key: ${{ runner.os }}-cargo-js-live-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-js-live-

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'

- name: Run the JS SDK guide's query examples against a live server
run: make js-test-live

- name: Upload server log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: inputlayer-js-live-server-log
path: /tmp/il_js_live_server.log
if-no-files-found: ignore
retention-days: 7

# Lint and unit-test the performance gate tool only: measuring needs a
# quiet same-host runner, not a shared one (perf-gate/README.md).
perf-gate-tool:
Expand Down
30 changes: 29 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all ci fmt fmt-check lint pre-pr pre-pr-snapshots pre-pr-js pre-pr-selftest perf-gate perf-gate-check secret-check install-gitleaks install-hooks uninstall-hooks hooks-test bench-genbi test test-fast test-release unit-test integration-test oracle-test e2e-test e2e-reactive e2e-update test-affected doc doc-check check build build-release clean fix release snapshot-test test-all ci-test-all flush-dev docker docker-run docker-deploy docker-deploy-no-tls docker-logs docker-stop k8s-check deny python-test python-test-live python-test-examples vc-gate js-test front-build front-deploy gui-build run run-server demo coverage view-coverage static-analysis
.PHONY: all ci fmt fmt-check lint pre-pr pre-pr-snapshots pre-pr-js pre-pr-selftest perf-gate perf-gate-check secret-check install-gitleaks install-hooks uninstall-hooks hooks-test bench-genbi test test-fast test-release unit-test integration-test oracle-test e2e-test e2e-reactive e2e-update test-affected doc doc-check check build build-release clean fix release snapshot-test test-all ci-test-all flush-dev docker docker-run docker-deploy docker-deploy-no-tls docker-logs docker-stop k8s-check deny python-test python-test-live python-test-examples vc-gate js-test js-test-live front-build front-deploy gui-build run run-server demo coverage view-coverage static-analysis

SHELL := /bin/bash

Expand Down Expand Up @@ -428,6 +428,34 @@ vc-gate:
js-test:
cd packages/inputlayer-js && npm ci --ignore-scripts && npm test

# js-test-live runs every query example in the JS SDK guide
# (docs/content/docs/guides/js-sdk.mdx) against a live server, so a query
# form the engine rejects fails here rather than in a user's hands.
JS_LIVE_PORT ?= 8091
js-test-live:
@cargo build --release --bin inputlayer-server
@cd packages/inputlayer-js && npm ci --ignore-scripts
@DATA_DIR=$$(mktemp -d -t il-js-live-XXXXXX); \
INPUTLAYER_ADMIN_PASSWORD=admin ./target/release/inputlayer-server \
--host 127.0.0.1 --data-dir $$DATA_DIR --port $(JS_LIVE_PORT) \
> /tmp/il_js_live_server.log 2>&1 & \
SERVER_PID=$$!; \
for i in $$(seq 1 40); do \
if curl -sf http://127.0.0.1:$(JS_LIVE_PORT)/health > /dev/null 2>&1; then break; fi; \
sleep 0.5; \
done; \
cd packages/inputlayer-js && \
INPUTLAYER_TEST_SERVER=ws://127.0.0.1:$(JS_LIVE_PORT)/ws \
INPUTLAYER_TEST_USER=admin \
INPUTLAYER_TEST_PASSWORD=admin \
npx vitest run tests/docs-queries.integration.test.ts; \
TEST_EXIT=$$?; \
cd - > /dev/null; \
kill $$SERVER_PID 2>/dev/null || true; \
wait $$SERVER_PID 2>/dev/null || true; \
rm -rf $$DATA_DIR; \
exit $$TEST_EXIT

# Coverage & Static Analysis

# Generate test coverage report (requires cargo-tarpaulin)
Expand Down
30 changes: 18 additions & 12 deletions docs/content/docs/guides/js-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ const result = await kg.query({
});
```

For more specialized aggregation, `topK` lets you find the top entries per group:
Each aggregate gets its own result column, named after the function and the column: `CountId`, `AvgSalary` and `MaxSalary` above.

For more specialized aggregation, `topK` lets you find the top entries per group. The selected columns are the groups; the columns to keep from each top entry go in `passthrough`:

```typescript
import { topK } from "inputlayer";
Expand All @@ -326,12 +328,16 @@ import { topK } from "inputlayer";
const result = await kg.query({
select: [
Employee.col("department").toAst(),
Employee.col("name").toAst(),
Employee.col("salary").toAst(),
topK({ k: 3, orderBy: Employee.col("salary"), desc: true }),
topK({
k: 3,
passthrough: [Employee.col("name")],
orderBy: Employee.col("salary"),
desc: true,
}),
],
join: [Employee],
});
// Columns: Department, Name, Salary
```

### Working with Results
Expand Down Expand Up @@ -627,18 +633,18 @@ Int8 variants: `fn.cosineInt8`, `fn.euclideanInt8`, `fn.manhattanInt8`, `fn.dotI
For working with timestamp columns:

```typescript
import { Timestamp } from "inputlayer";
import { relation } from "inputlayer";
import * as fn from "inputlayer/functions";

// Timestamps are Unix milliseconds.
const Reading = relation("Reading", { sensorId: "int", value: "float", timestamp: "int" });
const Article = relation("Article", { title: "string", publishedAt: "int" });

// Rows from the last hour
const result = await kg.query({
select: [SensorReading],
join: [SensorReading],
where: fn.withinLast(
SensorReading.col("timestamp"),
fn.timeNow(),
3600000,
),
select: [Reading],
join: [Reading],
where: Reading.col("timestamp").gt(fn.timeSub(fn.timeNow(), 3600000)),
});

// Time-decayed scoring
Expand Down
4 changes: 2 additions & 2 deletions packages/inputlayer-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"scripts": {
"build": "tsup src/index.ts src/functions.ts --format cjs,esm --dts --clean",
"dev": "tsup src/index.ts src/functions.ts --format cjs,esm --dts --watch",
"test": "vitest run --exclude tests/integration.test.ts",
"test:integration": "vitest run tests/integration.test.ts",
"test": "vitest run --exclude 'tests/*integration.test.ts'",
"test:integration": "vitest run integration.test.ts",
"test:all": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
Expand Down
Loading
Loading