Skip to content

Commit

Permalink
Approach 1: rewrite the output to add signal
Browse files Browse the repository at this point in the history
  • Loading branch information
AdityaHegde committed Jan 10, 2024
1 parent ae97745 commit 565af38
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 15 deletions.
16 changes: 1 addition & 15 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
{
// TODO: SvelteKit recommends extending their config, but it currently triggers type import errors throughout application that we need to fix
// "extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2020",
/**
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using \`import type\` instead of \`import\` for Types.
*/
"importsNotUsedAsValues": "error",
/**
ignoreDeprecations is recommended by the SvelteKit maintainers until SvelteKit 2.0.
See: https://github.com/sveltejs/kit/issues/8650#issuecomment-1607282327
*/
"ignoreDeprecations": "5.0",
"isolatedModules": true,
"resolveJsonModule": true,
/**
To have warnings/errors of the Svelte compiler at the correct position,
enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
Expand All @@ -43,6 +29,6 @@
"**/*.d.ts",
"**/*.ts",
"**/*.svelte",
"**/rollup.config.js",
"**/rollup.config.js"
]
}
7 changes: 7 additions & 0 deletions web-common/orval.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,43 @@ export default defineConfig({
QueryService_MetricsViewAggregation: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewTotals: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewTimeSeries: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewToplist: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewComparison: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewRows: {
query: {
useQuery: true,
signal: true,
},
},
QueryService_MetricsViewTimeRange: {
query: {
useQuery: true,
signal: true,
},
},
},
Expand Down
138 changes: 138 additions & 0 deletions web-common/src/runtime-client/add-signal-argument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import ts from "typescript";
import tsConfig from "../../../tsconfig.json";
import orvalConfig from "../../orval.config";

const Operations: Record<
string,
{
query: {
useQuery: boolean;
signal: boolean;
};
}
> = (orvalConfig as any).api.output.override.operations;

function transformFile(fileName: string) {
const program = ts.createProgram([fileName], {
moduleResolution: ts.ModuleResolutionKind.Node10,
baseUrl: ".",
paths: tsConfig.compilerOptions.paths,
});

const sourceFile = program.getSourceFile(fileName);
if (!sourceFile) return;

const transformationResult = ts.transform(sourceFile, [addSignalTransformer]);

const transformedSourceFile = transformationResult.transformed[0];
const printer = ts.createPrinter();

const result = printer.printNode(
ts.EmitHint.Unspecified,
transformedSourceFile,
sourceFile,
);

console.log(result);
}

function addSignalTransformer(context: ts.TransformationContext) {
return (rootNode: ts.Node) => {
function visit(node: ts.Node): ts.Node {
node = ts.visitEachChild(node, visit, context);

if (
// ignore non variable declarations
!ts.isVariableDeclaration(node) ||
// ignore non identifier names
!ts.isIdentifier(node.name) ||
// ignore methods that are not the query function
!node.name.escapedText.toString().startsWith("queryService")
) {
return node;
}

const queryName = node.name.escapedText.toString();
if (!isOverriddenPostQuery(queryName)) {
return node;
}

const init = node.initializer;
// safeguard to make sure initializer is defined and is an arrow function
if (!init || !ts.isArrowFunction(init) || !ts.isBlock(init.body)) {
return node;
}

const callStatement = init.body.statements[0];
if (
!callStatement ||
!ts.isReturnStatement(callStatement) ||
!callStatement.expression ||
!ts.isCallExpression(callStatement.expression) ||
!callStatement.expression.arguments[0] ||
!ts.isObjectLiteralExpression(callStatement.expression.arguments[0])
) {
return node;
}

const callArg = callStatement.expression.arguments[0];
const lastProp = callArg.properties[callArg.properties.length - 1];
if (lastProp?.name && (lastProp.name as any).escapedText === "signal") {
return node;
}

console.log("Replacing", queryName);
return context.factory.createVariableDeclaration(
queryName,
node.exclamationToken,
node.type,
context.factory.createArrowFunction(
init.modifiers,
init.typeParameters,
[
...init.parameters,
context.factory.createParameterDeclaration(
undefined,
undefined,
"signal",
context.factory.createToken(ts.SyntaxKind.QuestionToken),
context.factory.createTypeReferenceNode("AbortSignal"),
),
],
init.type,
init.equalsGreaterThanToken,
context.factory.createBlock([
context.factory.createReturnStatement(
context.factory.createCallExpression(
callStatement.expression.expression,
callStatement.expression.typeArguments,
[
context.factory.createObjectLiteralExpression(
[
...callArg.properties,
context.factory.createShorthandPropertyAssignment(
"signal",
),
],
true,
),
],
),
),
]),
),
);
}

return ts.visitNode(rootNode, visit);
};
}

function isOverriddenPostQuery(name: string) {
const operationName =
"QueryService_" +
name.replace(/queryService(.)/, (_, c: string) => c.toUpperCase());
return Operations[operationName]?.query?.signal;
}

transformFile(process.argv[2]);

0 comments on commit 565af38

Please sign in to comment.