Skip to content

Commit 1dc36a1

Browse files
committed
init
0 parents  commit 1dc36a1

18 files changed

+5640
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.idea/
2+
.vscode/
3+
.DS_Store
4+
node_modules/
5+
/lib/
6+
npm-debug.log
7+
.env

.lintstagedrc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"linters": {
3+
"*.{ts,tsx}": [
4+
"./node_modules/.bin/tslint --fix",
5+
"./node_modules/.bin/prettier --write",
6+
"git add"
7+
]
8+
},
9+
"ignore": []
10+
}

.npmignore

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.idea/
2+
.vscode/
3+
__tests__/
4+
src/
5+
.lintstagedrc
6+
.nvmrc
7+
.prettierrc
8+
jest.config.js
9+
tsconfig.json
10+
tslint.json
11+
yarn.lock

.nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lts/carbon

.prettierrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "es5",
4+
"semi": false
5+
}

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Taylor Goolsby - <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# graphql-directive-sql
2+
3+
Unify your SQL schema and your GraphQL Schema. Use GraphQL SDL as the lingua franca to define your data requirements.
4+
5+
Given a GraphQL schema defined in SDL, this function will output a schema script which, when ran on your database, will create all the tables in your database.
6+
7+
## Example
8+
9+
`node generate-sql.js`
10+
```js
11+
// generate-sql.js
12+
const gql = require('graphql-tag')
13+
const {
14+
makeSqlSchema,
15+
getSchemaDirectives
16+
} = require('graphql-to-sql')
17+
18+
const typeDefs = gql`
19+
directive @sql (
20+
unicode: Boolean
21+
constraints: String
22+
auto: Boolean
23+
default: String
24+
index: Boolean
25+
nullable: Boolean
26+
primary: Boolean
27+
type: String
28+
unique: Boolean
29+
) on OBJECT | FIELD_DEFINITION
30+
31+
# See graphql-directive-private
32+
directive @private on OBJECT | FIELD_DEFINITION
33+
34+
type User @sql(unicode: true) {
35+
userId: String @sql(type: "BINARY(16)", primary: true)
36+
uniqueColumn: Int @sql(unique: true)
37+
databaseOnlyField: Int @sql @private
38+
39+
graphqlOnlyField: String
40+
posts: [Post]
41+
}
42+
43+
type Post {
44+
postId: Int @sql(primary: true, auto: true)
45+
userId: String @sql(type: "BINARY(16)", index: true)
46+
content: String @sql(type: "VARCHAR(300)", unicode: true, nullable: true)
47+
likes: Int @sql
48+
dateCreated: String @sql(type: "TIMESTAMP", default: "CURRENT_TIMESTAMP")
49+
}
50+
51+
type UserPair @sql(constraints: "UNIQUE(parentUserId, childUserId),\\n FOREIGN KEY (parentUserId) REFERENCES User(userId)") {
52+
userPairId: String @sql(type: "BINARY(16)", primary: true)
53+
parentUserId: String @sql(type: "BINARY(16)", index: true)
54+
childUserId: String @sql(type: "BINARY(16)", index: true)
55+
}
56+
`
57+
58+
const outputFilepath = 'schemaScript.sql'
59+
const directives = getSchemaDirectives()
60+
makeSqlSchema({
61+
typeDefs,
62+
schemaDirectives: directives,
63+
outputFilepath,
64+
databaseName: 'dbname',
65+
tablePrefix: 'test_',
66+
dbType: 'mysql' // 'postgres'
67+
})
68+
```
69+
The script above will produce this file:
70+
```sql
71+
-- schemaScript.sql
72+
CREATE TABLE `dbname`.`test_User` (
73+
`userId` BINARY(16) NOT NULL,
74+
`uniqueColumn` INT NOT NULL UNIQUE,
75+
`databaseOnlyField` INT NOT NULL,
76+
PRIMARY KEY (`userId`)
77+
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
78+
79+
CREATE TABLE `dbname`.`test_Post` (
80+
`postId` INT NOT NULL AUTO_INCREMENT,
81+
`userId` BINARY(16) NOT NULL,
82+
`content` VARCHAR(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL,
83+
`likes` INT NOT NULL,
84+
`dateCreated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
85+
PRIMARY KEY (`postId`),
86+
INDEX `USERIDINDEX` (`userId` ASC)
87+
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
88+
89+
CREATE TABLE `dbname`.`test_UserPair` (
90+
`userPairId` BINARY(16) NOT NULL,
91+
`parentUserId` BINARY(16) NOT NULL,
92+
`childUserId` BINARY(16) NOT NULL,
93+
PRIMARY KEY (`userPairId`),
94+
INDEX `PARENTUSERIDINDEX` (`parentUserId` ASC),
95+
INDEX `CHILDUSERIDINDEX` (`childUserId` ASC),
96+
UNIQUE(parentUserId, childUserId),
97+
FOREIGN KEY (parentUserId) REFERENCES User(userId)
98+
);
99+
```
100+
101+
Also see [main-test.ts](__tests__/main-test.ts) for a working example.
102+
103+
## MySQL Syntax
104+
For reference:
105+
```sql
106+
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
107+
(create_definition,...)
108+
[table_options]
109+
[partition_options]
110+
```
111+
112+
## Arguments for `@sql()`:
113+
ON OBJECT:
114+
* unicode
115+
* Adds `CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci` as *table_option*.
116+
* constraints
117+
* Any text written in here will be appended "as is" to the *create_definition*.
118+
119+
ON FIELD_DEFINITION:
120+
* auto
121+
* Marks a column as being AUTO_INCREMENT.
122+
* Column with "auto" must have INT or SERIAL type.
123+
* "default" is not allowed with "auto".
124+
* "unicode" is not allowed with "auto".
125+
* default
126+
* Sets the DEFAULT clause.
127+
* index
128+
* Creates an index for the column.
129+
* nullable
130+
* Marks the column with NULL. By default, all columns are NOT NULL.
131+
* primary
132+
* Creates a PRIMARY KEY clause for the column.
133+
* At least one column needs to be marked as "primary".
134+
* "primary" is not allowed with "nullable".
135+
* type
136+
* Specify the column type.
137+
* If type is not specified, the MySQL type will be inferred from the GraphQL type.
138+
* GraphQLString types must be explicitly defined using "type".
139+
* unicode
140+
* If any column is marked with "unicode", then the table will have `CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`.
141+
* unique
142+
* Marks a column with the UNIQUE keyword.
143+
* generated
144+
* Marks a generated column.
145+
* Example: `@sql(generated: "(data->>'$.test')")`. See [main-test.ts](__tests__/main-test.ts#L137) for more examples.
146+
147+
## SQL Features Supported:
148+
- [x] Auto Increment
149+
- [x] Default
150+
- [x] Index
151+
- [x] Not Null
152+
- [x] Primary Key
153+
- [x] Unicode
154+
- [x] Unique
155+
- [ ] Check
156+
- [X] Constraints
157+
- [X] Foreign Key (via @constraints)
158+
- [x] Generated Columns
159+
160+
MySQL and PostgreSQL are supported.

0 commit comments

Comments
 (0)