Skip to content

Commit

Permalink
Saving files locally in both yaml and json format. (#904)
Browse files Browse the repository at this point in the history
Co-authored-by: Evan Shi <[email protected]>
  • Loading branch information
TayyabAsghar and evshi authored Nov 15, 2024
1 parent becf415 commit 0a37d2b
Show file tree
Hide file tree
Showing 19 changed files with 14,288 additions and 7,441 deletions.
6 changes: 6 additions & 0 deletions .changeset/six-scissors-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ensembleui/js-commons": patch
"@ensembleui/cli": patch
---

Add apps:get command for copying yaml to local folder
5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"format": "prettier --write \"**/*.{ts,tsx,md,yaml,json}\"",
"release": "turbo run build --filter='./packages/*' && changeset publish",
"schema:generate": "ts-node --esm ./scripts/generateSchema.ts"
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"eslint": "^8.49.0",
"eslint-plugin-react-hooks": "^4.6.0",
"jest": "^27.5.1",
"lint-staged": "^14.0.1",
"lodash-es": "^4.17.21",
"prettier": "^3.0.3",
"ts-jest": "27.1.5",
"ts-json-schema-generator": "^1.5.0",
Expand Down
1 change: 0 additions & 1 deletion packages/cli/.eslintignore

This file was deleted.

3 changes: 2 additions & 1 deletion packages/cli/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"extends": ["oclif", "oclif-typescript", "prettier"]
"extends": ["oclif", "oclif-typescript", "prettier"],
"ignorePatterns": ["dist/"]
}
2 changes: 1 addition & 1 deletion packages/cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/node_modules
oclif.manifest.json


tsconfig.tsbuildinfo
yarn.lock
package-lock.json

2 changes: 0 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@
"@types/mocha": "^10",
"@types/node": "^16.18.45",
"chai": "^4",
"eslint": "^8",
"eslint-plugin-unicorn": "56.0.0",
"eslint-config-oclif": "^5",
"eslint-config-oclif-typescript": "^3",
"eslint-config-prettier": "^9",
"mocha": "^10",
"oclif": "^4",
"shx": "^0.3.3",
Expand Down
48 changes: 48 additions & 0 deletions packages/cli/src/commands/apps/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { getFirestoreApplicationTransporter, getLocalApplicationTransporter } from '@ensembleui/js-commons'
import {Args, Command, Flags} from '@oclif/core'
import { get } from 'lodash-es'
import path from 'node:path'

import { db } from '../../firebase.js'
import { getStoredToken, signInWithEmailPassword } from '../../utils.js'

export default class AppsGet extends Command {
static override args = {
id: Args.string({description: 'Ensemble App ID', required: true}),
}

static override description = 'Get a local copy of the app'

static override examples = [
'<%= config.bin %> <%= command.id %>',
]

static override flags = {
dir: Flags.string({char: 'd', description: 'Where the app should be copied to'}),
}

public async run(): Promise<void> {
const { args, flags } = await this.parse(AppsGet);
const cachedAuth = getStoredToken();
if (!cachedAuth) {
this.error('Please login first.')
}

const { email, password } = cachedAuth;
await signInWithEmailPassword(email, password);

const appId = args.id;
const dir = path.join(process.cwd(), flags.dir ?? appId);

try {
const firestoreAppTransporter = getFirestoreApplicationTransporter(db);
const localAppTransporter = getLocalApplicationTransporter(this.config.dataDir);
const app = await firestoreAppTransporter.get(appId);
await localAppTransporter.put(app, dir);

this.log(`Wrote app ${app.name} to ${dir}`)
} catch (error) {
this.error(get(error, "message") ?? "An error occurred")
}
}
}
20 changes: 5 additions & 15 deletions packages/cli/src/commands/apps/list.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApplicationDTO, CollectionsName } from '@ensembleui/js-commons'
import { getCloudApps } from '@ensembleui/js-commons'
import {Command} from '@oclif/core'
import { collection, getDocs, query, where } from 'firebase/firestore/lite';
import { jwtDecode } from "jwt-decode";
import { get } from 'lodash-es';

Expand Down Expand Up @@ -29,23 +28,14 @@ export default class AppsList extends Command {
if (!userId) {
this.error('Invalid token. Please try logging in again.')
}

const q = query(
collection(db, CollectionsName.Apps),
where("isArchived", "==", false),
where(`collaborators.users_${userId}`, "in", ["read", "write", "owner"]),
);

const result = await getDocs(q);
const list = result.docs.map((doc) => {
const appData = doc.data() as ApplicationDTO;
return {
const result = await getCloudApps(db, userId)
const list = result.map((appData) => ({
description: appData.description,
id: doc.id,
id: appData.id,
name: appData.name,
role: appData.collaborators?.[`users_${userId}`]
}
});
}));

// TODO: tabulate results
this.log(JSON.stringify(list, null, 2))
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/test/commands/apps/get.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {runCommand} from '@oclif/test'
import {expect} from 'chai'

describe.skip('apps:get', () => {
it('runs apps:get cmd', async () => {
const {stdout} = await runCommand('apps:get')
expect(stdout).to.contain('hello world')
})

it('runs apps:get --name oclif', async () => {
const {stdout} = await runCommand('apps:get --name oclif')
expect(stdout).to.contain('hello oclif')
})
})
3 changes: 2 additions & 1 deletion packages/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"strict": true,
"target": "es2022",
"moduleResolution": "node16",
"skipLibCheck": true
"skipLibCheck": true,
"composite": true
},
"include": ["./src/**/*"],
"ts-node": {
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-config-custom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"version": "0.0.1",
"private": true,
"devDependencies": {
"prettier": "^3.0.3",
"eslint": "^8",
"@vercel/style-guide": "^4.0.2",
"eslint-config-prettier": "^9.0.0",
"eslint-config-turbo": "^1.10.12",
Expand Down
6 changes: 6 additions & 0 deletions packages/js-commons/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"name": "@ensembleui/js-commons",
"version": "0.0.4",
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/index.mjs"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
Expand Down
34 changes: 17 additions & 17 deletions packages/js-commons/src/dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
*
* Mostly equivalent to raw JSON definition over wire
*/
export interface HasManifest {
manifest?: Record<
string,
Partial<EnsembleDocument> & {
relativePath?: string;
}
>;
}

export interface EnsembleDocument {
readonly id: string;
readonly name: string;
Expand Down Expand Up @@ -33,33 +42,24 @@ export enum EnsembleDocumentType {
}

export interface ApplicationDTO
extends Omit<EnsembleDocument, "content" | "type"> {
readonly description?: string;
readonly isPublic?: boolean;
readonly isAutoGenerated?: boolean;
extends Omit<EnsembleDocument, "type" | "content">,
HasManifest {
readonly isReact?: boolean;
readonly isAutoGenerated?: boolean;
readonly status?: string;
readonly category?: AppCategory;
readonly collaborators?: Map<string, AccessType>;
readonly collaborators?: Record<string, AccessType>;
readonly demoOrder?: number;
readonly publishingHistory?: PublishingHistory[];
readonly groupLabels?: Map<string, string>;

readonly manifest?: Record<
string,
Partial<EnsembleDocument> & {
filePath?: string;
}
>;

readonly screens: ScreenDTO[];
readonly widgets: WidgetDTO[];
readonly scripts: ScriptDTO[];
readonly widgets?: WidgetDTO[];
readonly scripts?: ScriptDTO[];
readonly theme?: ThemeDTO;
readonly themes?: ThemeDTO[];
readonly languages?: LanguageDTO[];
readonly assets?: AssetDTO[];
readonly env?: EnvironmentDTO;
readonly translations?: TranslationDTO[];
}

export interface HasLabel {
Expand Down Expand Up @@ -100,7 +100,7 @@ export type ThemeDTO = EnsembleDocument & {
readonly type: EnsembleDocumentType.Theme;
};

export type LanguageDTO = EnsembleDocument & {
export type TranslationDTO = EnsembleDocument & {
readonly defaultLocale: boolean;
};

Expand Down
49 changes: 27 additions & 22 deletions packages/js-commons/src/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import type {
ApplicationDTO,
ScreenDTO,
ScriptDTO,
ThemeDTO,
WidgetDTO,
LanguageDTO,
EnvironmentDTO,
TranslationDTO,
ThemeDTO,
HasManifest,
} from "./dto";
import type { ApplicationTransporter } from "./transporter";

Expand All @@ -38,17 +38,17 @@ export const getFirestoreApplicationTransporter = (
...appDoc.data(),
} as ApplicationDTO;

const artifacts = await getArtifacts(appDocRef);
const artifactsByType = await getArtifactsByType(appDocRef);

const screens = artifacts[EnsembleDocumentType.Screen] as ScreenDTO[];
const widgets = artifacts[EnsembleDocumentType.Widget] as WidgetDTO[];
const scripts = artifacts[EnsembleDocumentType.Script] as ScriptDTO[];
const theme = head(artifacts[EnsembleDocumentType.Theme]) as ThemeDTO;
const languages = artifacts[EnsembleDocumentType.I18n] as LanguageDTO[];
const assets = artifacts[EnsembleDocumentType.Asset] as AssetDTO[];
const env = head(
artifacts[EnsembleDocumentType.Environment],
) as EnvironmentDTO;
const screens = artifactsByType[EnsembleDocumentType.Screen] as ScreenDTO[];
const widgets = artifactsByType[EnsembleDocumentType.Widget] as WidgetDTO[];
const scripts = artifactsByType[EnsembleDocumentType.Script] as ScriptDTO[];
const theme = head(artifactsByType[EnsembleDocumentType.Theme]) as ThemeDTO;
const assets = artifactsByType[EnsembleDocumentType.Asset] as AssetDTO[];
const translations = artifactsByType[
EnsembleDocumentType.I18n
] as TranslationDTO[];
const env = head(artifactsByType[EnsembleDocumentType.Environment]);

return {
...app,
Expand All @@ -57,9 +57,14 @@ export const getFirestoreApplicationTransporter = (
widgets,
theme,
scripts,
languages,
translations,
assets,
env,
manifest: Object.fromEntries(
Object.values(artifactsByType).flatMap((artifacts) =>
artifacts.map((artifact) => [artifact.id, artifact]),
),
) as Pick<HasManifest, "manifest">,
};
},

Expand All @@ -81,7 +86,7 @@ export const getFirestoreApplicationTransporter = (
CollectionsName.InternalArtifacts,
);

const { screens, widgets, scripts, languages, theme, env } = app;
const { screens, widgets, scripts, translations, theme, env } = app;

screens.forEach((screen) => {
const screenRef = doc(artifactsRef, screen.id);
Expand All @@ -95,7 +100,7 @@ export const getFirestoreApplicationTransporter = (
});
});

widgets.forEach((widget) =>
widgets?.forEach((widget) =>
batch.set(doc(internalArtifactsRef, widget.id), {
type: EnsembleDocumentType.Widget,
name: widget.name,
Expand All @@ -116,7 +121,7 @@ export const getFirestoreApplicationTransporter = (
});
}

scripts.forEach((script) =>
scripts?.forEach((script) =>
batch.set(doc(internalArtifactsRef, script.id), {
type: EnsembleDocumentType.Script,
name: script.name,
Expand All @@ -127,12 +132,12 @@ export const getFirestoreApplicationTransporter = (
}),
);

languages?.forEach((language) =>
batch.set(doc(internalArtifactsRef, language.id), {
...language,
translations?.forEach((translation) =>
batch.set(doc(internalArtifactsRef, translation.id), {
...translation,
...updatedByDetails,
type: EnsembleDocumentType.I18n,
defaultLocale: language.defaultLocale ?? false,
defaultLocale: translation.defaultLocale,
}),
);

Expand All @@ -156,7 +161,7 @@ export const getFirestoreApplicationTransporter = (
},
});

const getArtifacts = async (
const getArtifactsByType = async (
appRef: DocumentReference,
): Promise<Record<EnsembleDocumentType, DocumentData[]>> => {
const [artifactsSnapshot, internalArtifactsSnapshot, labelsSnapshot] =
Expand Down
3 changes: 2 additions & 1 deletion packages/js-commons/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./dto";
export * from "./service";
export * from "./firebase";
export * from "./transporter";
export * from "./service";
export * from "./local-files";
Loading

0 comments on commit 0a37d2b

Please sign in to comment.