Skip to content

Commit 2ed9a84

Browse files
author
wellingtonjr3873
committed
Merge branch 'main' of github.com:deco-cx/apps
2 parents ed5e1e3 + 3808a3b commit 2ed9a84

File tree

69 files changed

+1174
-142
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1174
-142
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<hr/>
1+
<hr/>
22

33
<a href="https://deco.cx/discord" target="_blank"><img alt="Discord" src="https://img.shields.io/discord/985687648595243068?label=Discord&color=7289da" /></a>
44
&nbsp;

airtable/actions/createRecords.ts

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import type { AppContext } from "../mod.ts";
2+
import type {
3+
AirtableRecord,
4+
CreateRecordsBody,
5+
FieldSet,
6+
} from "../utils/types.ts";
7+
8+
interface RecordToCreate {
9+
fields: FieldSet;
10+
typecast?: boolean;
11+
}
12+
13+
interface Props {
14+
/**
15+
* @title Base ID
16+
* @description The ID of the Airtable base
17+
*/
18+
baseId: string;
19+
20+
/**
21+
* @title Table ID
22+
* @description The ID of the table within the base
23+
*/
24+
tableId: string;
25+
26+
/**
27+
* @title Records to Create
28+
* @description An array of records to create. Each record must have a fields object.
29+
*/
30+
records: RecordToCreate[];
31+
32+
/**
33+
* @title Typecast
34+
* @description Optional. If true, Airtable will attempt to convert cell values to the appropriate type.
35+
*/
36+
typecast?: boolean;
37+
}
38+
39+
interface ErrorObject {
40+
message: string;
41+
code?: string;
42+
}
43+
44+
interface ResponsePayload {
45+
data: AirtableRecord[];
46+
error?: ErrorObject | null;
47+
}
48+
49+
/**
50+
* @title Create Airtable Records
51+
* @description Creates one or more records in a specified table using OAuth.
52+
*/
53+
const action = async (
54+
props: Props,
55+
_req: Request,
56+
ctx: AppContext,
57+
): Promise<ResponsePayload> => {
58+
try {
59+
if (!ctx.client) {
60+
return {
61+
data: [],
62+
error: { message: "OAuth authentication is required" },
63+
};
64+
}
65+
66+
const validationResult = await ctx.invoke["airtable"].loaders.permissioning
67+
.validatePermissions({
68+
mode: "check",
69+
baseId: props.baseId,
70+
tableIdOrName: props.tableId,
71+
});
72+
73+
if (
74+
"hasPermission" in validationResult && !validationResult.hasPermission
75+
) {
76+
return {
77+
data: [],
78+
error: {
79+
message: validationResult.message || "Access denied",
80+
},
81+
};
82+
}
83+
84+
const { baseId, tableId, records, typecast } = props;
85+
86+
if (!records || records.length === 0) {
87+
return {
88+
data: [],
89+
error: { message: "At least one record is required" },
90+
};
91+
}
92+
93+
if (records.length > 10) {
94+
return {
95+
data: [],
96+
error: { message: "Maximum 10 records can be created at once" },
97+
};
98+
}
99+
100+
const invalidRecords = records.filter((record) => !record.fields);
101+
if (invalidRecords.length > 0) {
102+
return {
103+
data: [],
104+
error: { message: "All records must have a 'fields' property" },
105+
};
106+
}
107+
108+
// Transform records to the format expected by Airtable API
109+
const requestBody: CreateRecordsBody = {
110+
records: records.map((record) => ({
111+
fields: record.fields,
112+
...(record.typecast !== undefined && { typecast: record.typecast }),
113+
})),
114+
};
115+
116+
// Apply global typecast if provided
117+
if (
118+
typecast !== undefined && !records.some((r) => r.typecast !== undefined)
119+
) {
120+
requestBody.typecast = typecast;
121+
}
122+
123+
// deno-lint-ignore no-explicit-any
124+
const response = await (ctx.client as any)["POST /v0/:baseId/:tableId"](
125+
{ baseId, tableId },
126+
{ body: requestBody },
127+
);
128+
129+
if (!response.ok) {
130+
const errorText = await response.text();
131+
return {
132+
data: [],
133+
error: { message: `Error creating records: ${errorText}` },
134+
};
135+
}
136+
137+
const result = await response.json();
138+
const createdRecords = result.records || [];
139+
140+
return {
141+
data: createdRecords,
142+
};
143+
} catch (error) {
144+
const errorMessage = error instanceof Error
145+
? error.message
146+
: "Unknown error occurred";
147+
148+
return {
149+
data: [],
150+
error: { message: errorMessage },
151+
};
152+
}
153+
};
154+
155+
export default action;

airtable/manifest.gen.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
// This file is automatically updated during development when running `dev.ts`.
44

55
import * as $$$$$$$$$0 from "./actions/createField.ts";
6-
import * as $$$$$$$$$1 from "./actions/createTable.ts";
7-
import * as $$$$$$$$$2 from "./actions/deleteRecords.ts";
8-
import * as $$$$$$$$$3 from "./actions/oauth/callback.ts";
9-
import * as $$$$$$$$$4 from "./actions/permissioning/addNewPermitions.ts";
10-
import * as $$$$$$$$$5 from "./actions/updateField.ts";
11-
import * as $$$$$$$$$6 from "./actions/updateRecords.ts";
12-
import * as $$$$$$$$$7 from "./actions/updateTable.ts";
6+
import * as $$$$$$$$$1 from "./actions/createRecords.ts";
7+
import * as $$$$$$$$$2 from "./actions/createTable.ts";
8+
import * as $$$$$$$$$3 from "./actions/deleteRecords.ts";
9+
import * as $$$$$$$$$4 from "./actions/oauth/callback.ts";
10+
import * as $$$$$$$$$5 from "./actions/permissioning/addNewPermitions.ts";
11+
import * as $$$$$$$$$6 from "./actions/updateField.ts";
12+
import * as $$$$$$$$$7 from "./actions/updateRecords.ts";
13+
import * as $$$$$$$$$8 from "./actions/updateTable.ts";
1314
import * as $$$0 from "./loaders/getBaseSchema.ts";
1415
import * as $$$1 from "./loaders/getRecord.ts";
1516
import * as $$$2 from "./loaders/listBases.ts";
@@ -34,13 +35,14 @@ const manifest = {
3435
},
3536
"actions": {
3637
"airtable/actions/createField.ts": $$$$$$$$$0,
37-
"airtable/actions/createTable.ts": $$$$$$$$$1,
38-
"airtable/actions/deleteRecords.ts": $$$$$$$$$2,
39-
"airtable/actions/oauth/callback.ts": $$$$$$$$$3,
40-
"airtable/actions/permissioning/addNewPermitions.ts": $$$$$$$$$4,
41-
"airtable/actions/updateField.ts": $$$$$$$$$5,
42-
"airtable/actions/updateRecords.ts": $$$$$$$$$6,
43-
"airtable/actions/updateTable.ts": $$$$$$$$$7,
38+
"airtable/actions/createRecords.ts": $$$$$$$$$1,
39+
"airtable/actions/createTable.ts": $$$$$$$$$2,
40+
"airtable/actions/deleteRecords.ts": $$$$$$$$$3,
41+
"airtable/actions/oauth/callback.ts": $$$$$$$$$4,
42+
"airtable/actions/permissioning/addNewPermitions.ts": $$$$$$$$$5,
43+
"airtable/actions/updateField.ts": $$$$$$$$$6,
44+
"airtable/actions/updateRecords.ts": $$$$$$$$$7,
45+
"airtable/actions/updateTable.ts": $$$$$$$$$8,
4446
},
4547
"name": "airtable",
4648
"baseUrl": import.meta.url,

airtable/utils/client.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
BaseSchemaResponse,
44
CreateFieldBody,
55
CreateRecordBody,
6+
CreateRecordsBody,
67
CreateTableBody,
78
Field,
89
ListBasesResponse,
@@ -15,6 +16,10 @@ import type {
1516
WhoamiResponse,
1617
} from "./types.ts";
1718

19+
// Type helper to allow both single and batch record creation
20+
type CreateRecordPayload = CreateRecordBody | CreateRecordsBody;
21+
type CreateRecordResponse = AirtableRecord | { records: AirtableRecord[] };
22+
1823
export interface AirtableClient {
1924
/**
2025
* Get current user
@@ -61,14 +66,12 @@ export interface AirtableClient {
6166

6267
/**
6368
* Create records
64-
* NOTE: Airtable API allows creating multiple records (up to 10). This client method is for a single record for simplicity to match service layer.
65-
* For batch creation, the service method `createRecord` would call this and wrap it in an array if needed, or a separate client method for batch could be made.
66-
* Let's define it for creating a single record as per the IAirtableService.createRecord
69+
* NOTE: Airtable API allows creating multiple records (up to 10). This can accept both single and batch creation.
6770
* @see https://airtable.com/developers/web/api/create-records
6871
*/
6972
"POST /v0/:baseId/:tableId": {
70-
body: CreateRecordBody; // { fields: FieldSet, typecast?: boolean }
71-
response: AirtableRecord;
73+
body: CreateRecordPayload; // Single or multiple records
74+
response: CreateRecordResponse;
7275
};
7376

7477
/**

airtable/utils/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ export interface CreateRecordBody {
7575
typecast?: boolean;
7676
}
7777

78+
export interface CreateRecordsBody {
79+
records: Array<{ fields: FieldSet; typecast?: boolean }>;
80+
typecast?: boolean;
81+
}
82+
7883
export interface UpdateRecordsBody {
7984
records: Array<{ id: string; fields: FieldSet }>;
8085
typecast?: boolean;

airtable/utils/ui-templates/selection-page.template.html

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- ignore -->
1+
<!-- deno-fmt-ignore-file -->
22
<!DOCTYPE html>
33
<html lang="en">
44
<head>
@@ -12,7 +12,11 @@
1212

1313
body {
1414
font-family:
15-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
15+
Inter,
16+
-apple-system,
17+
BlinkMacSystemFont,
18+
"Segoe UI",
19+
Roboto,
1620
sans-serif;
1721
margin: 0;
1822
padding: 20px;
@@ -90,7 +94,11 @@
9094
text-align: left;
9195
margin: 0 16px;
9296
font-family:
93-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
97+
Inter,
98+
-apple-system,
99+
BlinkMacSystemFont,
100+
"Segoe UI",
101+
Roboto,
94102
sans-serif;
95103
}
96104

@@ -148,7 +156,11 @@
148156
font-size: 14px;
149157
text-align: left;
150158
font-family:
151-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
159+
Inter,
160+
-apple-system,
161+
BlinkMacSystemFont,
162+
"Segoe UI",
163+
Roboto,
152164
sans-serif;
153165
}
154166

@@ -183,7 +195,11 @@
183195
color: #f5f5f4;
184196
transition: border-color 0.2s;
185197
font-family:
186-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
198+
Inter,
199+
-apple-system,
200+
BlinkMacSystemFont,
201+
"Segoe UI",
202+
Roboto,
187203
sans-serif;
188204
}
189205

@@ -336,7 +352,11 @@
336352
font-size: 14px;
337353
color: #f5f5f4;
338354
font-family:
339-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
355+
Inter,
356+
-apple-system,
357+
BlinkMacSystemFont,
358+
"Segoe UI",
359+
Roboto,
340360
sans-serif;
341361
}
342362

@@ -471,7 +491,11 @@
471491
font-size: 14px;
472492
color: #f5f5f4;
473493
font-family:
474-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
494+
Inter,
495+
-apple-system,
496+
BlinkMacSystemFont,
497+
"Segoe UI",
498+
Roboto,
475499
sans-serif;
476500
}
477501

@@ -486,7 +510,11 @@
486510
color: #737373;
487511
font-size: 14px;
488512
font-family:
489-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
513+
Inter,
514+
-apple-system,
515+
BlinkMacSystemFont,
516+
"Segoe UI",
517+
Roboto,
490518
sans-serif;
491519
}
492520

@@ -519,7 +547,11 @@
519547
align-items: center;
520548
justify-content: center;
521549
font-family:
522-
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
550+
Inter,
551+
-apple-system,
552+
BlinkMacSystemFont,
553+
"Segoe UI",
554+
Roboto,
523555
sans-serif;
524556
}
525557

compat/std/mod.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ export default function Std(props: CommerceProps): App<Manifest, State, [
259259
...props.commerce,
260260
};
261261
const { manifest, state: appState } = vtex(props.commerce);
262-
state = { ...state, ...appState };
262+
const { cachedSearchTerms: _cachedSearchTerms, ...restAppState } = appState;
263+
state = { ...state, ...restAppState };
263264
targetApps["vtex"] = {
264265
importMap: buildImportMap(manifest),
265266
manifest,

0 commit comments

Comments
 (0)