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

Apply Elm Format in single, dir-wide step #87

Merged
merged 18 commits into from
Nov 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions CHANGELOG-NPM-PACKAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Fixed

- `elm-format` failed to run during the code generation in some configurations.
The new solution uses [an NPM peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/)
of `elm-format`. That means that it will make you install it if it's not already
in your dependencies in your `package.json`. With that as a local dependency, we
can safely call [`npx`](https://www.npmjs.com/package/npx) to run your local
elm-format version. Note that this requires `npm >= 5.2.0`.
See [#87](https://github.com/dillonkearns/elm-graphql/pull/87) and
[#91](https://github.com/dillonkearns/elm-graphql/issues/91) for more details.
- The `elm-format` binary was previously run for each individual file asynchronously, which
could cause performance issues in some environments. Now, `elm-format` is run
as a single step on the entire generated directory after files are generated.
This is more performant and more reliable.

## [1.0.7] - 2018-11-06

### Changed
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Interface.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Interface exposing (..)
module Api.Interface exposing (placeholder)


placeholder : String
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Mutation.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Mutation exposing (..)
module Api.Mutation exposing (createComment, createPost, selection)

import Api.Interface
import Api.Object
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Object.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Object exposing (..)
module Api.Object exposing (Comment(..), Post(..))


type Comment
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Object/Comment.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Object.Comment exposing (..)
module Api.Object.Comment exposing (body, created_at, id, selection)

import Api.Interface
import Api.Object
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Object/Post.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Object.Post exposing (..)
module Api.Object.Post exposing (body, comments, id, selection, title)

import Api.Interface
import Api.Object
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Query.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Query exposing (..)
module Api.Query exposing (comments, post, posts, selection)

import Api.Interface
import Api.Object
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Scalar.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Scalar exposing (..)
module Api.Scalar exposing (Id(..))


type Id
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Subscription.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Subscription exposing (..)
module Api.Subscription exposing (commentAdded, postAdded, selection)

import Api.Interface
import Api.Object
Expand Down
2 changes: 1 addition & 1 deletion ete_tests/src/Api/Union.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- https://github.com/dillonkearns/elm-graphql


module Api.Union exposing (..)
module Api.Union exposing (placeholder)


placeholder : String
Expand Down
2 changes: 1 addition & 1 deletion examples/src/Github/Object/User.elm
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ type alias RepositoriesContributedToOptionalArguments =
- orderBy - Ordering options for repositories returned from the connection
- isLocked - If non-null, filters repositories according to whether they have been locked
- includeUserRepositories - If true, include user repositories
- contributionTypes - If non-null, include only the specified types of contributions. The GitHub.com UI uses [COMMIT, ISSUE, PULL\_REQUEST, REPOSITORY][COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]
- contributionTypes - If non-null, include only the specified types of contributions. The GitHub.com UI uses [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]

-}
repositoriesContributedTo : (RepositoriesContributedToOptionalArguments -> RepositoriesContributedToOptionalArguments) -> SelectionSet decodesTo Github.Object.RepositoryConnection -> Field decodesTo Github.Object.User
Expand Down
121 changes: 74 additions & 47 deletions generator/src/elm-graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { GraphQLClient } from "graphql-request";
import * as http from "http";
import * as minimist from "minimist";
import * as request from "request";
import { writeFile } from "./formatted-write";
import { applyElmFormat } from "./formatted-write";
import { introspectionQuery } from "./introspection-query";
import * as glob from "glob";
import * as path from "path";
Expand All @@ -24,30 +24,6 @@ const usage = `Usage:
elm-graphql --version # print the current @dillonkearns/elm-graphql version and target elm package version
elm-graphql url [--header 'headerKey: header value'...] # you can supply multiple header args`;

function isGenerated(path: string): boolean {
return (
fs
.readFileSync(path)
.indexOf("Do not manually edit this file, it was auto-generated by") >= 0
);
}
function warnIfContainsNonGenerated(path: string): void {
const files: string[] = glob.sync(path + "/**/*.elm");
const nonGenerated = files.filter(file => !isGenerated(file));

if (nonGenerated.length > 0) {
console.log(
"@dillonkearns/elm-graphql found some files that it did not generate. Please move or delete the following files and run @dillonkearns/elm-graphql again.",
nonGenerated
);
process.exit(1);
}
}

function removeGenerated(path: string): void {
glob.sync(path + "/**/*.elm").forEach(fs.unlinkSync);
}

const targetComment = `-- Do not manually edit this file, it was auto-generated by dillonkearns/elm-graphql
-- https://github.com/dillonkearns/elm-graphql
`;
Expand Down Expand Up @@ -100,30 +76,9 @@ if (!(graphqlUrl || introspectionFile)) {
console.log(usage);
process.exit(0);
}

warnIfContainsNonGenerated(prependBasePath("/"));

const onDataAvailable = (data: {}) => {
console.log("Generating files...");
let app = Elm.Main.init({ flags: { data, baseModule } });
app.ports.generatedFiles.subscribe(function(generatedFile: any) {
removeGenerated(prependBasePath("/"));
fs.mkdirpSync(prependBasePath("InputObject"));
fs.mkdirpSync(prependBasePath("Object"));
fs.mkdirpSync(prependBasePath("Interface"));
fs.mkdirpSync(prependBasePath("Union"));
fs.mkdirpSync(prependBasePath("Enum"));
for (let key in generatedFile) {
let filePath = path.join(outputPath, key);
let value = generatedFile[key];
writeFile(filePath, targetComment + value);
}
fs.writeFileSync(
prependBasePath("elm-graphql-metadata.json"),
`{"targetElmPackageVersion": "${elmPackageVersion}", "generatedByNpmPackageVersion": "${npmPackageVersion}"}`
);
console.log("Success!");
});
};
if (introspectionFile) {
const introspectionFileJson = JSON.parse(
fs.readFileSync(introspectionFile).toString()
Expand All @@ -144,3 +99,75 @@ if (introspectionFile) {
process.exit(1);
});
}

function makeEmptyDirectories(directoryNames: string[]): void {
directoryNames.forEach(dir => {
fs.mkdirpSync(prependBasePath(dir));
});
}

function onDataAvailable(data: {}) {
console.log("Generating files...");
let app = Elm.Main.init({ flags: { data, baseModule } });
app.ports.generatedFiles.subscribe(async function(generatedFile: {
[s: string]: string;
}) {
removeGenerated(prependBasePath("/"));
makeEmptyDirectories([
"InputObject",
"Object",
"Interface",
"Union",
"Enum"
]);
await Promise.all(writeGeneratedFiles(generatedFile));
writeIntrospectionFile();
applyElmFormat(outputPath);
console.log("Success!");
});
}

function isGenerated(path: string): boolean {
return (
fs
.readFileSync(path)
.indexOf("Do not manually edit this file, it was auto-generated by") >= 0
);
}

function warnIfContainsNonGenerated(path: string): void {
const files: string[] = glob.sync(path + "/**/*.elm");
const nonGenerated = files.filter(file => !isGenerated(file));

if (nonGenerated.length > 0) {
console.log(
"@dillonkearns/elm-graphql found some files that it did not generate. Please move or delete the following files and run @dillonkearns/elm-graphql again.",
nonGenerated
);
process.exit(1);
}
}

function removeGenerated(path: string): void {
glob.sync(path + "/**/*.elm").forEach(fs.unlinkSync);
}

function writeGeneratedFiles(generatedFile: {
[s: string]: string;
}): Promise<void>[] {
return Object.entries(generatedFile).map(([fileName, fileContents]) => {
const filePath = path.join(outputPath, fileName);
const fileToWritePromise = fs.writeFile(
filePath,
targetComment + fileContents
);
return fileToWritePromise;
});
}

function writeIntrospectionFile() {
fs.writeFile(
prependBasePath("elm-graphql-metadata.json"),
`{"targetElmPackageVersion": "${elmPackageVersion}", "generatedByNpmPackageVersion": "${npmPackageVersion}"}`
);
}
60 changes: 3 additions & 57 deletions generator/src/formatted-write.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,9 @@
import { spawn } from "child_process";
import { execSync } from "child_process";
import * as fs from "fs-extra";

const globalInstallPath = `${__dirname}/../node_modules/.bin/elm-format`;
const localInstallPath = `${__dirname}/../../.bin/elm-format`;

export const writeFile = (path: string, value: string): void => {
const elmFormatPath = findElmFormatPath();

if (elmFormatPath) {
writeWithElmFormat(path, value, elmFormatPath);
} else {
writeWithoutFormatting(path, value);
}
};

const writeWithElmFormat = (
path: string,
value: string,
elmFormatPath: string
): void => {
const elmFormat = spawn(
elmFormatPath,
["--stdin", "--elm-version=0.19", "--output", path],
{
shell: true
}
);

elmFormat.stdin.write(value);
elmFormat.stdin.end();

elmFormat.stdout.on("data", data => {
console.log(data.toString());
});

elmFormat.stderr.on("data", data => {
console.log(data.toString());
});

elmFormat.on("close", code => {
if (code !== 0) {
console.log(`elm-format process exited with code ${code}.
Was attempting to write to path ${path} with contents:
${value}`);
process.exit(code);
}
});
};

const writeWithoutFormatting = (path: string, value: string) => {
fs.writeFileSync(path, value);
};

const findElmFormatPath = (): string | null => {
if (fs.existsSync(globalInstallPath)) {
return globalInstallPath;
} else if (fs.existsSync(localInstallPath)) {
return localInstallPath;
} else {
return null;
}
export const applyElmFormat = (fileOrFolderToFormat: string): void => {
execSync(`npx elm-format --elm-version=0.19 --yes ${fileOrFolderToFormat}/`);
};
Loading