From fad8e91224309da02f60c8d6f8debf846d2dbc7f Mon Sep 17 00:00:00 2001 From: Patrik Date: Wed, 24 Aug 2022 13:42:50 +0200 Subject: [PATCH 1/3] chore: remove deprecated command placeholders This change removes the `namespace migrate ...` commands, as they were only placeholders for deprecation warnings until now. --- cmd/namespace/migrate_down.go | 26 -------------------------- cmd/namespace/migrate_status.go | 23 ----------------------- cmd/namespace/migrate_up.go | 25 ------------------------- cmd/namespace/root.go | 24 ++---------------------- 4 files changed, 2 insertions(+), 96 deletions(-) delete mode 100644 cmd/namespace/migrate_down.go delete mode 100644 cmd/namespace/migrate_status.go delete mode 100644 cmd/namespace/migrate_up.go diff --git a/cmd/namespace/migrate_down.go b/cmd/namespace/migrate_down.go deleted file mode 100644 index 3a72c445c..000000000 --- a/cmd/namespace/migrate_down.go +++ /dev/null @@ -1,26 +0,0 @@ -package namespace - -import ( - "github.com/ory/keto/cmd/migrate" - - "github.com/spf13/cobra" -) - -func NewMigrateDownCmd() *cobra.Command { - cmd := &cobra.Command{ - Deprecated: "This step is not necessary anymore, see https://github.com/ory/keto/pull/638", - Use: "down ", - Short: "Migrate a namespace down", - Long: "Migrate a namespace down.\n" + - "Pass 0 steps to fully migrate down.", - Args: cobra.ExactArgs(2), - RunE: func(_ *cobra.Command, _ []string) error { - return nil - }, - } - - migrate.RegisterYesFlag(cmd.Flags()) - registerPackageFlags(cmd.Flags()) - - return cmd -} diff --git a/cmd/namespace/migrate_status.go b/cmd/namespace/migrate_status.go deleted file mode 100644 index c95139f82..000000000 --- a/cmd/namespace/migrate_status.go +++ /dev/null @@ -1,23 +0,0 @@ -package namespace - -import ( - "github.com/ory/x/cmdx" - "github.com/spf13/cobra" -) - -func NewMigrateStatusCmd() *cobra.Command { - cmd := &cobra.Command{ - Deprecated: "This step is not necessary anymore, see https://github.com/ory/keto/pull/638", - Use: "status ", - Short: "Get the current namespace migration status", - Long: "Get the current migration status of one specific namespace.\nDoes not apply any changes.", - Args: cobra.ExactArgs(1), - RunE: func(_ *cobra.Command, _ []string) error { - return nil - }, - } - - cmdx.RegisterFormatFlags(cmd.Flags()) - - return cmd -} diff --git a/cmd/namespace/migrate_up.go b/cmd/namespace/migrate_up.go deleted file mode 100644 index d0a4debf6..000000000 --- a/cmd/namespace/migrate_up.go +++ /dev/null @@ -1,25 +0,0 @@ -package namespace - -import ( - "github.com/ory/keto/cmd/migrate" - - "github.com/spf13/cobra" -) - -func NewMigrateUpCmd() *cobra.Command { - cmd := &cobra.Command{ - Deprecated: "This step is not necessary anymore, see https://github.com/ory/keto/pull/638", - Use: "up ", - Short: "Migrate a namespace up", - Long: "Migrate a namespace up to the most recent migration.", - Args: cobra.ExactArgs(1), - RunE: func(_ *cobra.Command, _ []string) error { - return nil - }, - } - - migrate.RegisterYesFlag(cmd.Flags()) - registerPackageFlags(cmd.Flags()) - - return cmd -} diff --git a/cmd/namespace/root.go b/cmd/namespace/root.go index dc82414c1..73c80dfc7 100644 --- a/cmd/namespace/root.go +++ b/cmd/namespace/root.go @@ -1,13 +1,8 @@ package namespace import ( - "github.com/ory/x/cmdx" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/ory/keto/ketoctx" - - "github.com/ory/keto/cmd/client" + "github.com/spf13/cobra" ) func NewNamespaceCmd() *cobra.Command { @@ -17,24 +12,9 @@ func NewNamespaceCmd() *cobra.Command { } } -func NewMigrateCmd() *cobra.Command { - return &cobra.Command{ - Use: "migrate", - Short: "Migrate a namespace", - } -} - func RegisterCommandsRecursive(parent *cobra.Command, _ []ketoctx.Option) { rootCmd := NewNamespaceCmd() - migrateCmd := NewMigrateCmd() - migrateCmd.AddCommand(NewMigrateUpCmd(), NewMigrateDownCmd(), NewMigrateStatusCmd()) - - rootCmd.AddCommand(migrateCmd, NewValidateCmd()) + rootCmd.AddCommand(NewValidateCmd()) parent.AddCommand(rootCmd) } - -func registerPackageFlags(flags *pflag.FlagSet) { - client.RegisterRemoteURLFlags(flags) - cmdx.RegisterFormatFlags(flags) -} From 41cb94ea73bfc50a5afe0f79b48e95e294978380 Mon Sep 17 00:00:00 2001 From: Patrik Date: Wed, 24 Aug 2022 13:45:16 +0200 Subject: [PATCH 2/3] chore: deprecate namespace validate command --- cmd/namespace/validate.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/namespace/validate.go b/cmd/namespace/validate.go index a8b38dfec..a42a8a349 100644 --- a/cmd/namespace/validate.go +++ b/cmd/namespace/validate.go @@ -21,9 +21,11 @@ import ( func NewValidateCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "validate [ ...] | validate -c ", - Short: "Validate namespace definitions", - Long: `validate + Deprecated: "The legacy namespaces are deprecated. Please use the new Ory Permission Language instead.", + Aliases: []string{"validate"}, + Use: "validate-legacy [ ...] | validate -c ", + Short: "Validate legacy namespace definitions", + Long: `validate-legacy Validates namespace definitions. Parses namespace yaml files or configuration files passed via the configuration flag. Returns human readable errors. Useful for debugging.`, From 9c912a98ef81c51900f8f371154235a2e36c8a84 Mon Sep 17 00:00:00 2001 From: Patrik Date: Thu, 25 Aug 2022 10:06:12 +0200 Subject: [PATCH 3/3] WIP namespace CLI --- .../config_template/namespaces.ts.tmpl | 22 ++++++ .../config_template/package.json.tmpl | 7 ++ cmd/namespace/config_template/tsconfig.json | 7 ++ cmd/namespace/from_legacy.go | 20 +++++ cmd/namespace/init.go | 26 ++++++ cmd/namespace/opl_generate.go | 68 ++++++++++++++++ cmd/namespace/root.go | 2 +- contrib/namespace-type-lib/index.d.ts | 33 ++++++++ contrib/namespace-type-lib/package-lock.json | 58 ++++++++++++++ contrib/namespace-type-lib/package.json | 18 +++++ contrib/namespace-type-lib/test.ts | 26 ++++++ contrib/namespace-type-lib/tsconfig.json | 7 ++ contrib/rewrites-example/lib.ts | 18 ----- contrib/rewrites-example/namespaces.keto.ts | 2 +- contrib/rewrites-example/namespaces.ts | 79 +++++++++++++++++++ contrib/rewrites-example/package-lock.json | 56 +++++++++++++ contrib/rewrites-example/package.json | 7 ++ contrib/rewrites-example/tsconfig.json | 7 ++ 18 files changed, 443 insertions(+), 20 deletions(-) create mode 100644 cmd/namespace/config_template/namespaces.ts.tmpl create mode 100644 cmd/namespace/config_template/package.json.tmpl create mode 100644 cmd/namespace/config_template/tsconfig.json create mode 100644 cmd/namespace/from_legacy.go create mode 100644 cmd/namespace/init.go create mode 100644 cmd/namespace/opl_generate.go create mode 100644 contrib/namespace-type-lib/index.d.ts create mode 100644 contrib/namespace-type-lib/package-lock.json create mode 100644 contrib/namespace-type-lib/package.json create mode 100644 contrib/namespace-type-lib/test.ts create mode 100644 contrib/namespace-type-lib/tsconfig.json delete mode 100644 contrib/rewrites-example/lib.ts create mode 100644 contrib/rewrites-example/namespaces.ts create mode 100644 contrib/rewrites-example/package-lock.json create mode 100644 contrib/rewrites-example/package.json create mode 100644 contrib/rewrites-example/tsconfig.json diff --git a/cmd/namespace/config_template/namespaces.ts.tmpl b/cmd/namespace/config_template/namespaces.ts.tmpl new file mode 100644 index 000000000..bb1971455 --- /dev/null +++ b/cmd/namespace/config_template/namespaces.ts.tmpl @@ -0,0 +1,22 @@ +import { Namespace, SubjectSet, Context } from '@ory/keto-namespace-types' + +// Declare new namespaces as classes that implement `Namespace`{{ range .Namespaces }} +class {{ . }} implements Namespace { + related: { + // Define relations to other objects here. + // Examples: + // + // parents: (File | Folder)[] + // viewers: SubjectSet[] + } + + permits = { + // Define permissions here. These can be derived from the relations above. + // Examples: + // + // view: (ctx: Context): boolean => + // this.related.viewers.includes(ctx.subject) || + // this.related.parents.traverse((p) => p.permits.view(ctx)), + } +} +{{ end }} diff --git a/cmd/namespace/config_template/package.json.tmpl b/cmd/namespace/config_template/package.json.tmpl new file mode 100644 index 000000000..69f2f2caa --- /dev/null +++ b/cmd/namespace/config_template/package.json.tmpl @@ -0,0 +1,7 @@ +{ + "private": true, + "devDependencies": { + "@ory/keto-namespace-types": "{{ .Version }}", + "typescript": "latest" + } +} diff --git a/cmd/namespace/config_template/tsconfig.json b/cmd/namespace/config_template/tsconfig.json new file mode 100644 index 000000000..7599d6be6 --- /dev/null +++ b/cmd/namespace/config_template/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "noLib": true, + "noEmit": true, + "types": [] + } +} diff --git a/cmd/namespace/from_legacy.go b/cmd/namespace/from_legacy.go new file mode 100644 index 000000000..cea5da0fb --- /dev/null +++ b/cmd/namespace/from_legacy.go @@ -0,0 +1,20 @@ +package namespace + +import ( + "github.com/ory/x/cmdx" + "github.com/spf13/cobra" +) + +func NewFromLegacy() *cobra.Command { + cmd := &cobra.Command{ + Use: "from-legacy", + Short: "Convert legacy namespace configs to OPL configs", + Long: `This command converts legacy namespace configs to OPL configs.`, + RunE: func(cmd *cobra.Command, args []string) error { + cmdx.RegisterFormatFlags() + return nil + }, + } + + return cmd +} diff --git a/cmd/namespace/init.go b/cmd/namespace/init.go new file mode 100644 index 000000000..c5e5885a9 --- /dev/null +++ b/cmd/namespace/init.go @@ -0,0 +1,26 @@ +package namespace + +import ( + "github.com/spf13/cobra" +) + +func NewInitCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "init [ ...]", + Short: "Initialize the namespace config", + Long: `This command initializes the namespace config for the given namespaces. +A "default" namespace is created if none is specified.`, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + args = []string{"default"} + } + if err := generateConfigFiles(args, cmd.Flag(FlagOut).Value.String()); err != nil { + return err + } + return nil + }, + } + registerOutputFlag(cmd) + + return cmd +} diff --git a/cmd/namespace/opl_generate.go b/cmd/namespace/opl_generate.go new file mode 100644 index 000000000..89dbd6b2b --- /dev/null +++ b/cmd/namespace/opl_generate.go @@ -0,0 +1,68 @@ +package namespace + +import ( + "embed" + "github.com/ory/keto/internal/driver/config" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "io" + "io/fs" + "os" + "path/filepath" + "strings" + "text/template" +) + +const FlagOut = "out" + +func registerOutputFlag(cmd *cobra.Command) { + cmd.Flags().StringP(FlagOut, "o", ".", "output directory, will be created if it does not exist") +} + +//go:embed config_template/* +var configTemplate embed.FS +var version string + +func init() { + version = config.Version + if version == "master" || version == "" { + version = "latest" + } +} + +func generateConfigFiles(nspaces []string, out string) error { + t, err := template.New("config_template").ParseFS(configTemplate, "config_template/*") + if err != nil { + return errors.WithStack(err) + } + return fs.WalkDir(configTemplate, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return errors.WithStack(err) + } + if d.IsDir() { + return nil + } + orig, _ := configTemplate.Open(path) + defer orig.Close() + other, err := os.Create(filepath.Join(out, strings.TrimSuffix(d.Name(), ".tmpl"))) + if err != nil { + return err + } + defer other.Close() + if !strings.HasSuffix(path, ".tmpl") { + _, err := io.Copy(other, orig) + if err != nil { + return errors.WithStack(err) + } + return nil + } + + return errors.WithStack(t.ExecuteTemplate(other, d.Name(), struct { + Namespaces []string + Version string + }{ + Namespaces: nspaces, + Version: version, + })) + }) +} diff --git a/cmd/namespace/root.go b/cmd/namespace/root.go index 73c80dfc7..4f0a645f5 100644 --- a/cmd/namespace/root.go +++ b/cmd/namespace/root.go @@ -14,7 +14,7 @@ func NewNamespaceCmd() *cobra.Command { func RegisterCommandsRecursive(parent *cobra.Command, _ []ketoctx.Option) { rootCmd := NewNamespaceCmd() - rootCmd.AddCommand(NewValidateCmd()) + rootCmd.AddCommand(NewValidateCmd(), NewInitCmd()) parent.AddCommand(rootCmd) } diff --git a/contrib/namespace-type-lib/index.d.ts b/contrib/namespace-type-lib/index.d.ts new file mode 100644 index 000000000..f12c3d81d --- /dev/null +++ b/contrib/namespace-type-lib/index.d.ts @@ -0,0 +1,33 @@ +/// + +declare interface Boolean {} +declare interface String {} +declare interface Number {} +declare interface Function {} +declare interface Object {} +declare interface IArguments {} +declare interface RegExp {} + +declare interface Array { + includes(element: T): boolean + traverse(iteratorfn: (element: T) => boolean): boolean +} + +interface context { + subject: never +} + +interface namespace { + related?: { [relation: string]: namespace[] } + permits?: { [method: string]: (ctx: context) => boolean } +} + +declare module "@ory/keto-namespace-types" { + export type Context = context + + export type Namespace = namespace + + export type SubjectSet = A["related"][R] extends Array ? T : never +} diff --git a/contrib/namespace-type-lib/package-lock.json b/contrib/namespace-type-lib/package-lock.json new file mode 100644 index 000000000..bc04f9bea --- /dev/null +++ b/contrib/namespace-type-lib/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "@ory/keto-namespace-types", + "version": "0.9.0-alpha.0", + "lockfileVersion": 2, + "requires": true, + "dev": true, + "packages": { + "": { + "name": "@ory/keto-namespace-types", + "version": "0.9.0-alpha.0", + "dev": true, + "devDependencies": { + "@ory/keto-namespace-types": "file:./", + "typescript": "^4.7.4" + } + }, + "node_modules/@ory/keto-namespace-types": { + "resolved": "", + "link": true + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + }, + "dependencies": { + "@ory/keto-namespace-types": { + "version": "file:", + "requires": { + "@ory/keto-namespace-types": "file:", + "typescript": "^4.7.4" + }, + "dependencies": { + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + } + } + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + } + } +} diff --git a/contrib/namespace-type-lib/package.json b/contrib/namespace-type-lib/package.json new file mode 100644 index 000000000..6d45f9866 --- /dev/null +++ b/contrib/namespace-type-lib/package.json @@ -0,0 +1,18 @@ +{ + "name": "@ory/keto-namespace-types", + "version": "0.9.0-alpha.0", + "description": "TypeScript definitions for Ory Keto Namespaces", + "homepage": "https://www.ory.sh/keto", + "bugs": "https://github.com/ory/keto/issues", + "dependencies": {}, + "devDependencies": { + "@ory/keto-namespace-types": "file:./", + "typescript": "^4.7.4" + }, + "scripts": { + "test": "tsc --types --noEmit --noLib test.ts" + }, + "main": "", + "types": "index.d.ts", + "files": ["index.d.ts"] +} diff --git a/contrib/namespace-type-lib/test.ts b/contrib/namespace-type-lib/test.ts new file mode 100644 index 000000000..fd7323d79 --- /dev/null +++ b/contrib/namespace-type-lib/test.ts @@ -0,0 +1,26 @@ +import { Namespace, SubjectSet, Context } from '@ory/keto-namespace-types' + +class User implements Namespace { + related: { + friends: User[] + } +} + +class Group implements Namespace { + related: { + members: (User | Group)[] + } +} + +class File implements Namespace { + related: { + viewers: (User | SubjectSet)[] + } + + // Some comment + permits = { + view: (ctx: Context): boolean => + this.related.viewers.traverse((p) => (p instanceof User ? p.related.friends.includes(ctx.subject) : p.related.members.traverse())) || + this.related.viewers.includes(ctx.subject) + } +} diff --git a/contrib/namespace-type-lib/tsconfig.json b/contrib/namespace-type-lib/tsconfig.json new file mode 100644 index 000000000..7599d6be6 --- /dev/null +++ b/contrib/namespace-type-lib/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "noLib": true, + "noEmit": true, + "types": [] + } +} diff --git a/contrib/rewrites-example/lib.ts b/contrib/rewrites-example/lib.ts deleted file mode 100644 index ebf6d5bf1..000000000 --- a/contrib/rewrites-example/lib.ts +++ /dev/null @@ -1,18 +0,0 @@ -/// - -type Context = { subject: never } - -interface Namespace { - related?: { [relation: string]: Namespace[] } - permits?: { [method: string]: (ctx: Context) => boolean } -} - -interface Array { - includes(element: Namespace): boolean - traverse(iteratorfn: (element: Namespace) => boolean): boolean -} - -type SubjectSet< - A extends Namespace, - R extends keyof A["related"], -> = A["related"][R] extends Array ? T : never diff --git a/contrib/rewrites-example/namespaces.keto.ts b/contrib/rewrites-example/namespaces.keto.ts index 1884336d3..ae7739e00 100644 --- a/contrib/rewrites-example/namespaces.keto.ts +++ b/contrib/rewrites-example/namespaces.keto.ts @@ -1,4 +1,4 @@ -/// +import { Namespace, SubjectSet, Context } from '@ory/keto-namespace-types' class User implements Namespace { related: { diff --git a/contrib/rewrites-example/namespaces.ts b/contrib/rewrites-example/namespaces.ts new file mode 100644 index 000000000..16d057aab --- /dev/null +++ b/contrib/rewrites-example/namespaces.ts @@ -0,0 +1,79 @@ +import { Namespace, SubjectSet, Context } from '@ory/keto-namespace-types' + +// Declare new namespaces as classes that implement `Namespaces` +class User implements Namespace { + related: { + // Define relations to other objects here. + // Examples: + // + // parents: (File | Folder)[] + // viewers: SubjectSet[] + } + + permits = { + // Define permissions here. These can be derived from the relations above. + // Examples: + // + // view: (ctx: Context): boolean => + // this.related.viewers.includes(ctx.subject) || + // this.related.parents.traverse((p) => p.permits.view(ctx)), + } +} + +class Group implements Namespace { + related: { + // Define relations to other objects here. + // Examples: + // + // parents: (File | Folder)[] + // viewers: SubjectSet[] + } + + permits = { + // Define permissions here. These can be derived from the relations above. + // Examples: + // + // view: (ctx: Context): boolean => + // this.related.viewers.includes(ctx.subject) || + // this.related.parents.traverse((p) => p.permits.view(ctx)), + } +} + +class Folder implements Namespace { + related: { + // Define relations to other objects here. + // Examples: + // + // parents: (File | Folder)[] + // viewers: SubjectSet[] + } + + permits = { + // Define permissions here. These can be derived from the relations above. + // Examples: + // + // view: (ctx: Context): boolean => + // this.related.viewers.includes(ctx.subject) || + // this.related.parents.traverse((p) => p.permits.view(ctx)), + } +} + +class File implements Namespace { + related: { + // Define relations to other objects here. + // Examples: + // + // parents: (File | Folder)[] + // viewers: SubjectSet[] + } + + permits = { + // Define permissions here. These can be derived from the relations above. + // Examples: + // + // view: (ctx: Context): boolean => + // this.related.viewers.includes(ctx.subject) || + // this.related.parents.traverse((p) => p.permits.view(ctx)), + } +} + diff --git a/contrib/rewrites-example/package-lock.json b/contrib/rewrites-example/package-lock.json new file mode 100644 index 000000000..7fe9354fe --- /dev/null +++ b/contrib/rewrites-example/package-lock.json @@ -0,0 +1,56 @@ +{ + "name": "rewrites-example", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@ory/keto-namespace-types": "file:../namespace-type-lib", + "typescript": "latest" + } + }, + "../../../../../../namespace-type-lib": { + "extraneous": true + }, + "../namespace-type-lib": { + "version": "0.9.0-alpha.0", + "dev": true, + "devDependencies": { + "@ory/keto-namespace-types": "file:./", + "typescript": "^4.7.4" + } + }, + "node_modules/@ory/keto-namespace-types": { + "resolved": "../namespace-type-lib", + "link": true + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + }, + "dependencies": { + "@ory/keto-namespace-types": { + "version": "file:../namespace-type-lib", + "requires": { + "@ory/keto-namespace-types": "file:", + "typescript": "^4.7.4" + } + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + } + } +} diff --git a/contrib/rewrites-example/package.json b/contrib/rewrites-example/package.json new file mode 100644 index 000000000..f2eed3d92 --- /dev/null +++ b/contrib/rewrites-example/package.json @@ -0,0 +1,7 @@ +{ + "private": true, + "devDependencies": { + "@ory/keto-namespace-types": "file:../namespace-type-lib", + "typescript": "latest" + } +} diff --git a/contrib/rewrites-example/tsconfig.json b/contrib/rewrites-example/tsconfig.json new file mode 100644 index 000000000..7599d6be6 --- /dev/null +++ b/contrib/rewrites-example/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "noLib": true, + "noEmit": true, + "types": [] + } +}