@crvouga/mockingbird-service-formbricks 0.1.0 → 1.0.0
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 +16 -0
- package/README.md +63 -56
- package/dist/{chunk-2FV4RSDZ.js → chunk-RITQFAWR.js} +11 -14
- package/dist/{chunk-2FV4RSDZ.js.map → chunk-RITQFAWR.js.map} +2 -2
- package/dist/chunk-ZFDC3GHV.js +3980 -0
- package/dist/chunk-ZFDC3GHV.js.map +7 -0
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +74 -60
- package/dist/index.js +7 -9
- package/dist/server.d.ts +46 -33
- package/dist/server.js +2 -2
- package/package.json +8 -4
- package/dist/chunk-FZI2QHRQ.js +0 -11714
- package/dist/chunk-FZI2QHRQ.js.map +0 -7
package/dist/cli.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
runCli,
|
|
4
4
|
serveCommand,
|
|
5
5
|
serveTarget
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-RITQFAWR.js";
|
|
7
|
+
import "./chunk-ZFDC3GHV.js";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
var code = await runCli(
|
|
11
11
|
{
|
|
12
12
|
bin: "mockingbird-formbricks",
|
|
13
|
-
description: "stateful Formbricks
|
|
13
|
+
description: "stateful Formbricks mock",
|
|
14
14
|
commands: { serve: serveCommand(serveTarget) }
|
|
15
15
|
},
|
|
16
16
|
process.argv.slice(2)
|
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cli.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/// <reference types=\"node\" />\nimport { runCli, serveCommand } from \"@crvouga/mockingbird-adapter-node\"\nimport { serveTarget } from \"./server.js\"\n\nconst code = await runCli(\n {\n bin: \"mockingbird-formbricks\",\n description: \"stateful Formbricks
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/// <reference types=\"node\" />\nimport { runCli, serveCommand } from \"@crvouga/mockingbird-adapter-node\"\nimport { serveTarget } from \"./server.js\"\n\nconst code = await runCli(\n {\n bin: \"mockingbird-formbricks\",\n description: \"stateful Formbricks mock\",\n commands: { serve: serveCommand(serveTarget) },\n },\n process.argv.slice(2),\n)\nif (code !== 0) process.exitCode = code\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;AAKA,IAAM,OAAO,MAAM;AAAA,EACjB;AAAA,IACE,KAAK;AAAA,IACL,aAAa;AAAA,IACb,UAAU,EAAE,OAAO,aAAa,WAAW,EAAE;AAAA,EAC/C;AAAA,EACA,QAAQ,KAAK,MAAM,CAAC;AACtB;AACA,IAAI,SAAS,EAAG,SAAQ,WAAW;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -832,14 +832,20 @@ interface SqliteClient {
|
|
|
832
832
|
transaction<T>(fn: () => T): T;
|
|
833
833
|
}
|
|
834
834
|
|
|
835
|
-
/** A survey definition, passed through as Formbricks serves it (blocks, elements,
|
|
835
|
+
/** A survey definition, passed through as Formbricks serves it (blocks, elements, endings, …). */
|
|
836
836
|
type Survey = Record<string, unknown> & {
|
|
837
837
|
id: string;
|
|
838
838
|
name: string;
|
|
839
839
|
type: string;
|
|
840
840
|
status: string;
|
|
841
|
-
/** `null` for the shared
|
|
842
|
-
|
|
841
|
+
/** `null` for the shared corpus surveys, which every configured workspace serves. */
|
|
842
|
+
workspaceId?: string | null;
|
|
843
|
+
};
|
|
844
|
+
/** A contact (`PUT /__admin/contacts`); `attributes.userId` becomes the response's `contact.userId`. */
|
|
845
|
+
type Contact = {
|
|
846
|
+
id: string;
|
|
847
|
+
workspaceId: string | null;
|
|
848
|
+
attributes: Record<string, string>;
|
|
843
849
|
};
|
|
844
850
|
/** One stored response, in Formbricks' `TResponse` shape. */
|
|
845
851
|
type ResponseRecord = {
|
|
@@ -847,11 +853,11 @@ type ResponseRecord = {
|
|
|
847
853
|
createdAt: string;
|
|
848
854
|
updatedAt: string;
|
|
849
855
|
surveyId: string;
|
|
850
|
-
|
|
856
|
+
workspaceId: string;
|
|
851
857
|
displayId: string | null;
|
|
852
858
|
contact: {
|
|
853
859
|
id: string;
|
|
854
|
-
userId
|
|
860
|
+
userId?: string;
|
|
855
861
|
} | null;
|
|
856
862
|
contactAttributes: Record<string, string> | null;
|
|
857
863
|
finished: boolean;
|
|
@@ -866,34 +872,29 @@ type ResponseRecord = {
|
|
|
866
872
|
};
|
|
867
873
|
/** Per-namespace knobs, set through `PUT /__admin/settings`; cleared on reset. */
|
|
868
874
|
type Settings = {
|
|
869
|
-
/**
|
|
870
|
-
|
|
875
|
+
/** Workspace ids that exist and serve the shared corpus surveys. */
|
|
876
|
+
workspaces: string[];
|
|
877
|
+
/** Pre-Formbricks-5 environment ids, each an alias of a workspace (`{envId: workspaceId}`). */
|
|
878
|
+
legacyEnvironmentIds: Record<string, string>;
|
|
871
879
|
/** Accepted management API keys; empty means any non-empty `x-api-key` works. */
|
|
872
880
|
apiKeys: string[];
|
|
873
881
|
/** The `webhookId` put in webhook bodies. */
|
|
874
882
|
webhookId: string;
|
|
875
|
-
/**
|
|
883
|
+
/** Contacts are an Enterprise feature: when off, a response with a `contactId` is 403. */
|
|
876
884
|
contactsEnabled: boolean;
|
|
877
885
|
};
|
|
878
|
-
/**
|
|
879
|
-
declare const
|
|
880
|
-
|
|
886
|
+
/** The default workspace every namespace starts with. */
|
|
887
|
+
declare const WORKSPACE_ID = "cworkspace000000000000001";
|
|
888
|
+
/** A legacy environment id that resolves to {@link WORKSPACE_ID} (older SDKs still send one). */
|
|
889
|
+
declare const ENVIRONMENT_ID = "cenvironment0000000000001";
|
|
881
890
|
declare const DEFAULT_SETTINGS: Settings;
|
|
882
|
-
/**
|
|
883
|
-
|
|
884
|
-
* (`packages/forms-fixtures/formbricks/prod-clone.json` in geviti-monorepo).
|
|
885
|
-
*/
|
|
886
|
-
declare const PROD_CLONE_SURVEYS: readonly Survey[];
|
|
887
|
-
declare const PROD_CLONE_EXPORTED_AT: string;
|
|
891
|
+
/** The synthetic survey corpus every namespace is seeded with (`src/corpus/surveys.json`). */
|
|
892
|
+
declare const CORPUS_SURVEYS: readonly Survey[];
|
|
888
893
|
declare class FormbricksState {
|
|
889
894
|
private readonly seed;
|
|
890
895
|
readonly surveys: Collection<Survey>;
|
|
891
896
|
readonly responses: Collection<ResponseRecord>;
|
|
892
|
-
readonly contacts: Collection<
|
|
893
|
-
id: string;
|
|
894
|
-
environmentId: string;
|
|
895
|
-
userId: string;
|
|
896
|
-
}>;
|
|
897
|
+
readonly contacts: Collection<Contact>;
|
|
897
898
|
readonly settings: Collection<Settings>;
|
|
898
899
|
readonly ids: IdSequence;
|
|
899
900
|
constructor(sqlite: SqliteClient, namespace: string, seed: {
|
|
@@ -905,17 +906,20 @@ declare class FormbricksState {
|
|
|
905
906
|
update(patch: Partial<Settings>): Settings;
|
|
906
907
|
/** Formbricks ids are cuid2: lower-case alphanumerics starting with a letter, 25 long. */
|
|
907
908
|
nextId(): string;
|
|
908
|
-
|
|
909
|
+
/**
|
|
910
|
+
* `resolveClientApiIds`: a workspace id, or a legacy environment id, to its workspace id
|
|
911
|
+
* (`undefined` when neither is known).
|
|
912
|
+
*/
|
|
913
|
+
resolveWorkspace(id: string): string | undefined;
|
|
914
|
+
/** The v1 `environmentId` of a workspace: its legacy environment id, else its own id. */
|
|
915
|
+
legacyEnvironmentId(workspaceId: string): string;
|
|
909
916
|
allSurveys(): Survey[];
|
|
910
|
-
/** Surveys
|
|
911
|
-
surveysOf(
|
|
912
|
-
/** Whether a survey belongs to
|
|
913
|
-
belongsTo(survey: Survey,
|
|
914
|
-
/**
|
|
915
|
-
|
|
916
|
-
id: string;
|
|
917
|
-
userId: string;
|
|
918
|
-
};
|
|
917
|
+
/** Surveys a workspace serves: its own, plus the shared corpus when it is configured. */
|
|
918
|
+
surveysOf(workspaceId: string): Survey[];
|
|
919
|
+
/** Whether a survey belongs to a workspace (`survey.workspaceId !== workspaceId` check). */
|
|
920
|
+
belongsTo(survey: Survey, workspaceId: string): boolean;
|
|
921
|
+
/** `getContact(contactId, workspaceId)`: a contact of that workspace (or a shared one). */
|
|
922
|
+
contactOf(contactId: string, workspaceId: string): Contact | undefined;
|
|
919
923
|
}
|
|
920
924
|
|
|
921
925
|
/**
|
|
@@ -1090,20 +1094,21 @@ declare const operationIds: readonly ["GetEnvironmentState", "CreateClientRespon
|
|
|
1090
1094
|
declare const supportedOperationIds: readonly ["GetEnvironmentState", "CreateClientResponse", "ListResponses", "GetResponse", "ListSurveys", "CreateSurvey", "GetSurvey", "GetWidgetScript"];
|
|
1091
1095
|
|
|
1092
1096
|
/**
|
|
1093
|
-
*
|
|
1094
|
-
* in `packages/surveys/src/lib/validation/evaluator.ts`), trimmed to
|
|
1095
|
-
* required elements,
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1097
|
+
* Formbricks' response validation (`validateResponseData` in `apps/web/modules/api/lib/validation.ts`
|
|
1098
|
+
* → `validateBlockResponses` in `packages/surveys/src/lib/validation/evaluator.ts`), trimmed to the
|
|
1099
|
+
* structural checks: required elements, choice membership for choice elements without an "other"
|
|
1100
|
+
* option, and the implicit email / url / phone rules of openText elements. Only the elements
|
|
1101
|
+
* present in `data` are checked, finished or not (upstream never checks absent elements).
|
|
1102
|
+
* Custom `validation.rules` are not evaluated.
|
|
1098
1103
|
*/
|
|
1099
1104
|
|
|
1100
1105
|
/** `{<elementId>: [messages]}`, or `null` when the response passes. */
|
|
1101
|
-
declare const validateResponseData: (survey: Survey, data: Record<string, unknown>,
|
|
1106
|
+
declare const validateResponseData: (survey: Survey, data: Record<string, unknown>, language?: string) => Record<string, string[]> | null;
|
|
1102
1107
|
|
|
1103
|
-
/**
|
|
1104
|
-
declare const WEBHOOK_PATH = "/
|
|
1108
|
+
/** A conventional path for the consumer app's webhook receiver (examples and the CLI help use it). */
|
|
1109
|
+
declare const WEBHOOK_PATH = "/webhooks/formbricks";
|
|
1105
1110
|
/**
|
|
1106
|
-
* Every named Formbricks misbehaviour
|
|
1111
|
+
* Every named Formbricks misbehaviour a consumer app may branch on, switched on with
|
|
1107
1112
|
* `POST /__admin/faults {"preset": "<name>"}` (add `count` to limit it).
|
|
1108
1113
|
*/
|
|
1109
1114
|
declare const FORMBRICKS_PRESETS: Record<string, FaultPreset>;
|
|
@@ -1120,8 +1125,8 @@ type FormbricksRuntimeOptions = {
|
|
|
1120
1125
|
surveys?: readonly Survey[];
|
|
1121
1126
|
settings?: Partial<Settings>;
|
|
1122
1127
|
/**
|
|
1123
|
-
* Where webhooks go: `url`
|
|
1124
|
-
* `whsec_…` Standard Webhooks key) signs `webhook-signature`; `events` defaults to
|
|
1128
|
+
* Where webhooks go: `url` (any query, e.g. a `?token=` your receiver checks, is kept); `secret`
|
|
1129
|
+
* (a `whsec_…` Standard Webhooks key) signs `webhook-signature`; `events` defaults to
|
|
1125
1130
|
* `["responseFinished"]` (add `"responseCreated"` for both).
|
|
1126
1131
|
*/
|
|
1127
1132
|
webhooks?: Omit<WebhookEndpoint, "id"> & WebhookHubOptionsSubset;
|
|
@@ -1130,22 +1135,22 @@ type FormbricksRuntime = ServiceRuntime<FormbricksAPI> & {
|
|
|
1130
1135
|
readonly webhooks: WebhookHub;
|
|
1131
1136
|
};
|
|
1132
1137
|
/**
|
|
1133
|
-
* The namespace carrier for the client API is the environment id in the
|
|
1134
|
-
*
|
|
1138
|
+
* The namespace carrier for the client API is the workspace (or legacy environment) id in the
|
|
1139
|
+
* path (the SDK cannot add headers); the management API's is its `x-api-key`.
|
|
1135
1140
|
*/
|
|
1136
1141
|
declare const formbricksCredential: (request: Request) => string | undefined;
|
|
1137
1142
|
/**
|
|
1138
1143
|
* The Formbricks mock with Mockingbird's full service contract: `/health`, `/__admin/*`,
|
|
1139
|
-
* namespaces by header, by `/ns/<name>` prefix on
|
|
1140
|
-
*
|
|
1144
|
+
* namespaces by header, by `/ns/<name>` prefix on the app URL, or by workspace id / API key
|
|
1145
|
+
* (`PUT /__admin/credentials {"credentials": {"<workspace id or key>": "<namespace>"}}`),
|
|
1141
1146
|
* clock control, fault presets, and Standard-Webhooks-signed `responseFinished` webhooks.
|
|
1142
1147
|
*/
|
|
1143
1148
|
declare const createRuntime: (options?: FormbricksRuntimeOptions) => FormbricksRuntime;
|
|
1144
1149
|
|
|
1145
1150
|
declare const FORMBRICKS_NAMESPACE = "formbricks";
|
|
1146
1151
|
/** The response as the API (and the webhook) renders it: `TResponse`. */
|
|
1147
|
-
type ApiResponse = Omit<ResponseRecord, "
|
|
1148
|
-
/** The body Formbricks' pipeline posts to a webhook (`
|
|
1152
|
+
type ApiResponse = Omit<ResponseRecord, "workspaceId">;
|
|
1153
|
+
/** The body Formbricks' response pipeline posts to a webhook (`process-response-pipeline-job.ts`). */
|
|
1149
1154
|
type FormbricksWebhook = {
|
|
1150
1155
|
webhookId: string;
|
|
1151
1156
|
event: "responseCreated" | "responseFinished";
|
|
@@ -1160,18 +1165,21 @@ type FormbricksWebhook = {
|
|
|
1160
1165
|
};
|
|
1161
1166
|
};
|
|
1162
1167
|
type FormbricksAPIOptions = APIOptions & {
|
|
1163
|
-
/** Surveys every namespace starts with. Default:
|
|
1168
|
+
/** Surveys every namespace starts with. Default: the synthetic corpus (`CORPUS_SURVEYS`). */
|
|
1164
1169
|
surveys?: readonly Survey[];
|
|
1165
1170
|
settings?: Partial<Settings>;
|
|
1166
1171
|
/** Called for every pipeline event; the runtime signs and delivers it. */
|
|
1167
1172
|
onWebhook?: (event: FormbricksWebhook) => void;
|
|
1168
1173
|
};
|
|
1169
|
-
type ErrorCode = "not_found" | "bad_request" | "internal_server_error" | "not_authenticated" | "forbidden" | "too_many_requests";
|
|
1170
|
-
/** The fork's error envelope (`app/lib/api/response.ts`), with its CORS/no-store headers. */
|
|
1171
|
-
declare const formbricksError: (status: number, code: ErrorCode, message: string, details?: Record<string, unknown>) => Response;
|
|
1174
|
+
type ErrorCode = "not_found" | "bad_request" | "internal_server_error" | "unauthorized" | "not_authenticated" | "forbidden" | "too_many_requests";
|
|
1172
1175
|
/**
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1176
|
+
* Formbricks' v1 error envelope (`apps/web/app/lib/api/response.ts`): `{code, message, details}`,
|
|
1177
|
+
* `Cache-Control: private, no-store`, and the CORS headers on the routes that pass `cors`.
|
|
1178
|
+
*/
|
|
1179
|
+
declare const formbricksError: (status: number, code: ErrorCode, message: string, details?: Record<string, unknown>, cors?: boolean) => Response;
|
|
1180
|
+
/**
|
|
1181
|
+
* Stateful mock of open-source Formbricks: the client environment state and response creation
|
|
1182
|
+
* the JS SDK uses, the v1 management API, and the response pipeline's webhooks.
|
|
1175
1183
|
*/
|
|
1176
1184
|
declare class FormbricksAPI implements FetchAPI$1 {
|
|
1177
1185
|
readonly app: Hono;
|
|
@@ -1184,17 +1192,23 @@ declare class FormbricksAPI implements FetchAPI$1 {
|
|
|
1184
1192
|
fetch(request: Request): Promise<Response>;
|
|
1185
1193
|
reset(): Promise<void>;
|
|
1186
1194
|
private iso;
|
|
1187
|
-
/**
|
|
1188
|
-
|
|
1195
|
+
/**
|
|
1196
|
+
* A survey as the v1 management API serves it: `questions` derived from `blocks`, the owning
|
|
1197
|
+
* `workspaceId` and its legacy `environmentId`, and `projectOverwrites`. Shared corpus surveys
|
|
1198
|
+
* are reported under the first configured workspace.
|
|
1199
|
+
*/
|
|
1200
|
+
wireSurvey(survey: Survey): Survey;
|
|
1189
1201
|
render(record: ResponseRecord, context?: OperationContext): ApiResponse;
|
|
1190
1202
|
private environmentState;
|
|
1191
1203
|
private createResponse;
|
|
1192
|
-
/** Emit a pipeline event for a stored response
|
|
1204
|
+
/** Emit a pipeline event (`responseCreated` / `responseFinished`) for a stored response. */
|
|
1193
1205
|
pipeline(event: FormbricksWebhook["event"], record: ResponseRecord, survey: Survey): void;
|
|
1194
1206
|
private listResponses;
|
|
1207
|
+
/** `getSurveys(workspaceIds, limit, offset)`: newest `updatedAt` first. */
|
|
1208
|
+
private listSurveys;
|
|
1195
1209
|
private createSurvey;
|
|
1196
1210
|
responses(): ApiResponse[];
|
|
1197
1211
|
}
|
|
1198
1212
|
|
|
1199
|
-
export { DEFAULT_SETTINGS,
|
|
1200
|
-
export type { ApiResponse, FetchAPI$1 as FetchAPI, FormbricksAPIOptions, FormbricksRuntime, FormbricksRuntimeOptions, FormbricksWebhook, OperationId, ResponseRecord, Settings, SqliteClient, SupportedOperationId, Survey };
|
|
1213
|
+
export { CORPUS_SURVEYS, DEFAULT_SETTINGS, ENVIRONMENT_ID, FORMBRICKS_NAMESPACE, FORMBRICKS_PRESETS, FormbricksAPI, WEBHOOK_PATH, WORKSPACE_ID, createRuntime, document, formbricksCredential, formbricksError, operationIds, supportedOperationIds, validateResponseData };
|
|
1214
|
+
export type { ApiResponse, Contact, FetchAPI$1 as FetchAPI, FormbricksAPIOptions, FormbricksRuntime, FormbricksRuntimeOptions, FormbricksWebhook, OperationId, ResponseRecord, Settings, SqliteClient, SupportedOperationId, Survey };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CORPUS_SURVEYS,
|
|
2
3
|
DEFAULT_SETTINGS,
|
|
3
|
-
|
|
4
|
+
ENVIRONMENT_ID,
|
|
4
5
|
FORMBRICKS_NAMESPACE,
|
|
5
6
|
FORMBRICKS_PRESETS,
|
|
6
7
|
FormbricksAPI,
|
|
7
|
-
PRODUCTION_ENVIRONMENT_ID,
|
|
8
|
-
PROD_CLONE_EXPORTED_AT,
|
|
9
|
-
PROD_CLONE_SURVEYS,
|
|
10
8
|
WEBHOOK_PATH,
|
|
9
|
+
WORKSPACE_ID,
|
|
11
10
|
createRuntime,
|
|
12
11
|
document,
|
|
13
12
|
formbricksCredential,
|
|
@@ -15,17 +14,16 @@ import {
|
|
|
15
14
|
operationIds,
|
|
16
15
|
supportedOperationIds,
|
|
17
16
|
validateResponseData
|
|
18
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZFDC3GHV.js";
|
|
19
18
|
export {
|
|
19
|
+
CORPUS_SURVEYS,
|
|
20
20
|
DEFAULT_SETTINGS,
|
|
21
|
-
|
|
21
|
+
ENVIRONMENT_ID,
|
|
22
22
|
FORMBRICKS_NAMESPACE,
|
|
23
23
|
FORMBRICKS_PRESETS,
|
|
24
24
|
FormbricksAPI,
|
|
25
|
-
PRODUCTION_ENVIRONMENT_ID,
|
|
26
|
-
PROD_CLONE_EXPORTED_AT,
|
|
27
|
-
PROD_CLONE_SURVEYS,
|
|
28
25
|
WEBHOOK_PATH,
|
|
26
|
+
WORKSPACE_ID,
|
|
29
27
|
createRuntime,
|
|
30
28
|
document,
|
|
31
29
|
formbricksCredential,
|
package/dist/server.d.ts
CHANGED
|
@@ -1342,14 +1342,20 @@ interface FetchAPI {
|
|
|
1342
1342
|
fetch(request: Request): Promise<Response>;
|
|
1343
1343
|
}
|
|
1344
1344
|
|
|
1345
|
-
/** A survey definition, passed through as Formbricks serves it (blocks, elements,
|
|
1345
|
+
/** A survey definition, passed through as Formbricks serves it (blocks, elements, endings, …). */
|
|
1346
1346
|
type Survey = Record<string, unknown> & {
|
|
1347
1347
|
id: string;
|
|
1348
1348
|
name: string;
|
|
1349
1349
|
type: string;
|
|
1350
1350
|
status: string;
|
|
1351
|
-
/** `null` for the shared
|
|
1352
|
-
|
|
1351
|
+
/** `null` for the shared corpus surveys, which every configured workspace serves. */
|
|
1352
|
+
workspaceId?: string | null;
|
|
1353
|
+
};
|
|
1354
|
+
/** A contact (`PUT /__admin/contacts`); `attributes.userId` becomes the response's `contact.userId`. */
|
|
1355
|
+
type Contact = {
|
|
1356
|
+
id: string;
|
|
1357
|
+
workspaceId: string | null;
|
|
1358
|
+
attributes: Record<string, string>;
|
|
1353
1359
|
};
|
|
1354
1360
|
/** One stored response, in Formbricks' `TResponse` shape. */
|
|
1355
1361
|
type ResponseRecord = {
|
|
@@ -1357,11 +1363,11 @@ type ResponseRecord = {
|
|
|
1357
1363
|
createdAt: string;
|
|
1358
1364
|
updatedAt: string;
|
|
1359
1365
|
surveyId: string;
|
|
1360
|
-
|
|
1366
|
+
workspaceId: string;
|
|
1361
1367
|
displayId: string | null;
|
|
1362
1368
|
contact: {
|
|
1363
1369
|
id: string;
|
|
1364
|
-
userId
|
|
1370
|
+
userId?: string;
|
|
1365
1371
|
} | null;
|
|
1366
1372
|
contactAttributes: Record<string, string> | null;
|
|
1367
1373
|
finished: boolean;
|
|
@@ -1376,24 +1382,22 @@ type ResponseRecord = {
|
|
|
1376
1382
|
};
|
|
1377
1383
|
/** Per-namespace knobs, set through `PUT /__admin/settings`; cleared on reset. */
|
|
1378
1384
|
type Settings = {
|
|
1379
|
-
/**
|
|
1380
|
-
|
|
1385
|
+
/** Workspace ids that exist and serve the shared corpus surveys. */
|
|
1386
|
+
workspaces: string[];
|
|
1387
|
+
/** Pre-Formbricks-5 environment ids, each an alias of a workspace (`{envId: workspaceId}`). */
|
|
1388
|
+
legacyEnvironmentIds: Record<string, string>;
|
|
1381
1389
|
/** Accepted management API keys; empty means any non-empty `x-api-key` works. */
|
|
1382
1390
|
apiKeys: string[];
|
|
1383
1391
|
/** The `webhookId` put in webhook bodies. */
|
|
1384
1392
|
webhookId: string;
|
|
1385
|
-
/**
|
|
1393
|
+
/** Contacts are an Enterprise feature: when off, a response with a `contactId` is 403. */
|
|
1386
1394
|
contactsEnabled: boolean;
|
|
1387
1395
|
};
|
|
1388
1396
|
declare class FormbricksState {
|
|
1389
1397
|
private readonly seed;
|
|
1390
1398
|
readonly surveys: Collection<Survey>;
|
|
1391
1399
|
readonly responses: Collection<ResponseRecord>;
|
|
1392
|
-
readonly contacts: Collection<
|
|
1393
|
-
id: string;
|
|
1394
|
-
environmentId: string;
|
|
1395
|
-
userId: string;
|
|
1396
|
-
}>;
|
|
1400
|
+
readonly contacts: Collection<Contact>;
|
|
1397
1401
|
readonly settings: Collection<Settings>;
|
|
1398
1402
|
readonly ids: IdSequence;
|
|
1399
1403
|
constructor(sqlite: SqliteClient, namespace: string, seed: {
|
|
@@ -1405,22 +1409,25 @@ declare class FormbricksState {
|
|
|
1405
1409
|
update(patch: Partial<Settings>): Settings;
|
|
1406
1410
|
/** Formbricks ids are cuid2: lower-case alphanumerics starting with a letter, 25 long. */
|
|
1407
1411
|
nextId(): string;
|
|
1408
|
-
|
|
1412
|
+
/**
|
|
1413
|
+
* `resolveClientApiIds`: a workspace id, or a legacy environment id, to its workspace id
|
|
1414
|
+
* (`undefined` when neither is known).
|
|
1415
|
+
*/
|
|
1416
|
+
resolveWorkspace(id: string): string | undefined;
|
|
1417
|
+
/** The v1 `environmentId` of a workspace: its legacy environment id, else its own id. */
|
|
1418
|
+
legacyEnvironmentId(workspaceId: string): string;
|
|
1409
1419
|
allSurveys(): Survey[];
|
|
1410
|
-
/** Surveys
|
|
1411
|
-
surveysOf(
|
|
1412
|
-
/** Whether a survey belongs to
|
|
1413
|
-
belongsTo(survey: Survey,
|
|
1414
|
-
/**
|
|
1415
|
-
|
|
1416
|
-
id: string;
|
|
1417
|
-
userId: string;
|
|
1418
|
-
};
|
|
1420
|
+
/** Surveys a workspace serves: its own, plus the shared corpus when it is configured. */
|
|
1421
|
+
surveysOf(workspaceId: string): Survey[];
|
|
1422
|
+
/** Whether a survey belongs to a workspace (`survey.workspaceId !== workspaceId` check). */
|
|
1423
|
+
belongsTo(survey: Survey, workspaceId: string): boolean;
|
|
1424
|
+
/** `getContact(contactId, workspaceId)`: a contact of that workspace (or a shared one). */
|
|
1425
|
+
contactOf(contactId: string, workspaceId: string): Contact | undefined;
|
|
1419
1426
|
}
|
|
1420
1427
|
|
|
1421
1428
|
/** The response as the API (and the webhook) renders it: `TResponse`. */
|
|
1422
|
-
type ApiResponse = Omit<ResponseRecord, "
|
|
1423
|
-
/** The body Formbricks' pipeline posts to a webhook (`
|
|
1429
|
+
type ApiResponse = Omit<ResponseRecord, "workspaceId">;
|
|
1430
|
+
/** The body Formbricks' response pipeline posts to a webhook (`process-response-pipeline-job.ts`). */
|
|
1424
1431
|
type FormbricksWebhook = {
|
|
1425
1432
|
webhookId: string;
|
|
1426
1433
|
event: "responseCreated" | "responseFinished";
|
|
@@ -1435,15 +1442,15 @@ type FormbricksWebhook = {
|
|
|
1435
1442
|
};
|
|
1436
1443
|
};
|
|
1437
1444
|
type FormbricksAPIOptions = APIOptions & {
|
|
1438
|
-
/** Surveys every namespace starts with. Default:
|
|
1445
|
+
/** Surveys every namespace starts with. Default: the synthetic corpus (`CORPUS_SURVEYS`). */
|
|
1439
1446
|
surveys?: readonly Survey[];
|
|
1440
1447
|
settings?: Partial<Settings>;
|
|
1441
1448
|
/** Called for every pipeline event; the runtime signs and delivers it. */
|
|
1442
1449
|
onWebhook?: (event: FormbricksWebhook) => void;
|
|
1443
1450
|
};
|
|
1444
1451
|
/**
|
|
1445
|
-
* Stateful mock of Formbricks
|
|
1446
|
-
*
|
|
1452
|
+
* Stateful mock of open-source Formbricks: the client environment state and response creation
|
|
1453
|
+
* the JS SDK uses, the v1 management API, and the response pipeline's webhooks.
|
|
1447
1454
|
*/
|
|
1448
1455
|
declare class FormbricksAPI implements FetchAPI {
|
|
1449
1456
|
readonly app: Hono;
|
|
@@ -1456,14 +1463,20 @@ declare class FormbricksAPI implements FetchAPI {
|
|
|
1456
1463
|
fetch(request: Request): Promise<Response>;
|
|
1457
1464
|
reset(): Promise<void>;
|
|
1458
1465
|
private iso;
|
|
1459
|
-
/**
|
|
1460
|
-
|
|
1466
|
+
/**
|
|
1467
|
+
* A survey as the v1 management API serves it: `questions` derived from `blocks`, the owning
|
|
1468
|
+
* `workspaceId` and its legacy `environmentId`, and `projectOverwrites`. Shared corpus surveys
|
|
1469
|
+
* are reported under the first configured workspace.
|
|
1470
|
+
*/
|
|
1471
|
+
wireSurvey(survey: Survey): Survey;
|
|
1461
1472
|
render(record: ResponseRecord, context?: OperationContext): ApiResponse;
|
|
1462
1473
|
private environmentState;
|
|
1463
1474
|
private createResponse;
|
|
1464
|
-
/** Emit a pipeline event for a stored response
|
|
1475
|
+
/** Emit a pipeline event (`responseCreated` / `responseFinished`) for a stored response. */
|
|
1465
1476
|
pipeline(event: FormbricksWebhook["event"], record: ResponseRecord, survey: Survey): void;
|
|
1466
1477
|
private listResponses;
|
|
1478
|
+
/** `getSurveys(workspaceIds, limit, offset)`: newest `updatedAt` first. */
|
|
1479
|
+
private listSurveys;
|
|
1467
1480
|
private createSurvey;
|
|
1468
1481
|
responses(): ApiResponse[];
|
|
1469
1482
|
}
|
|
@@ -1481,8 +1494,8 @@ type FormbricksRuntimeOptions = {
|
|
|
1481
1494
|
surveys?: readonly Survey[];
|
|
1482
1495
|
settings?: Partial<Settings>;
|
|
1483
1496
|
/**
|
|
1484
|
-
* Where webhooks go: `url`
|
|
1485
|
-
* `whsec_…` Standard Webhooks key) signs `webhook-signature`; `events` defaults to
|
|
1497
|
+
* Where webhooks go: `url` (any query, e.g. a `?token=` your receiver checks, is kept); `secret`
|
|
1498
|
+
* (a `whsec_…` Standard Webhooks key) signs `webhook-signature`; `events` defaults to
|
|
1486
1499
|
* `["responseFinished"]` (add `"responseCreated"` for both).
|
|
1487
1500
|
*/
|
|
1488
1501
|
webhooks?: Omit<WebhookEndpoint, "id"> & WebhookHubOptionsSubset;
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/mockingbird-service-formbricks",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Stateful mock of Formbricks
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Stateful mock of open-source Formbricks: the client environment state (seeded with a synthetic survey corpus), response creation with upstream's validation and {code, message, details} errors, the v1 management API, the widget script, and signed response webhooks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -52,6 +52,10 @@
|
|
|
52
52
|
"layer": "service",
|
|
53
53
|
"category": "productivity",
|
|
54
54
|
"displayName": "Formbricks",
|
|
55
|
+
"vendor": {
|
|
56
|
+
"website": "https://formbricks.com",
|
|
57
|
+
"docs": "https://formbricks.com/docs"
|
|
58
|
+
},
|
|
55
59
|
"status": "wip"
|
|
56
60
|
},
|
|
57
61
|
"scripts": {
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
"pack:check": "bun ../../../scripts/pack-check.ts"
|
|
68
72
|
},
|
|
69
73
|
"dependencies": {
|
|
70
|
-
"@crvouga/mockingbird-service-sqlite": "0.
|
|
74
|
+
"@crvouga/mockingbird-service-sqlite": "1.0.0",
|
|
71
75
|
"hono": "4.11.9"
|
|
72
76
|
},
|
|
73
77
|
"devDependencies": {
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
"@crvouga/mockingbird-testing": "0.1.0",
|
|
76
80
|
"@crvouga/mockingbird-service-sqlite": "0.0.0-development",
|
|
77
81
|
"@crvouga/mockingbird-parity": "0.0.0-development",
|
|
78
|
-
"@crvouga/mockingbird-
|
|
82
|
+
"@crvouga/mockingbird-credentials": "0.0.0-development",
|
|
79
83
|
"@crvouga/mockingbird-openapi-codegen": "0.1.0",
|
|
80
84
|
"@crvouga/mockingbird-openapi-metadata": "0.0.0-development",
|
|
81
85
|
"@crvouga/mockingbird-core": "0.0.0-development",
|