@stepzen/transpiler 0.28.0-experimental.dd6fead → 0.28.0-experimental.f225ee8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/lib/actions/configure.js +3 -3
  2. package/lib/actions/configure.js.map +1 -1
  3. package/lib/actions/lint.d.ts.map +1 -1
  4. package/lib/actions/lint.js +20 -12
  5. package/lib/actions/lint.js.map +1 -1
  6. package/lib/actions/merge.d.ts +7 -6
  7. package/lib/actions/merge.d.ts.map +1 -1
  8. package/lib/actions/merge.js +42 -26
  9. package/lib/actions/merge.js.map +1 -1
  10. package/lib/actions/stitch.d.ts +2 -2
  11. package/lib/actions/stitch.d.ts.map +1 -1
  12. package/lib/actions/stitch.js +30 -12
  13. package/lib/actions/stitch.js.map +1 -1
  14. package/lib/actions/transpile.d.ts.map +1 -1
  15. package/lib/actions/transpile.js +9 -3
  16. package/lib/actions/transpile.js.map +1 -1
  17. package/lib/actions/validate.js +4 -4
  18. package/lib/actions/validate.js.map +1 -1
  19. package/lib/utils/copy-workspace-content.js +4 -4
  20. package/lib/utils/copy-workspace-content.js.map +1 -1
  21. package/lib/utils/merge-helpers.d.ts.map +1 -1
  22. package/lib/utils/merge-helpers.js +23 -18
  23. package/lib/utils/merge-helpers.js.map +1 -1
  24. package/lib/utils/rmtemp.d.ts +11 -0
  25. package/lib/utils/rmtemp.d.ts.map +1 -0
  26. package/lib/utils/rmtemp.js +43 -0
  27. package/lib/utils/rmtemp.js.map +1 -0
  28. package/lib/utils/set-files-in-sdl.d.ts +2 -2
  29. package/lib/utils/set-files-in-sdl.d.ts.map +1 -1
  30. package/lib/utils/set-files-in-sdl.js +12 -12
  31. package/lib/utils/set-files-in-sdl.js.map +1 -1
  32. package/package.json +14 -12
  33. package/src/actions/configure.ts +3 -3
  34. package/src/actions/lint.ts +20 -17
  35. package/src/actions/merge.ts +70 -39
  36. package/src/actions/stitch.ts +32 -15
  37. package/src/actions/transpile.ts +9 -4
  38. package/src/actions/validate.ts +4 -4
  39. package/src/utils/copy-workspace-content.ts +4 -4
  40. package/src/utils/merge-helpers.ts +23 -19
  41. package/src/utils/rmtemp.ts +48 -0
  42. package/src/utils/set-files-in-sdl.ts +16 -13
@@ -1,6 +1,6 @@
1
1
  import {clone, cloneDeep} from 'lodash'
2
2
  import {parse, print, visit} from 'graphql'
3
- import * as fs from 'fs-extra'
3
+ import * as fsx from 'fs-extra'
4
4
  import * as glob from 'glob'
5
5
  import * as os from 'os'
6
6
  import * as path from 'path'
@@ -9,15 +9,13 @@ import * as prettier from 'prettier'
9
9
  import dedupeQueryAndMutationTypes from '../utils/dedupe-query-and-mutation-types'
10
10
  import {ALL_GRAPHQL_FILES} from '../utils/constants'
11
11
  import {getAllGraphQLFiles} from '../utils/copy-workspace-content'
12
+ import {rmtemp} from '../utils/rmtemp'
12
13
 
13
- export default (
14
- source: string,
15
- output: string = path.join(os.tmpdir(), `stepzen-tmp-${Date.now()}`),
16
- ) => {
14
+ const doStitch = (source: string, output: string) => {
17
15
  // Ensure source and output directories exist
18
- if (!fs.existsSync(source))
16
+ if (!fsx.existsSync(source))
19
17
  throw new Error(`Cannot find source directory ${source}`)
20
- fs.ensureDirSync(output)
18
+ fsx.ensureDirSync(output, 0o700)
21
19
 
22
20
  // Get a list of files.
23
21
  let ast: any
@@ -26,8 +24,8 @@ export default (
26
24
  // If there's an index.graphQL - get files argument in @sdl directive
27
25
  const sourceIndex = path.join(source, 'index.graphql')
28
26
 
29
- if (fs.existsSync(sourceIndex)) {
30
- const index = fs.readFileSync(sourceIndex, 'utf8')
27
+ if (fsx.existsSync(sourceIndex)) {
28
+ const index = fsx.readFileSync(sourceIndex, 'utf8')
31
29
  ast = parse(index)
32
30
  ast = visit(ast, {
33
31
  Directive(node) {
@@ -58,7 +56,7 @@ export default (
58
56
  const content = glob
59
57
  .sync('**/*.graphql', {cwd: source})
60
58
  .map((file: string) => {
61
- const graphql = fs.readFileSync(`${source}/${file}`, 'utf8')
59
+ const graphql = fsx.readFileSync(`${source}/${file}`, 'utf8')
62
60
  return graphql
63
61
  })
64
62
  ast = parse(content.join(os.EOL))
@@ -74,7 +72,7 @@ export default (
74
72
  // Check all the files exist
75
73
  for (const file of files) {
76
74
  const find = path.join(source, file)
77
- if (!fs.existsSync(find)) {
75
+ if (!fsx.existsSync(find)) {
78
76
  throw new Error(
79
77
  `Cannot find file ${file} referenced in the @sdl directive in index.graphql`,
80
78
  )
@@ -86,7 +84,7 @@ export default (
86
84
  let stitched = `${printed}${os.EOL}`
87
85
  for (const file of files) {
88
86
  const find = path.join(source, file)
89
- const content = fs.readFileSync(find, 'utf8')
87
+ const content = fsx.readFileSync(find, 'utf8')
90
88
  stitched += `${content}${os.EOL}`
91
89
  }
92
90
 
@@ -98,16 +96,35 @@ export default (
98
96
 
99
97
  // Write to output folder
100
98
  const outputIndex = path.join(output, 'index.graphql')
101
- fs.writeFileSync(outputIndex, stitched)
99
+ fsx.writeFileSync(outputIndex, stitched)
102
100
 
103
101
  // Copy config if exists, too
104
102
  const sourceConfig = path.join(source, 'config.yaml')
105
103
  const outputConfig = path.join(output, 'config.yaml')
106
104
 
107
- if (fs.existsSync(sourceConfig)) {
108
- fs.copyFileSync(sourceConfig, outputConfig)
105
+ if (fsx.existsSync(sourceConfig)) {
106
+ fsx.copyFileSync(sourceConfig, outputConfig)
109
107
  }
110
108
 
111
109
  // Return output folder
112
110
  return output
113
111
  }
112
+
113
+ const stitch = (source: string, output?: string) => {
114
+ if (output) {
115
+ return doStitch(source, output)
116
+ }
117
+
118
+ output = path.join(os.tmpdir(), `stepzen-tmp-${Date.now()}`)
119
+ try {
120
+ return doStitch(source, output)
121
+ } catch (error) {
122
+ // In case of an error delete the temp output folder created earlier so that
123
+ // it does not "leak". In case of a success, deleting the output folder is
124
+ // the caller responsibility.
125
+ rmtemp(output)
126
+ throw error
127
+ }
128
+ }
129
+
130
+ export default stitch
@@ -1,4 +1,4 @@
1
- import {DocumentNode, parse} from 'graphql'
1
+ import {parse} from 'graphql'
2
2
  import * as dotenv from 'dotenv'
3
3
  import * as debug from 'debug'
4
4
  import * as fs from 'fs'
@@ -10,6 +10,7 @@ import stitch from '../actions/stitch'
10
10
  import configure from './configure'
11
11
 
12
12
  import configMutations from '../mutations/config'
13
+ import {rmtemp} from '../utils/rmtemp'
13
14
 
14
15
  /**
15
16
  * Read a StepZen workspace directory, apply StepZen-specific schema and config
@@ -61,9 +62,13 @@ export default async (source: string) => {
61
62
 
62
63
  if (graphqlFiles.length > 0) {
63
64
  const stitched = await stitch(source)
64
- const index = path.join(stitched, 'index.graphql')
65
- const graphql = fs.readFileSync(index, 'utf8')
66
- schema = print(parse(graphql))
65
+ try {
66
+ const index = path.join(stitched, 'index.graphql')
67
+ const graphql = fs.readFileSync(index, 'utf8')
68
+ schema = print(parse(graphql))
69
+ } finally {
70
+ rmtemp(stitched)
71
+ }
67
72
  }
68
73
 
69
74
  return {
@@ -1,5 +1,5 @@
1
1
  import {buildASTSchema, DocumentNode, parse, print} from 'graphql'
2
- import * as fs from 'fs-extra'
2
+ import * as fsx from 'fs-extra'
3
3
  import * as os from 'os'
4
4
  import * as path from 'path'
5
5
 
@@ -16,18 +16,18 @@ export default (
16
16
  },
17
17
  ) => {
18
18
  // Ensure source and output directories exist
19
- if (!fs.existsSync(source)) {
19
+ if (!fsx.existsSync(source)) {
20
20
  throw new Error(`Cannot find source directory ${source}`)
21
21
  }
22
22
 
23
23
  // Ensure index.graphql exists
24
- if (!fs.existsSync(`${source}/index.graphql`)) {
24
+ if (!fsx.existsSync(`${source}/index.graphql`)) {
25
25
  throw new Error(`Cannot find index.graphql in ${source}`)
26
26
  }
27
27
 
28
28
  // Get the index.graphql file
29
29
  const file = path.join(source, 'index.graphql')
30
- const index = fs.readFileSync(file, 'utf8')
30
+ const index = fsx.readFileSync(file, 'utf8')
31
31
 
32
32
  // Parse
33
33
  let ast: DocumentNode = parse(
@@ -1,4 +1,4 @@
1
- import * as fs from 'fs-extra'
1
+ import * as fsx from 'fs-extra'
2
2
  import * as glob from 'glob'
3
3
  import * as path from 'path'
4
4
  import {flatMap} from 'lodash'
@@ -24,7 +24,7 @@ const IGNORED_PATTERNS = ['node_modules/**']
24
24
  * Exclude special folders, e.g. node_modules
25
25
  */
26
26
  export default (srcPath: string, dstPath: string) => {
27
- if (!fs.existsSync(srcPath)) {
27
+ if (!fsx.existsSync(srcPath)) {
28
28
  throw new Error(`Cannot find source directory ${srcPath}`)
29
29
  }
30
30
 
@@ -36,8 +36,8 @@ export default (srcPath: string, dstPath: string) => {
36
36
  ).forEach(relativePath => {
37
37
  const srcFileFullPath = path.join(srcPath, relativePath)
38
38
  const dstFileFullPath = path.join(dstPath, relativePath)
39
- fs.ensureDirSync(path.dirname(dstFileFullPath))
40
- fs.copyFileSync(srcFileFullPath, dstFileFullPath)
39
+ fsx.ensureDirSync(path.dirname(dstFileFullPath))
40
+ fsx.copyFileSync(srcFileFullPath, dstFileFullPath)
41
41
  })
42
42
  }
43
43
 
@@ -2,7 +2,7 @@ import * as debug from 'debug'
2
2
  import {BREAK, GraphQLSchema, visit} from 'graphql'
3
3
  import {buildSchema} from 'graphql/utilities'
4
4
  import fetch from '@stepzen/fetch'
5
- import * as fs from 'fs-extra'
5
+ import * as fsx from 'fs-extra'
6
6
  import * as glob from 'glob'
7
7
  import * as os from 'os'
8
8
  import * as path from 'path'
@@ -13,6 +13,7 @@ import {STEPZEN_SERVER_URL} from './constants'
13
13
 
14
14
  import configure from '../actions/configure'
15
15
  import transpile from '../actions/transpile'
16
+ import {rmtemp} from './rmtemp'
16
17
 
17
18
  export const dedupeTempFolder = (dirpath: string) => {
18
19
  do {
@@ -27,7 +28,7 @@ export const dedupeTempFolder = (dirpath: string) => {
27
28
  export const findNextAvailableSubfolder = (folder: string, name: string) => {
28
29
  let subfolder = name
29
30
  let counter = 1
30
- while (fs.existsSync(path.join(folder, subfolder))) {
31
+ while (fsx.existsSync(path.join(folder, subfolder))) {
31
32
  const suffix = `${counter++}`.padStart(2, '0')
32
33
  subfolder = `${name}-${suffix}`
33
34
  }
@@ -76,30 +77,33 @@ export const getConfiguration = async (
76
77
  answers: any = {},
77
78
  ): Promise<string | boolean> => {
78
79
  const tmp = path.join(os.tmpdir(), `stepzen-tmp-config-${Date.now()}`)
79
- fs.ensureDirSync(tmp)
80
+ fsx.ensureDirSync(tmp)
80
81
 
81
- for (const directory of directories) {
82
- const configs = [
83
- ...glob.sync('**/config.yaml', {cwd: directory}),
84
- ...glob.sync('**/stepzen.config.json', {cwd: directory}),
85
- ]
82
+ try {
83
+ for (const directory of directories) {
84
+ const configs = [
85
+ ...glob.sync('**/config.yaml', {cwd: directory}),
86
+ ...glob.sync('**/stepzen.config.json', {cwd: directory}),
87
+ ]
86
88
 
87
- for (const config of configs) {
88
- const configFolder = path.join(directory, config)
89
+ for (const config of configs) {
90
+ const configFolder = path.join(directory, config)
89
91
 
90
- let writeFolder = path.join(tmp, directory, config)
91
- writeFolder = dedupeTempFolder(writeFolder)
92
+ let writeFolder = path.join(tmp, directory, config)
93
+ writeFolder = dedupeTempFolder(writeFolder)
92
94
 
93
- const content = fs.readFileSync(configFolder, 'utf8')
95
+ const content = fsx.readFileSync(configFolder, 'utf8')
94
96
 
95
- fs.ensureFileSync(writeFolder)
96
- fs.writeFileSync(writeFolder, content)
97
+ fsx.ensureFileSync(writeFolder)
98
+ fsx.writeFileSync(writeFolder, content, {mode: 0o600})
99
+ }
97
100
  }
98
- }
99
101
 
100
- const configuration = await configure(tmp, silent, answers)
101
- fs.removeSync(tmp)
102
- return configuration
102
+ const configuration = await configure(tmp, silent, answers)
103
+ return configuration
104
+ } finally {
105
+ rmtemp(tmp)
106
+ }
103
107
  }
104
108
 
105
109
  export const getExtensions = async (): Promise<string> => {
@@ -0,0 +1,48 @@
1
+ // Copyright (c) 2020,2021,2022,2023, StepZen, Inc.
2
+
3
+ import * as fs from 'fs'
4
+ import * as path from 'path'
5
+ import * as os from 'os'
6
+ import * as debug from 'debug'
7
+
8
+ // ----------------------------------------------------------------------------
9
+ // THIS ENTIRE FILE IS COPIED FROM packages/cli/src/shared/rmtemp.ts
10
+ // (because there is no effective way to share util classes between packages yet)
11
+ // ----------------------------------------------------------------------------
12
+
13
+ /**
14
+ * Verify that the given path is indeed inside the tmp folder,
15
+ * and delete it recursively suppressing any errors.
16
+ *
17
+ * If the given path is not inside the tmp folder, do nothing.
18
+ *
19
+ * @param {*} fileOrDirPath path to a temp file or folder to delete
20
+ */
21
+ export const rmtemp = (fileOrDirPath?: string) => {
22
+ if (!fileOrDirPath) {
23
+ return
24
+ }
25
+
26
+ // https://stackoverflow.com/a/45242825
27
+ const relative = path.relative(os.tmpdir(), fileOrDirPath)
28
+ const isInTemp =
29
+ relative && !relative.startsWith('..') && !path.isAbsolute(relative)
30
+
31
+ if (isInTemp) {
32
+ try {
33
+ fs.rmSync(fileOrDirPath, {recursive: true, force: true})
34
+ } catch (error) {
35
+ // ignore errors
36
+ debug('stepzen:rmtemp')(
37
+ `WARN: caught an exception while deleting ${fileOrDirPath}: `,
38
+ error,
39
+ )
40
+ }
41
+ } else {
42
+ debug('stepzen:rmtemp')(
43
+ `WARN: got a temp path ${fileOrDirPath} out of the TMP folder -- ignoring`,
44
+ )
45
+ }
46
+ }
47
+
48
+ export default rmtemp
@@ -1,11 +1,14 @@
1
1
  import * as fs from 'fs'
2
2
  import * as glob from 'glob'
3
3
  import {
4
+ ConstDirectiveNode,
4
5
  DirectiveNode,
6
+ Kind,
5
7
  ListValueNode,
6
8
  parse,
7
9
  SchemaDefinitionNode,
8
10
  StringValueNode,
11
+ OperationTypeNode,
9
12
  visit,
10
13
  } from 'graphql'
11
14
  import * as path from 'path'
@@ -23,28 +26,28 @@ export const createOrUpdateSdlDirective = (
23
26
  allGraphQLFiles: readonly string[],
24
27
  origSdlDirective?: DeepWriteable<DirectiveNode>,
25
28
  ) => {
26
- let sdlDirective: DeepWriteable<DirectiveNode>
29
+ let sdlDirective: DeepWriteable<ConstDirectiveNode>
27
30
  if (origSdlDirective) {
28
31
  sdlDirective = cloneDeep(origSdlDirective)
29
32
  } else {
30
33
  sdlDirective = {
31
- kind: 'Directive',
34
+ kind: Kind.DIRECTIVE,
32
35
  name: {
33
- kind: 'Name',
36
+ kind: Kind.NAME,
34
37
  value: 'sdl',
35
38
  },
36
39
  arguments: [
37
40
  {
38
- kind: 'Argument',
41
+ kind: Kind.ARGUMENT,
39
42
  name: {
40
- kind: 'Name',
43
+ kind: Kind.NAME,
41
44
  value: 'files',
42
45
  },
43
46
  value: {
44
- kind: 'ListValue',
47
+ kind: Kind.LIST,
45
48
  values: [
46
49
  {
47
- kind: 'StringValue',
50
+ kind: Kind.STRING,
48
51
  value: ALL_GRAPHQL_FILES,
49
52
  },
50
53
  ],
@@ -72,7 +75,7 @@ export const createOrUpdateSdlDirective = (
72
75
  allGraphQLFiles.forEach(file => fileset.add(normalizePathSep(file)))
73
76
  }
74
77
  filesValueNodes.values = [...fileset].map(file => ({
75
- kind: 'StringValue',
78
+ kind: Kind.STRING,
76
79
  value: file,
77
80
  }))
78
81
  }
@@ -87,18 +90,18 @@ export const createSchemaElement = (
87
90
  allGraphQLFiles: readonly string[],
88
91
  ) => {
89
92
  const schemaElement: DeepWriteable<SchemaDefinitionNode> = {
90
- kind: 'SchemaDefinition',
93
+ kind: Kind.SCHEMA_DEFINITION,
91
94
  directives: [
92
95
  createOrUpdateSdlDirective(importedGraphQLFiles, allGraphQLFiles),
93
96
  ],
94
97
  operationTypes: [
95
98
  {
96
- kind: 'OperationTypeDefinition',
97
- operation: 'query',
99
+ kind: Kind.OPERATION_TYPE_DEFINITION,
100
+ operation: OperationTypeNode.QUERY,
98
101
  type: {
99
- kind: 'NamedType',
102
+ kind: Kind.NAMED_TYPE,
100
103
  name: {
101
- kind: 'Name',
104
+ kind: Kind.NAME,
102
105
  value: 'Query',
103
106
  },
104
107
  },