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

[JET-2406] refactor: read files from assets directory #78

Merged
merged 2 commits into from
Jan 13, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main]
pull_request:
branches: [main, 'epic/**']
branches: [main, "epic/**"]

jobs:
ci:
Expand All @@ -16,7 +16,7 @@ jobs:
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: "v1.x"
deno-version-file: .tool-versions

- name: Check formatting
run: deno fmt --check
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: "v1.x"
deno-version-file: .tool-versions

- name: Build and Archive jcli
run: |
Expand Down
7 changes: 5 additions & 2 deletions src/api/mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { join } from "path";

import { Console, consoleImpl } from "@/api/console.ts";
import { DB, db, DBClass } from "@/api/db.ts";
import { DirEntry, FS, fs, MkdirOptions, WriteFileOptions } from "@/api/fs.ts";
Expand All @@ -18,6 +20,9 @@ import {
jcliConfigDotJSONPath,
} from "@/jcli/config/jcli-config-json.ts";

export const PROJECT_ASSETS_DIRECTORY = ".jcli";
export const PROJECT_DB_PATH = join(PROJECT_ASSETS_DIRECTORY, "project.sqlite");

let config: Config<JcliConfigDotJSON>;

export function getConfig(): Config<JcliConfigDotJSON> {
Expand All @@ -28,8 +33,6 @@ export function getConfig(): Config<JcliConfigDotJSON> {
return config;
}

export const PROJECT_DB_PATH = ".jcli/project.sqlite";

export type {
Console,
DB,
Expand Down
7 changes: 4 additions & 3 deletions src/jcli/file/files-man.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { extname, join } from "path";
import { api, DirEntry, FS } from "@/api/mod.ts";
import { api, DirEntry, FS, PROJECT_ASSETS_DIRECTORY } from "@/api/mod.ts";
import { digest } from "@/jcli/crypto.ts";

export class FileEntry {
Expand All @@ -21,8 +21,9 @@ export class FileEntry {

async content(): Promise<string> {
if (undefined === this.#content) {
const path = await api.fs.realPath(this.path);
this.#content = await api.fs.readTextFile(path);
const path = join(PROJECT_ASSETS_DIRECTORY, this.path);
const file = await api.fs.realPath(path);
this.#content = await api.fs.readTextFile(file);
}

return this.#content;
Expand Down
30 changes: 15 additions & 15 deletions src/jcli/file/functions-man.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { join } from "path";
import { join, relative } from "path";

import { chunk } from "@/utility/async-iterable.ts";

import { api, DBClass } from "@/api/mod.ts";
import { api, DBClass, PROJECT_ASSETS_DIRECTORY } from "@/api/mod.ts";
import {
FileChange,
FileEntry,
Expand All @@ -13,7 +13,7 @@ import { digest } from "@/jcli/crypto.ts";

import { PreparedQuery } from "sqlite";

const BASE_PATH = "./functions";
const BASE_PATH = "functions";

interface FunctionFileEntryBase {
serverPath: string;
Expand Down Expand Up @@ -76,9 +76,10 @@ async function* diffFunctions(
const existingFunctionNames = listFunctionNamesQuery();
const newFunctionNames = new Set<string>();

const basePath = await api.fs.realPath(BASE_PATH);
const root = join(PROJECT_ASSETS_DIRECTORY, BASE_PATH);
const directory = await api.fs.realPath(root);

for await (const e of api.fs.readDir(basePath)) {
for await (const e of api.fs.readDir(directory)) {
if (e.isDirectory) {
fahchen marked this conversation as resolved.
Show resolved Hide resolved
newFunctionNames.add(e.name);

Expand All @@ -97,19 +98,18 @@ function buildFunctionFileRelativePath(
path: string,
functionName: string,
): string {
/* basePathLength = "./functions" - "./" + "/" + "my_func" */
const basePathLength = (BASE_PATH.length - 2) + 1 + functionName.length;
/* functions/my_func/users/index.ts -> users/index.ts */
return path.slice(basePathLength + 1);
return relative(join(BASE_PATH, functionName), path);
}

async function* listFunctionFileEntries<T extends FileEntry>(
functionName: string,
FileEntryConstructor: new (path: string) => T,
): AsyncIterable<[path: string, entry: T]> {
const functionPath = join(BASE_PATH, functionName);
const directoryPath = join(PROJECT_ASSETS_DIRECTORY, functionPath);

for await (const path of listFilesRec(functionPath)) {
for await (const path of listFilesRec(directoryPath)) {
yield [join(functionPath, path), new FileEntryConstructor(path)];
}
}
Expand All @@ -123,12 +123,12 @@ async function* diffFunctionFiles<
>,
FileEntryConstructor: new (path: string) => T,
): AsyncIterable<FileChange<T>> {
const prefix = join(BASE_PATH, functionName);

const functionFilesWas = new Map<string, T>(
listFunctionFileHashesQuery()
.filter(([path]) => path.startsWith(`functions/${functionName}`))
.map((
[path, hash],
) => {
.filter(([path]) => path.startsWith(prefix))
.map(([path, hash]) => {
const entry = new FileEntryConstructor(
buildFunctionFileRelativePath(path, functionName),
);
Expand Down Expand Up @@ -308,7 +308,7 @@ async function pushFunctionFiles(
options?: PushFunctionsOptions,
): Promise<void> {
for await (
const fileChanges of chunk(
const changes of chunk(
diffFunctionFiles(
functionName,
queries.listFunctionFileHashesQuery,
Expand All @@ -318,7 +318,7 @@ async function pushFunctionFiles(
)
) {
await Promise.allSettled(
fileChanges.map((fileChange) =>
changes.map((fileChange) =>
pushFunctionFile(fileChange, queries, projectId, functionName)
),
);
Expand Down
6 changes: 4 additions & 2 deletions src/jcli/file/migrations-man.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { join, parse } from "path";
import { PreparedQuery } from "sqlite";

import { api, DBClass } from "@/api/mod.ts";
import { api, DBClass, PROJECT_ASSETS_DIRECTORY } from "@/api/mod.ts";
import {
FileChange,
FileEntry,
Expand Down Expand Up @@ -97,7 +97,9 @@ export class MigrationFileEntry extends FileEntry {
async function* listMigrationFileEntries(): AsyncIterable<
[key: number, entry: MigrationFileEntry]
> {
for await (const relativePath of listFiles(BASE_PATH, ".sql")) {
const directory = join(PROJECT_ASSETS_DIRECTORY, BASE_PATH);

for await (const relativePath of listFiles(directory, ".sql")) {
const path = join(BASE_PATH, relativePath);
const entry = new MigrationFileEntry(path);

Expand Down
11 changes: 6 additions & 5 deletions src/jcli/file/workflows-man.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { join } from "path";
import { PreparedQuery } from "sqlite";

import { api, DBClass, DirEntry } from "@/api/mod.ts";
import { api, DBClass, DirEntry, PROJECT_ASSETS_DIRECTORY } from "@/api/mod.ts";
import { digest } from "@/jcli/file/project.ts";
import { chunk } from "@/utility/async-iterable.ts";
import { WorkflowDraftWorkflow } from "@/jet/workflow.ts";
Expand Down Expand Up @@ -40,7 +40,7 @@ interface WorkflowDeleted {

type WorkflowChange = WorkflowCreated | WorkflowUpdated | WorkflowDeleted;

const BASE_PATH = "./workflows";
const BASE_PATH = "workflows";

function isJSONFile(file: DirEntry): boolean {
return file.isFile && /\w+\.json$/i.test(file.name);
Expand All @@ -62,13 +62,14 @@ export async function parseParams(
async function* diffWorkflows(
listWorkflowsQuery: () => ReadonlyMap<string, string>,
): AsyncIterable<WorkflowChange> {
const basePath = await api.fs.realPath(BASE_PATH);
const root = join(PROJECT_ASSETS_DIRECTORY, BASE_PATH);
const directory = await api.fs.realPath(root);
const remoteWorkflows = listWorkflowsQuery();
const localNames = new Set<string>();

for await (const file of api.fs.readDir(basePath)) {
for await (const file of api.fs.readDir(directory)) {
if (isJSONFile(file)) {
const params = await readParams(basePath, file.name);
const params = await readParams(directory, file.name);
const { name, hash } = await parseParams(params);

if (remoteWorkflows.has(name) && remoteWorkflows.get(name) !== hash) {
Expand Down
46 changes: 23 additions & 23 deletions src/jcli/project-builder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { api, PROJECT_DB_PATH } from "@/api/mod.ts";
import { api, PROJECT_ASSETS_DIRECTORY, PROJECT_DB_PATH } from "@/api/mod.ts";
import { createConfigurationQuery } from "@/api/db/queries/create-configuration.ts";
import { createFunctionsQuery } from "@/api/db/queries/create-functions.ts";
import { createMetadataQuery } from "@/api/db/queries/create-metadata.ts";
Expand Down Expand Up @@ -70,9 +70,9 @@ class DatabaseBuilder extends BaseBuilder {
}

async provisionFiles(): Promise<void> {
const directory = this.directory;
const directory = join(this.directory, PROJECT_ASSETS_DIRECTORY);

await api.fs.mkdir(join(directory, ".jcli"));
await api.fs.mkdir(directory);
}

provisionDatabases(): void {
Expand Down Expand Up @@ -202,16 +202,16 @@ class FileBuilder extends BaseBuilder {
}

async provisionFiles(): Promise<void> {
const directory = this.directory;
const directory = join(this.directory, PROJECT_ASSETS_DIRECTORY);

await api.fs.mkdir(this.directory);
await api.fs.mkdir(directory);
await api.fs.mkdir(join(directory, ".jcli"));
await api.fs.mkdir(join(directory, "functions"));
await api.fs.mkdir(join(directory, "migrations"));
await api.fs.mkdir(join(directory, "workflows"));

const projectDotJSON = new Config<ProjectDotJSON>(
projectDotJSONPath(directory),
projectDotJSONPath(this.directory),
);

await projectDotJSON.set(this.configuration, { createNew: true });
Expand Down Expand Up @@ -275,14 +275,10 @@ class FileBuilder extends BaseBuilder {
createFunctionQuery.execute({ name: func.name });

for (const { path, hash, code } of func.files) {
const filePath = join("functions", func.name, path);

writeFunctionFile(join(this.directory, filePath), code);
const file = join("functions", func.name, path);

createFunctionFileQuery.execute({
path: filePath,
hash,
});
await writeFunctionFile(this.directory, file, code);
createFunctionFileQuery.execute({ path: file, hash });
}
}

Expand Down Expand Up @@ -311,15 +307,12 @@ class FileBuilder extends BaseBuilder {

for await (const { version, name, hash, content } of migrations) {
const versionStr = this.buildVersionString(version);

const path = name
? join("migrations", `${versionStr}_${name}.sql`)
: join("migrations", `${versionStr}.sql`);
const file = join(this.directory, PROJECT_ASSETS_DIRECTORY, path);

await api.fs.writeTextFile(join(this.directory, path), content, {
createNew: true,
});

await api.fs.writeTextFile(file, content, { createNew: true });
createMigrationQuery.execute({ path, hash });
}

Expand All @@ -340,9 +333,10 @@ class FileBuilder extends BaseBuilder {
);

for await (const { name, data, hash } of workflows) {
const path = join(this.directory, "workflows", `${name}.json`);
const directory = join(this.directory, PROJECT_ASSETS_DIRECTORY);
const file = join(directory, "workflows", `${name}.json`);
const definition = JSON.stringify({ name, ...data }, null, 2);
await api.fs.writeTextFile(path, definition, { createNew: true });
await api.fs.writeTextFile(file, definition, { createNew: true });

createWorkflowQuery.execute({ name, hash });
}
Expand Down Expand Up @@ -408,9 +402,15 @@ class ProjectBuilder {
}
}

async function writeFunctionFile(path: string, code: string) {
await api.fs.mkdir(dirname(path), { recursive: true });
await api.fs.writeTextFile(path, code, { createNew: true });
async function writeFunctionFile(
directory: string,
path: string,
code: string,
) {
const file = join(directory, PROJECT_ASSETS_DIRECTORY, path);

await api.fs.mkdir(dirname(file), { recursive: true });
await api.fs.writeTextFile(file, code, { createNew: true });
}

export { ProjectBuilder };
1 change: 1 addition & 0 deletions src/subcommands/clone/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export default async function action(
builder.buildMetadata(projectId);
await builder.buildFunctions(project.functions);
await builder.buildMigrations(project.migrations);
await builder.buildWorkflows(project.workflows);
}
5 changes: 3 additions & 2 deletions test/subcommands/admin/projects/create/action_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ describe("works", () => {
await action(options, "my_proj");

assert(api.fs.hasDir("my_proj"));
assert(api.fs.hasDir("my_proj/migrations"));
assert(api.fs.hasDir("my_proj/functions"));
assert(api.fs.hasDir("my_proj/.jcli"));
assert(api.fs.hasDir("my_proj/.jcli/functions"));
assert(api.fs.hasDir("my_proj/.jcli/migrations"));
assert(api.fs.hasDir("my_proj/.jcli/workflows"));
});

it("provision my_proj/project.json", async () => {
Expand Down
Loading
Loading