Code Monkey home page Code Monkey logo

ent's People

Contributors

dependabot[bot] avatar lolopinto avatar mrtom avatar sophiebits avatar swahvay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ent's Issues

enum foreign key constraints broken

% tsent codegen
panic: invalid foreign key table RequestOutcomeConfig

goroutine 1 [running]:
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processConstraints(0xc0001312f0, 0xc000165dc0)
	/Users/ola/code/ent/internal/schema/node_map.go:542 +0xce5
github.com/lolopinto/ent/internal/schema.NodeMapInfo.buildPostRunDepgraph.func5(0xc000165dc0)
	/Users/ola/code/ent/internal/schema/node_map.go:126 +0x34
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah.func1(0x15eb6a0, 0xc00013d730)
	/Users/ola/code/ent/internal/schema/node_map.go:146 +0x4c
github.com/lolopinto/ent/internal/depgraph.(*Depgraph).Run(0xc000165d40, 0xc0001ada40)
	/Users/ola/code/ent/internal/depgraph/depgraph.go:45 +0x1b4
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah(0xc0001312f0, 0xc000168240, 0xc0003c1310, 0xf, 0xc00016d5d0)
	/Users/ola/code/ent/internal/schema/node_map.go:141 +0xdb
github.com/lolopinto/ent/internal/schema.NodeMapInfo.parseInputSchema(0xc0001312f0, 0xc000163310, 0xc0000a28d0, 0x16dae88, 0xa, 0x100f8dd, 0x16a5220, 0xc000131320)
	/Users/ola/code/ent/internal/schema/node_map.go:763 +0x6ef
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema.func1(0xc000163310, 0xc000163310, 0x16d1471, 0x3)
	/Users/ola/code/ent/internal/schema/schema.go:186 +0x4e
github.com/lolopinto/ent/internal/schema.parse(0xc0001adca0, 0x16f5cd1, 0x17, 0xc0001cc500)
	/Users/ola/code/ent/internal/schema/schema.go:193 +0x87
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema(0xc0000a28d0, 0x16dae88, 0xa, 0xc0000a28d0, 0x0, 0x0)
	/Users/ola/code/ent/internal/schema/schema.go:185 +0x62
github.com/lolopinto/ent/tsent/cmd.glob..func1(0x1c09c00, 0x1c3b840, 0x0, 0x0, 0x0, 0x0)
	/Users/ola/code/ent/tsent/cmd/codegen.go:39 +0x87
github.com/spf13/cobra.(*Command).execute(0x1c09c00, 0x1c3b840, 0x0, 0x0, 0x1c09c00, 0x1c3b840)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x453
github.com/spf13/cobra.(*Command).ExecuteC(0x1c0a100, 0x104386a, 0x1bcc540, 0xc000000180)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:864
github.com/lolopinto/ent/tsent/cmd.Execute()
	/Users/ola/code/ent/tsent/cmd/root.go:28 +0x31
main.main()
	/Users/ola/code/ent/tsent/main.go:6 +0x20

trying to add a new non-null field when there's data in the table causes an error

command run was tsent codegen

output is below:

2020/03/18 10:50:58 wrote to file  src/schema/schema.py
Generating /Users/ola/code/ent/ts/examples/simple/src/schema/versions/2d3f00438240_2020318175059_add_column_email_address_to_table_users_.py ... done
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
    cursor, statement, parameters, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.NotNullViolation: column "email_address" contains null values


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/ola/code/ent/python/auto_schema/gen_db_schema.py", line 37, in <module>
    r.run()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 156, in run
    self._apply_changes(diff)
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 168, in _apply_changes
    self.upgrade()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 222, in upgrade
    self.cmd.upgrade()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/command.py", line 40, in upgrade
    command.upgrade(self.alembic_cfg, revision)
  File "/usr/local/lib/python3.7/site-packages/alembic/command.py", line 276, in upgrade
    script.run_env()
  File "/usr/local/lib/python3.7/site-packages/alembic/script/base.py", line 475, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/usr/local/lib/python3.7/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
    module = load_module_py(module_id, path)
  File "/usr/local/lib/python3.7/site-packages/alembic/util/compat.py", line 156, in load_module_py
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 137, in <module>
    run_migrations_online()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 130, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/usr/local/lib/python3.7/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/usr/local/lib/python3.7/site-packages/alembic/runtime/migration.py", line 361, in run_migrations
    step.migration_fn(**kw)
  File "/Users/ola/code/ent/ts/examples/simple/src/schema/versions/2d3f00438240_2020318175059_add_column_email_address_to_table_users_.py", line 24, in upgrade
    op.add_column('users', sa.Column('email_address', sa.Text(), nullable=False))
  File "<string>", line 8, in add_column
  File "<string>", line 3, in add_column
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/ops.py", line 1904, in add_column
    return operations.invoke(op)
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/base.py", line 345, in invoke
    return fn(self, operation)
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/toimpl.py", line 131, in add_column
    operations.impl.add_column(table_name, column, schema=schema)
  File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 230, in add_column
    self._exec(base.AddColumn(table_name, column, schema=schema))
  File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 134, in _exec
    return conn.execute(construct, *multiparams, **params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 982, in execute
    return meth(self, multiparams, params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/ddl.py", line 72, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1044, in _execute_ddl
    compiled,
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context
    e, statement, parameters, cursor, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
    cursor, statement, parameters, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) column "email_address" contains null values

[SQL: ALTER TABLE users ADD COLUMN email_address TEXT NOT NULL]
(Background on this error at: http://sqlalche.me/e/gkpj)
2020/03/18 10:50:59 cmd.Run() failed with exit status 1
ola@Olas-personal-MBP simple % 

need to handle this because this will be something that for sure happens in real life. now it's all test data so can easily just delete table and start over.

need to provide a way for user to provide default or ask them to change it to nullable.

what should happen if there's an error writing the migration to the db?

right now, if something like #82 happens, we're left with a dangling schema.py and dangling version file.

it's difficult to know what the state of things is without going to the db and checking the state of alembic_version:

db=# select * from alembic_version ;
 version_num 
-------------
(0 rows)

db=# 

when it's the first write, it's easy to tell

when it's not, it's even more difficult and one has to figure out what the right way to fix things

validate schema name early on before creating db or anything

right now it makes the db changes and then fails later on because of codegen

fails here...

checking for custom graphql definitions...
../../../../src/ent/generated/hours_of_operation_base.ts(20,20): error TS2307: Cannot find module 'src/schema/hours_of_operation' or its corresponding type declarations.

(node:85250) UnhandledPromiseRejectionWarning: Error: Cannot find module 'src/schema/hours_of_operation'
Require stack:

  • /Users/ola/code/ent/ts/examples/simple/src/ent/generated/hours_of_operation_base.ts
  • /Users/ola/code/ent/ts/examples/simple/src/ent/internal.ts
  • /Users/ola/code/ent/ts/examples/simple/src/ent/index.ts
  • /Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/scripts/custom_graphql.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1085:15)
    at Function.Module._resolveFilename (/Users/ola/code/ent/ts/examples/simple/node_modules/tsconfig-paths/lib/register.js:75:40)
    at Function.Module._load (internal/modules/cjs/loader.js:928:27)
    at Module.require (internal/modules/cjs/loader.js:1145:19)
    at require (internal/modules/cjs/helpers.js:75:18)
    at Object. (/Users/ola/code/ent/ts/examples/simple/src/ent/generated/hours_of_operation_base.ts:20:1)
    at Module._compile (internal/modules/cjs/loader.js:1256:30)
    at Module.m._compile (/usr/local/lib/node_modules/ts-node/src/index.ts:1043:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1277:10)
    at Object.require.extensions. [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:1046:12)
    (Use node --trace-warnings ... to show where the warning was created)
    (node:85250) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
    (node:85250) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    ([]uint8) (cap=512) {
    }
    Error: error unmarshalling custom data: unexpected end of JSON input
    Usage:
    tsent codegen [flags]

Flags:
-h, --help help for codegen
-s, --step string limit to only run a particular step e.g. db, graphql, codegen

error unmarshalling custom data: unexpected end of JSON input
ola@OlaspersonalMBP simple % tsent codegen
ola@OlaspersonalMBP simple % tsent codegen

need to validate fields

has been a longstanding TODO

  fields: Field[] = [
    StringType({ name: "FirstName" }),
    StringType({ name: "FirstName" }),
...

should clearly fail

list of things that need to be broken into their own repo and npm module

TS: add better support for multiple actions of the same type

when it's

  actions: Action[] = [
    {
      operation: ActionOperation.Create,
      fields: createFields,
      // when all 3 presented, things are fine
      actionName: "UserCreateRequesterAction",
      graphQLName: "userCreateRequester",
      inputName: "UserCreateRequesterInput",
    },
    {
      operation: ActionOperation.Create,
      fields: createFields,
      actionName: "UserCreateVolunteerAction",
      graphQLName: "userCreateVolunteer",
      inputName: "UserCreateVolunteerInput",
    },
  ];

it works, anything else, it doesn't

plus other issues referenced at #85

maybe generate accessors for inputedgeData in builder files

#109 chose not to generate unique methods in builder because it would be a lot of extra methods there and each generated builder already has a lot of methods:

It doesn't generate unique callsites in the builders yet because we want to avoid API bloat for now. Can add the generated callsites if this is a requested feature.

However, this leads to callsites needing to cast to and being ugly.

e.g. here's what a callsite after that change looks like:

        const removedData = builder.getEdgeInputData(
          EdgeType.OrganizationToMembers,
          WriteOperation.Delete,
        );
        removedData.forEach((removed) =>
          // so not needing this cast is why we want to generate this...
          builder.addArchivedMemberID(removed.id as (Builder<Recipient> | ID)),
        );

if it were generated, it'd be more like this

        const removedData = builder.getRemovedMembers(); // or getRemovedInputData
        removedData.forEach((removed) => builder.addArchivedMemberID(removed.id));

which is a lot easier to read since the return type would have been typed correctly too

it's not possible to have multiple foreign keys to the same table at the moment

we create field edges from field edge to source node and we end up hitting this error since we use the name of the edge to create the field edge

We need a way to name fieldEdges differently so we can name these things

e.g.

    UUIDType({ name: "CreatorID", foreignKey: ["User", "ID"] }),
    UUIDType({
      name: "HelperID",
      nullable: true,
      //      foreignKey: ["User", "ID"], 
    }),

2nd one fails because we end up with multiple User -> Requests edge so we need a way to name the edge

Make codegen more user friendly

    UUIDType({ name: "CreatorID", foreignKey: ["User", "ID"] }),

gives

% tsent codegen
panic: could not find field id by name

goroutine 1 [running]:
github.com/lolopinto/ent/internal/schema.NodeMapInfo.addForeignKeyEdges(0xc0003c3080, 0xc0003fea20, 0xc0003e7720, 0xc000141710, 0xc0004005b0, 0xc0003f53e0)
	/Users/ola/code/ent/internal/schema/node_map.go:338 +0x24c
github.com/lolopinto/ent/internal/schema.NodeMapInfo.addEdgesFromFields(0xc0003c3080, 0xc0003f5820)
	/Users/ola/code/ent/internal/schema/node_map.go:315 +0xdf
github.com/lolopinto/ent/internal/schema.NodeMapInfo.buildPostRunDepgraph.func2(0xc0003f5820)
	/Users/ola/code/ent/internal/schema/node_map.go:110 +0x34
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah.func1(0x15e3a60, 0xc0003fa3b0)
	/Users/ola/code/ent/internal/schema/node_map.go:141 +0x4c
github.com/lolopinto/ent/internal/depgraph.(*Depgraph).Run(0xc0003f57c0, 0xc0001aba70)
	/Users/ola/code/ent/internal/depgraph/depgraph.go:45 +0x1b4
github.com/lolopinto/ent/internal/schema.NodeMapInfo.processDepgrah(0xc0003c3080, 0xc0001e5940, 0xc0004050b0, 0xa, 0xc0003ec660)
	/Users/ola/code/ent/internal/schema/node_map.go:136 +0xdb
github.com/lolopinto/ent/internal/schema.NodeMapInfo.parseInputSchema(0xc0003c3080, 0xc000010f78, 0x16d1ec3, 0xa, 0x100f8dd, 0x169c740, 0xc0003c3080)
	/Users/ola/code/ent/internal/schema/node_map.go:618 +0x52e
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema.func1(0xc0001e5780, 0xc0001e5780, 0x16c84d1, 0x3)
	/Users/ola/code/ent/internal/schema/schema.go:42 +0x49
github.com/lolopinto/ent/internal/schema.parse(0xc0001abca0, 0x16ecbfa, 0x17, 0xc000028780)
	/Users/ola/code/ent/internal/schema/schema.go:49 +0x68
github.com/lolopinto/ent/internal/schema.ParseFromInputSchema(0xc000010f78, 0x16d1ec3, 0xa, 0xc000010f78, 0x0, 0x0)
	/Users/ola/code/ent/internal/schema/schema.go:41 +0x62
github.com/lolopinto/ent/tsent/cmd.glob..func1(0x1bfaba0, 0x1c2c7e0, 0x0, 0x0, 0x0, 0x0)
	/Users/ola/code/ent/tsent/cmd/codegen.go:39 +0x87
github.com/spf13/cobra.(*Command).execute(0x1bfaba0, 0x1c2c7e0, 0x0, 0x0, 0x1bfaba0, 0x1c2c7e0)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:826 +0x453
github.com/spf13/cobra.(*Command).ExecuteC(0x1bfb0a0, 0x104386a, 0x1bbd520, 0xc000000180)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:914 +0x2fb
github.com/spf13/cobra.(*Command).Execute(...)
	/Users/ola/code/gocode/pkg/mod/github.com/spf13/[email protected]/command.go:864
github.com/lolopinto/ent/tsent/cmd.Execute()
	/Users/ola/code/ent/tsent/cmd/root.go:28 +0x31
main.main()
	/Users/ola/code/ent/tsent/main.go:6 +0x20

1/ we need the object and referencing field e.g. Request.creatorID
2/ error message isn't clear
3/ there should be no stack traces
4/ for default fields like 'id', we should be lenient and support 'id', 'ID' and a few others

`npm run compile` doesn't find as many errors as `tsc`

there may be a missing flag that needs to be passed to the typescript compiler?

errors like this are not found by the new compiler but tsc would have caught it

ola@Olas-personal-MBP simple % tsc          
src/graphql/mutations/generated/contact/create_contact_action_type.ts:67:68 - error TS2345: Argument of type '{ emailAddress: string; firstName: string; lastName: string; }' is not assignable to parameter of type 'ContactCreateInput'.
  Property 'userID' is missing in type '{ emailAddress: string; firstName: string; lastName: string; }' but required in type 'ContactCreateInput'.

 67     let contact = await CreateContactAction.create(context.viewer, {
                                                                       ~
 68       emailAddress: args.emailAddress,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 70       lastName: args.lastName,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 71     }).saveX();
    ~~~~~

  src/ent/contact/actions/generated/create_contact_action_base.ts:16:3
    16   userID: ID | Builder<User>;
         ~~~~~~
    'userID' is declared here.

src/graphql/mutations/generated/event/create_event_action_type.ts:71:64 - error TS2345: Argument of type '{ name: string; startTime: Date; endTime: Date | null | undefined; location: string; }' is not assignable to parameter of type 'EventCreateInput'.
  Property 'creatorID' is missing in type '{ name: string; startTime: Date; endTime: Date | null | undefined; location: string; }' but required in type 'EventCreateInput'.

 71     let event = await CreateEventAction.create(context.viewer, {
                                                                   ~
 72       name: args.name,
    ~~~~~~~~~~~~~~~~~~~~~~
... 
 75       location: args.location,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 76     }).saveX();
    ~~~~~

  src/ent/event/actions/generated/create_event_action_base.ts:11:3
    11   creatorID: ID | Builder<User>;
         ~~~~~~~~~
    'creatorID' is declared here.


Found 2 errors.

have to break up lookup table enum uses into multiple steps

export default class RequestStatus implements Schema {
  fields: Field[] = [
    StringType({
      name: "status",
      primaryKey: true,
    }),
  ];

  enumTable = true;

  dbRows = [
    {
      outcome: "OPEN",
    },
    {
      outcome: "PENDING_FULFILLMENT",
    },
    {
      outcome: "CLOSED",
    },
  ];
}

and

    EnumType({
      name: "Status",
      defaultValueOnCreate: () => "OPEN",
      foreignKey: ["RequestStatus", "status"],
    }),

in a different file don't work at the same time if there's already rows that have that step there:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('request_statuses',
                    sa.Column('status', sa.Text(), nullable=False),
                    sa.PrimaryKeyConstraint(
                        'status', name='request_statuses_status_pkey')
                    )
    op.create_foreign_key('requests_status_fkey', 'requests', 'request_statuses', [
                          'status'], ['status'], ondelete='CASCADE')
    op.add_rows('request_statuses', ['status'], [
        {'status': 'OPEN'},
        {'status': 'PENDING_FULFILLMENT'},
        {'status': 'CLOSED'},
    ])
    # ### end Alembic commands ###

is generated and foreign key on OPEN without the rows being there is an issues

deleting actions from schema should delete generated files

e.g. going from

  actions: Action[] = [
    {
      operation: ActionOperation.Mutations,
    },
  ];

to

  actions: Action[] = [
    {
      operation: ActionOperation.Create,
    },
  ];

deletes the edit and delete mutation from graphql schema but the graphql and action files are left dangling. would be nice to automatically delete this as opposed to leaving it to developer to do so

an edge that's no longer referenced should be dropped from db

e9f3a0c dropped UserToUserToHostedEvents edge but it still exists in the db after

It's not causing any harm but we should drop it

tsent_test=# select * from assoc_edge_config where edge_type = 'e5555185-91bf-4322-8130-d0a00eb605b7';
              edge_type               |          edge_name           | symmetric_edge |          inverse_edge_type           |    edge_table     |        created_at         |        updated_at         
--------------------------------------+------------------------------+----------------+--------------------------------------+-------------------+---------------------------+---------------------------
 e5555185-91bf-4322-8130-d0a00eb605b7 | UserToUserToHostedEventsEdge | f              | ebe3e709-845c-4723-ac9c-29f983f2b8ea | event_hosts_edges | 2020-10-22 22:48:25.77343 | 2020-10-22 22:48:25.77343
(1 row)

BooleanType with ServerDefault false breaks poorly

BooleanType({ name: "NeedsHelp", serverDefault: false }),

breaks with error

Generating /Users/ola/code/helping-hands-on-ent/src/schema/versions/a1973ac9e252_202073181625_add_users_table.py ... done
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
    cursor, statement, parameters, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type boolean: "%!s(bool=false)"


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "auto_schema/gen_db_schema.py", line 37, in <module>
    r.run()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 185, in run
    self._apply_changes(diff)
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 197, in _apply_changes
    self.upgrade()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/runner.py", line 251, in upgrade
    self.cmd.upgrade()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/command.py", line 40, in upgrade
    command.upgrade(self.alembic_cfg, revision)
  File "/usr/local/lib/python3.7/site-packages/alembic/command.py", line 276, in upgrade
    script.run_env()
  File "/usr/local/lib/python3.7/site-packages/alembic/script/base.py", line 475, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/usr/local/lib/python3.7/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
    module = load_module_py(module_id, path)
  File "/usr/local/lib/python3.7/site-packages/alembic/util/compat.py", line 156, in load_module_py
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 137, in <module>
    run_migrations_online()
  File "/Users/ola/code/ent/python/auto_schema/auto_schema/env.py", line 130, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/usr/local/lib/python3.7/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/usr/local/lib/python3.7/site-packages/alembic/runtime/migration.py", line 361, in run_migrations
    step.migration_fn(**kw)
  File "/Users/ola/code/helping-hands-on-ent/src/schema/versions/a1973ac9e252_202073181625_add_users_table.py", line 34, in upgrade
    sa.PrimaryKeyConstraint('id', name='users_id_pkey')
  File "<string>", line 8, in create_table
  File "<string>", line 3, in create_table
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/ops.py", line 1248, in create_table
    return operations.invoke(op)
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/base.py", line 345, in invoke
    return fn(self, operation)
  File "/usr/local/lib/python3.7/site-packages/alembic/operations/toimpl.py", line 101, in create_table
    operations.impl.create_table(table)
  File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 251, in create_table
    self._exec(schema.CreateTable(table))
  File "/usr/local/lib/python3.7/site-packages/alembic/ddl/impl.py", line 134, in _exec
    return conn.execute(construct, *multiparams, **params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 982, in execute
    return meth(self, multiparams, params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/ddl.py", line 72, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1044, in _execute_ddl
    compiled,
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context
    e, statement, parameters, cursor, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
    cursor, statement, parameters, context
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type boolean: "%!s(bool=false)"

[SQL: 
CREATE TABLE users (
	id UUID NOT NULL, 
	created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL, 
	updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL, 
	first_name TEXT NOT NULL, 
	last_name TEXT NOT NULL, 
	email_address TEXT, 
	phone_number TEXT NOT NULL, 
	bio TEXT, 
	can_help BOOLEAN DEFAULT '%%!s(bool=false)' NOT NULL, 
	needs_help BOOLEAN DEFAULT '%%!s(bool=false)' NOT NULL, 
	CONSTRAINT users_id_pkey PRIMARY KEY (id)
)

]
(Background on this error at: http://sqlalche.me/e/9h9h)
2020/07/31 01:16:25 cmd.Run() failed with exit status 1

Current acceptable format is

BooleanType({ name: "NeedsHelp", serverDefault: "false" }),

make error about missing type better

ola@OlaspersonalMBP simple % tsent codegen --step graphql
checking for custom graphql definitions...
(node:93884) UnhandledPromiseRejectionWarning: Error: type is required when accessor/function/property returns a Object
    at Function.getResultFromMetadata (/Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:99:19)
    at /Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:214:40
    at Array.forEach (<anonymous>)
    at Function.getCustomField (/Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:211:24)
    at /Users/ola/code/ent/ts/examples/simple/node_modules/@lolopinto/ent/graphql/graphql.js:313:56
    at DecorateProperty (/Users/ola/code/ent/ts/examples/simple/node_modules/reflect-metadata/Reflect.js:553:33)
    at Object.decorate (/Users/ola/code/ent/ts/examples/simple/node_modules/reflect-metadata/Reflect.js:123:24)
    at __decorate (/Users/ola/code/ent/ts/examples/simple/src/graphql/mutations/import_contact.ts:4:92)
    at Object.<anonymous> (/Users/ola/code/ent/ts/examples/simple/src/graphql/mutations/import_contact.ts:8:3)
    at Module._compile (internal/modules/cjs/loader.js:1256:30)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:93884) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:93884) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
([]uint8) (cap=512) {
}
Error: error unmarshalling custom data: unexpected end of JSON input
Usage:
  tsent codegen [flags]

Flags:
  -h, --help          help for codegen
  -s, --step string   limit to only run a particular step e.g. db, graphql, codegen

error unmarshalling custom data: unexpected end of JSON input
ola@OlaspersonalMBP simple % 

error was from this code:

export class ImportContactResolver {
  @gqlMutation({ type: User })
  async bulkUploadContact(
    @gqlContextType() context: RequestContext,
    @gqlArg("user") userID: ID,
    @gqlArg("file") file: FileUpload,
  ) {
    // TODO parse file
    return await User.loadX(context.getViewer(), userID);
  }
}

it was missing type in argument not returned object so that's confusing

also needs to be prettier without all the extra cruft but that's separate.

schema: when there's a custom action name, inputName should be derived from that

    {
      operation: ActionOperation.Edit,
      // everything is optional by default in edits anyway
      fields: ["FirstName", "LastName"],
    },
    {
      operation: ActionOperation.Edit,
      actionName: "EditEmailAddressAction",
      graphQLName: "emailAddressEdit",
      fields: [NoFields],
      actionOnlyFields: [{ name: "emailAddress", type: "String" }],
    },

results in multiple "UserEditInput" when we should do something like "EditEmailAddressInput" based on custom action name.

Also, we should throw when duplicate input names exist

errors in compile aren't surfaced

had an error that didn't show up and had to find it by running tsc.

was easily fixable by just deleting a file but :(

ola@OlaspersonalMBP backend % ./node_modules/.bin/ent-custom-compiler  
ola@OlaspersonalMBP backend % tsc
src/graphql/mutations/generated/event_activity/event_activityrsvp_status_edit_type.ts:16:3 - error TS2305: Module '"../../../resolvers"' has no exported member 'EventActivityRsvpStatusInputType'.

16   EventActivityRsvpStatusInputType,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Found 1 error.

fix double calling of some observers in typescript

In ComplexExecutor, there's a logic issue somewhere which is leading to double counting of operations. I "solved" that by using a set to keep track of operations but that same issue reared its head with some observers running multiple times which we don't want.

this is a pretty bad bug because it can mean emails being double sent, texts being double sent etc, things being double logged tc

Relevant code is at https://github.com/lolopinto/ent/blob/ts-observers/ts/src/executor.ts#L94-L139

could change the data structure/API around to make this work.

this live bug is manifested in some deeply nested observers being called multiple times. see https://github.com/lolopinto/ent/blob/master/ts/src/action/executor.test.ts#L608-L622 for the logging about contact being called twice.

native polymorphism support

e.g. given an address schema

export default class Address extends BaseEntSchema implements Schema {
  fields: Field[] = [
    StringType({ name: "Street" }),
    StringType({ name: "City" }),
    StringType({ name: "State" }),
    StringType({ name: "ZipCode" }), // need to support US vs not, 5 or 9 letter zip codes
    StringType({ name: "Apartment" }),
    UUIDType({ name: "OwnerID", index: true, hideFromGraphQL: true }), // polymorphic. should require ID and Type together...
    StringType({ name: "OwnerType", hideFromGraphQL: true }), // should be an enum
  ];
}

and multiple types which could have an address e.g. User, Store, etc

We should support polymorphic types natively so that it's something like:

export default class Address extends BaseEntSchema implements Schema {
  fields: Field[] = [
    StringType({ name: "Street" }),
    StringType({ name: "City" }),
    StringType({ name: "State" }),
    StringType({ name: "ZipCode" }), // need to support US vs not, 5 or 9 letter zip codes
    StringType({ name: "Apartment" }),
    PolymorphicType({name: "Owner", index:true}), // this creates owner_id and owner_type fields, indexes on owner_id
  ];
}

^ should also create something along the lines of the following:

class AddressBase {
  owner(): Ent {
// loadOwnEnt takes an id and NodeType and knows how to load ownerId based on the type
// this will also create Owner: Node in GraphQL
// can also create an interface in the future instead of Ent/Node here 
    return loadOwnEnt(this.ownerId, this.ownerType);
  } 
} 

also needs this in the other object based on some reference that indicates the type of relationship?
// below is using a current incorrect API since there's nothing that indicates it's 1/1 (it assumes 1/1). if not, it should support 1-n also...

class UserBase {
  @gqlField({ nullable: true, type: "Address" })
  async address(): Promise<Address | null> {
    // there's nothing that says there's only one of this
    // this API is wrong...
    return Address.loadFromOwnerID(this.viewer, this.id);
  }
}

API generated for index fields is wrong

It assumes there's a 1-1 mapping but there can be one -to-n

we need to generate a different one to N API for this

    UUIDType({
      name: "OwnerID",
      index: true,
      hideFromGraphQL: true,
    }),

generates

  static async loadFromOwnerID<T extends AddressBase>(
    this: new (viewer: Viewer, id: ID, data: Data) => T,
    viewer: Viewer,
    ownerID: ID,
  ): Promise<T | null> {
    return loadEntFromClause(
      viewer,
      AddressBase.loaderOptions.apply(this),
      query.Eq("owner_id", ownerID),
    );
  }

we can have multiple of these...

provide an easy way to validate ID fields are loadable by the viewer in an action or input

doesn't seem like this should be done by default but an opt-in way of doing that will be cool

e.g. having to write all this code is annoying

        let input = builder.getInput();
        let orgID = input.organizationID!;
        let pickupLocationID = input.pickupLocationID!;

        if (builder.isBuilder(orgID) || builder.isBuilder(pickupLocationID)) {
          return;
        }
        
        let [org, pickupLocation] = await Promise.all([
          Organization.load(builder.viewer, orgID),
          PickupLocation.load(builder.viewer, pickupLocationID),
        ]);

        if (!org || !pickupLocation) {
          throw new Error('need to be able to load org and/or pickuplocation')
        }

#128 is related too

make this error better

tsent codegen --step graphql
checking for custom graphql definitions...
2020/10/30 00:39:09 wrote to file  src/graphql/resolvers/generated/viewer_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/resolvers/generated/address_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/mutations/generated/user_auth_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/mutations/generated/user_auth_jwt_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/resolvers/generated/contact_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/resolvers/generated/event_type.ts
2020/10/30 00:39:09 wrote to file  src/graphql/resolvers/generated/user_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/contact/contact_delete_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/event/event_to_invited_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/event/event_to_declined_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/event/event_to_attending_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/event/event_to_maybe_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/event/event_create_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/contact/contact_create_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/event/event_to_hosts_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/event/event_add_host_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_invited_events_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/contact/contact_edit_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/event/event_edit_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/event/event_delete_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_declined_events_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_created_events_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_friends_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_events_attending_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_hosted_events_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/user/user_to_maybe_events_connection_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/user/user_edit_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/user/user_delete_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/mutations/generated/user/user_create_type.ts
2020/10/30 00:39:11 wrote to file  src/graphql/resolvers/generated/query_type.ts
2020/10/30 00:39:12 wrote to file  src/graphql/mutations/generated/mutation_type.ts
2020/10/30 00:39:12 wrote to file  src/graphql/resolvers/internal.ts
2020/10/30 00:39:13 wrote to file  src/graphql/resolvers/index.ts

/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:425
    throw new Error("Expected ".concat((0, _inspect.default)(type), " to be a GraphQL nullable type."));
          ^
Error: Expected undefined to be a GraphQL nullable type.
    at assertNullableType (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:425:11)
    at new GraphQLNonNull (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:377:19)
    at Object.GraphQLNonNull (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:379:12)
    at fields (/Users/ola/code/ent/ts/dist/graphql/query/connection_type.js:37:84)
    at resolveThunk (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:478:40)
    at defineFieldMap (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:690:18)
    at GraphQLConnectionType.getFields (/Users/ola/code/ent/ts/node_modules/graphql/type/definition.js:631:27)
    at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:366:81)
    at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:368:9)
    at collectReferencedTypes (/Users/ola/code/ent/ts/node_modules/graphql/type/schema.js:368:9)
(*os.File)(0xc0000a2008)({
 file: (*os.file)(0xc0000a4060)({
  pfd: (poll.FD) {
   fdmu: (poll.fdMutex) {
    state: (uint64) 0,
    rsema: (uint32) 0,
    wsema: (uint32) 0
   },
   Sysfd: (int) 1,
   pd: (poll.pollDesc) {
    runtimeCtx: (uintptr) <nil>
   },
   iovecs: (*[]syscall.Iovec)(<nil>),
   csema: (uint32) 0,
   isBlocking: (uint32) 1,
   IsStream: (bool) true,
   ZeroReadIsEOF: (bool) true,
   isFile: (bool) true
  },
  name: (string) (len=11) "/dev/stdout",
  dirinfo: (*os.dirInfo)(<nil>),
  nonblock: (bool) false,
  stdoutOrErr: (bool) true,
  appendMode: (bool) false
 })
})
(*os.File)(0xc0000a2010)({
 file: (*os.file)(0xc0000a40c0)({
  pfd: (poll.FD) {
   fdmu: (poll.fdMutex) {
    state: (uint64) 0,
    rsema: (uint32) 0,
    wsema: (uint32) 0
   },
   Sysfd: (int) 2,
   pd: (poll.pollDesc) {
    runtimeCtx: (uintptr) <nil>
   },
   iovecs: (*[]syscall.Iovec)(<nil>),
   csema: (uint32) 0,
   isBlocking: (uint32) 1,
   IsStream: (bool) true,
   ZeroReadIsEOF: (bool) true,
   isFile: (bool) true
  },
  name: (string) (len=11) "/dev/stderr",
  dirinfo: (*os.dirInfo)(<nil>),
  nonblock: (bool) false,
  stdoutOrErr: (bool) true,
  appendMode: (bool) false
 })
})
Error: error writing schema file: exit status 1
Usage:
  tsent codegen [flags]

Flags:
  -h, --help          help for codegen
  -s, --step string   limit to only run a particular step e.g. db, graphql, codegen

error writing schema file: exit status 1
ola@OlaspersonalMBP simple % 
  • look at how we're capturing this here and apply same logic if possible to other places e.g. parseCustomData in generate_ts_code.go

consistent import paths in generated code

sort should be as follows:

  • Consistently load src/ent BEFORE src/graphql
  • Load external dependencies first then src/ent then src/graphql

order:

  • Non-ent e.g. graphql
  • Then @lolopinto/ent root
  • Then @lolopinto/ent/graphql etc (in given order)
  • Then src/ent
  • Then src/graphql
  • Then relative paths (in custom mutations)
    alphabetical sort of items within each group?

also need to make sure to use src/graphql/resolvers/internal in graphql/resolvers paths and src/graphql/resolvers in mutation paths

running tsent codegen after first ent doesn't work if graphql not installed

graphql is a peer dependency and since the generated code assumes graphql is installed, things just fail without it being obvious what the issue is

need to detect this issue and surface it and make it clearer graphql is required beforehand.

error just looks like

Error: error unmarshalling custom data: unexpected end of JSON input
Usage:
  tsent codegen [flags]

Flags:
  -h, --help          help for codegen
  -s, --step string   limit to only run a particular step e.g. db, graphql, codegen

error unmarshalling custom data: unexpected end of JSON input

which isn't really helpful

we're fetching edge data twice for every write

need edge caching (like all caching that's needed):

need caching to make this faster

caching generally already on the list at https://github.com/lolopinto/ent/blob/7b522fe970e70f4411858e1b612655a234b3bba3/features.md#cache-support

specific caching that this applies to is more like: per request in memory cache (raw data) under https://github.com/lolopinto/ent/blob/7b522fe970e70f4411858e1b612655a234b3bba3/features.md#ent-framework

adding an enum db type doesn't seem to add the requisite op.drop_type() in downgrade

adding an enum e.g. rainbow_type in tests at #113

generates the following code:

# Code generated by github.com/lolopinto/ent/ent, DO NOT edit. 

"""add accounts table

Revision ID: bcfa772af8d3
Revises: 
Create Date: 2020-08-22 08:37:36.040787+00:00

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'bcfa772af8d3'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('accounts',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('rainbow', sa.Enum('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', name='rainbow_type'), nullable=False),
    sa.PrimaryKeyConstraint('id', name='accounts_id_pkey')
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('accounts')
    # ### end Alembic commands ###

there's no explicit create type but the type is created.
however, since no explicit create type, there ends up not being a drop type either

notes for myself: graphql findings for TS

played with multiple ways of integrating graphql in TypeScript. No obvious winner the way gqlgen seemed to be for go.

I think something nexus-like is probably what I want long-term assuming the schema is decoupled but it's just too early at the moment and I couldn't immediately get it to work the day I tried. I assume I did something wrong here.

type-graphql is cool and seems to work well. However, uses reflection at runtime which isn't officially supported yet and is dependent on decorators and reflect-metadata which I suspected would negatively affect performance.

Everything in JS land seems to eventually boil down to being built on graphql-js itself anyways. It seems like express-graphql, graphql-yoga, apollo-server etc all take the GraphQLSchema generated from the schema and do things with it.

Considering most of the graphql code here will be codegenned, it seems the best thing is to skip most of the extra stuff that comes with all these other frameworks and just use graphql-js directly. And then eventually provide options for clients to use whichever graphql server they want if they need other features that aren't supported in the default implemention. And since the same schema should theoretically be passable to all the other frameworks, it should be fine.

One thing that type-graphql does is provide an easy way to have custom code since it'll be the same format being used by custom and non-custom code. To figure out if the presumed overhead of runtime reflection we'd get here was worth it, I did some simple profiling based on https://nodejs.org/en/docs/guides/simple-profiling/.

Quick profiling shows that there's a 2x overhead that comes with reflection at runtime if my numbers are to be believed.

I ran ab -k -p postfile.txt -c 20 -n 250 -H 'Content-Type: application/json' http://localhost:4000/graphql/ for both the type-graphql and graphql-js implementations and ended up with the following results:

tye-graphql (first time)

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        
Server Hostname:        localhost
Server Port:            4000

Document Path:          /graphql/
Document Length:        148 bytes

Concurrency Level:      20
Time taken for tests:   0.228 seconds
Complete requests:      250
Failed requests:        0
Non-2xx responses:      250
Keep-Alive requests:    250
Total transferred:      107250 bytes
Total body sent:        119500
HTML transferred:       37000 bytes
Requests per second:    1094.89 [#/sec] (mean)
Time per request:       18.267 [ms] (mean)
Time per request:       0.913 [ms] (mean, across all concurrent requests)
Transfer rate:          458.70 [Kbytes/sec] received
                        511.09 kb/s sent
                        969.79 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       2
Processing:     7   17   7.6     16      52
Waiting:        7   17   7.6     15      52
Total:          7   17   7.7     16      53

Percentage of the requests served within a certain time (ms)
  50%     16
  66%     18
  75%     20
  80%     20
  90%     23
  95%     26
  98%     50
  99%     51
 100%     53 (longest request)

(2nd time)

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        
Server Hostname:        localhost
Server Port:            4000

Document Path:          /graphql/
Document Length:        148 bytes

Concurrency Level:      20
Time taken for tests:   0.282 seconds
Complete requests:      250
Failed requests:        0
Non-2xx responses:      250
Keep-Alive requests:    250
Total transferred:      107250 bytes
Total body sent:        119500
HTML transferred:       37000 bytes
Requests per second:    885.84 [#/sec] (mean)
Time per request:       22.577 [ms] (mean)
Time per request:       1.129 [ms] (mean, across all concurrent requests)
Transfer rate:          371.12 [Kbytes/sec] received
                        413.51 kb/s sent
                        784.63 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       2
Processing:     2   21  12.7     17      78
Waiting:        2   21  12.7     17      78
Total:          2   21  12.6     17      78

Percentage of the requests served within a certain time (ms)
  50%     17
  66%     25
  75%     26
  80%     29
  90%     39
  95%     47
  98%     55
  99%     55
 100%     78 (longest request)

graphql-js

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        
Server Hostname:        localhost
Server Port:            4000

Document Path:          /graphql
Document Length:        53 bytes

Concurrency Level:      20
Time taken for tests:   0.139 seconds
Complete requests:      250
Failed requests:        0
Non-2xx responses:      250
Keep-Alive requests:    250
Total transferred:      68500 bytes
Total body sent:        119500
HTML transferred:       13250 bytes
Requests per second:    1803.56 [#/sec] (mean)
Time per request:       11.089 [ms] (mean)
Time per request:       0.554 [ms] (mean, across all concurrent requests)
Transfer rate:          482.59 [Kbytes/sec] received
                        841.89 kb/s sent
                        1324.49 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       1
Processing:     5    8   2.7      7      37
Waiting:        5    8   2.6      7      36
Total:          5    8   2.7      7      37

Percentage of the requests served within a certain time (ms)
  50%      7
  66%      8
  75%      8
  80%      8
  90%     10
  95%     12
  98%     14
  99%     16
 100%     37 (longest request)

(2nd time)

This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        
Server Hostname:        localhost
Server Port:            4000

Document Path:          /graphql
Document Length:        53 bytes

Concurrency Level:      20
Time taken for tests:   0.120 seconds
Complete requests:      250
Failed requests:        0
Non-2xx responses:      250
Keep-Alive requests:    250
Total transferred:      68500 bytes
Total body sent:        119500
HTML transferred:       13250 bytes
Requests per second:    2086.64 [#/sec] (mean)
Time per request:       9.585 [ms] (mean)
Time per request:       0.479 [ms] (mean, across all concurrent requests)
Transfer rate:          558.34 [Kbytes/sec] received
                        974.04 kb/s sent
                        1532.37 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:     1    7   1.9      7      24
Waiting:        1    7   1.9      7      23
Total:          1    8   1.9      7      24

Percentage of the requests served within a certain time (ms)
  50%      7
  66%      7
  75%      7
  80%      8
  90%      9
  95%     11
  98%     14
  99%     16
 100%     24 (longest request)

and the contents of postfile.txt:

 cat postfile.txt 
{"query":"{viewer {user {id,emailAddress,firstName,lastName,accountStatus,selfContact {id,firstName,lastName,emailAddress,},contacts {id,firstName,lastName,emailAddress,user {id,firstName,}},friends {id,firstName,lastName,},friendsCount,createdEvents {id,name,startTime,endTime,}}}}"}

based on these, going to implement graphql-js directly for TypeScript GraphQL integration but will also need to implement decorators which will be used for custom graphql integrations which will be determined statically to generate the graphql code similar to what we do for go.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.