@jskit-ai/connectors-core 0.2.15 → 0.2.16

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - connector_authorization_attempts declares its foreign key, connection_key to connector_connections.connection_key (`foreignKeys`), so json-rest-api 3.1.0 can skip the visibility query a system-context read makes for a record such a key guarantees exists. `jskit test --databases` checks each against an app's test database. `knexConnectionStore.test.js` proves it matches the migration on the connector test database.
5
6
  - `@jskit-ai/database-runtime` and `@jskit-ai/resource-runtime` are optional peer dependencies, as they are of assistant-runtime, instead of dependencies: an app without a database installs, composes and starts the package without them, where installing them made boot refuse it for want of a database driver. An app that uses its knex connection store (`./server/storage`) has them through its database.
6
7
  - `createKnexConnectionStore` owns the connector tables through resource-runtime's `createStandaloneResources`, with the connection store's declared system scope, instead of building a resource runtime and host of its own.
7
8
  - `connectors.core` without a store requires `connectors.store` again, with a hint, so the kernel's startup error names the missing capability and says to register `createConnectionStoreFeature({ protection })` or pass `createConnectorsFeature({ store })`, instead of a check in its own setup.
package/README.md CHANGED
@@ -426,6 +426,14 @@ Import `createKnexConnectionStore` and `createCredentialProtection` from
426
426
  `@jskit-ai/connectors-core/server/storage`. Use the application's existing Knex
427
427
  client, with its selected JSKIT MySQL or PostgreSQL driver.
428
428
 
429
+ `./server/storage` imports `@jskit-ai/resource-runtime`, which this package
430
+ takes as an optional peer, so npm does not install it. An application using the
431
+ database-backed store declares `@jskit-ai/resource-runtime` and
432
+ `@jskit-ai/database-runtime` itself, at the catalog's versions, as a JSKIT
433
+ application on a database already does; without them, importing
434
+ `./server/storage` fails with `ERR_MODULE_NOT_FOUND`. An application on file
435
+ storage imports `./server/file-storage` and needs neither.
436
+
429
437
  ```js
430
438
  const protection = createCredentialProtection({
431
439
  keys: { current: decoded32ByteSecretKey },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/connectors-core",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "Portable integration configuration and server-side account connection runtime.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -15,7 +15,7 @@
15
15
  "./locales/en.json": "./locales/en.json"
16
16
  },
17
17
  "dependencies": {
18
- "@jskit-ai/resource-core": "0.1.205",
18
+ "@jskit-ai/resource-core": "0.1.206",
19
19
  "jose": "^6.1.3",
20
20
  "json-rest-schema": "^1.0.17",
21
21
  "oauth4webapi": "3.8.8",
@@ -56,10 +56,10 @@
56
56
  }
57
57
  },
58
58
  "peerDependencies": {
59
- "@jskit-ai/database-runtime": "0.1.263",
60
- "@jskit-ai/http-runtime": "0.2.14",
61
- "@jskit-ai/kernel": "0.2.14",
62
- "@jskit-ai/resource-runtime": "0.2.12"
59
+ "@jskit-ai/database-runtime": "0.1.264",
60
+ "@jskit-ai/http-runtime": "0.2.15",
61
+ "@jskit-ai/kernel": "0.2.15",
62
+ "@jskit-ai/resource-runtime": "0.2.13"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
65
  "@jskit-ai/database-runtime": {
@@ -26,6 +26,7 @@ const connectorAuthorizationAttemptResource = defineTableResource({
26
26
  name: "connectorAuthorizationAttempts",
27
27
  tableName: "connector_authorization_attempts",
28
28
  ownership: "public",
29
+ foreignKeys: [{ columns: ["connectionKey"], referencedTableName: "connector_connections", referencedColumns: ["connection_key"] }],
29
30
  idProperty: "attempt_key",
30
31
  sortableFields: ["expiresAt"],
31
32
  schema: {
@@ -10,6 +10,8 @@ import { fileURLToPath } from "node:url";
10
10
  import test from "node:test";
11
11
  import createKnex from "knex";
12
12
  import migration from "../migrations/connectors_core_initial.cjs";
13
+ import { checkForeignKeys } from "@jskit-ai/resource-runtime/server";
14
+ import { CONNECTOR_TABLES } from "../src/server/connectorResources.js";
13
15
  import { createCredentialProtection, createKnexConnectionStore } from "../src/server/storage.js";
14
16
 
15
17
  test("credential protection binds ciphertext to its record and supports key rotation", async () => {
@@ -42,6 +44,12 @@ test("durable connector storage on an isolated SQL database", { skip: !databaseU
42
44
  const connection = { tokens: { accessToken: "private-access", refreshToken: "private-refresh" }, version: 0 };
43
45
  await migration.up(knex);
44
46
  try {
47
+ await t.test("the table resources declare exactly the foreign keys the migration creates", async () => {
48
+ const resources = CONNECTOR_TABLES.map(({ resource }) => resource);
49
+ const tables = resources.map((resource) => resource.tableName);
50
+ assert.deepEqual(await checkForeignKeys({ knex, resources, tables }), { missing: [], undeclared: [] });
51
+ });
52
+
45
53
  await t.test("persists encrypted records and reopens them through another database pool", async () => {
46
54
  await store.withConnection(scope, async ({ save }) => save(connection));
47
55
  const rows = await knex("connector_connections").select();