Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
77 changes: 61 additions & 16 deletions packages/typescript/scripts/generateSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,21 @@ const SRC = join(ROOT, "src", "api");
const TEST = join(ROOT, "test");

type SourceTransform = (source: string, fileName: string) => string;
type SyncVariant = "sync" | "generators";

function generateSyncFile(
srcPath: string,
destPath: string,
transform: SourceTransform,
variant: SyncVariant = "sync",
): string {
const source = readFileSync(srcPath, "utf-8");

// Normalize line endings to LF
const normalized = source.replace(/\r/g, "");

// Phase 1: Process sync directives (text-based, operates on comments/lines)
const afterDirectives = processDirectives(normalized.split("\n")).join("\n");
const afterDirectives = processDirectives(normalized.split("\n"), variant).join("\n");

// Phase 2: AST-based async→sync transforms
const fileName = destPath.split("/").pop()!;
Expand All @@ -85,14 +87,24 @@ function generateSyncFile(

// ── Directive processing ─────────────────────────────────────────

function processDirectives(lines: string[]): string[] {
function processDirectives(lines: string[], variant: SyncVariant): string[] {
const output: string[] = [];
let skipBlock = false;
let syncOnlyBlock = false;
let generatorsOnlyBlock = false;

for (const line of lines) {
const trimmed = line.trim();

if (trimmed === "// @generators-skip-block-start") {
skipBlock = variant === "generators";
continue;
}
if (trimmed === "// @generators-skip-block-end") {
skipBlock = false;
continue;
}

// Block-skip markers
if (trimmed === "// @sync-skip-block-start") {
skipBlock = true;
Expand All @@ -104,6 +116,20 @@ function processDirectives(lines: string[]): string[] {
}
if (skipBlock) continue;

if (trimmed === "// @generators-only-start") {
generatorsOnlyBlock = true;
continue;
}
if (trimmed === "// @generators-only-end") {
generatorsOnlyBlock = false;
continue;
}

if (generatorsOnlyBlock) {
if (variant === "generators") output.push(uncommentLine(line));
continue;
}

// Sync-only markers (uncomment block)
if (trimmed === "// @sync-only-start") {
syncOnlyBlock = true;
Expand All @@ -115,17 +141,11 @@ function processDirectives(lines: string[]): string[] {
}

if (syncOnlyBlock) {
const indent = line.match(/^(\s*)/)![1];
const rest = line.slice(indent.length);
if (rest.startsWith("// ")) {
output.push(indent + rest.slice(3));
}
else if (rest === "//") {
output.push(indent);
}
else {
output.push(line);
}
output.push(uncommentLine(line));
continue;
}

if (variant === "generators" && line.includes("// @generators-skip")) {
continue;
}

Expand All @@ -135,19 +155,37 @@ function processDirectives(lines: string[]): string[] {
}

// Single-line replacement: // @sync: <replacement>
const syncReplaceMatch = line.match(/\/\/ @sync: (.+)$/);
if (syncReplaceMatch) {
const generatorsReplaceMatch = line.match(/\/\/ @generators: (.+)$/);
if (variant === "generators" && generatorsReplaceMatch) {
const indent = line.match(/^(\s*)/)![1];
output.push(indent + generatorsReplaceMatch[1]);
continue;
}

const lineWithoutGeneratorsDirective = generatorsReplaceMatch
? line.slice(0, generatorsReplaceMatch.index).trimEnd()
: line;
const syncReplaceMatch = lineWithoutGeneratorsDirective.match(/\/\/ @sync: (.+)$/);
if (syncReplaceMatch) {
const indent = lineWithoutGeneratorsDirective.match(/^(\s*)/)![1];
output.push(indent + syncReplaceMatch[1]);
continue;
}

output.push(line);
output.push(lineWithoutGeneratorsDirective);
}

return output;
}

function uncommentLine(line: string): string {
const indent = line.match(/^(\s*)/)![1];
const rest = line.slice(indent.length);
if (rest.startsWith("// ")) return indent + rest.slice(3);
if (rest === "//") return indent;
return line;
}

// ── AST-based transforms ────────────────────────────────────────

interface Edit {
Expand Down Expand Up @@ -624,6 +662,13 @@ export function generateSync(): void {
));
}

generatedFiles.push(generateSyncFile(
join(TEST, "async", "api.bench.ts"),
join(TEST, "generators", "api.bench.ts"),
(source, fileName) => transformAsyncSource(source, fileName, false),
"generators",
));

console.log("Formatting...");
formatFiles(generatedFiles);
console.log("Done.");
Expand Down
2 changes: 1 addition & 1 deletion packages/typescript/src/api/async/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export interface TranspileOutput {
}

// @sync-only-start
// export { all, defer, type APIRequestGenerator, type AnyAPIRequestGenerator, type DeferredAPIRequestGenerator, type ExecutedGeneratorsResults } from "./generatorSupport.ts";
// export { all, defer, type APIRequestGenerator, type AnyAPIRequestGenerator, type AllAPIRequestGenerator, type DeferredAPIRequestGenerator, type ExecutedGeneratorsResults } from "./generatorSupport.ts";
// import {executeRequestGenerators, type ExecutedGeneratorsResults, type AnyAPIRequestGenerator} from "./generatorSupport.ts";
// @sync-only-end

Expand Down
2 changes: 1 addition & 1 deletion packages/typescript/src/api/sync/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export interface TranspileOutput {
sourceMapText?: string;
}

export { all, type AnyAPIRequestGenerator, type APIRequestGenerator, defer, type DeferredAPIRequestGenerator, type ExecutedGeneratorsResults } from "./generatorSupport.ts";
export { all, type AllAPIRequestGenerator, type AnyAPIRequestGenerator, type APIRequestGenerator, defer, type DeferredAPIRequestGenerator, type ExecutedGeneratorsResults } from "./generatorSupport.ts";
import {
type AnyAPIRequestGenerator,
type ExecutedGeneratorsResults,
Expand Down
Loading