@sockethub/schemas 3.0.0-alpha.12 → 3.0.0-alpha.14

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.
Files changed (46) hide show
  1. package/dist/activity-stream-helper.d.ts +5 -0
  2. package/dist/activity-stream-helper.js +36 -0
  3. package/dist/activity-stream-helper.js.map +10 -0
  4. package/dist/context.d.ts +56 -0
  5. package/dist/context.js +20 -41
  6. package/dist/context.js.map +3 -3
  7. package/dist/helpers/error-parser.d.ts +13 -0
  8. package/dist/helpers/objects.d.ts +122 -0
  9. package/dist/index.d.ts +9 -0
  10. package/dist/index.js +235 -218
  11. package/dist/index.js.map +12 -12
  12. package/dist/maps/context-map.json +2 -2
  13. package/dist/object-types.d.ts +2 -0
  14. package/dist/object-types.js +296 -0
  15. package/dist/object-types.js.map +12 -0
  16. package/dist/schemas/activity-stream.d.ts +161 -0
  17. package/dist/schemas/platform/feeds/v1/messages.schema.json +8 -17
  18. package/dist/schemas/platform/irc/v1/credentials.schema.json +71 -1
  19. package/dist/schemas/platform/irc/v1/messages.schema.json +84 -0
  20. package/dist/schemas/platform/metadata/v1/messages.schema.json +1 -16
  21. package/dist/schemas/platform/xmpp/v1/credentials.schema.json +2 -2
  22. package/dist/schemas/platform/xmpp/v1/messages.schema.json +108 -0
  23. package/dist/schemas/platform.d.ts +62 -0
  24. package/dist/schemas/sockethub-config.d.ts +316 -0
  25. package/{src/types.ts → dist/types.d.ts} +17 -45
  26. package/dist/validator.d.ts +26 -0
  27. package/package.json +13 -8
  28. package/src/context.ts +0 -125
  29. package/src/helpers/error-parser.ts +0 -160
  30. package/src/helpers/objects.ts +0 -283
  31. package/src/index.test.data.credentials.ts +0 -103
  32. package/src/index.test.data.objects.ts +0 -241
  33. package/src/index.test.data.platform.ts +0 -48
  34. package/src/index.test.data.streams.ts +0 -590
  35. package/src/index.test.ts +0 -127
  36. package/src/index.ts +0 -56
  37. package/src/schemas/activity-object.ts +0 -19
  38. package/src/schemas/activity-stream.ts +0 -75
  39. package/src/schemas/json/activity-object.json +0 -405
  40. package/src/schemas/json/activity-stream.json +0 -502
  41. package/src/schemas/json/platform.json +0 -48
  42. package/src/schemas/json/sockethub-config.json +0 -236
  43. package/src/schemas/platform.ts +0 -71
  44. package/src/schemas/sockethub-config.ts +0 -220
  45. package/src/types/ajv-formats-draft2019.d.ts +0 -5
  46. package/src/validator.ts +0 -207
@@ -6,74 +6,51 @@ export interface ASCollection {
6
6
  totalItems: number;
7
7
  items: Array<ActivityStream>;
8
8
  }
9
-
10
9
  export type JsonLdContext = Array<string>;
11
-
12
10
  export interface ActivityStream {
13
11
  "@context": JsonLdContext;
14
12
  id?: string;
15
13
  type: string;
16
- platform?: string;
17
14
  actor: ActivityActor;
18
15
  object?: ActivityObject;
19
16
  target?: ActivityActor;
20
17
  error?: string;
21
18
  }
22
-
23
19
  export interface InternalActivityStream extends ActivityStream {
24
20
  sessionSecret?: string;
25
21
  }
26
-
27
22
  export interface BaseActivityObject {
28
23
  id?: string;
29
24
  type: string;
30
25
  }
31
-
32
26
  export interface ActivityActor extends BaseActivityObject {
33
27
  id: string;
34
28
  type: string;
35
29
  name?: string;
36
30
  [key: string]: unknown;
37
31
  }
38
-
39
32
  export interface ActivityObject extends BaseActivityObject {
40
33
  content?: string;
41
34
  [key: string]: unknown;
42
35
  }
43
-
44
36
  type ErrorMsg = string | Error;
45
-
46
- export type PlatformCallback = (
47
- err?: ErrorMsg,
48
- data?: ActivityStream | ASCollection,
49
- ) => void;
50
-
37
+ export type PlatformCallback = (err?: ErrorMsg, data?: ActivityStream | ASCollection) => void;
51
38
  export type CallbackInterface = (err?: ErrorMsg, data?: unknown) => void;
52
-
53
39
  export type MiddlewareCallback = (data: ActivityStream | Error) => void;
54
-
55
40
  export type CompletedJobHandler = (data: ActivityStream | undefined) => void;
56
-
57
- export type PlatformSendToClient = (
58
- msg: ActivityStream,
59
- special?: string,
60
- ) => void;
61
-
41
+ export type PlatformSendToClient = (msg: ActivityStream, special?: string) => void;
62
42
  export type PlatformUpdateActor = (credentials: object) => Promise<void>;
63
-
64
43
  export interface Logger {
65
44
  error(message: string, meta?: object): void;
66
45
  warn(message: string, meta?: object): void;
67
46
  info(message: string, meta?: object): void;
68
47
  debug(message: string, meta?: object): void;
69
48
  }
70
-
71
49
  export interface PlatformSession {
72
50
  log: Logger;
73
51
  sendToClient: PlatformSendToClient;
74
52
  updateActor: PlatformUpdateActor;
75
53
  }
76
-
77
54
  export interface CredentialsObject {
78
55
  "@context": JsonLdContext;
79
56
  type: "credentials";
@@ -84,7 +61,6 @@ export interface CredentialsObject {
84
61
  };
85
62
  target?: ActivityActor;
86
63
  }
87
-
88
64
  /**
89
65
  * Platform configuration discriminated union.
90
66
  *
@@ -103,17 +79,23 @@ export interface CredentialsObject {
103
79
  * - Example: IRC, XMPP
104
80
  */
105
81
  export type PlatformConfig = StatelessPlatformConfig | PersistentPlatformConfig;
106
-
107
82
  interface BasePlatformConfig {
108
83
  connectTimeoutMs?: number;
84
+ allowPrivateAddresses?: boolean;
109
85
  }
110
-
111
86
  /** Configuration for stateless platforms that start/stop per-request */
112
87
  export interface StatelessPlatformConfig extends BasePlatformConfig {
113
88
  persist: false;
114
89
  requireCredentials?: string[];
90
+ /**
91
+ * Number of jobs the platform's worker processes in parallel. Stateless
92
+ * platforms are shared by every session on the server, so serial
93
+ * processing lets one slow job (e.g. a hanging feed fetch) stall all
94
+ * other clients. Defaults to 10; override per-platform via
95
+ * `packageConfig`.
96
+ */
97
+ concurrency?: number;
115
98
  }
116
-
117
99
  /**
118
100
  * Configuration for persistent platforms with long-running connections.
119
101
  * These always require credentials because persistent state is actor-specific.
@@ -123,7 +105,6 @@ export interface PersistentPlatformConfig extends BasePlatformConfig {
123
105
  /** Message types requiring credentials (must be non-empty for persistent platforms) */
124
106
  requireCredentials: string[];
125
107
  }
126
-
127
108
  export interface PlatformSchemaStruct {
128
109
  name: string;
129
110
  version: string;
@@ -140,12 +121,13 @@ export interface PlatformSchemaStruct {
140
121
  };
141
122
  };
142
123
  };
124
+ responses?: object;
143
125
  }
144
-
145
126
  export interface PlatformConstructor {
146
- new (session: PlatformSession): { log: Logger };
127
+ new (session: PlatformSession): {
128
+ log: Logger;
129
+ };
147
130
  }
148
-
149
131
  /**
150
132
  * Base interface for all Sockethub platforms.
151
133
  * Platforms implement protocol-specific logic for ActivityStreams messages.
@@ -167,7 +149,6 @@ export interface PlatformInterface {
167
149
  isInitialized(): boolean;
168
150
  cleanup(cb: PlatformCallback): void;
169
151
  }
170
-
171
152
  /**
172
153
  * Interface for persistent platforms with long-running connections.
173
154
  *
@@ -185,15 +166,6 @@ export interface PersistentPlatformInterface extends PlatformInterface {
185
166
  */
186
167
  credentialsHash: string | undefined;
187
168
  get config(): PersistentPlatformConfig;
188
- connect(
189
- job: ActivityStream,
190
- credentials: CredentialsObject,
191
- done: PlatformCallback,
192
- ): void;
193
- }
194
-
195
- export interface PlatformSession {
196
- log: Logger;
197
- sendToClient: PlatformSendToClient;
198
- updateActor: PlatformUpdateActor;
169
+ connect(job: ActivityStream, credentials: CredentialsObject, done: PlatformCallback): void;
199
170
  }
171
+ export {};
@@ -0,0 +1,26 @@
1
+ import { type Schema } from "ajv";
2
+ import { type ValidationErrorOptions } from "./helpers/error-parser.js";
3
+ import type { ActivityStream } from "./types.js";
4
+ export declare function registerSystemPlatformContexts(): void;
5
+ export declare function setValidationErrorOptions(options: ValidationErrorOptions): void;
6
+ /**
7
+ * Validate a (fully-materialized) Sockethub server config object against the
8
+ * canonical config schema. Returns "" when valid, otherwise a human-readable
9
+ * error string. Used by the server at startup so a mis-typed or unknown config
10
+ * value — including inside a platform's `packageConfig` entry — fails loudly
11
+ * rather than reaching a platform wrong-typed.
12
+ */
13
+ export declare function validateSockethubConfig(config: unknown): string;
14
+ export declare function validateActivityStream(msg: ActivityStream): string;
15
+ /**
16
+ * Validate an outbound platform response against that platform's `responses`
17
+ * schema. Returns "" when the platform has no responses schema registered (yet),
18
+ * so outbound validation can be adopted platform-by-platform.
19
+ */
20
+ export declare function validateActivityStreamResponse(msg: ActivityStream): string;
21
+ export declare function validateCredentials(msg: ActivityStream): string;
22
+ export declare function validatePlatformSchema(schema: Schema): string;
23
+ export declare function addPlatformSchema(schema: Schema, platform_type: string): void;
24
+ export declare function getPlatformSchema(platform_type: string): import("ajv/dist/core.js").AnyValidateFunction<unknown>;
25
+ export declare function addPlatformContext(platformId: string, platformContextUrl: string): void;
26
+ export declare function resolvePlatformId(msg: ActivityStream): string | null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sockethub/schemas",
3
3
  "description": "JSON schema files for validating Sockethub Activity Streams",
4
- "version": "3.0.0-alpha.12",
4
+ "version": "3.0.0-alpha.14",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "author": "Nick Jennings <nick@silverbucket.net>",
@@ -12,25 +12,29 @@
12
12
  "main": "dist/index.js",
13
13
  "exports": {
14
14
  ".": {
15
- "bun": "./src/index.ts",
15
+ "types": "./dist/index.d.ts",
16
16
  "import": "./dist/index.js",
17
17
  "default": "./dist/index.js"
18
18
  },
19
19
  "./context": {
20
- "bun": "./src/context.ts",
20
+ "types": "./dist/context.d.ts",
21
21
  "import": "./dist/context.js",
22
22
  "default": "./dist/context.js"
23
23
  },
24
+ "./object-types": {
25
+ "types": "./dist/object-types.d.ts",
26
+ "import": "./dist/object-types.js",
27
+ "default": "./dist/object-types.js"
28
+ },
24
29
  "./schemas/json/sockethub-config.json": {
25
- "default": "./src/schemas/json/sockethub-config.json"
30
+ "default": "./dist/schemas/json/sockethub-config.json"
26
31
  }
27
32
  },
28
33
  "files": [
29
- "src/",
30
34
  "dist/"
31
35
  ],
32
36
  "engines": {
33
- "bun": ">=1.2"
37
+ "node": ">=20"
34
38
  },
35
39
  "keywords": [
36
40
  "sockethub",
@@ -49,7 +53,7 @@
49
53
  "@types/bun": "latest"
50
54
  },
51
55
  "scripts": {
52
- "build": "bun ./scripts/export-json-schema.ts && bun ./scripts/export-canonical-assets.ts && bun build src/index.ts src/context.ts --outdir dist --target node --format esm --sourcemap=external",
56
+ "build": "bun ./scripts/export-json-schema.ts && bun ./scripts/export-canonical-assets.ts && bun build src/index.ts src/object-types.ts --outdir dist --target node --format esm --sourcemap=external && bun build src/context.ts src/activity-stream-helper.ts --outdir dist --target browser --format esm --sourcemap=external",
53
57
  "clean": "rm -rf dist",
54
58
  "clean:deps": "rm -rf node_modules"
55
59
  },
@@ -58,5 +62,6 @@
58
62
  "ajv-formats": "^2.1.1",
59
63
  "ajv-formats-draft2019": "^1.6.1"
60
64
  },
61
- "gitHead": "f039dab3c3f67cbbf204476fc397532e973f82a8"
65
+ "gitHead": "4f99b07fc19c9606875621b3f96323fa6e62ae3f",
66
+ "types": "./dist/index.d.ts"
62
67
  }
package/src/context.ts DELETED
@@ -1,125 +0,0 @@
1
- import type { ActivityStream, JsonLdContext } from "./types.js";
2
-
3
- /**
4
- * Canonical AS2 base vocabulary URL.
5
- */
6
- export const AS2_BASE_CONTEXT_URL = "https://www.w3.org/ns/activitystreams";
7
-
8
- /**
9
- * Sockethub base vocabulary URL for shared platform terms.
10
- */
11
- export const SOCKETHUB_BASE_CONTEXT_URL =
12
- "https://sockethub.org/ns/context/v1.jsonld";
13
-
14
- /**
15
- * URL prefix for per-platform context URLs.
16
- */
17
- export const PLATFORM_CONTEXT_PREFIX =
18
- "https://sockethub.org/ns/context/platform/";
19
-
20
- /**
21
- * Built-in pseudo-platform used for server-side error payloads.
22
- */
23
- export const ERROR_PLATFORM_ID = "error";
24
- export const ERROR_PLATFORM_CONTEXT_URL =
25
- "https://sockethub.org/ns/context/platform/error/v1.jsonld";
26
-
27
- /**
28
- * Built-in pseudo-platform used for internal control messages.
29
- */
30
- export const INTERNAL_PLATFORM_ID = "sockethub:internal";
31
- export const INTERNAL_PLATFORM_CONTEXT_URL =
32
- "https://sockethub.org/ns/context/platform/sockethub:internal/v1.jsonld";
33
-
34
- const platformContextToPlatformId = new Map<string, string>();
35
- const platformContextToSchemaId = new Map<string, string>();
36
- const platformContextToCredentialsSchemaId = new Map<string, string>();
37
-
38
- /**
39
- * Build the canonical Sockethub @context array for a platform context URL.
40
- */
41
- export function buildCanonicalContext(
42
- platformContextUrl: string,
43
- ): JsonLdContext {
44
- return [
45
- AS2_BASE_CONTEXT_URL,
46
- SOCKETHUB_BASE_CONTEXT_URL,
47
- platformContextUrl,
48
- ];
49
- }
50
-
51
- /**
52
- * Normalize unknown @context input into a string-only array.
53
- */
54
- function normalizeContextArray(value: unknown): Array<string> {
55
- if (!Array.isArray(value)) {
56
- return [];
57
- }
58
- return value.filter((entry): entry is string => typeof entry === "string");
59
- }
60
-
61
- /**
62
- * Get a normalized @context array from an activity stream.
63
- */
64
- export function getContextArray(msg: ActivityStream): Array<string> {
65
- return normalizeContextArray(msg["@context"]);
66
- }
67
-
68
- /**
69
- * Register a platform context URL and its schema IDs for runtime resolution.
70
- */
71
- export function registerPlatformContext(
72
- platformId: string,
73
- platformContextUrl: string,
74
- schemaId: string,
75
- credentialsSchemaId: string,
76
- ) {
77
- platformContextToPlatformId.set(platformContextUrl, platformId);
78
- platformContextToSchemaId.set(platformContextUrl, schemaId);
79
- platformContextToCredentialsSchemaId.set(
80
- platformContextUrl,
81
- credentialsSchemaId,
82
- );
83
- }
84
-
85
- /**
86
- * Resolve the single registered platform context URL from a message.
87
- * Returns null when there are zero or multiple registered platform contexts.
88
- */
89
- export function resolvePlatformContextUrl(msg: ActivityStream): string | null {
90
- const contexts = getContextArray(msg);
91
- const matches = contexts.filter((contextUrl) =>
92
- platformContextToPlatformId.has(contextUrl),
93
- );
94
- if (matches.length !== 1) {
95
- return null;
96
- }
97
- return matches[0];
98
- }
99
-
100
- /**
101
- * Resolve a platform ID from a platform context URL.
102
- */
103
- export function getPlatformIdByContextUrl(
104
- platformContextUrl: string,
105
- ): string | undefined {
106
- return platformContextToPlatformId.get(platformContextUrl);
107
- }
108
-
109
- /**
110
- * Resolve a message schema ID from a platform context URL.
111
- */
112
- export function getSchemaIdByContextUrl(
113
- platformContextUrl: string,
114
- ): string | undefined {
115
- return platformContextToSchemaId.get(platformContextUrl);
116
- }
117
-
118
- /**
119
- * Resolve a credentials schema ID from a platform context URL.
120
- */
121
- export function getCredentialsSchemaIdByContextUrl(
122
- platformContextUrl: string,
123
- ): string | undefined {
124
- return platformContextToCredentialsSchemaId.get(platformContextUrl);
125
- }
@@ -1,160 +0,0 @@
1
- import type { ErrorObject } from "ajv";
2
- import type { ActivityObject, ActivityStream } from "../types.js";
3
- import { ActorTypesList, ObjectTypesList, TargetTypesList } from "./objects.js";
4
-
5
- export interface ValidationErrorOptions {
6
- excludeTypes?: Array<string>;
7
- }
8
-
9
- interface TypeBreakdown {
10
- actor: Array<string>;
11
- object: Array<string>;
12
- target: Array<string>;
13
- }
14
-
15
- function parseMsg(error: ErrorObject): string {
16
- let err = `${
17
- error.instancePath ? error.instancePath : "activity stream"
18
- }: ${error.message}`;
19
- if (error.keyword === "additionalProperties") {
20
- err += `: ${error.params.additionalProperty}`;
21
- } else if (error.keyword === "enum") {
22
- err += `: ${error.params.allowedValues.join(", ")}`;
23
- }
24
- return err;
25
- }
26
-
27
- function getTypeList(msg: ActivityStream | ActivityObject): Array<string> {
28
- const types: Array<string> = [];
29
- if (msg?.type) {
30
- types.push(msg.type);
31
- }
32
- const record = msg as Record<string, unknown>;
33
- for (const prop in record) {
34
- const value = record[prop];
35
- if (value && typeof value === "object" && "type" in value) {
36
- types.push(
37
- ...getTypeList(value as ActivityStream | ActivityObject),
38
- );
39
- }
40
- }
41
- return types;
42
- }
43
-
44
- function getSchemaType(error: ErrorObject): string | undefined {
45
- const schemaTypeRes = error.schemaPath.match(/#\/\w+\/\w+\/([\w-]+)\//);
46
- return schemaTypeRes ? schemaTypeRes[1] : undefined;
47
- }
48
-
49
- function getErrType(error: ErrorObject): string | undefined {
50
- const errTypeRes = error.instancePath.match(/\/(\w+)/);
51
- return errTypeRes ? errTypeRes[1] : undefined;
52
- }
53
-
54
- function getPartsCount(error: ErrorObject, types: TypeBreakdown): number {
55
- const schemaType = getSchemaType(error);
56
- const errType = getErrType(error);
57
- if (!errType) {
58
- return -1;
59
- }
60
- const typeList = (types as unknown as Record<string, Array<string>>)[
61
- errType
62
- ];
63
- if (!typeList) {
64
- return -1;
65
- }
66
- if (!schemaType || !typeList.includes(schemaType)) {
67
- return -1;
68
- }
69
- const parts = error.instancePath.split("/");
70
- return parts.length;
71
- }
72
-
73
- function getTypes(msg: ActivityStream | ActivityObject): TypeBreakdown {
74
- if (!Array.isArray((msg as ActivityStream)["@context"])) {
75
- return {
76
- actor: [],
77
- target: [],
78
- object: getTypeList(msg),
79
- };
80
- }
81
-
82
- const stream = msg as ActivityStream;
83
- return {
84
- actor: getTypeList(stream.actor),
85
- target: getTypeList(stream.target),
86
- object: stream.object ? getTypeList(stream.object) : [],
87
- };
88
- }
89
-
90
- /**
91
- * Traverses the errors array from ajv, and makes a series of filtering decisions to
92
- * try to arrive at the most useful error.
93
- * @param msg
94
- * @param errors
95
- * @returns {string}
96
- */
97
- export default function getErrorMessage(
98
- msg: ActivityStream | ActivityObject,
99
- errors: Array<ErrorObject>,
100
- options?: ValidationErrorOptions,
101
- ): string {
102
- const types = getTypes(msg);
103
- let deepest_entry = 0;
104
- let highest_depth = -1;
105
-
106
- for (let i = 0; i < errors.length; i++) {
107
- const partsCount = getPartsCount(errors[i], types);
108
- if (partsCount > highest_depth) {
109
- highest_depth = partsCount;
110
- deepest_entry = i;
111
- }
112
- }
113
-
114
- return highest_depth >= 0
115
- ? parseMsg(errors[deepest_entry])
116
- : composeFinalError(errors[errors.length - 1], options);
117
- }
118
-
119
- function filterTypeList(
120
- types: Array<string>,
121
- options?: ValidationErrorOptions,
122
- ): Array<string> {
123
- if (!options?.excludeTypes || options.excludeTypes.length === 0) {
124
- return types;
125
- }
126
- const exclude = new Set(options.excludeTypes);
127
- return types.filter((type) => !exclude.has(type));
128
- }
129
-
130
- function composeFinalError(
131
- error: ErrorObject,
132
- options?: ValidationErrorOptions,
133
- ): string {
134
- // if we have yet to build an error message, assume this is an invalid type value (oneOf),
135
- // try to build a list of valid types
136
- let msg: string;
137
- if (error.keyword === "oneOf") {
138
- const instanceRoot = error.instancePath.split("/")[1];
139
- const pathScopedTypes =
140
- instanceRoot === "actor"
141
- ? ActorTypesList
142
- : instanceRoot === "target"
143
- ? TargetTypesList
144
- : ObjectTypesList;
145
- const filteredTypes = filterTypeList(pathScopedTypes, options);
146
- const typesList =
147
- filteredTypes.length > 0 ? filteredTypes : pathScopedTypes;
148
- msg =
149
- `${error.instancePath}: ${error.message}: ` +
150
- `${typesList.join(", ")}`;
151
- } else {
152
- msg = `${
153
- error.instancePath ? error.instancePath : "activity stream"
154
- }: ${error.message}`;
155
- }
156
- if ("additionalProperty" in error.params) {
157
- msg += `: ${error.params.additionalProperty}`;
158
- }
159
- return msg;
160
- }