Skip to content

Commit

Permalink
[PDE-5395] feat(schema): Add meta field support for FieldSchema (#883)
Browse files Browse the repository at this point in the history
* initial implementation idea

* more complete example

* typo

* updated typing

* Update packages/core/types/zapier.generated.d.ts

Co-authored-by: Fokke Zandbergen <[email protected]>

* Update packages/schema/exported-schema.json

Co-authored-by: Fokke Zandbergen <[email protected]>

* Update packages/schema/lib/schemas/FieldMetaSchema.js

Co-authored-by: Fokke Zandbergen <[email protected]>

* review suggestions

* typing doc changes

* update FieldMetaSchema

* update typing

---------

Co-authored-by: Fokke Zandbergen <[email protected]>
  • Loading branch information
rnegron and FokkeZB authored Nov 25, 2024
1 parent 787317f commit 66dc9da
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 2 deletions.
7 changes: 7 additions & 0 deletions packages/core/types/zapier.custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ export interface Bundle<InputData = { [x: string]: any }> {
timezone: string;
};
};

/**
* Contains metadata about the input fields, optionally provided
* by the inputField.meta property. Useful for storing extra data
* in dynamically created input fields.
*/
inputFields: { [fieldKey: string]: { [metaKey: string]: string | number | boolean } };
};
rawRequest?: Partial<{
method: HttpMethod;
Expand Down
22 changes: 22 additions & 0 deletions packages/core/types/zapier.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,22 @@ export type FieldChoices =
| { [k: string]: unknown }
| (string | FieldChoiceWithLabel)[];

/**
* Allows for additional metadata to be stored on the field.
*
* [Docs: FieldMetaSchema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#FieldMetaSchema)
*/
export interface FieldMeta {
/**
* Only string, integer or boolean values are allowed.
*
* This interface was referenced by `FieldMetaSchema`'s JSON-Schema
* definition
* via the `patternProperty` "[^\s]+".
*/
[k: string]: string | number | boolean;
}

/**
* Defines a field an app either needs as input, or gives as output.
* In addition to the requirements below, the following keys are
Expand Down Expand Up @@ -323,6 +339,12 @@ export interface Field {
* "https://{{input}}.yourdomain.com").
*/
inputFormat?: string;

/**
* Allows for additional metadata to be stored on the field.
* Supports simple key-values only (no sub-objects or arrays).
*/
meta?: FieldMeta;
}

/**
Expand Down
36 changes: 36 additions & 0 deletions packages/schema/docs/build/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This is automatically generated by the `npm run docs` command in `zapier-platfor
* [/DynamicFieldsSchema](#dynamicfieldsschema)
* [/FieldChoiceWithLabelSchema](#fieldchoicewithlabelschema)
* [/FieldChoicesSchema](#fieldchoicesschema)
* [/FieldMetaSchema](#fieldmetaschema)
* [/FieldOrFunctionSchema](#fieldorfunctionschema)
* [/FieldSchema](#fieldschema)
* [/FieldsSchema](#fieldsschema)
Expand Down Expand Up @@ -931,6 +932,33 @@ Yes | Yes | Array of [FieldChoiceWithLabel](#fieldchoicewithlabelschema)

-----

## /FieldMetaSchema

Allows for additional metadata to be stored on the field.

#### Details

* **Type** - `object`
* [**Source Code**](https://github.com/zapier/zapier-platform/blob/[email protected]/packages/schema/lib/schemas/FieldMetaSchema.js)

#### Properties

Key | Required | Type | Description
--- | -------- | ---- | -----------
`[^\s]+` | no | anyOf(`string`, `integer`, `boolean`) | Only string, integer or boolean values are allowed.

#### Examples

* `{ shouldCapitalize: true }`
* `{ shouldCapitalize: true, internalType: 'datetime' }`

#### Anti-Examples

* `{ databank: { primaryContact: 'abc' } }` - _No complex values allowed_
* `{ needsProcessing: null }` - _No null values allowed_

-----

## /FieldOrFunctionSchema

Represents an array of fields or functions.
Expand Down Expand Up @@ -997,6 +1025,7 @@ Key | Required | Type | Description
`altersDynamicFields` | no | `boolean` | Does the value of this field affect the definitions of other fields in the set?
`steadyState` | no | `boolean` | Prevents triggering on new output until all values for fields with this property remain unchanged for 2 polls. It can be used to, e.g., not trigger on a new contact until the contact has completed typing their name. NOTE that this only applies to the `outputFields` of polling triggers.
`inputFormat` | no | `string` | Useful when you expect the input to be part of a longer string. Put "{{input}}" in place of the user's input (IE: "https://{{input}}.yourdomain.com").
`meta` | no | [/FieldMetaSchema](#fieldmetaschema) | Allows for additional metadata to be stored on the field. Supports simple key-values only (no sub-objects or arrays).

#### Examples

Expand All @@ -1006,6 +1035,13 @@ Key | Required | Type | Description
* `{ key: 'abc', choices: [ { label: 'Red', sample: '#f00', value: '#f00' } ] }`
* `{ key: 'abc', children: [ { key: 'abc' } ] }`
* `{ key: 'abc', type: 'integer', helpText: 'neat' }`
* ```
{
key: 'abc',
type: 'integer',
meta: { internalType: 'numeric', should_call_api: true, display_order: 1 }
}
```

#### Anti-Examples

Expand Down
25 changes: 25 additions & 0 deletions packages/schema/exported-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,27 @@
}
]
},
"FieldMetaSchema": {
"id": "/FieldMetaSchema",
"type": "object",
"description": "Allows for additional metadata to be stored on the field.",
"patternProperties": {
"[^\\s]+": {
"description": "Only string, integer or boolean values are allowed.",
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "boolean"
}
]
}
}
},
"FieldSchema": {
"id": "/FieldSchema",
"description": "Defines a field an app either needs as input, or gives as output. In addition to the requirements below, the following keys are mutually exclusive:\n\n* `children` & `list`\n* `children` & `dict`\n* `children` & `type`\n* `children` & `placeholder`\n* `children` & `helpText`\n* `children` & `default`\n* `dict` & `list`\n* `dynamic` & `dict`\n* `dynamic` & `choices`",
Expand Down Expand Up @@ -249,6 +270,10 @@
"description": "Useful when you expect the input to be part of a longer string. Put \"{{input}}\" in place of the user's input (IE: \"https://{{input}}.yourdomain.com\").",
"type": "string",
"pattern": "^.*{{input}}.*$"
},
"meta": {
"description": "Allows for additional metadata to be stored on the field. Supports simple key-values only (no sub-objects or arrays).",
"$ref": "/FieldMetaSchema"
}
},
"additionalProperties": false
Expand Down
29 changes: 29 additions & 0 deletions packages/schema/lib/schemas/FieldMetaSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

const makeSchema = require('../utils/makeSchema');

module.exports = makeSchema({
id: '/FieldMetaSchema',
type: 'object',
description: 'Allows for additional metadata to be stored on the field.',
patternProperties: {
'[^\\s]+': {
description: 'Only string, integer or boolean values are allowed.',
anyOf: [{ type: 'string' }, { type: 'integer' }, { type: 'boolean' }],
},
},
examples: [
{ shouldCapitalize: true },
{ shouldCapitalize: true, internalType: 'datetime' },
],
antiExamples: [
{
example: { databank: { primaryContact: 'abc' } },
reason: 'No complex values allowed',
},
{
example: { needsProcessing: null },
reason: 'No null values allowed',
},
],
});
18 changes: 17 additions & 1 deletion packages/schema/lib/schemas/FieldSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const RefResourceSchema = require('./RefResourceSchema');

const FieldChoicesSchema = require('./FieldChoicesSchema');

const FieldMetaSchema = require('./FieldMetaSchema');

const { INCOMPATIBLE_FIELD_SCHEMA_KEYS } = require('../constants');

// the following takes an array of string arrays (string[][]) and returns the follwing string:
Expand Down Expand Up @@ -137,6 +139,11 @@ module.exports = makeSchema(
// TODO: Check if it contains one and ONLY ONE '{{input}}'
pattern: '^.*{{input}}.*$',
},
meta: {
description:
'Allows for additional metadata to be stored on the field. Supports simple key-values only (no sub-objects or arrays).',
$ref: FieldMetaSchema.id,
},
},
examples: [
{ key: 'abc' },
Expand All @@ -148,6 +155,15 @@ module.exports = makeSchema(
},
{ key: 'abc', children: [{ key: 'abc' }] },
{ key: 'abc', type: 'integer', helpText: 'neat' },
{
key: 'abc',
type: 'integer',
meta: {
internalType: 'numeric',
should_call_api: true,
display_order: 1,
},
},
],
antiExamples: [
{
Expand Down Expand Up @@ -190,5 +206,5 @@ module.exports = makeSchema(
],
additionalProperties: false,
},
[RefResourceSchema, FieldChoicesSchema]
[RefResourceSchema, FieldChoicesSchema, FieldMetaSchema]
);
2 changes: 1 addition & 1 deletion packages/schema/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const appDefinition = require('../examples/definition.json');

const copy = (o) => JSON.parse(JSON.stringify(o));

const NUM_SCHEMAS = 56; // changes regularly as we expand
const NUM_SCHEMAS = 57; // changes regularly as we expand

describe('app', () => {
describe('validation', () => {
Expand Down

0 comments on commit 66dc9da

Please sign in to comment.