Skip to content

Commit

Permalink
feature: read files from assets directory
Browse files Browse the repository at this point in the history
  • Loading branch information
vanppo committed Jan 10, 2025
1 parent bf5749f commit a337fe9
Show file tree
Hide file tree
Showing 19 changed files with 327 additions and 247 deletions.
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
29 changes: 14 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) {
newFunctionNames.add(e.name);

Expand All @@ -97,17 +98,15 @@ 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 functionPath = join(PROJECT_ASSETS_DIRECTORY, BASE_PATH, functionName);

for await (const path of listFilesRec(functionPath)) {
yield [join(functionPath, path), new FileEntryConstructor(path)];
Expand All @@ -123,12 +122,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 +307,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 +317,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

0 comments on commit a337fe9

Please sign in to comment.