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

fix: cli encoding issue #1248

Merged
merged 38 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2b96bea
fix: improve error upon component not found and remove unnecessary async
oliverqx Jan 30, 2025
794039b
fix: update colors, remove kleur in favour of chalk
oliverqx Feb 1, 2025
860b02c
Merge branch 'main' into fix.screenpipe-cli-encoding
oliverqx Feb 2, 2025
a9c3338
feat(cli): migrate components commands to Commander
oliverqx Feb 2, 2025
f402c2d
feat(cli): migrate components commands to Commander
oliverqx Feb 2, 2025
faf8350
feat(cli): migrate create command to Commander
oliverqx Feb 2, 2025
5d1de69
feat(cli): migrate publish command to Commander
oliverqx Feb 2, 2025
813e016
feat(cli): migrate register command
oliverqx Feb 2, 2025
019b811
feat(cli): migrate list-versions command to Commander
oliverqx Feb 2, 2025
b50c6bf
feat(cli): migrate login command to Commander
oliverqx Feb 2, 2025
af76f9a
feat(cli): migrate logout command to Commander
oliverqx Feb 2, 2025
7d2b02d
chore(cli): update dist
oliverqx Feb 2, 2025
da57c2d
Merge branch 'main' into fix.screenpipe-cli-encoding
oliverqx Feb 3, 2025
30a1404
fix: import lost in merge
oliverqx Feb 3, 2025
1ab6c15
chore(cli): remove dead code
oliverqx Feb 3, 2025
37cf7b7
chore(cli): remove unused deps
oliverqx Feb 3, 2025
fb0a589
fix(cli): remove prompts from all commands
oliverqx Feb 3, 2025
74a260f
fix(cli): remove test registered component
oliverqx Feb 3, 2025
fec1a20
feat(cli): add hint to register command
oliverqx Feb 3, 2025
967cf15
chore(cli): update dist and lockfile
oliverqx Feb 3, 2025
295a29a
feat(cli): make all logging lowercase by default
oliverqx Feb 4, 2025
1b77041
feat(cli): implement logger
oliverqx Feb 4, 2025
685d536
feat(cli): implement logger publish command
oliverqx Feb 4, 2025
1707f59
feat(cli): implement logger logout
oliverqx Feb 4, 2025
fd135c9
feat(cli): implement logger in login command
oliverqx Feb 4, 2025
c2fab14
feat(cli): implement logger in list-versions command
oliverqx Feb 4, 2025
91e229f
feat(cli): lowercase logger
oliverqx Feb 4, 2025
88faacb
refactor(cli): create command refactor. preparing for create app
oliverqx Feb 4, 2025
519a0df
feat(cli): implement logger in create pipe command
oliverqx Feb 4, 2025
2ebee8e
feat(cli): migrate create pipe to use simpleGit
oliverqx Feb 4, 2025
efef558
fix(cli): rectify typo
oliverqx Feb 4, 2025
bd645a5
feat(cli): add create app command
oliverqx Feb 4, 2025
618cf9d
fix(cli): expose create commands
oliverqx Feb 4, 2025
522ed46
feat(cli): update dist
oliverqx Feb 4, 2025
94acfce
Merge branch 'main' into fix.screenpipe-cli-encoding
oliverqx Feb 5, 2025
0559196
chore(cli): publish command to Commander
oliverqx Feb 5, 2025
3bc6591
refactor(cli): modify create command
oliverqx Feb 5, 2025
327ff28
feat(cli): refactor pipes components
oliverqx Feb 6, 2025
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
Binary file modified screenpipe-js/cli/bun.lockb
Binary file not shown.
64,485 changes: 31,257 additions & 33,228 deletions screenpipe-js/cli/dist/index.js

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions screenpipe-js/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
"dev": "bun run src/index.ts"
},
"dependencies": {
"@drizzle-team/brocli": "^0.11.0",
"@screenpipe/browser": "^0.1.24",
"@screenpipe/browser": "^0.1.26",
"@screenpipe/js": "^1.0.7",
"archiver": "^7.0.1",
"chalk": "^5.4.1",
Expand All @@ -24,16 +23,16 @@
"fs-extra": "^11.3.0",
"ignore": "^7.0.3",
"inquirer": "^12.3.2",
"kleur": "^4.1.5",
"lodash": "^4.17.21",
"ora": "^8.1.1",
"prompts": "^2.4.2",
"simple-git": "^3.27.0",
"unzip-stream": "^0.3.4",
"zod": "^3.24.1"
},
"devDependencies": {
"@types/archiver": "^6.0.3",
"@types/fs-extra": "^11.0.4",
"@types/lodash": "^4.17.15",
"@types/node": "^20.11.5",
"@types/prompts": "^2.4.9",
"@types/unzip-stream": "^0.3.4",
Expand Down
80 changes: 80 additions & 0 deletions screenpipe-js/cli/src/commands/app/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env node
import { input } from "@inquirer/prompts"; // Import select from inquirer prompts
import { Command } from "commander";
import inquirer from "inquirer";
import simpleGit from "simple-git";
import { logger, spinner } from "../components/commands/add/utils/logger";
import { handleError } from "../components/commands/add/utils/handle-error";

const TEMPLATE_REPOS = {
electron: "https://github.com/neo773/screenpipe-electron",
tauri: "https://github.com/LorenzoBloedow/screenpipe-tauri-template-dev",
};

export const createAppCommand = new Command()
.name("create")
.description("create a new desktop app project")
.option(
"-a, --name <name>",
"the name of your app (optional)",
)
.option(
"-t, --appType <type>",
"the type of desktop app (electron or tauri)",
)
.action(async (options) => {
let { name, appType } = options;

if (!appType) {
let { appTypePrompt } = await inquirer.prompt({
name: "appTypePrompt",
type: "select",
message: "what type of desktop app would you like to create?",
choices: [
{ name: "electron", value: "electron"},
{ name: "tauri", value: "tauri"}
],
default: "tauri"
});

appType = appTypePrompt
}


if (!name || name.length === 0) {
name = await input({
message: "What is your project name?",
default: "my-desktop-app",
validate: (input) => {
if (input.trim().length === 0) return "project name is required.";
return true;
},
});
}

const loadingSpinner = spinner("creating your desktop app...");

try {
loadingSpinner.start();

await simpleGit().clone(TEMPLATE_REPOS[appType as "electron" | "tauri"], name);
loadingSpinner.succeed("Project created successfully! 🎉");

logger.info("\ncredits to the template authors:");
if (appType === "electron") {
logger.info("electron template by: Neo @ https://github.com/neo773");
} else {
logger.info("tauri template by: Lorenzo @ https://github.com/LorenzoBloedow");
}

logger.info("\nto get started:");
logger.info(`cd ${name}`);
logger.info("npm install # or bun install, pnpm install, yarn");
logger.info("npm run dev # or bun dev, pnpm dev, yarn dev");

logger.info("\nwhen you're ready, you can deploy your app following the documentation for the respective framework.\n");
} catch (error) {
loadingSpinner.fail("failed to create project");
handleError(error instanceof Error ? error.message : String(error));
}
});
8 changes: 8 additions & 0 deletions screenpipe-js/cli/src/commands/app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Command } from "commander";
import { createAppCommand } from "./create";

export const appCommands = new Command()
.name("app")
.description("create a new screenpipe application using default templates")

appCommands.addCommand(createAppCommand)
61 changes: 21 additions & 40 deletions screenpipe-js/cli/src/commands/components/commands/add/add.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,42 @@
import {
boolean,
command,
GenericCommandHandler,
OutputType,
positional,
string,
} from "@drizzle-team/brocli";
import { logger } from "./utils/logger";
import { ERRORS, handleError } from "./utils/handle-error";
import { promptForRegistryComponents } from "./utils/prompt-for-component";
import { preFlightAdd } from "./preflights/preflight-add";
import { addComponents } from "./utils/add-components";
import { Command } from "commander";

export const addComponentCommand = command({
name: "add",
desc: "add components and dependencies to your pipe",
options: {
components: positional().desc("list of components by name"),
path: string().desc("the path to add the component to."),
silent: boolean().desc("mute output.").default(false),
overwrite: boolean().desc("overwrite existing files.").default(false),
cwd: string()
.desc("the working directory. defaults to the current directory.")
.default(process.cwd()),
},
handler: async (opts) => {
export const addComponentCommand = new Command()
.name("add")
.description("add components and dependencies to your pipe")
.argument('[components...]', 'List of components by name')
.option('--path <path>', 'The path to add the component to.')
.option('--silent', 'Mute output.', false)
.option('--overwrite', 'Overwrite existing files.', false)
.option('--cwd <cwd>', 'The working directory. Defaults to the current directory.', process.cwd())
.action(async (comps, opts) => {
try {
let components;
let components

// If there are no components, ask the user which ones they want.
if (!opts?.components?.length) {
components = await promptForRegistryComponents();
if (!comps?.length) {
components = await promptForRegistryComponents()
} else {
components = [opts.components];
components = [comps]
}

// Before addig check a few things
const result = await preFlightAdd(opts.cwd);
const result = preFlightAdd(opts.cwd)

// If the current directory is not a pipe, create one
if (result?.errors[ERRORS.MISSING_DIR_OR_EMPTY_PIPE]) {
logger.warn(
"you need to create a pipe first. run bunx @screenpipe/dev@latest create or visit https://docs.screenpi.pe/docs/plugins for more information."
);
process.exit(1);
// await createPipe(options)
logger.warn('you need to create a pipe first. run bunx @screenpipe/dev create or visit https://docs.screenpi.pe/docs/plugins for more information.')
process.exit(1)
}

// Add components to the directory
await addComponents(components, {
silent: opts.silent,
cwd: opts.cwd,
overwrite: opts.overwrite,
});
await addComponents(components, {silent: opts.silent, cwd: opts.cwd, overwrite: opts.overwrite})
} catch (error) {
logger.break();
handleError(error);
logger.break()
handleError(error)
}
},
});
})
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import fs from 'fs';
import path from 'path';
import { z } from 'zod';
import { ERRORS } from '../utils/handle-error';

export async function preFlightAdd(cwd: string) {
export function preFlightAdd(cwd: string) {
const errors: Record<string, boolean> = {}

// Ensure target directory exists.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import { registryResolvedComponentsTreeSchema, RegistrySchema, registrySchema }
import registry from "./registry.json";
import deepmerge from "deepmerge";

export async function getRegistry() {
export function getRegistry() {
try {
const parsedRegistry = registrySchema.parse(registry)
return parsedRegistry
} catch (error) {
logger.error("\n")
logger.break()
handleError(error)
}
}

async function resolveRegistryItems(names: string[]) {
function resolveRegistryItems(names: string[]) {
let registryDependencies: RegistrySchema = {}
const registry = await getRegistry()
const registry = getRegistry()
if(!registry) return

for (const name of names) {
const itemRegistryDependencies = await resolveRegistryDependencies(
const itemRegistryDependencies = resolveRegistryDependencies(
name,
registry
)
Expand All @@ -34,75 +34,66 @@ async function resolveRegistryItems(names: string[]) {
return registryDependencies
}

async function resolveRegistryDependencies(
function resolveRegistryDependencies(
name: string,
registry: RegistrySchema
): Promise<RegistrySchema> {
): RegistrySchema {
const components: RegistrySchema = {}


async function resolveDependencies(componentName: string) {
try {
function resolveDependencies(componentName: string) {
if (registry[componentName]) {
components[componentName] = registry[componentName]
} else {
throw Error(componentName)
logger.break()
handleError(
`Component ${componentName} not found.`,
)
}

if (registry[componentName].registryDependencies) {
for (const dependency of registry[componentName].registryDependencies) {
await resolveDependencies(dependency)
resolveDependencies(dependency)
}
}
} catch (error: any) {
console.error(
`Component ${error.message} not found.`,
error
)
}
}

await resolveDependencies(name)
resolveDependencies(name)
return components
}

export async function registryResolveItemsTree(
export function registryResolveItemsTree(
names: RegistrySchema['']["name"][],
) {
try {
let relevantItemsRegistry = await resolveRegistryItems(names)
const payload = registrySchema.parse(relevantItemsRegistry)
let relevantItemsRegistry = resolveRegistryItems(names)
const payload = registrySchema.parse(relevantItemsRegistry)

if (!payload) {
return null
}
if (!payload) {
return null
}

const componentArray = Object.values(payload)
const componentArray = Object.values(payload)

let docs = ""
componentArray.forEach((item) => {
if (item.docs) {
docs += `${item.docs}\n`
}
})
let docs = ""
componentArray.forEach((item) => {
if (item.docs) {
docs += `${item.docs}\n`
}
})

return registryResolvedComponentsTreeSchema.parse({
dependencies: deepmerge.all(
componentArray.map((item) => item.dependencies ?? [])
),
devDependencies: deepmerge.all(
componentArray.map((item) => item.devDependencies ?? [])
),
files: componentArray.map((item) => {
return {
src: item.src,
target: item.target
}
}),
docs,
})
} catch (error) {
handleError(error)
return null
}
return registryResolvedComponentsTreeSchema.parse({
dependencies: deepmerge.all(
componentArray.map((item) => item.dependencies ?? [])
),
devDependencies: deepmerge.all(
componentArray.map((item) => item.devDependencies ?? [])
),
files: componentArray.map((item) => {
return {
src: item.src,
target: item.target
}
}),
docs,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"dependencies": [
"@screenpipe/browser"
],
"devDependencies": [],
"registryDependencies": []
"registryDependencies": [],
"devDependencies": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function addComponents(
silent: options.silent,
})?.start()

const tree = await registryResolveItemsTree(components)
const tree = registryResolveItemsTree(components)

if (!tree) {
registrySpinner?.fail()
Expand Down
Loading
Loading