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
12 changes: 12 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions packages/pieces/community/deftform/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": ["../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": {} },
{ "files": ["*.ts", "*.tsx"], "rules": {} },
{ "files": ["*.js", "*.jsx"], "rules": {} }
]
}
16 changes: 16 additions & 0 deletions packages/pieces/community/deftform/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@activepieces/piece-deftform",
"version": "0.0.1",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.lib.json && cp package.json dist/",
"lint": "eslint 'src/**/*.ts'"
},
"dependencies": {
"@activepieces/pieces-common": "workspace:*",
"@activepieces/pieces-framework": "workspace:*",
"@activepieces/shared": "workspace:*",
"tslib": "2.6.2"
}
}
41 changes: 41 additions & 0 deletions packages/pieces/community/deftform/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createPiece } from '@activepieces/pieces-framework';
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { PieceCategory } from '@activepieces/shared';
import { deftformAuth } from './lib/auth';
import { getWorkspaceDetails } from './lib/actions/get-workspace';
import { getAllForms } from './lib/actions/get-all-forms';
import { getFormFields } from './lib/actions/get-form-fields';
import { getFormResponses } from './lib/actions/get-form-responses';
import { getSubmissionPdf } from './lib/actions/get-submission-pdf';
import { addFormResponse } from './lib/actions/add-form-response';
import { updateFormSettings } from './lib/actions/update-form-settings';
import { newFormResponseTrigger } from './lib/triggers/new-form-response';

export { deftformAuth };

export const deftform = createPiece({
displayName: 'Deftform',
description: 'Build powerful forms and automate your workflow with Deftform.',
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/deftform.png',
categories: [PieceCategory.FORMS_AND_SURVEYS],
auth: deftformAuth,
authors: ['cumonvip1'],
actions: [
getWorkspaceDetails,
getAllForms,
getFormFields,
getFormResponses,
getSubmissionPdf,
addFormResponse,
updateFormSettings,
createCustomApiCallAction({
baseUrl: () => 'https://deftform.com/api/v1',
auth: deftformAuth,
authMapping: async (auth) => ({
Authorization: `Bearer ${auth}`,
}),
}),
],
triggers: [newFormResponseTrigger],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall, DeftformCommon } from '../common';

export const addFormResponse = createAction({
auth: deftformAuth,
name: 'add_form_response',
displayName: 'Add Form Response',
description: `Submits a new response programmatically to a form.
**Note:** This does **not** trigger email notifications to the form admin, unlike regular public submissions.`,
props: {
formId: DeftformCommon.formDropdown,
responseData: Property.Object({
displayName: 'Response Data',
description: 'Key-value pairs where each key is the field UUID and the value is the user input.',
required: true,
}),
},
async run(context) {
const response = await deftformApiCall<{ data?: { id?: string; uuid?: string } }>({
token: context.auth.secret_text,
method: HttpMethod.POST,
path: `/forms/${context.propsValue.formId}/response`,
body: { data: context.propsValue.responseData },
});

return {
id: response.body.data?.id ?? null,
uuid: response.body.data?.uuid ?? null,
message: 'Response submitted successfully.',
};
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall } from '../common';

export const getAllForms = createAction({
auth: deftformAuth,
name: 'get_all_forms',
displayName: 'Get All Forms and Fields',
description: 'Lists all forms in your workspace, including their fields.',
props: {},
async run(context) {
const response = await deftformApiCall<{ data: unknown[] }>({
token: context.auth.secret_text,
method: HttpMethod.GET,
path: '/forms',
});

return response.body.data.map((form) => {
const f = form as Record<string, unknown>;
const fieldsRaw = Array.isArray(f['fields'])
? (f['fields'] as Record<string, unknown>[])
: [];
return {
id: f['id'] ?? null,
name: f['name'] ?? null,
description: f['description'] ?? null,
is_closed: f['is_closed'] ?? null,
slug: f['slug'] ?? null,
created_at: f['created_at'] ?? null,
updated_at: f['updated_at'] ?? null,
fields_count: fieldsRaw.length,
fields: fieldsRaw.map((field) => ({
id: field['id'] ?? null,
label: field['label'] ?? field['name'] ?? null,
type: field['type'] ?? null,
})),
responses_limit: f['responses_limit'] ?? null,
admin_email_subject: f['admin_email_subject'] ?? null,
};
});
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall, DeftformCommon } from '../common';

export const getFormFields = createAction({
auth: deftformAuth,
name: 'get_form_fields',
displayName: 'Get Form Fields',
description: 'Retrieves only the fields of a specific form. Great for understanding the structure before building automations.',
props: {
formId: DeftformCommon.formDropdown,
},
async run(context) {
const response = await deftformApiCall<{ data: unknown[] }>({
token: context.auth.secret_text,
method: HttpMethod.GET,
path: `/forms/${context.propsValue.formId}/fields`,
});

return response.body.data.map((field) => {
const f = field as Record<string, unknown>;
return {
id: f['id'] ?? null,
name: f['name'] ?? null,
label: f['label'] ?? null,
type: f['type'] ?? null,
required: f['required'] ?? null,
options: Array.isArray(f['options']) ? f['options'] : null,
default_value: f['default_value'] ?? null,
placeholder: f['placeholder'] ?? null,
validation: f['validation'] ?? null,
};
});
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall, DeftformCommon } from '../common';

export const getFormResponses = createAction({
auth: deftformAuth,
name: 'get_form_responses',
displayName: 'Get Form Responses',
description: 'Retrieves all submissions (responses) for a specific form. Useful for reporting and data exports.',
props: {
formId: DeftformCommon.formDropdown,
},
async run(context) {
const response = await deftformApiCall<{ data: unknown[] }>({
token: context.auth.secret_text,
method: HttpMethod.GET,
path: `/responses/${context.propsValue.formId}`,
});

return response.body.data.map((item) => {
const i = item as Record<string, unknown>;
return {
id: i['id'] ?? null,
uuid: i['uuid'] ?? null,
form_id: i['form_id'] ?? null,
created_at: i['created_at'] ?? null,
updated_at: i['updated_at'] ?? null,
...Object.fromEntries(
Object.entries((i['fields'] as Record<string, unknown>) || {}).map(([k, v]) => [
`field_${k}`,
typeof v === 'object' ? JSON.stringify(v) : v,
]),
),
};
});
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall } from '../common';

export const getSubmissionPdf = createAction({
auth: deftformAuth,
name: 'get_submission_pdf',
displayName: 'Get Submission PDF',
description: 'Generates a PDF download link for a specific form submission by its unique response UUID.',
props: {
responseUuid: Property.ShortText({
displayName: 'Response UUID',
description: 'The unique identifier of the submission. You can find this in the form responses list.',
required: true,
}),
},
async run(context) {
const response = await deftformApiCall<{ data?: { pdf_url?: string; url?: string } }>({
token: context.auth.secret_text,
method: HttpMethod.GET,
path: `/response/${context.propsValue.responseUuid}/pdf`,
});

return {
pdf_url: response.body.data?.pdf_url ?? response.body.data?.url ?? null,
response_uuid: context.propsValue.responseUuid,
};
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { deftformAuth } from '../auth';
import { deftformApiCall, flattenObject } from '../common';

export const getWorkspaceDetails = createAction({
auth: deftformAuth,
name: 'get_workspace_details',
displayName: 'Get Workspace Details',
description: 'Retrieves all information about your Deftform workspace. Useful as a connection test.',
props: {},
async run(context) {
const response = await deftformApiCall<Record<string, unknown>>({
token: context.auth.secret_text,
method: HttpMethod.GET,
path: '/workspace',
});
return flattenObject(response.body);
},
});
Loading
Loading