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

Dolt #373

Draft
wants to merge 51 commits into
base: main
Choose a base branch
from
Draft

Dolt #373

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
e623989
chore(dolt): init cdb
ShaunSHamilton Apr 17, 2024
e28040a
feat: modify challenge parser to use raw md
moT01 Apr 18, 2024
76d5fe6
fix: seed script
moT01 Apr 18, 2024
e7822d9
chore: update queries
moT01 Apr 18, 2024
7b46b19
fix(dolt): add raw markdown
ShaunSHamilton Apr 18, 2024
5e52669
fix: drop tables with refs first
ShaunSHamilton Apr 22, 2024
48a6776
chore: remove hasNoTests
ShaunSHamilton Apr 22, 2024
d3a1b33
chore: remove unused, duplicate challenge type
ShaunSHamilton Apr 22, 2024
06633c7
fix: manually set all id's in seed script
moT01 Apr 22, 2024
a25c6e4
fix: remove comment
moT01 Apr 22, 2024
d011b64
fix: manually set all id's in seed script
ShaunSHamilton Apr 23, 2024
e4616de
add comment
ShaunSHamilton Apr 23, 2024
24f58a8
feat: add super-challenge to challenge parser
moT01 Apr 23, 2024
6dac92b
Revert "chore: remove hasNoTests"
ShaunSHamilton Apr 24, 2024
09c7410
add challenge_type to cdb
ShaunSHamilton Apr 24, 2024
c667081
merge upstream/main into dolt
ShaunSHamilton Apr 24, 2024
f6f1a50
feat: add super-challenge to challenge parser
ShaunSHamilton Apr 24, 2024
36b469c
feat: add challenge_type table
ShaunSHamilton Apr 25, 2024
f568c27
merge origin/dolt into dolt
ShaunSHamilton Apr 25, 2024
2f1e406
test: refactor with challenge-type-to-tables-map
ShaunSHamilton Apr 27, 2024
640d9ec
feat: add 5 map tables
ShaunSHamilton Apr 27, 2024
81f94b5
Merge branch 'freeCodeCamp:main' into dolt
ShaunSHamilton Apr 27, 2024
1a3beb3
refactor: modularise dolt
ShaunSHamilton Apr 30, 2024
9098d64
feat(curriculum): add capi connector
ShaunSHamilton May 2, 2024
bc8e4dc
fix: titles and superblocks_blocks
moT01 May 2, 2024
def6f2f
feat(curriculum): add capi connector
ShaunSHamilton May 3, 2024
b7dde02
fix(dolt): use real titles and add superblocks_blocks data (#375)
ShaunSHamilton May 3, 2024
76a88b2
feat: add start to cap api
moT01 Apr 30, 2024
45d4210
feat: add start to CAP API (#376)
moT01 May 3, 2024
3bab0c4
feat: build client with description + instructions from CAP API (#378)
moT01 May 9, 2024
95fe1fe
fix: split parser to use regular or for seeding dolt db (#379)
moT01 May 10, 2024
fe0266c
feat(script): add isupcomingchange table to seed script (#380)
moT01 May 14, 2024
a2298cb
feat: add uses_multifile_editor table to seed script (#381)
moT01 May 17, 2024
2477b46
revert: pnpm lock changes (#382)
moT01 May 20, 2024
22aa647
Merge branch 'main' into dolt
moT01 May 20, 2024
2891f14
feat: start to create endpoint that reproduces getChallengesForLang (…
moT01 May 21, 2024
c38e548
refactor(dolt): move table queries into file
ShaunSHamilton May 22, 2024
a22f99a
feat(cap): add comparator functions
ShaunSHamilton May 22, 2024
3d04889
feat(CAP/API): trying to recreate curriculum.json (#387)
moT01 May 31, 2024
64467c0
fix(CAP): dont use nulls in objects (#386)
moT01 May 31, 2024
082a5f3
Merge branch 'main' into dolt
moT01 May 31, 2024
26bdd4a
fix: changes after reseeding (#388)
moT01 May 31, 2024
ba8cb48
fix(cap-api): adjustments after updating and reseeding (#389)
moT01 May 31, 2024
919d30d
Merge branch 'main' into dolt
moT01 Jun 3, 2024
542280a
fix: seed script after merging main (#390)
moT01 Jun 3, 2024
22acaae
fix(cap): curriculum tests after updating (#391)
moT01 Jun 4, 2024
bc2d444
chore: temp remove prettierignore (#392)
moT01 Jun 4, 2024
374e770
Merge branch 'main' into dolt
moT01 Jun 4, 2024
3d81d3a
revert: temp remove from prettierignore (#393)
moT01 Jun 4, 2024
43c5364
chore(cap): remove time table after merging main (#394)
moT01 Jun 4, 2024
91fc99e
fix(cap): api after removing time (#395)
moT01 Jun 4, 2024
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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,10 @@ curriculum/build
### Playwright ###

/playwright

### Dolt ###
.sqlhistory
.dolt*
dolt/api/curriculum.json
dolt/api/learn-curriculum.json
dolt/api/mobile-curriculum.json
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ shared/utils/get-lines.test.js
shared/utils/is-audited.js
shared/utils/validate.js
shared/utils/validate.test.js
tools/challenge-parser/parser/super-challenge.md
6 changes: 5 additions & 1 deletion client/utils/build-challenges.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const path = require('path');

const { writeFileSync } = require('fs');
const _ = require('lodash');

const envData = require('../config/env.json');
Expand Down Expand Up @@ -38,6 +38,10 @@ exports.replaceChallengeNode = () => {

exports.buildChallenges = async function buildChallenges() {
const curriculum = await getChallengesForLang(curriculumLocale);
writeFileSync(
`../dolt/api/learn-curriculum.json`,
JSON.stringify(curriculum, null, 2)
);
const superBlocks = Object.keys(curriculum);
const blocks = superBlocks
.map(superBlock => curriculum[superBlock].blocks)
Expand Down
189 changes: 189 additions & 0 deletions curriculum/capi-connector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
const { readFile, writeFile } = require('fs/promises');

async function fetchCapCurriculum() {
try {
const response = await fetch('http://localhost:3010/curriculum');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching curriculum data:', error);
throw error;
}
}

function getChallengeFromPath(capCurriculum, englishPath) {
return capCurriculum.find(
c =>
englishPath.endsWith(`${c.block}/${c.objectId}.md`) ||
englishPath.endsWith(`${c.block}/${c.challengeDashedName}.md`)
);
}

function getCapDescription(capCurriculum, englishPath) {
const challenge = getChallengeFromPath(capCurriculum, englishPath);

return challenge?.description
? `<section id="description">${challenge.description}</section>`
: '';
}

function getCapInstructions(capCurriculum, englishPath) {
const challenge = getChallengeFromPath(capCurriculum, englishPath);

return challenge?.instructions
? `<section id="instruction">${challenge.instructions}</section>`
: '';
}

/**
* Compares the challenge in the Curriculum Database with the challenge in the file system after parsing.
*
* Stores a log of the differences at `/curriculum/cdb-progress.json`
*
* ```json
* [{
* "challenge_id": string,
* "property": string,
* "expected": JSON,
* "actual": JSON | undefined
* }]
* ```
* @param {Object} file - The file information
* @param {Record<string, unknown>} file.challenge - The challenge information
* @param {string} file.lang - The langauge of the file
*/
async function compareCDBToFS({ challenge, lang }) {
const challenges = await getChallenges();
const matching_challenge = challenges.find(({ id }) => id === challenge.id);

if (!matching_challenge) {
await addToLog('./cdb-progress.json', {
challenge_id: challenge.id,
property: null,
expected: challenge,
actual: undefined
});
}

const challenge_keys = Object.keys(challenge);

for (const key of challenge_keys) {
if (!isDeepEqual(challenge[key], matching_challenge[key])) {
await addToLog({
challenge_id: challenge.id,
property: key,
expected: challenge[key],
actual: matching_challenge[key]
});
}
}
}

function isDeepEqual(a, b) {
if (a === b) {
return true;
}

if (typeof a !== typeof b) {
return false;
}

if (typeof a === 'object' && a !== null && b !== null) {
const a_keys = Object.keys(a);
const b_keys = Object.keys(b);

if (a_keys.length !== b_keys.length) {
return false;
}

for (const key of a_keys) {
if (!isDeepEqual(a[key], b[key])) {
return false;
}
}

return true;
}

return false;
}

async function addToLog(value) {
const data = await readFile('./cdb-progress.json');
const logs = JSON.parse(data);

if (logs.length === 0) {
await writeFile('./cdb-progress.json', JSON.stringify([value]));
} else {
logs.push(value);
await writeFile('./cdb-progress.json', JSON.stringify(logs));
}
}

/**
* @type {{
* audioPath?: string,
* block: string,
* blockId?: string,
* challengeOrder?: number,
* certification: string,
* challengeType: number,
* dashedName: string,
* description?: string,
* disableLoopProtectTests: boolean,
* disableLoopProtectPreview: boolean,
* challengeFiles?: { fileKey: string, ext: string, name: string, editableRegionBoundaries: number[], path: string, head: string, tail: string, seed: string, contents: string, id: string, history: string[]},
* guideUrl?: string,
* hasEditableBoundaries?: boolean,
* helpCategory?: string,
* videoUrl?: string,
* fillInTheBlank?: { sentence: string, blanks: { answer: string, feedback: string }[] },
* forumTopicId?: number,
* id: string,
* instructions?: string,
* isComingSoon?: boolean,
* isLocked?: boolean,
* isPrivate?: boolean,
* msTrophyId?: string,
* notes?: string,
* order?: number,
* prerequisites?: { id: string, title: string }[],
* videoId?: string,
* videoLocaleIds?: string[],
* bilibiliIds?: { aid: number, bvid: string, cid: number },
* question?: { text: string, answers: { answer: string, feedback: string }[] },
* required?: { link: string, raw: boolean, src: string, crossDomain: boolean}[],
* assignments?: string[],
* scene?: { setup: { code: string, language: string }, commands: { command: string, code: string, language: string }[] },
* solutions?: { [T in FileKey]: FileKeyChallenge },
* superBlock: string,
* superOrder?: number,
* tests: { id: string, text: string, testString?: string, title?: string }[],
* template?: string,
* title: string,
* time?: string,
* translationPending: boolean,
* url?: string,
* usesMultifileEditor?: boolean,
* }}
*/
let curriculum;

async function getChallenges(lang = 'english') {
if (curriculum) {
return curriculum;
}

curriculum = await fetch(
`http://localhost:3010/curriculum?lang=${lang}`
).then(res => res.json());

return curriculum;
}

module.exports = {
compareCDBToFS,
getCapDescription,
getCapInstructions,
fetchCapCurriculum
};
4 changes: 4 additions & 0 deletions curriculum/get-challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const { createPoly } = require('../shared/utils/polyvinyl');
const { getSuperOrder, getSuperBlockFromDir } = require('./utils');
const { metaSchemaValidator } = require('./schema/meta-schema');

// const { compareCDBToFS } = require('./capi-connector');

const access = util.promisify(fs.access);

const CHALLENGES_DIR = path.resolve(__dirname, 'challenges');
Expand Down Expand Up @@ -317,6 +319,8 @@ function generateChallengeCreator(lang, englishPath, i18nPath) {
addMetaToChallenge(challenge, meta);
fixChallengeProperties(challenge);

// await compareCDBToFS({ challenge, lang });

return challenge;
}
return createChallenge;
Expand Down
53 changes: 53 additions & 0 deletions dolt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Curriculum Database

## Usage

1. Start the SQL server:

```bash
dolt sql-server
```

2. Run commands/scripts
3. Stop the SQL server
4. Commit changes:

```bash
dolt add .
dolt commit -m "message"
dolt push origin main
```

**NOTE:** If you drop the database, you will have a bad time. Instead drop all the tables for a clean start. See `queries/drop-tables.sql`

## Notes

The database name in Dolt is the directory name. This is NOT configurable.

Make a query with a file

```bash
mysql --host 127.0.0.1 --port 3306 -u root -p dolt < queries/<name>.sql
# OR
dolt sql < queries/<name>.sql
```

```bash
DATABASE_URL=mysql://root:@127.0.0.1/dolt
```

MYSQL has reserved words: https://dev.mysql.com/doc/refman/8.0/en/keywords.html

- `description` has been renamed to `descriptions`
- `url` has been renamed to `course_url`
- `required` has been renamed to `required_resources`

- [x] `fields` to go
- [x] `time` to stay, but be added per block **not** per challenge
- Turned into `block_time_to_complete` table
- `disableLoopProtect*` to go?
- Maybe, because we can.
- [x] `hasEditableBoundaries` to go
- `if challengeFiles && challengeFiles.editabledBoundaries.length > 0`
- [x] `certification.slug` keep out of database
- [ ] `certification.dashed_name` remove
8 changes: 8 additions & 0 deletions dolt/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Run the main repo,
Two JSON files will be created in dolt/api/

Clone the DB and run the server
Start the API with `node index.js` while in the dolt folder
It will write a third JSON file in dolt/api/

Run `npx jest curriculum.test.js` while in the dolt folder to test the JSON created from the API against one of the ones created from the client
Loading