Skip to content

Commit

Permalink
refactoring to move to app router (#96)
Browse files Browse the repository at this point in the history
* refactoring to move to app router and other reasons

* updated package.lock

* Update apps/registry/lib/getResumeGist.js

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/registry/pages/api/[payload].js

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/registry/lib/generateResume.js

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/registry/lib/generateResume.js

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix problem by coderabbit

* update readme

* fix lint

* remove ruby from build

* fix registry port

* updated clicky id and ai model

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
thomasdavis and coderabbitai[bot] committed May 25, 2024
1 parent f60a1aa commit a958ca1
Show file tree
Hide file tree
Showing 25 changed files with 782 additions and 534 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
node-version: 18
cache: 'pnpm'
- run: pnpm install
- run: pnpm start-server-and-test 'turbo dev --filter=registry' 3002 'exit 0;'
- run: pnpm start-server-and-test 'turbo dev --filter=registry' 3000 'exit 0;'
working-directory: apps/registry
build:
runs-on: ubuntu-latest
Expand All @@ -55,9 +55,6 @@ jobs:
with:
node-version: 18
cache: pnpm
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: pnpm install
- run: pnpm turbo build
test:
Expand Down
1 change: 0 additions & 1 deletion .ruby-version

This file was deleted.

53 changes: 18 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ This is a monorepo, will be the home of the registry, the homepage, ui kit, base

All projects hosted on this domain, will be found in the /apps folder.

- [jsonresume.org](https://jsonresume.org) - the homepage, currently built in Jekyll, would like to move to a Javascript framework for easier contributions
- found in [/apps/homepage](https://github.com/jsonresume/jsonresume.org/tree/master/apps/homepage)
- [registry.jsonresume.org](https://registry.jsonresume.org) - the opt-in hosted place blah blah
- [jsonresume.org](https://jsonresume.org) - the homepage
- found in [/apps/homepage2](https://github.com/jsonresume/jsonresume.org/tree/master/apps/homepage2)
- [registry.jsonresume.org](https://registry.jsonresume.org) - the opensource free to use registry
- found in [/apps/registry](https://github.com/jsonresume/jsonresume.org/tree/master/apps/registry)

## Requirements
Expand Down Expand Up @@ -41,9 +41,15 @@ To start an individual app;
pnpm turbo dev --filter=registry
```

## App - Registry

```
pnpm dev --filter=registry
```

**Environment variables**:

These are required to run the registry. (only the github token, but it probably crashs without the rest for now)
These are optionally to run the different parts of the registry. The main behavior of rendering resumes does not need any.

```
# classic token
Expand All @@ -59,13 +65,7 @@ PINECONE_ENVIRONMENT=
OPENAI_API_KEY=
```

## App - Registry

```
pnpm dev --filter=registry
```

This will start a local server at [http://localhost:3002/thomasdavis](http://localhost:3002/thomasdavis)
This will start a local server at [http://localhost:3000/thomasdavis](http://localhost:3000/thomasdavis)

### Formats

Expand All @@ -75,32 +75,15 @@ This will start a local server at [http://localhost:3002/thomasdavis](http://loc
- Text
- Lex

### Notes

- Gonna drop Typescript, prefer less barriers to entry
- Templates cannot read from the file system when using the registry
- Base templates using react/svelte/etc
- pdf? lol

## App - Homepage

```
pnpm dev --filter=homepage
```

Kind of a mess, but it works.

It uses Jekyll, to install it

```
gem install bundler jekyll
pnpm dev --filter=homepage2
```

Then to run it
## Contributors

```
jekyll serve
```
|Contribs|

## AI

Expand All @@ -112,27 +95,27 @@ This project creates embeddings out of Hacker News Who Is Hiring post, it then g

It is not setup to be automated at the moment, and the formatting is garbage. Each post should be sent to GPT to reformat it into a templated job description before generating embeddings.

[http://localhost:3002/thomasdavis/jobs](http://localhost:3002/thomasdavis/jobs)
[http://localhost:3000/thomasdavis/jobs](http://localhost:3000/thomasdavis/jobs)

### Letter

This is a very simple service that prompts GPT with your resume and asks to generate a cover letter.

It could be easily improved to also contain the context of the job you are applying for.

[http://localhost:3002/thomasdavis/letter](http://localhost:3002/thomasdavis/letter)
[http://localhost:3000/thomasdavis/letter](http://localhost:3000/thomasdavis/letter)

### Suggestions

This is a very simple service that prompts GPT with your resume and asks to generate a list of suggestions for you to improve your resume.

[http://localhost:3002/thomasdavis/suggestions](http://localhost:3002/thomasdavis/suggestions)
[http://localhost:3000/thomasdavis/suggestions](http://localhost:3000/thomasdavis/suggestions)

### Interview

This is an implementation of a chat bot, your resume is injected, and the conversation is included in the prompt. So you can interview your self or talk as if you were being interviewed.

[http://localhost:3002/thomasdavis/interview](http://localhost:3002/thomasdavis/interview)
[http://localhost:3000/thomasdavis/interview](http://localhost:3000/thomasdavis/interview)

# todo

Expand Down
43 changes: 43 additions & 0 deletions apps/registry/lib/error/buildError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export const ERROR_CODES = Object.freeze({
INVALID_USERNAME: 'INVALID_USERNAME',
NON_EXISTENT_GIST: 'NON_EXISTENT_GIST',
GIST_UNKNOWN_ERROR: 'GIST_UNKNOWN_ERROR',
RESUME_SCHEMA_ERROR: 'RESUME_SCHEMA_ERROR',
TEMPLATE_MISSING: 'TEMPLATE_MISSING',
UNKNOWN_TEMPLATE_ERROR: 'UNKNOWN_TEMPLATE_ERROR',
INVALID_EXTENSION: 'INVALID_EXTENSION',
UNKNOWN_FORMATTER: 'UNKNOWN_FORMATTER',
RESUME_NOT_VALID_JSON: 'RESUME_NOT_VALID_JSON',
});

export const ERROR_CODE_MESSAGES = Object.freeze({
INVALID_USERNAME: 'This is not a valid Github username',
NON_EXISTENT_GIST:
'You have no gists named resume.json or your gist is private',
GIST_UNKNOWN_ERROR: 'Cannot fetch gist, no idea why',
RESUME_SCHEMA_ERROR:
'Your resume does not conform to the schema, visit https://jsonresume.org/schema/ to double check why. But the error message below should contain all the information you need.',
TEMPLATE_MISSING:
'This theme is currently unsupported. Please visit this Github issue to request it https://github.com/jsonresume/jsonresume.org/issues/36 (unfortunately we have recently (11/2023) disabled a bunch of legacy themes due to critical flaws in them, please request if you would like them back.)',
UNKNOWN_TEMPLATE_ERROR:
'Cannot format resume, no idea why #likely-a-validation-error',
INVALID_EXTENSION: `We only support the following extensions: ${[...[]].join(
', '
)}`,
UNKNOWN_FORMATTER:
'This is a valid extension but we do not have a formatter for it. Please visit github issues.',
RESUME_NOT_VALID_JSON:
'Your resume is not valid JSON. Find an online JSON validator to help you debug this.',
});

const buildError = (error, extra) => {
return {
error: {
code: error,
message: ERROR_CODE_MESSAGES[error],
extra,
},
};
};

export default buildError;
17 changes: 17 additions & 0 deletions apps/registry/lib/formatters/formatters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import qr from './qr';
import template from './template';
import txt from './text';
import tex from './tex';
import json from './json';
import yaml from './yaml';

const formatters = {
qr,
json,
tex,
txt,
template,
yaml,
};

export default formatters;
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const THEMES = {
rickosborne: require('jsonresume-theme-rickosborne'),
spartan: require('jsonresume-theme-spartan'),
spartacus,
stackoverflowed: require('jsonresume-theme-stackoverflowed'),
standard,
stackoverflow,
'standard-resume': require('jsonresume-theme-standard-resume'),
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
86 changes: 86 additions & 0 deletions apps/registry/lib/generateResume.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import schema from './schema';
import buildError, { ERROR_CODES } from './error/buildError';
import getResumeGist from './getResumeGist';
import formatters from './formatters/formatters';

const Validator = require('jsonschema').Validator;

const { createClient } = require('@supabase/supabase-js');

const supabaseUrl = 'https://itxuhvvwryeuzuyihpkp.supabase.co';
const supabaseKey = process.env.SUPABASE_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);

const EXTENSIONS = new Set(['qr', 'json', 'tex', 'txt', 'template', 'yaml']);

const generateResume = async (username, extension = 'template', query = {}) => {
const { theme } = query;
const formatter = formatters[extension];

if (!EXTENSIONS.has(extension)) {
return buildError(ERROR_CODES.INVALID_EXTENSION);
}

if (!formatter) {
return buildError(ERROR_CODES.UNKNOWN_FORMATTER);
}

// retrieve the users github gist
const { error: gistError, resume } = await getResumeGist(username);

if (gistError) {
return buildError(gistError);
}

const v = new Validator();
const validation = v.validate(resume, schema);

if (!validation.valid) {
return buildError(ERROR_CODES.RESUME_SCHEMA_ERROR, {
validation: validation.errors,
});
}

let selectedTheme = theme || resume.meta?.theme || 'elegant';

selectedTheme = selectedTheme.toLowerCase();

// @todo - using as a resume cache for extra features
(async () => {
try {
await supabase
.from('resumes')
.upsert(
{
username,
resume: JSON.stringify(resume),
updated_at: new Date(),
},
{ onConflict: 'username' }
)
.select();
} catch (error) {
console.error('Failed to cache resume:', error);
}
})();

const options = { ...query, theme: selectedTheme, username };

let formatted = {};

try {
formatted = await formatter.format(resume, options);
} catch (e) {
console.error(e);
// @todo - do this better
if (e.message === 'theme-missing') {
return buildError(ERROR_CODES.TEMPLATE_MISSING);
}

return buildError(ERROR_CODES.UNKNOWN_TEMPLATE_ERROR);
}

return { content: formatted.content, headers: formatted.headers || [] };
};

export default generateResume;
54 changes: 54 additions & 0 deletions apps/registry/lib/getResumeGist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import axios from 'axios';
import { find } from 'lodash';
import buildError, { ERROR_CODES } from './error/buildError';

const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

const getResumeGist = async (username) => {
let gistData = null;
try {
gistData = await axios.get(
`https://api.github.com/users/${username}/gists?per_page=100`,
{
headers: {
...(GITHUB_TOKEN ? { Authorization: 'Bearer ' + GITHUB_TOKEN } : {}), // If we have no token and are in development, we can still make some requests.
},
}
);
} catch (e) {
console.log(e);
return buildError(ERROR_CODES.INVALID_USERNAME);
}

if (!gistData.data) {
return buildError(ERROR_CODES.GIST_UNKNOWN_ERROR);
}

const resumeUrl = find(gistData.data, (f) => {
return f.files['resume.json'];
});

if (!resumeUrl) {
return buildError(ERROR_CODES.NON_EXISTENT_GIST);
}

const gistId = resumeUrl.id;

let resumeRes = {};

try {
const fullResumeGistUrl = `https://gist.githubusercontent.com/${username}/${gistId}/raw?cachebust=${new Date().getTime()}`;

resumeRes = await axios({
method: 'GET',
headers: { 'content-type': 'application/json' },
url: fullResumeGistUrl,
});
} catch (e) {
return buildError(ERROR_CODES.GIST_UNKNOWN_ERROR);
}

return { resume: resumeRes.data };
};

export default getResumeGist;
Loading

0 comments on commit a958ca1

Please sign in to comment.