Oleg Isonen cd0174807d chore: use console.info instead of console.log (#3049)
## Description

We allow console.info (btw we should also allow warn/error/info), we
only disallow console.log in the linter because that's what we use for
debugging.

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @TrySound , I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
2024-03-24 12:52:46 +01:00

211 lines
5.7 KiB
TypeScript

import { PrismaClient } from "./client";
type BaseProp = {
id: string;
instanceId: string;
name: string;
required?: boolean;
};
type Prop = BaseProp &
(
| { type: "number"; value: number }
| { type: "string"; value: string }
| { type: "boolean"; value: boolean }
| { type: "asset"; value: string }
| { type: "page"; value: string | { pageId: string; instanceId: string } }
| { type: "string[]"; value: string[] }
| { type: "dataSource"; value: string }
| { type: "expression"; value: string }
| {
type: "action";
value: Array<{ type: "execute"; args: string[]; code: string }>;
}
);
type PropsList = Prop[];
type DataSourceVariableValue =
| { type: "number"; value: number }
| { type: "string"; value: string }
| { type: "boolean"; value: boolean }
| { type: "string[]"; value: string[] }
| { type: "json"; value: unknown };
type DataSource =
| {
type: "variable";
id: string;
scopeInstanceId?: string;
name: string;
value: DataSourceVariableValue;
}
| {
type: "expression";
id: string;
scopeInstanceId?: string;
name: string;
code: string;
};
type DataSourcesList = DataSource[];
const dataSourceVariablePrefix = "$ws$dataSource$";
const encodeDataSourceVariable = (id: string) => {
const encoded = id.replaceAll("-", "__DASH__");
return `${dataSourceVariablePrefix}${encoded}`;
};
export default async () => {
const client = new PrismaClient({
// Uncomment to see the queries in console as the migration runs
// log: ["query", "info", "warn", "error"],
});
await client.$transaction(
async (prisma) => {
const chunkSize = 1000;
let cursor: undefined | string = undefined;
let hasNext = true;
while (hasNext) {
console.info("CHUNK", cursor);
console.time("read");
const cursorOptions: {} = cursor
? {
skip: 1, // Skip the cursor
cursor: { id: cursor },
}
: {};
const builds = await prisma.build.findMany({
select: {
id: true,
props: true,
dataSources: true,
},
take: chunkSize,
orderBy: {
id: "asc",
},
where: {
AND: [
{
OR: [
{
props: {
not: "[]",
},
},
{
dataSources: {
not: "[]",
},
},
],
},
{
deployment: null,
},
],
},
...cursorOptions,
});
console.timeEnd("read");
console.time("parse-change");
cursor = builds.at(-1)?.id;
hasNext = builds.length === chunkSize;
const changedBuilds: typeof builds = [];
for (const build of builds) {
const buildId = build.id;
try {
let dataSourcesList: DataSourcesList = JSON.parse(
build.dataSources
);
let propsList: PropsList = JSON.parse(build.props);
let changed = false;
const dataSources = new Map(
dataSourcesList.map((dataSource) => [dataSource.id, dataSource])
);
// convert type=dataSource to type=expression
propsList = propsList.map((prop) => {
if (prop.type === "dataSource") {
changed = true;
const dataSourceId = prop.value;
const dataSource = dataSources.get(dataSourceId);
if (dataSource?.type === "variable") {
return {
...prop,
type: "expression",
value: encodeDataSourceVariable(dataSourceId),
};
}
if (dataSource?.type === "expression") {
return {
...prop,
type: "expression",
value: dataSource.code,
};
}
}
return prop;
});
// delete all expression data sources
dataSourcesList = dataSourcesList.filter((dataSource) => {
if (dataSource.type === "variable") {
changed = true;
return true;
}
return false;
});
if (changed) {
build.dataSources = JSON.stringify(dataSourcesList);
build.props = JSON.stringify(propsList);
changedBuilds.push(build);
}
} catch {
console.info(`build ${buildId} cannot be converted`);
}
}
console.timeEnd("parse-change");
console.info("changedBuilds.length", changedBuilds.length);
console.time("update");
const sql = `
UPDATE "Build"
SET
"props" = data."props",
"dataSources" = data."dataSources"
FROM unnest(ARRAY[$1], ARRAY[$2], ARRAY[$3]) as data(id, props, "dataSources")
WHERE "Build"."id" = data."id"
`;
if (changedBuilds.length === 0) {
return;
}
const res = await prisma.$executeRawUnsafe(
sql,
changedBuilds.map((changedBuild) => changedBuild.id),
changedBuilds.map((changedBuild) => changedBuild.props),
changedBuilds.map((changedBuild) => changedBuild.dataSources)
);
console.timeEnd("update");
console.info("res", res);
}
},
{ timeout: 3600000 }
);
};