From b24d62e7188ebc7db021704af8b7688ba3f83236 Mon Sep 17 00:00:00 2001 From: Kevin F Date: Mon, 25 Sep 2023 23:26:24 +0200 Subject: [PATCH 1/4] Add auto generation logic for index.js --- ARCtrl.sln | 1 + build/TestTasks.fs | 115 +++++++++++++++++++++++++-- build/release_package.json | 4 +- src/ARCtrl/ARCtrl.fsproj | 31 +++----- src/ARCtrl/Index.fs | 10 +++ src/ARCtrl/Templates/Template.Web.fs | 2 - tests/JavaScript/ARCtrl.Index.js | 20 +++++ 7 files changed, 155 insertions(+), 28 deletions(-) create mode 100644 src/ARCtrl/Index.fs create mode 100644 tests/JavaScript/ARCtrl.Index.js diff --git a/ARCtrl.sln b/ARCtrl.sln index cbdf5826..dba1dac1 100644 --- a/ARCtrl.sln +++ b/ARCtrl.sln @@ -55,6 +55,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "playground", "playground", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JavaScript", "JavaScript", "{913222CA-261F-49CB-A823-CC7C335F964A}" ProjectSection(SolutionItems) = preProject + tests\JavaScript\ARCtrl.Index.js = tests\JavaScript\ARCtrl.Index.js tests\JavaScript\ISA.CompositeHeader.js = tests\JavaScript\ISA.CompositeHeader.js tests\JavaScript\ISA.Person.js = tests\JavaScript\ISA.Person.js tests\JavaScript\Main.js = tests\JavaScript\Main.js diff --git a/build/TestTasks.fs b/build/TestTasks.fs index ae0a1fd8..a7703dd6 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -115,8 +115,116 @@ module private Helper = |> Proc.Parallel.run |> ignore +module GenerateIndexJs = + + open System + open System.IO + open System.Text.RegularExpressions + + let private getAllJsFiles(path: string) = + let options = EnumerationOptions() + options.RecurseSubdirectories <- true + IO.Directory.EnumerateFiles(path,"*.js",options) + + let private pattern (className: string) = sprintf @"^export class (?%s)+.*{" className + + type private FileInformation = { + FilePath : string + Lines : string [] + } with + static member create(filePath: string, lines: string []) = { + FilePath = filePath + Lines = lines + } + + let private findClasses (rootPath: string) (cois: string []) (filePaths: seq ) = + let files = [| + for fp in filePaths do + yield FileInformation.create(fp, System.IO.File.ReadAllLines (fp)) + |] + let importStatements = ResizeArray() + let findClass (className: string) = + /// maybe set this as default if you do not want any whitelist + let classNameDefault = @"[a-zA-Z_0-9]" + let regex = Regex(Regex.Escape(className) |> pattern) + let mutable found = false + let mutable result = None + let enum = files.GetEnumerator() + while not found && enum.MoveNext() do + let fileInfo = enum.Current :?> FileInformation + for line in fileInfo.Lines do + let m = regex.Match(line) + match m.Success with + | true -> + found <- true + result <- Some <| (className, IO.Path.GetRelativePath(rootPath,fileInfo.FilePath)) + | false -> + () + match result with + | None -> + failwithf "Unable to find %s" className + | Some r -> + importStatements.Add r + for coi in cois do findClass coi + importStatements + |> Array.ofSeq + + open System.Text + + let private createImportStatements (info: (string*string) []) = + let sb = StringBuilder() + let importCollection = info |> Array.groupBy snd |> Array.map (fun (p,a) -> p, a |> Array.map fst ) + for filePath, imports in importCollection do + let p = filePath.Replace("\\","/") + sb.Append "export { " |> ignore + sb.AppendJoin(", ", imports) |> ignore + sb.Append " } from " |> ignore + sb.Append (sprintf "\"./%s\"" p) |> ignore + sb.Append ";" |> ignore + sb.AppendLine() |> ignore + sb.ToString() + + let private writeJsIndexfile (path: string) (fileName: string) (content: string) = + let filePath = Path.Combine(path, fileName) + File.WriteAllText(filePath, content) + + let private generateIndexfile (rootPath: string, fileName: string, whiteList: string []) = + getAllJsFiles(rootPath) + |> findClasses rootPath whiteList + |> createImportStatements + |> writeJsIndexfile rootPath fileName + + let ARCtrl_generate(rootPath: string) = + let whiteList = [| + "Comment$" + "Person" + "OntologyAnnotation"; + "IOType" + "CompositeHeader"; + "CompositeCell" + "CompositeColumn" + "ArcTable" + "ArcAssay"; + "ArcStudy"; + "ArcInvestigation"; + "Template" + "Organisation" + "JsWeb" + "ARC" + |] + generateIndexfile(rootPath, "index.js", whiteList) + module RunTests = + let runTestsJsNative = BuildTask.create "runTestsJSNative" [clean; build] { + Trace.traceImportant "Start native JavaScript tests" + for path in ProjectInfo.jsTestProjects do + // transpile library for native access + run dotnet $"fable src/ARCtrl -o {path}/ARCtrl" "" + GenerateIndexJs.ARCtrl_generate($"{path}/ARCtrl") + run npx $"mocha {path} --timeout 20000" "" + } + let runTestsJs = BuildTask.create "runTestsJS" [clean; build] { for path in ProjectInfo.testProjects do // transpile js files from fsharp code @@ -124,11 +232,6 @@ module RunTests = // run mocha in target path to execute tests // "--timeout 20000" is used, because json schema validation takes a bit of time. run npx $"mocha {path}/js --timeout 20000" "" - Trace.traceImportant "Start native JavaScript tests" - for path in ProjectInfo.jsTestProjects do - // transpile library for native access - run dotnet $"fable src/ARCtrl -o {path}/ARCtrl" "" - run npx $"mocha {path} --timeout 20000" "" } let runTestsDotnet = BuildTask.create "runTestsDotnet" [clean; build] { @@ -145,6 +248,6 @@ module RunTests = ) } -let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsDotnet] { +let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsJsNative; RunTests.runTestsDotnet] { () } \ No newline at end of file diff --git a/build/release_package.json b/build/release_package.json index 20c63bca..d95fe71b 100644 --- a/build/release_package.json +++ b/build/release_package.json @@ -3,6 +3,7 @@ "version": "1.0.0+1c6c4fa", "description": "Top level ARC DataModel and API function descriptions.", "type": "module", + "main": "Index.js", "repository": { "type": "git", "url": "git+https://github.com/nfdi4plants/arcAPI.git" @@ -17,6 +18,7 @@ }, "homepage": "https://github.com/nfdi4plants/arcAPI#readme", "dependencies": { - "fable-library": "^1.1.1" + "fable-library": "^1.1.1", + "isomorphic-fetch": "^3.0.0" } } diff --git a/src/ARCtrl/ARCtrl.fsproj b/src/ARCtrl/ARCtrl.fsproj index e1379e78..55bc7a9f 100644 --- a/src/ARCtrl/ARCtrl.fsproj +++ b/src/ARCtrl/ARCtrl.fsproj @@ -4,19 +4,6 @@ netstandard2.0 true - - nfdi4plants, Lukas Weil, Kevin Frey, Kevin Schneider, Oliver Maus - Library for management of Annotated Research Contexts (ARCs) using an in-memory representation and runtimer agnostic contract systems. - MIT - logo.png - ARC F# FSharp dotnet .Net bioinformatics biology fable-library datascience dataplant nfdi metadata - https://github.com/nfdi4plants/ARCtrl - https://github.com/nfdi4plants/ARCtrl - git - - - - @@ -43,13 +30,19 @@ - - - - - - + + + + nfdi4plants, Lukas Weil, Kevin Frey, Kevin Schneider, Oliver Maus + Library for management of Annotated Research Contexts (ARCs) using an in-memory representation and runtimer agnostic contract systems. + MIT + logo.png + ARC F# FSharp dotnet .Net bioinformatics biology fable-library datascience dataplant nfdi metadata + https://github.com/nfdi4plants/ARCtrl + https://github.com/nfdi4plants/ARCtrl + git + \ No newline at end of file diff --git a/src/ARCtrl/Index.fs b/src/ARCtrl/Index.fs new file mode 100644 index 00000000..b620f948 --- /dev/null +++ b/src/ARCtrl/Index.fs @@ -0,0 +1,10 @@ +module ARCtrl.Index + +open Fable.Core +open Fable.Core.JsInterop + +exportDefault {| + ArcAssay = ARCtrl.ISA.ArcAssay + ArcStudy = ARCtrl.ISA.ArcStudy + ArcInvestigation = ARCtrl.ISA.ArcInvestigation +|} \ No newline at end of file diff --git a/src/ARCtrl/Templates/Template.Web.fs b/src/ARCtrl/Templates/Template.Web.fs index b3355899..d58d3d27 100644 --- a/src/ARCtrl/Templates/Template.Web.fs +++ b/src/ARCtrl/Templates/Template.Web.fs @@ -14,8 +14,6 @@ let getTemplates(url: string option) = return mapResult } -open Fable.Core.JsInterop - /// /// This class is used to make async functions more accessible from JavaScript. /// diff --git a/tests/JavaScript/ARCtrl.Index.js b/tests/JavaScript/ARCtrl.Index.js new file mode 100644 index 00000000..bff7349d --- /dev/null +++ b/tests/JavaScript/ARCtrl.Index.js @@ -0,0 +1,20 @@ +import { equal, deepEqual } from 'assert'; +import { OntologyAnnotation, ArcAssay, ArcInvestigation, ArcTable } from './ARCtrl/index.js' + +//import file './ARCtrl/index.js' is generated by FAKE never by NPM. +describe('Auto Generated Index', function () { + it('OntologyAnnotation', function () { + let actual = OntologyAnnotation.fromString("My OA") + equal(actual.NameText, "My OA") + }); + it('ArcAssay', function () { + let actual = new ArcAssay("My Assay", null, null, null, [ArcTable.init("MyTable")]) + equal(actual.Identifier, "My Assay", "Id") + equal(actual.TableCount, 1, "TableCount") + }); + it('ArcInvestigation', function () { + let actual = new ArcInvestigation("My Investigation", "Super Awesome Experiment") + equal(actual.Identifier, "My Investigation", "Id") + equal(actual.Title, "Super Awesome Experiment", "Title") + }); +}); \ No newline at end of file From 8086ee38a85e753ce303f49a95ace50b98222ce2 Mon Sep 17 00:00:00 2001 From: Kevin F Date: Tue, 26 Sep 2023 06:27:50 +0200 Subject: [PATCH 2/4] Make Index.js Regex more strict avoiding ArcTables with ArcTable --- build/Build.fsproj | 1 + build/GenerateIndexJs.fs | 98 +++++++++++++++++++++++++++++++++++++++ build/TestTasks.fs | 99 ---------------------------------------- 3 files changed, 99 insertions(+), 99 deletions(-) create mode 100644 build/GenerateIndexJs.fs diff --git a/build/Build.fsproj b/build/Build.fsproj index a4bb7e14..6db33c3a 100644 --- a/build/Build.fsproj +++ b/build/Build.fsproj @@ -12,6 +12,7 @@ + diff --git a/build/GenerateIndexJs.fs b/build/GenerateIndexJs.fs new file mode 100644 index 00000000..8ca14b49 --- /dev/null +++ b/build/GenerateIndexJs.fs @@ -0,0 +1,98 @@ +module GenerateIndexJs + +open System +open System.IO +open System.Text.RegularExpressions + +let private getAllJsFiles(path: string) = + let options = EnumerationOptions() + options.RecurseSubdirectories <- true + IO.Directory.EnumerateFiles(path,"*.js",options) + +let private pattern (className: string) = sprintf @"^export class (?%s)+[\s{].*({)?" className + +type private FileInformation = { + FilePath : string + Lines : string [] +} with + static member create(filePath: string, lines: string []) = { + FilePath = filePath + Lines = lines + } + +let private findClasses (rootPath: string) (cois: string []) (filePaths: seq ) = + let files = [| + for fp in filePaths do + yield FileInformation.create(fp, System.IO.File.ReadAllLines (fp)) + |] + let importStatements = ResizeArray() + let findClass (className: string) = + /// maybe set this as default if you do not want any whitelist + let classNameDefault = @"[a-zA-Z_0-9]" + let regex = Regex(Regex.Escape(className) |> pattern) + let mutable found = false + let mutable result = None + let enum = files.GetEnumerator() + while not found && enum.MoveNext() do + let fileInfo = enum.Current :?> FileInformation + for line in fileInfo.Lines do + let m = regex.Match(line) + match m.Success with + | true -> + found <- true + result <- Some <| (className, IO.Path.GetRelativePath(rootPath,fileInfo.FilePath)) + | false -> + () + match result with + | None -> + failwithf "Unable to find %s" className + | Some r -> + importStatements.Add r + for coi in cois do findClass coi + importStatements + |> Array.ofSeq + +open System.Text + +let private createImportStatements (info: (string*string) []) = + let sb = StringBuilder() + let importCollection = info |> Array.groupBy snd |> Array.map (fun (p,a) -> p, a |> Array.map fst ) + for filePath, imports in importCollection do + let p = filePath.Replace("\\","/") + sb.Append "export { " |> ignore + sb.AppendJoin(", ", imports) |> ignore + sb.Append " } from " |> ignore + sb.Append (sprintf "\"./%s\"" p) |> ignore + sb.Append ";" |> ignore + sb.AppendLine() |> ignore + sb.ToString() + +let private writeJsIndexfile (path: string) (fileName: string) (content: string) = + let filePath = Path.Combine(path, fileName) + File.WriteAllText(filePath, content) + +let private generateIndexfile (rootPath: string, fileName: string, whiteList: string []) = + getAllJsFiles(rootPath) + |> findClasses rootPath whiteList + |> createImportStatements + |> writeJsIndexfile rootPath fileName + +let ARCtrl_generate(rootPath: string) = + let whiteList = [| + "Comment$" + "Person" + "OntologyAnnotation"; + "IOType" + "CompositeHeader"; + "CompositeCell" + "CompositeColumn" + "ArcTable" + "ArcAssay"; + "ArcStudy"; + "ArcInvestigation"; + "Template" + "Organisation" + "JsWeb" + "ARC" + |] + generateIndexfile(rootPath, "index.js", whiteList) \ No newline at end of file diff --git a/build/TestTasks.fs b/build/TestTasks.fs index a7703dd6..300dbf2c 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -114,105 +114,6 @@ module private Helper = processes |> Proc.Parallel.run |> ignore - -module GenerateIndexJs = - - open System - open System.IO - open System.Text.RegularExpressions - - let private getAllJsFiles(path: string) = - let options = EnumerationOptions() - options.RecurseSubdirectories <- true - IO.Directory.EnumerateFiles(path,"*.js",options) - - let private pattern (className: string) = sprintf @"^export class (?%s)+.*{" className - - type private FileInformation = { - FilePath : string - Lines : string [] - } with - static member create(filePath: string, lines: string []) = { - FilePath = filePath - Lines = lines - } - - let private findClasses (rootPath: string) (cois: string []) (filePaths: seq ) = - let files = [| - for fp in filePaths do - yield FileInformation.create(fp, System.IO.File.ReadAllLines (fp)) - |] - let importStatements = ResizeArray() - let findClass (className: string) = - /// maybe set this as default if you do not want any whitelist - let classNameDefault = @"[a-zA-Z_0-9]" - let regex = Regex(Regex.Escape(className) |> pattern) - let mutable found = false - let mutable result = None - let enum = files.GetEnumerator() - while not found && enum.MoveNext() do - let fileInfo = enum.Current :?> FileInformation - for line in fileInfo.Lines do - let m = regex.Match(line) - match m.Success with - | true -> - found <- true - result <- Some <| (className, IO.Path.GetRelativePath(rootPath,fileInfo.FilePath)) - | false -> - () - match result with - | None -> - failwithf "Unable to find %s" className - | Some r -> - importStatements.Add r - for coi in cois do findClass coi - importStatements - |> Array.ofSeq - - open System.Text - - let private createImportStatements (info: (string*string) []) = - let sb = StringBuilder() - let importCollection = info |> Array.groupBy snd |> Array.map (fun (p,a) -> p, a |> Array.map fst ) - for filePath, imports in importCollection do - let p = filePath.Replace("\\","/") - sb.Append "export { " |> ignore - sb.AppendJoin(", ", imports) |> ignore - sb.Append " } from " |> ignore - sb.Append (sprintf "\"./%s\"" p) |> ignore - sb.Append ";" |> ignore - sb.AppendLine() |> ignore - sb.ToString() - - let private writeJsIndexfile (path: string) (fileName: string) (content: string) = - let filePath = Path.Combine(path, fileName) - File.WriteAllText(filePath, content) - - let private generateIndexfile (rootPath: string, fileName: string, whiteList: string []) = - getAllJsFiles(rootPath) - |> findClasses rootPath whiteList - |> createImportStatements - |> writeJsIndexfile rootPath fileName - - let ARCtrl_generate(rootPath: string) = - let whiteList = [| - "Comment$" - "Person" - "OntologyAnnotation"; - "IOType" - "CompositeHeader"; - "CompositeCell" - "CompositeColumn" - "ArcTable" - "ArcAssay"; - "ArcStudy"; - "ArcInvestigation"; - "Template" - "Organisation" - "JsWeb" - "ARC" - |] - generateIndexfile(rootPath, "index.js", whiteList) module RunTests = From 9b1995f69f47f92cf5bf827494c6ade1e67a1aaf Mon Sep 17 00:00:00 2001 From: Kevin F Date: Tue, 26 Sep 2023 10:48:19 +0200 Subject: [PATCH 3/4] Fix ARCtrl.fsproj --- package.json | 17 +---------------- src/ARCtrl/ARCtrl.fsproj | 37 ++++++++++++++++++++++--------------- src/ARCtrl/Index.fs | 10 ---------- 3 files changed, 23 insertions(+), 41 deletions(-) delete mode 100644 src/ARCtrl/Index.fs diff --git a/package.json b/package.json index 11b431dd..706fa16b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,4 @@ { - "name": "@nfdi4plants/arctrl", - "description": "Top level ARC DataModel and API function descriptions.", "type": "module", "scripts": { "mocha": "mocha", @@ -24,19 +22,10 @@ "testpy": "", "postinstall": "cd src/ISA & npm install" }, - "repository": { - "type": "git", - "url": "git+https://github.com/nfdi4plants/arcAPI.git" - }, "author": "Heinrich Lukas Weil (https://github.com/HLWeil)", "contributors": [ "Kevin Frey (https://github.com/Freymaurer)" ], - "license": "ISC", - "bugs": { - "url": "https://github.com/nfdi4plants/arcAPI/issues" - }, - "homepage": "https://github.com/nfdi4plants/arcAPI#readme", "dependencies": { "fable-library": "^1.1.1", "isomorphic-fetch": "^3.0.0" @@ -44,9 +33,5 @@ "devDependencies": { "mocha": "^10.2.0", "mkdirp": "3.0.1" - }, - "files": [ - "dist/js/**", - "dist/js/fable-modules**" - ] + } } diff --git a/src/ARCtrl/ARCtrl.fsproj b/src/ARCtrl/ARCtrl.fsproj index 55bc7a9f..c8e67dad 100644 --- a/src/ARCtrl/ARCtrl.fsproj +++ b/src/ARCtrl/ARCtrl.fsproj @@ -4,6 +4,20 @@ netstandard2.0 true + + nfdi4plants, Lukas Weil, Kevin Frey, Kevin Schneider, Oliver Maus + Library for management of Annotated Research Contexts (ARCs) using an in-memory representation and runtimer agnostic contract systems. + MIT + logo.png + ARC F# FSharp dotnet .Net bioinformatics biology fable-library datascience dataplant nfdi metadata + https://github.com/nfdi4plants/ARCtrl + https://github.com/nfdi4plants/ARCtrl + git + + + + + @@ -30,19 +44,12 @@ - - - - - - nfdi4plants, Lukas Weil, Kevin Frey, Kevin Schneider, Oliver Maus - Library for management of Annotated Research Contexts (ARCs) using an in-memory representation and runtimer agnostic contract systems. - MIT - logo.png - ARC F# FSharp dotnet .Net bioinformatics biology fable-library datascience dataplant nfdi metadata - https://github.com/nfdi4plants/ARCtrl - https://github.com/nfdi4plants/ARCtrl - git - - + + + + + + + + \ No newline at end of file diff --git a/src/ARCtrl/Index.fs b/src/ARCtrl/Index.fs deleted file mode 100644 index b620f948..00000000 --- a/src/ARCtrl/Index.fs +++ /dev/null @@ -1,10 +0,0 @@ -module ARCtrl.Index - -open Fable.Core -open Fable.Core.JsInterop - -exportDefault {| - ArcAssay = ARCtrl.ISA.ArcAssay - ArcStudy = ARCtrl.ISA.ArcStudy - ArcInvestigation = ARCtrl.ISA.ArcInvestigation -|} \ No newline at end of file From eec98cd4518db4e541da49e02552445e4edc2d91 Mon Sep 17 00:00:00 2001 From: Kevin F Date: Tue, 26 Sep 2023 10:49:18 +0200 Subject: [PATCH 4/4] Fix PR requests :art: --- build/GenerateIndexJs.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/GenerateIndexJs.fs b/build/GenerateIndexJs.fs index 8ca14b49..688b14a8 100644 --- a/build/GenerateIndexJs.fs +++ b/build/GenerateIndexJs.fs @@ -80,8 +80,9 @@ let private generateIndexfile (rootPath: string, fileName: string, whiteList: st let ARCtrl_generate(rootPath: string) = let whiteList = [| "Comment$" - "Person" "OntologyAnnotation"; + "Person"; + "Publication"; "IOType" "CompositeHeader"; "CompositeCell"