Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge queue: embarking main (2b2fb52) and #4062 together #4224

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1b74be4
dynamodb resource
eladcon Sep 3, 2023
8cef2a7
wip
eladcon Sep 3, 2023
e15440d
wip
eladcon Sep 3, 2023
6aca521
wip
eladcon Sep 3, 2023
4026e52
console interaction
eladcon Sep 3, 2023
289dec4
Merge branch 'main' into eladc/dynamodb-resource
monadabot Sep 3, 2023
dc49ef3
chore: self mutation (e2e-1of2.diff)
monadabot Sep 3, 2023
50d078c
remove resource from demo
eladcon Sep 3, 2023
cf05779
wip
eladcon Sep 6, 2023
c423558
Merge branch 'main' into eladc/dynamodb-resource
monadabot Sep 6, 2023
48d2c4c
chore: self mutation (build.diff)
monadabot Sep 6, 2023
38defb8
json keys
eladcon Sep 7, 2023
aac1c8f
Merge branch 'eladc/dynamodb-resource' of https://github.com/winglang…
eladcon Sep 7, 2023
395eb58
lint
eladcon Sep 7, 2023
30e79ba
wip
eladcon Sep 7, 2023
4b81794
wip
eladcon Sep 13, 2023
34a8644
Merge branch 'main' into eladc/dynamodb-resource
eladcon Sep 13, 2023
af08519
fix tests
eladcon Sep 13, 2023
d2dbcf9
pr changes
eladcon Sep 18, 2023
7c05f31
Merge branch 'main' into eladc/dynamodb-resource
eladcon Sep 18, 2023
0cda6da
merge main
eladcon Sep 18, 2023
f94cb75
wip
eladcon Sep 19, 2023
046bb4b
fix test
eladcon Sep 19, 2023
c8058ae
wip
eladcon Sep 19, 2023
e4dbcc1
wip
eladcon Sep 19, 2023
0e13279
lint
eladcon Sep 19, 2023
42bb2ee
add dynamodb icon
skyrpex Sep 20, 2023
5b9fc66
fix minor ui issue
skyrpex Sep 20, 2023
f8c534b
fix types error
eladcon Sep 20, 2023
386db32
Merge branch 'main' into eladc/dynamodb-resource
monadabot Sep 20, 2023
4f61357
chore: self mutation (build.diff)
monadabot Sep 20, 2023
d5a8008
Merge of #4062
mergify[bot] Sep 20, 2023
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
2 changes: 1 addition & 1 deletion apps/wing-console/console/app/test/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const describe = (wingfile: string, callback: () => void) => {

await page
.getByTestId("loading-overlay")
.waitFor({ state: "detached", timeout: 10_000 });
.waitFor({ state: "detached", timeout: 15_000 });
});

test.afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { type Page, expect, test } from "@playwright/test";

import { describe } from "../describe.js";
import { getResourceNode } from "../helpers.js";

const addRow = async (page: Page, data?: Record<string, any>) => {
await page.getByTestId("ex.DynamodbTable:new-row").click();
await page.getByTestId("ex.DynamodbTable:new-row").fill(JSON.stringify(data));

const addRowButton = page.getByTestId("ex.DynamodbTable:add-row");
await addRowButton.click();

const row = page.getByTestId("ex.DynamodbTable:row-0");
await expect(row).toBeVisible();
};

describe(`${__dirname}/main.w`, () => {
test("adds new item", async ({ page }) => {
await getResourceNode(page, "root/Default/ex.DynamodbTable").click();

await addRow(page, { id: "1", key1: "value1", key2: "value2" });
});

test("removes row", async ({ page }) => {
await getResourceNode(page, "root/Default/ex.DynamodbTable").click();

await addRow(page, { id: "1", key1: "value1", key2: "value2" });

const deleteButton = page.getByTestId("ex.DynamodbTable:remove-row-0");
await expect(deleteButton).toBeEnabled();
await deleteButton.click();

const row = page.getByTestId("ex.DynamodbTable:row-0");
await expect(row).toBeHidden();
});
});
7 changes: 7 additions & 0 deletions apps/wing-console/console/app/test/ex.dynamodb-table/main.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bring ex;

new ex.DynamodbTable({
name: "table",
attributeDefinitions: { "id": "S" },
hashKey: "id"
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { forwardRef } from "react";

type DynamoDBIconProps = React.PropsWithoutRef<
React.SVGProps<SVGSVGElement>
> & {
title?: string;
titleId?: string;
} & React.RefAttributes<SVGSVGElement>;

export const DynamoDBIcon = forwardRef<SVGSVGElement, DynamoDBIconProps>(
({ title, titleId, ...props }, svgRef) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid"
viewBox="0 0 256 289"
aria-hidden="true"
ref={svgRef}
aria-labelledby={titleId}
{...props}
>
{title && <title id={titleId}>{title}</title>}
<path
fill="#5294CF"
d="M165.3 288.5h3.5l57.2-28.6 1-1.4V30l-1-1.4L168.8 0h-3.6v288.5"
/>
<path
fill="#1F5B98"
d="M90.7 288.5h-3.5L30 259.9l-1.2-2L28.2 31l1.8-2.5L87.2 0h3.6v288.5"
/>
<path fill="#2D72B8" d="M87.3 0h81.4v288.5H87.3V0z" />
<path
fill="#1A476F"
d="m256 137.8-2-.5-27.6-2.5-.4.2-57.3-2.3H87.3L30 135V91.2l57.3-13.3h81.4L226 91.2l21.1 11.2v-7.2l8.9-1-1-1.8-28-20.2-.9.3-57.3-17.7H87.3L30 72.5V28.6L0 63.7v30.7l.2-.2 8.7 1v7.3L0 107.3v30.5h.2l8.7.1v12.8l-7.5.1-1.4-.1v30.5l8.9 4.8v7.4l-8.5 1-.4-.3v30.6L30 260v-44l57.3 17.8h81.4l57.5-17.8.8.3 27.8-19.8 1.2-2-8.9-1v-7.3l-1.2-.4-19 10.2-.7 1.5-57.5 13.2H87.3L30 197.3v-43.8l57.3 2.2v.1h81.4l57.3-2.3 1.3.6 26.8-2.3 1.9-1-8.9-.1v-12.8l8.9-.1"
/>
<path
fill="#2D72B8"
d="M226 216v43.9l30-35.2v-30.4l-29.8 21.6h-.2m0-18.5h.2l29.8-16v-30.7l-30 2.8v44m.2-106.3h-.2V135l30 2.8V107l-29.8-15.9m0-18.5L256 94.2V63.7l-30-35v43.8h.2v.2"
/>
</svg>
);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
TableCellsIcon as SolidTableCellsIcon,
} from "@heroicons/react/24/solid";

import { DynamoDBIcon } from "../icons/dynamodb-icon.js";
import { RedisIcon } from "../icons/redis-icon.js";

const isTest = /(\/test$|\/test:([^/\\])+$)/;
Expand Down Expand Up @@ -75,6 +76,9 @@ export const getResourceIconComponent = (
case "wingsdk.cloud.Test": {
return solid ? SolidBeakerIcon : BeakerIcon;
}
case "wingsdk.ex.DynamodbTable": {
return DynamoDBIcon;
}
default: {
return CubeIcon;
}
Expand Down
88 changes: 88 additions & 0 deletions apps/wing-console/console/server/src/router/dynamodb-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { z } from "zod";

import { createProcedure, createRouter } from "../utils/createRouter.js";
import { DynamodbTableSchema, IDynamodbTableClient, Json } from "../wingsdk.js";

export const createDynamodbTableRouter = () => {
return createRouter({
"dynamodb-table.info": createProcedure
.input(
z.object({
resourcePath: z.string(),
}),
)
.query(async ({ input, ctx }) => {
const simulator = await ctx.simulator();
const schema = simulator.getResourceConfig(
input.resourcePath,
) as DynamodbTableSchema;
const client = simulator.getResource(
input.resourcePath,
) as IDynamodbTableClient;
const rows = await client.scan();
const attributeDefinitions = schema.props.attributeDefinitions;
const hashKey = schema.props.hashKey;
const rangeKey = schema.props.rangeKey;
return {
name: schema.props.name,
attributeDefinitions,
hashKey,
rangeKey,
rows,
};
}),
"dynamodb-table.get": createProcedure
.input(
z.object({
resourcePath: z.string(),
key: z.record(z.any()),
}),
)
.query(async ({ input, ctx }) => {
const simulator = await ctx.simulator();
const client = simulator.getResource(
input.resourcePath,
) as IDynamodbTableClient;
return await client.getItem(input.key as any);
}),
"dynamodb-table.insert": createProcedure
.input(
z.object({
resourcePath: z.string(),
data: z.record(z.any()),
}),
)
.mutation(async ({ input, ctx }) => {
const simulator = await ctx.simulator();
const client = simulator.getResource(
input.resourcePath,
) as IDynamodbTableClient;

await client.putItem(input.data as Json);
}),
"dynamodb-table.delete": createProcedure
.input(
z.object({
resourcePath: z.string(),
data: z.record(z.any()),
}),
)
.mutation(async ({ input, ctx }) => {
const simulator = await ctx.simulator();
const client = simulator.getResource(
input.resourcePath,
) as IDynamodbTableClient;

const schema = simulator.getResourceConfig(
input.resourcePath,
) as DynamodbTableSchema;
const itemKey = {
[schema.props.hashKey]: input.data[schema.props.hashKey],
...(schema.props.rangeKey
? { [schema.props.rangeKey]: input.data[schema.props.rangeKey] }
: {}),
};
return await client.deleteItem(itemKey as Json);
}),
});
};
2 changes: 2 additions & 0 deletions apps/wing-console/console/server/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createAppRouter } from "./app.js";
import { createBucketRouter } from "./bucket.js";
import { createConfigRouter } from "./config.js";
import { createCounterRouter } from "./counter.js";
import { createDynamodbTableRouter } from "./dynamodb-table.js";
import { createFunctionRouter } from "./function.js";
import { createQueueRouter } from "./queue.js";
import { createRedisRouter } from "./redis.js";
Expand All @@ -31,6 +32,7 @@ export const mergeAllRouters = () => {
createRedisRouter(),
createWebsiteRouter(),
createConfigRouter(),
createDynamodbTableRouter(),
);

return { router };
Expand Down
7 changes: 6 additions & 1 deletion apps/wing-console/console/server/src/wingsdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ export type {

export type { ITestRunnerClient } from "@winglang/sdk/lib/std/index.js";

export type { IRedisClient, ITableClient } from "@winglang/sdk/lib/ex/index.js";
export type {
IRedisClient,
ITableClient,
IDynamodbTableClient,
} from "@winglang/sdk/lib/ex/index.js";

export type {
ApiSchema,
DynamodbTableSchema,
TableSchema,
WebsiteSchema,
} from "@winglang/sdk/lib/target-sim/schema-resources.js";
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useNotifications, Attribute } from "@wingconsole/design-system";
import { useCallback, useEffect, useState } from "react";

import { useDynamodbTable } from "../services/use-dynamodb-table.js";
import {
DynamodbTableInteraction,
RawRow,
} from "../ui/dynamodb-table-interaction.js";

export interface DynamodbTableInteractionViewProps {
resourcePath: string;
}

export const DynamodbTableInteractionView = ({
resourcePath,
}: DynamodbTableInteractionViewProps) => {
const notifications = useNotifications();

const showError = useCallback(
(error: string) => {
notifications.showNotification("Error", {
body: error,
type: "error",
});
},
[notifications],
);

const { table, removeRow, addRow, loading } = useDynamodbTable({
resourcePath,
});

const [rows, setRows] = useState<{ data: {}; error: string }[]>([]);

const onAddRow = useCallback(
async (data: RawRow) => {
try {
if (data.error) {
showError(`Row error: ${data.error}`);
return;
}

const row = JSON.parse(data.data);
await addRow(row);
} catch (error: any) {
showError(`Failed to add row: ${error.message}`);
}
},
[addRow, showError],
);

const onRemoveRow = useCallback(
async (index: number) => {
await removeRow(index);
},
[removeRow],
);

useEffect(() => {
if (table.data?.rows) {
const rows = table.data.rows.map((row) => {
return {
data: row,
error: "",
};
});
setRows(rows);
}
}, [table.data?.rows]);

return (
<div className="h-full flex-1 flex flex-col text-sm">
<div className="flex flex-col gap-2">
<div className="flex flex-col space-y-1">
<div className="w-full">
<Attribute name="Name" value={table.data?.name} noLeftPadding />
</div>

<div className="flex items-center gap-2 justify-end">
<DynamodbTableInteraction
rows={rows}
hashKey={table.data?.hashKey}
rangeKey={table.data?.rangeKey}
onAddRow={onAddRow}
onRemoveRow={onRemoveRow}
loading={loading}
/>
</div>
</div>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ApiInteractionView } from "./api-interaction-view.js";
import { BucketInteractionView } from "./bucket-interaction-view.js";
import { CounterInteractionView } from "./counter-interaction-view.js";
import { DynamodbTableInteractionView } from "./dynamodb-table-interaction-view.js";
import { FunctionInteractionView } from "./function-interaction-view.js";
import { QueueInteractionView } from "./queue-interaction-view.js";
import { RedisInteractionView } from "./redis-interaction-view.js";
Expand Down Expand Up @@ -50,6 +51,9 @@ export const ResourceInteractionView = ({
case "wingsdk.cloud.Website": {
return <WebsiteInteractionView resourcePath={resourcePath} />;
}
case "wingsdk.ex.DynamodbTable": {
return <DynamodbTableInteractionView resourcePath={resourcePath} />;
}
default: {
return <UnsupportedInteractionView resourceType={resourceType} />;
}
Expand Down
48 changes: 48 additions & 0 deletions apps/wing-console/console/ui/src/services/use-dynamodb-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useCallback, useMemo } from "react";

import { trpc } from "./trpc.js";

export interface UseTableOptions {
resourcePath: string;
}

export const useDynamodbTable = ({ resourcePath }: UseTableOptions) => {
const table = trpc["dynamodb-table.info"].useQuery({ resourcePath });
const tableInsert = trpc["dynamodb-table.insert"].useMutation();
const tableDelete = trpc["dynamodb-table.delete"].useMutation();

const addRow = useCallback(
async (row: any) => {
await tableInsert.mutateAsync({
resourcePath,
data: row,
});
},
[tableInsert, resourcePath],
);

const removeRow = useCallback(
async (index: number) => {
const row = table.data?.rows[index];
if (!row) {
return;
}
await tableDelete.mutateAsync({
resourcePath,
data: row,
});
},
[tableDelete, resourcePath, table.data?.rows],
);

const loading = useMemo(() => {
return table.isFetching || tableInsert.isLoading || tableDelete.isLoading;
}, [tableInsert.isLoading, tableDelete.isLoading, table.isFetching]);

return {
table,
addRow,
removeRow,
loading,
};
};
Loading
Loading