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

Laying the groundwork for the git refactor #50

Merged
merged 50 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a4af6c1
Laying the groundwork for the `git` refactor
confused-Techie Jan 11, 2023
d46a55a
Use `switch` for comparison, remove `lowercase()` external usage
confused-Techie Jan 12, 2023
0a13702
Added Codeberg VCS detection
confused-Techie Jan 12, 2023
53f3fce
Avoid semicolon auto-insertion, start specifying git class
confused-Techie Jan 12, 2023
76728aa
Framework of VCS Services, and testing them
confused-Techie Jan 12, 2023
f05b84d
Full testing suite written for GitHub `doesUserHaveRepo`
confused-Techie Jan 12, 2023
f4292dc
Updated `codeql` to ignore new testing location
confused-Techie Jan 12, 2023
1ccf4ae
Update fixture file name
confused-Techie Jan 12, 2023
67d4cbb
Move heavy lifting into `github.js` for ownership returns
confused-Techie Jan 12, 2023
abbbaa8
Fix typo `unkown` => `unknown`
confused-Techie Jan 13, 2023
60de1c4
Use new endpoint to find user ownership, new tests
confused-Techie Jan 13, 2023
33fbfab
`readme` & docs
confused-Techie Jan 13, 2023
d1140a3
Some more tests for new `readme` function
confused-Techie Jan 13, 2023
c77dfd4
Additional layout of core API structure
confused-Techie Jan 14, 2023
5ce374b
Merge branch 'main' into refactor-git
confused-Techie Jan 14, 2023
af71577
fix CodeQL issues
Digitalone1 Jan 14, 2023
872d107
github class: use const where possible
Digitalone1 Jan 14, 2023
850ea37
use an internal initializer and introduce private properties
Digitalone1 Jan 14, 2023
89e755a
camelCase properties + fix base class setters
Digitalone1 Jan 14, 2023
f3b609d
git class: remove setters and add jsdoc to methods
Digitalone1 Jan 15, 2023
fd84d66
Complete the specific components of the GitHub VCS Module
confused-Techie Jan 17, 2023
e0a4ddd
Fixed Undeclared Variable
confused-Techie Jan 17, 2023
2919648
Fix Syntax Error
confused-Techie Jan 17, 2023
d88fca7
Documentation, and refining exports and scope of responsibilites
confused-Techie Jan 17, 2023
fd69cf8
Progress on Publishing functionality
confused-Techie Jan 17, 2023
ee592e6
Some comments
confused-Techie Jan 17, 2023
d802f4b
Finish `newPackageData` begin fleshing out other functions
confused-Techie Jan 18, 2023
cfbd3a3
Fixed syntax error on ternary operator
confused-Techie Jan 18, 2023
9c92be4
Methodology to reduce repetitious package handling
confused-Techie Jan 18, 2023
d69a4c8
Initial construction of `package_json` class
confused-Techie Jan 19, 2023
99c2c8c
Continuing work on having easy interactions with package.json data
confused-Techie Jan 19, 2023
00dd86c
Merge remote-tracking branch 'upstream/refactor-git' into refactor-git
Digitalone1 Jan 19, 2023
bbddd30
fix CodeQL issues + typeof to check "function"
Digitalone1 Jan 19, 2023
080a7b7
Merge pull request #56 from Digitalone1/refactor-git
confused-Techie Jan 19, 2023
f7480f4
timestamps set by PostgreSQL by default
Digitalone1 Jan 19, 2023
f79cbf1
fix lexical scoping in switch
Digitalone1 Jan 19, 2023
d15d39f
downloads and stars count auto-initialized by PostgreSQL to 0
Digitalone1 Jan 19, 2023
de4bdc4
Merge pull request #61 from Digitalone1/refactor-git
confused-Techie Jan 22, 2023
7590a47
Fully Tested `vcs.newPackageData`
confused-Techie Jan 23, 2023
45a5543
Fully tested `newVersionData` agnostic logic after service selection
confused-Techie Jan 23, 2023
82e1ce9
Ownership tests, removed pseudo objects
confused-Techie Jan 23, 2023
48a93b5
`deletePackageName` & `postPackageVersion` using VCS + Removed Outdat…
confused-Techie Jan 24, 2023
3848b4c
Merge branch 'main' into refactor-git
confused-Techie Feb 5, 2023
408ac9e
Fix the failing test from generic test runners
confused-Techie Feb 5, 2023
ea97df1
Utilize VCS for `deletePackagesName`
confused-Techie Feb 5, 2023
ac5bf87
Update `postPackagesVersion` use VCS auth for `deletePackagesVersion`…
confused-Techie Feb 5, 2023
ab93fcb
Better docs, publishPackage auth feature added to `vcs.ownership()`
confused-Techie Feb 5, 2023
816cf70
Slight Refactor on VCS
confused-Techie Feb 5, 2023
74861ec
Remove final usage of `git` in `package_handler.js`
confused-Techie Feb 5, 2023
53cba5f
Remove unused variable
confused-Techie Feb 5, 2023
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
1 change: 1 addition & 0 deletions codeql-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ queries:
paths-ignore:
- ./src/tests
- ./src/tests_integration
- ./src/vcs_providers_tests
# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors
6 changes: 5 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ const config = {
},
{
displayName: "Unit-Tests",
testMatch: ["<rootDir>/src/tests/*.test.js"],
testMatch: ["<rootDir>/src/tests/vcs.test.js"],
},
{
displayName: "VCS-Tests",
testMatch: ["<rootDir>/src/vcs_providers_tests/**/*.test.js"],
}
],
};

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"test:integration": "cross-env NODE_ENV=test PULSAR_STATUS=dev jest --selectProjects Integration-Tests",
"start:dev": "cross-env PULSAR_STATUS=dev node ./src/dev_server.js",
"test": "cross-env NODE_ENV=test PULSAR_STATUS=dev jest",
"test:vcs": "cross-env NODE_ENV=test PULSAR_STATUS=dev jest --selectProjects VCS-Tests",
"api-docs": "quick-webserver-docs -i ./src/main.js -o ./docs/reference/API_Definition.md",
"lint": "prettier --check -u -w .",
"complex": "cr --newmi --config .complexrc .",
Expand Down
306 changes: 306 additions & 0 deletions src/pseudo_objects/package_json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
// Potentially this class will provide easy support for interacting with a package.json
// file. Bundling all the common methods of interaction here to avoid code duplication.
// As well as uneasy error handling.

// This Class seemingly would also be very helpful for the frontend, and is now being designed
// as possibly becoming it's own module, if proven useful.

// NOTES: opts.pack is the raw package that can be passed.
// Other modifiers can be provided as other opts
// Additionally: (This doesn't match currenlty) - The getters should simply locate
// the most likely location of the property that will contain the data requested.
// The setter itself should be in charge of validations, and error throwing.
// In the case where a getter cannot find anything relevant, -1 should be returned.
class PackageJSON {
constructor(opts) {
this.rawPack = opts.pack ?? {};

this.normalizedPack = {};
// normalizedMode will contain certain modes and settings to enforce.
this.mode = {
strict: opts.mode.strict ?? false, // strict Boolean will enforce strict adherance to specified service
service: opts.mode.service ?? "npm", // service is the intended service for the package.json
bug: opts.mode.bug ?? "string", // The Bug Mode used. Either Object or String is valid. Default can be used to stick with what's currently used.
};
}

// Below we will define the standard Values that are supported as Getters and
// as Setters
// Each getter will always first check the normalizedPack for it's needed value.
// Which if doesn't exist will work to find it in the rawPack.
// Once found it will be added to the normalizedPack. Setters themselves
// will only ever effect the normalizedPack. Ensuring we never overwrite
// any part of the rawPack, in case it's needed again.

/**
* === PROPERTIES ===
*/
get name() {

// First lets see if it's in the normalizedPack
if (typeof this.normalizedPack.name === "string") {
return this.normalizedPack.name;
}

if (typeof this.rawPack.name === "string") {
this.name = this.rawPack.name; // Use our setter to assign the value
return this.name; // Return the output of our setter
}

// If we have reached this point then we know we can't find this value.
// At this point we will return `undefined`
return undefined;
}

set name(value) {
if (this.mode.strict && typeof this.mode.service !== "undefined") {
let valid = this.validateName(this.mode.service);

if (valid.overall) {
this.normalizedPack.name = value;
return;
}

throw new Error(`Name is not valid for ${this.mode.service}: ${valid.invalid}`);
}

// No strict declared
this.normalizedPack.name = value;
}

get version() {
if (typeof this.normalizedPack.version === "string") {
return this.normalizedPack.version;
}

if (typeof this.rawPack.version === "string") {
this.version = this.rawPack.version;
return this.version;
}

return undefined;
}

set version(value) {
this.normalizedPack.version = value;
}

get description() {
if (typeof this.normalizedPack.description === "string") {
return this.normalizedPack.description;
}

if (typeof this.rawPack.description === "string") {
this.description = this.rawPack.description;
return this.description;
}

return undefined;
}

set description(value) {
this.normalizedPack.description = value;
}

get keywords() {
if (Array.isArray(this.normalizedPack.keywords)) {
return this.normalizedPack.keywords;
}

if (Array.isArray(this.rawPack.keywords)) {
this.keywords = this.rawPack.keywords;
return this.keywords;
}

return undefined;
}

set keywords(value) {
this.normalizedPack.keywords = value;
}

get homepage() {
if (typeof this.normalizedPack.homepage === "string") {
return this.normalizedPack.homepage;
}

if (typeof this.rawPack.homepage === "string") {
this.homepage = this.rawPack.homepage;
return this.homepage;
}

return undefined;
}

set homepage(value) {
this.normalizedPack = value;
}

get bugs() {
// this.mode.bugs can be Default, Object, or String
if (this.mode.bugs === "default" && typeof this.normalizedPack.bugs !== "undefined") {
return this.normalizedPack.bugs;
}

if (typeof this.normalizedPack.bugs === this.mode.bugs) {
return this.normalizedPack.bugs;
}

// Because Bugs has two modes, we will attempt to support either.
if (typeof this.rawPack.bugs === "string") {
switch(this.mode.bugs) {
case "object":
// we need to figure out if this is a URL or an email
case "string":
case "default":
default:
this.bugs = this.rawPack.bugs;
return this.bugs;
}
}

if (typeof this.rawPack.bugs === "object") {
switch(this.mode.bugs) {
case "string":
// Since when Bugs are in string mode we can only define a URL,
// we will throw away the email part of the object.
if (typeof this.rawPack.bugs.url !== "undefined") {
this.bugs = this.rawPack.bugs.url;
return this.bugs;
}
return undefined;
case "object":
case "default":
default:
if (typeof this.rawPack.bugs.url !== "undefined" && typeof this.rawPack.bugs.email !== "undefined") {
this.bugs = this.rawPack.bugs;
return this.bugs;
}
return undefined;
}
}

return undefined;
}

set bugs(value) {
if (this.mode.bugs === "object" || typeof value === "object") {
if (typeof value.url !== "undefined" && typeof value.email !== "undefined") {
this.normalizedPack.bugs = value;
return;
}
}

if (this.mode.bugs === "string" || typeof value === "string") {
if (typeof value === "string") {
// Also ensure it is a valid URL
this.normalizedPack.bugs = value;
return;
}
}

throw new Error(`Bugs value does't match ${this.mode.bugs} Bugs Mode`);
}

/**
* === VALIDATORS ===
*/
validateName(service) {
switch(service) {
case "npm": {
// This will ensure the package name meets the criteria of NPMJS
// https://docs.npmjs.com/cli/v9/configuring-npm/package-json#name
let name = this.name;
let validArray = [];
let invalidArray = [];

let length = {
status: false,
msg: "Length of Name"
};
let characters = {
status: false,
msg: "Allowed Characters"
};

if (name.length === 214 || name.length < 214) {
length.status = true;
validArray.push(length.msg);
}

if (!name.startsWith("_") && !name.startsWith(".")) {
characters.status = true;
validArray.push(characters.msg);
}

// Check for uppercase & URL safe

if (!length.status) {
invalidArray.push(length.msg);
}

if (!characters.status) {
invalidArray.push(characters.msg);
}

return {
overall: (length.status && characters.status) ? true : false,
valid: validArray,
invalid: invalidArray
};

}
default: {
// Since we found no explicit matching service, we will return fine.
return {
overall: true,
valid: [],
invalid: []
};
}
}
}

/**
* === METHODS ===
*/
parse(pack) {
// parse() accepts an optional `pack`, which can be used if PackageJSON was
// instiatied without passing any package data. In which case will be assigned
// here then have the whole file parsed, if left out the package data passed
// during class creation will be used. Erroring out if none is provided in either.

if (typeof pack !== "undefined") {
this.rawPack = pack;
}

if (typeof this.rawPack === "undefined") {
throw new Error("Raw PackageJSON Data never provided");
return;
Fixed Show fixed Hide fixed
}

// Now we know we should have this.rawPack defined properly, lets initiate parsing.

// Since the getter will find and assign all values using the setter, we now
// simply have to get every supported value.

for (const key in this.rawPack) {

if (typeof this[key] !== "function") {
// We don't have a method that supports the key found in the package.json
// It should be added arbitraly.
this.normalizedPack[key] = this.rawpack[key];
break;
}

// We know that the key taken from the package.json has a supported method.
// Lets call it.
this[key]();
}

return this.normalizedPack;
}

}

module.exports = PackageJSON;
13 changes: 13 additions & 0 deletions src/pseudo_objects/package_object_full.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Potentially this file will provide specialized handling of the
// Package Object Full object within the backend.
// Abstracting complex functions, and reducing code duplication.

const PackageJSON = require("./package_json.js");

class PackageObjectFull extends PackageJSON {
constructor() {
super();
}
}

module.exports = PackageObjectFull;
Loading