@knocklabs/cli 0.2.5 → 0.3.1

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.
@@ -44,8 +44,6 @@ class BranchCreate extends _basecommand.default {
44
44
  this.log(` Created at: ${data.created_at}`);
45
45
  }
46
46
  }
47
- // Hide until branches are released in GA
48
- _define_property(BranchCreate, "hidden", true);
49
47
  _define_property(BranchCreate, "summary", "Creates a new branch off of the development environment.");
50
48
  _define_property(BranchCreate, "enableJsonFlag", true);
51
49
  _define_property(BranchCreate, "args", {
@@ -44,8 +44,6 @@ class BranchDelete extends _basecommand.default {
44
44
  this.log(`‣ Successfully deleted branch \`${args.slug}\``);
45
45
  }
46
46
  }
47
- // Hide until branches are released in GA
48
- _define_property(BranchDelete, "hidden", true);
49
47
  _define_property(BranchDelete, "summary", "Deletes an existing branch with the given slug.");
50
48
  _define_property(BranchDelete, "args", {
51
49
  slug: _arg.CustomArgs.slug({
@@ -39,6 +39,4 @@ class BranchExit extends _basecommand.default {
39
39
  this.log("‣ Successfully exited the branch");
40
40
  }
41
41
  }
42
- // Hide until branches are released in GA
43
- _define_property(BranchExit, "hidden", true);
44
42
  _define_property(BranchExit, "summary", "Exits the current branch.");
@@ -80,8 +80,6 @@ class BranchList extends _basecommand.default {
80
80
  }
81
81
  }
82
82
  }
83
- // Hide until branches are released in GA
84
- _define_property(BranchList, "hidden", true);
85
83
  _define_property(BranchList, "summary", "Display all existing branches off of the development environment.");
86
84
  _define_property(BranchList, "flags", {
87
85
  ..._page.pageFlags
@@ -142,8 +142,6 @@ class BranchSwitch extends _basecommand.default {
142
142
  });
143
143
  }
144
144
  }
145
- // Hide until branches are released in GA
146
- _define_property(BranchSwitch, "hidden", true);
147
145
  _define_property(BranchSwitch, "summary", "Switches to an existing branch with the given slug.");
148
146
  _define_property(BranchSwitch, "flags", {
149
147
  create: _core.Flags.boolean({
@@ -108,7 +108,9 @@ class GuidePull extends _basecommand.default {
108
108
  });
109
109
  return this.apiV1.getGuide(props);
110
110
  });
111
- await _guide.writeGuideDirFromData(dirContext, resp.data);
111
+ await _guide.writeGuideDirFromData(dirContext, resp.data, {
112
+ withSchema: true
113
+ });
112
114
  const action = dirContext.exists ? "updated" : "created";
113
115
  const scope = (0, _command.formatCommandScope)(flags);
114
116
  this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
@@ -125,7 +127,9 @@ class GuidePull extends _basecommand.default {
125
127
  if (!input) return;
126
128
  _ux.spinner.start(`‣ Loading`);
127
129
  const guides = await this.listAllGuides();
128
- await _guide.writeGuidesIndexDir(targetDirCtx, guides);
130
+ await _guide.writeGuidesIndexDir(targetDirCtx, guides, {
131
+ withSchema: true
132
+ });
129
133
  _ux.spinner.stop();
130
134
  const action = targetDirCtx.exists ? "updated" : "created";
131
135
  const scope = (0, _command.formatCommandScope)(flags);
@@ -121,7 +121,9 @@ class GuidePush extends _basecommand.default {
121
121
  // Update the guide directory with the successfully pushed guide
122
122
  // payload from the server.
123
123
  // eslint-disable-next-line no-await-in-loop
124
- await _guide.writeGuideDirFromData(guide, resp.data.guide);
124
+ await _guide.writeGuideDirFromData(guide, resp.data.guide, {
125
+ withSchema: true
126
+ });
125
127
  continue;
126
128
  }
127
129
  const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _guide.guideJsonPath(guide), "ApiError");
@@ -109,7 +109,9 @@ class EmailLayoutPull extends _basecommand.default {
109
109
  });
110
110
  return this.apiV1.getEmailLayout(props);
111
111
  });
112
- await _emaillayout.writeEmailLayoutDirFromData(dirContext, resp.data);
112
+ await _emaillayout.writeEmailLayoutDirFromData(dirContext, resp.data, {
113
+ withSchema: true
114
+ });
113
115
  const action = dirContext.exists ? "updated" : "created";
114
116
  const scope = (0, _command.formatCommandScope)(flags);
115
117
  this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
@@ -127,7 +129,9 @@ class EmailLayoutPull extends _basecommand.default {
127
129
  if (!input) return;
128
130
  _ux.spinner.start(`‣ Loading`);
129
131
  const emailLayouts = await this.listAllEmailLayouts();
130
- await _emaillayout.writeEmailLayoutIndexDir(targetDirCtx, emailLayouts);
132
+ await _emaillayout.writeEmailLayoutIndexDir(targetDirCtx, emailLayouts, {
133
+ withSchema: true
134
+ });
131
135
  _ux.spinner.stop();
132
136
  const action = targetDirCtx.exists ? "updated" : "created";
133
137
  const scope = (0, _command.formatCommandScope)(flags);
@@ -121,7 +121,9 @@ class EmailLayoutPush extends _basecommand.default {
121
121
  // Update the layout directory with the successfully pushed layout
122
122
  // payload from the server.
123
123
  // eslint-disable-next-line no-await-in-loop
124
- await _emaillayout.writeEmailLayoutDirFromData(layout, resp.data.email_layout);
124
+ await _emaillayout.writeEmailLayoutDirFromData(layout, resp.data.email_layout, {
125
+ withSchema: true
126
+ });
125
127
  continue;
126
128
  }
127
129
  const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _emaillayout.emailLayoutJsonPath(layout), "ApiError");
@@ -112,7 +112,9 @@ class MessageTypePull extends _basecommand.default {
112
112
  });
113
113
  return this.apiV1.getMessageType(props);
114
114
  });
115
- await _messagetype.writeMessageTypeDirFromData(dirContext, resp.data);
115
+ await _messagetype.writeMessageTypeDirFromData(dirContext, resp.data, {
116
+ withSchema: true
117
+ });
116
118
  const action = dirContext.exists ? "updated" : "created";
117
119
  const scope = (0, _command.formatCommandScope)(flags);
118
120
  this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
@@ -161,7 +163,9 @@ class MessageTypePull extends _basecommand.default {
161
163
  if (!input) return;
162
164
  _ux.spinner.start(`‣ Loading`);
163
165
  const messageTypes = await this.listAllMessageTypes();
164
- await _messagetype.writeMessageTypesIndexDir(targetDirCtx, messageTypes);
166
+ await _messagetype.writeMessageTypesIndexDir(targetDirCtx, messageTypes, {
167
+ withSchema: true
168
+ });
165
169
  _ux.spinner.stop();
166
170
  const action = targetDirCtx.exists ? "updated" : "created";
167
171
  const scope = (0, _command.formatCommandScope)(flags);
@@ -121,7 +121,9 @@ class MessageTypePush extends _basecommand.default {
121
121
  // Update the message type directory with the successfully pushed message
122
122
  // type payload from the server.
123
123
  // eslint-disable-next-line no-await-in-loop
124
- await _messagetype.writeMessageTypeDirFromData(messageType, resp.data.message_type);
124
+ await _messagetype.writeMessageTypeDirFromData(messageType, resp.data.message_type, {
125
+ withSchema: true
126
+ });
125
127
  continue;
126
128
  }
127
129
  const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _messagetype.messageTypeJsonPath(messageType), "ApiError");
@@ -109,7 +109,9 @@ class PartialPull extends _basecommand.default {
109
109
  });
110
110
  return this.apiV1.getPartial(props);
111
111
  });
112
- await _partial.writePartialDirFromData(dirContext, resp.data);
112
+ await _partial.writePartialDirFromData(dirContext, resp.data, {
113
+ withSchema: true
114
+ });
113
115
  const action = dirContext.exists ? "updated" : "created";
114
116
  const scope = (0, _command.formatCommandScope)(flags);
115
117
  this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
@@ -127,7 +129,9 @@ class PartialPull extends _basecommand.default {
127
129
  if (!input) return;
128
130
  _ux.spinner.start(`‣ Loading`);
129
131
  const partials = await this.listAllPartials();
130
- await _partial.writePartialsIndexDir(targetDirCtx, partials);
132
+ await _partial.writePartialsIndexDir(targetDirCtx, partials, {
133
+ withSchema: true
134
+ });
131
135
  _ux.spinner.stop();
132
136
  const action = targetDirCtx.exists ? "updated" : "created";
133
137
  const scope = (0, _command.formatCommandScope)(flags);
@@ -121,7 +121,9 @@ class PartialPush extends _basecommand.default {
121
121
  // Update the partial directory with the successfully pushed partial
122
122
  // payload from the server.
123
123
  // eslint-disable-next-line no-await-in-loop
124
- await _partial.writePartialDirFromData(partial, resp.data.partial);
124
+ await _partial.writePartialDirFromData(partial, resp.data.partial, {
125
+ withSchema: true
126
+ });
125
127
  continue;
126
128
  }
127
129
  const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _partial.partialJsonPath(partial), "ApiError");
@@ -113,7 +113,9 @@ class WorkflowPull extends _basecommand.default {
113
113
  return this.apiV1.getWorkflow(props);
114
114
  });
115
115
  // 3. Write the fetched workflow to create or update the workflow directory.
116
- await _workflow.writeWorkflowDirFromData(dirContext, resp.data);
116
+ await _workflow.writeWorkflowDirFromData(dirContext, resp.data, {
117
+ withSchema: true
118
+ });
117
119
  const action = dirContext.exists ? "updated" : "created";
118
120
  const scope = (0, _command.formatCommandScope)(flags);
119
121
  this.log(`‣ Successfully ${action} \`${dirContext.key}\` at ${dirContext.abspath} using ${scope}`);
@@ -162,7 +164,9 @@ class WorkflowPull extends _basecommand.default {
162
164
  // Fetch all workflows then write them to the local file system.
163
165
  _ux.spinner.start(`‣ Loading`);
164
166
  const workflows = await this.listAllWorkflows();
165
- await _workflow.writeWorkflowsIndexDir(targetDirCtx, workflows);
167
+ await _workflow.writeWorkflowsIndexDir(targetDirCtx, workflows, {
168
+ withSchema: true
169
+ });
166
170
  _ux.spinner.stop();
167
171
  const action = targetDirCtx.exists ? "updated" : "created";
168
172
  const scope = (0, _command.formatCommandScope)(flags);
@@ -121,7 +121,9 @@ class WorkflowPush extends _basecommand.default {
121
121
  // Update the workflow directory with the successfully pushed workflow
122
122
  // payload from the server.
123
123
  // eslint-disable-next-line no-await-in-loop
124
- await _workflow.writeWorkflowDirFromData(workflow, resp.data.workflow);
124
+ await _workflow.writeWorkflowDirFromData(workflow, resp.data.workflow, {
125
+ withSchema: true
126
+ });
125
127
  continue;
126
128
  }
127
129
  const error = new _error.SourceError((0, _request.formatErrorRespMessage)(resp), _workflow.workflowJsonPath(workflow), "ApiError");
@@ -148,8 +148,6 @@ const slug = _core.Flags.custom({
148
148
  });
149
149
  const branch = slug({
150
150
  summary: "The slug of the branch to use.",
151
- // TODO Hide until branching is released in GA
152
- hidden: true,
153
151
  // Memoize this flag's default. oclif runs this default function even when the flag is unused.
154
152
  // Using lodash's once avoids unnecessarily reading the branch file multiple times.
155
153
  default: (0, _lodash.once)(_branch.readSlugFromBranchFile)
@@ -38,8 +38,9 @@ const compileExtractionSettings = (emailLayout)=>{
38
38
  }
39
39
  return map;
40
40
  };
41
- const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout = {})=>{
41
+ const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout, $schema)=>{
42
42
  const bundle = {};
43
+ localEmailLayout = localEmailLayout || {};
43
44
  const mutRemoteEmailLayout = (0, _lodash.cloneDeep)(remoteEmailLayout);
44
45
  // A map of extraction settings of every field in the email layout
45
46
  const compiledExtractionSettings = compileExtractionSettings(mutRemoteEmailLayout);
@@ -75,5 +76,5 @@ const buildEmailLayoutDirBundle = (remoteEmailLayout, localEmailLayout = {})=>{
75
76
  // the layout JSON realtive path + the file content.
76
77
  return (0, _lodash.set)(bundle, [
77
78
  LAYOUT_JSON
78
- ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteEmailLayout));
79
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteEmailLayout, $schema));
79
80
  };
@@ -73,13 +73,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
73
73
  }
74
74
  return newObj;
75
75
  }
76
- const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout)=>{
76
+ const EMAIL_LAYOUT_SCHEMA = "https://schemas.knock.app/cli/email-layout.json";
77
+ const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout, options)=>{
78
+ const { withSchema = false } = options || {};
77
79
  // If the layout directory exists on the file system (i.e. previously
78
80
  // pulled before), then read the layout file to use as a reference.
79
81
  const [localEmailLayout] = emailLayoutDirCtx.exists ? await (0, _reader.readEmailLayoutDir)(emailLayoutDirCtx, {
80
82
  withExtractedFiles: true
81
83
  }) : [];
82
- const bundle = (0, _processorisomorphic.buildEmailLayoutDirBundle)(remoteEmailLayout, localEmailLayout);
84
+ const bundle = (0, _processorisomorphic.buildEmailLayoutDirBundle)(remoteEmailLayout, localEmailLayout, withSchema ? EMAIL_LAYOUT_SCHEMA : undefined);
83
85
  const backupDirPath = _nodepath.default.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
84
86
  try {
85
87
  // We store a backup in case there's an error.
@@ -109,7 +111,7 @@ const writeEmailLayoutDirFromData = async (emailLayoutDirCtx, remoteEmailLayout)
109
111
  await _fsextra.remove(backupDirPath);
110
112
  }
111
113
  };
112
- const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts)=>{
114
+ const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts, options)=>{
113
115
  const backupDirPath = _nodepath.default.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
114
116
  try {
115
117
  if (indexDirCtx.exists) {
@@ -124,7 +126,7 @@ const writeEmailLayoutIndexDir = async (indexDirCtx, remoteEmailLayouts)=>{
124
126
  abspath: emailLayoutDirPath,
125
127
  exists: indexDirCtx.exists ? await (0, _helpers.isEmailLayoutDir)(emailLayoutDirPath) : false
126
128
  };
127
- return writeEmailLayoutDirFromData(emailLayoutDirCtx, remoteEmailLayout);
129
+ return writeEmailLayoutDirFromData(emailLayoutDirCtx, remoteEmailLayout, options);
128
130
  });
129
131
  await Promise.all(writeEmailLayoutDirPromises);
130
132
  } catch (error) {
@@ -45,8 +45,9 @@ const compileExtractionSettings = (guide)=>{
45
45
  }
46
46
  return map;
47
47
  };
48
- const buildGuideDirBundle = (remoteGuide, localGuide = {})=>{
48
+ const buildGuideDirBundle = (remoteGuide, localGuide, $schema)=>{
49
49
  const bundle = {};
50
+ localGuide = localGuide || {};
50
51
  const mutRemoteGuide = (0, _lodash.cloneDeep)(remoteGuide);
51
52
  // A map of extraction settings of every field in the guide.
52
53
  const compiledExtractionSettings = compileExtractionSettings(mutRemoteGuide);
@@ -81,5 +82,5 @@ const buildGuideDirBundle = (remoteGuide, localGuide = {})=>{
81
82
  // the guide JSON relative path + the file content.
82
83
  return (0, _lodash.set)(bundle, [
83
84
  GUIDE_JSON
84
- ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteGuide));
85
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteGuide, $schema));
85
86
  };
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
68
68
  }
69
69
  return newObj;
70
70
  }
71
- const writeGuideDirFromData = async (guideDirCtx, remoteGuide)=>{
71
+ const GUIDE_SCHEMA = "https://schemas.knock.app/cli/guide.json";
72
+ const writeGuideDirFromData = async (guideDirCtx, remoteGuide, options)=>{
73
+ const { withSchema = false } = options || {};
72
74
  // If the guide directory exists on the file system (i.e. previously
73
75
  // pulled before), then read the guide file to use as a reference.
74
76
  const [localGuide] = guideDirCtx.exists ? await (0, _reader.readGuideDir)(guideDirCtx, {
75
77
  withExtractedFiles: true
76
78
  }) : [];
77
- const bundle = (0, _processorisomorphic.buildGuideDirBundle)(remoteGuide, localGuide);
79
+ const bundle = (0, _processorisomorphic.buildGuideDirBundle)(remoteGuide, localGuide, withSchema ? GUIDE_SCHEMA : undefined);
78
80
  return writeGuideDirFromBundle(guideDirCtx, bundle);
79
81
  };
80
82
  /*
@@ -136,7 +138,7 @@ const writeGuideDirFromData = async (guideDirCtx, remoteGuide)=>{
136
138
  });
137
139
  await Promise.all(promises);
138
140
  };
139
- const writeGuidesIndexDir = async (indexDirCtx, remoteGuides)=>{
141
+ const writeGuidesIndexDir = async (indexDirCtx, remoteGuides, options)=>{
140
142
  const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
141
143
  try {
142
144
  // If the index directory already exists, back it up in the temp sandbox
@@ -154,7 +156,7 @@ const writeGuidesIndexDir = async (indexDirCtx, remoteGuides)=>{
154
156
  abspath: guideDirPath,
155
157
  exists: indexDirCtx.exists ? await (0, _helpers.isGuideDir)(guideDirPath) : false
156
158
  };
157
- return writeGuideDirFromData(guideDirCtx, guide);
159
+ return writeGuideDirFromData(guideDirCtx, guide, options);
158
160
  });
159
161
  await Promise.all(writeGuideDirPromises);
160
162
  } catch (error) {
@@ -38,9 +38,10 @@ const compileExtractionSettings = (messageType)=>{
38
38
  }
39
39
  return map;
40
40
  };
41
- const buildMessageTypeDirBundle = (remoteMessageType, localMessageType = {})=>{
41
+ const buildMessageTypeDirBundle = (remoteMessageType, localMessageType, $schema)=>{
42
42
  const bundle = {};
43
43
  const mutRemoteMessageType = (0, _lodash.cloneDeep)(remoteMessageType);
44
+ localMessageType = localMessageType || {};
44
45
  // A map of extraction settings of every field in the message type
45
46
  const compiledExtractionSettings = compileExtractionSettings(mutRemoteMessageType);
46
47
  // Iterate through each extractable field, determine whether we need to
@@ -74,5 +75,5 @@ const buildMessageTypeDirBundle = (remoteMessageType, localMessageType = {})=>{
74
75
  // the message type JSON relative path + the file content.
75
76
  return (0, _lodash.set)(bundle, [
76
77
  MESSAGE_TYPE_JSON
77
- ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteMessageType));
78
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutRemoteMessageType, $schema));
78
79
  };
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
68
68
  }
69
69
  return newObj;
70
70
  }
71
- const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType)=>{
71
+ const MESSAGE_TYPE_SCHEMA = "https://schemas.knock.app/cli/message-type.json";
72
+ const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType, options)=>{
73
+ const { withSchema = false } = options || {};
72
74
  // If the message type directory exists on the file system (i.e. previously
73
75
  // pulled before), then read the message type file to use as a reference.
74
76
  const [localMessageType] = messageTypeDirCtx.exists ? await (0, _reader.readMessageTypeDir)(messageTypeDirCtx, {
75
77
  withExtractedFiles: true
76
78
  }) : [];
77
- const bundle = (0, _processorisomorphic.buildMessageTypeDirBundle)(remoteMessageType, localMessageType);
79
+ const bundle = (0, _processorisomorphic.buildMessageTypeDirBundle)(remoteMessageType, localMessageType, withSchema ? MESSAGE_TYPE_SCHEMA : undefined);
78
80
  return writeMessageTypeDirFromBundle(messageTypeDirCtx, bundle);
79
81
  };
80
82
  /*
@@ -136,7 +138,7 @@ const writeMessageTypeDirFromData = async (messageTypeDirCtx, remoteMessageType)
136
138
  });
137
139
  await Promise.all(promises);
138
140
  };
139
- const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes)=>{
141
+ const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes, options)=>{
140
142
  const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
141
143
  try {
142
144
  // If the index directory already exists, back it up in the temp sandbox
@@ -154,7 +156,7 @@ const writeMessageTypesIndexDir = async (indexDirCtx, remoteMessageTypes)=>{
154
156
  abspath: messageTypeDirPath,
155
157
  exists: indexDirCtx.exists ? await (0, _helpers.isMessageTypeDir)(messageTypeDirPath) : false
156
158
  };
157
- return writeMessageTypeDirFromData(messageTypeDirCtx, messageType);
159
+ return writeMessageTypeDirFromData(messageTypeDirCtx, messageType, options);
158
160
  });
159
161
  await Promise.all(promises);
160
162
  } catch (error) {
@@ -61,8 +61,9 @@ const compileExtractionSettings = (partial)=>{
61
61
  }
62
62
  return map;
63
63
  };
64
- const buildPartialDirBundle = (remotePartial, localPartial = {})=>{
64
+ const buildPartialDirBundle = (remotePartial, localPartial, $schema)=>{
65
65
  const bundle = {};
66
+ localPartial = localPartial || {};
66
67
  const mutRemotePartial = (0, _lodash.cloneDeep)(remotePartial);
67
68
  // A map of extraction settings of every field in the partial
68
69
  const compiledExtractionSettings = compileExtractionSettings(mutRemotePartial);
@@ -97,5 +98,5 @@ const buildPartialDirBundle = (remotePartial, localPartial = {})=>{
97
98
  // the partial JSON relative path + the file content.
98
99
  return (0, _lodash.set)(bundle, [
99
100
  PARTIAL_JSON
100
- ], (0, _helpersisomorphic.prepareResourceJson)(mutRemotePartial));
101
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutRemotePartial, $schema));
101
102
  };
@@ -68,13 +68,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
68
68
  }
69
69
  return newObj;
70
70
  }
71
- const writePartialDirFromData = async (partialDirCtx, remotePartial)=>{
71
+ const PARTIAL_SCHEMA = "https://schemas.knock.app/cli/partial.json";
72
+ const writePartialDirFromData = async (partialDirCtx, remotePartial, options)=>{
73
+ const { withSchema = false } = options || {};
72
74
  // If the partial directory exists on the file system (i.e. previously
73
75
  // pulled before), then read the partial file to use as a reference.
74
76
  const [localPartial] = partialDirCtx.exists ? await (0, _reader.readPartialDir)(partialDirCtx, {
75
77
  withExtractedFiles: true
76
78
  }) : [];
77
- const bundle = (0, _processorisomorphic.buildPartialDirBundle)(remotePartial, localPartial);
79
+ const bundle = (0, _processorisomorphic.buildPartialDirBundle)(remotePartial, localPartial, withSchema ? PARTIAL_SCHEMA : undefined);
78
80
  return writePartialDirFromBundle(partialDirCtx, bundle);
79
81
  };
80
82
  /*
@@ -136,7 +138,7 @@ const writePartialDirFromData = async (partialDirCtx, remotePartial)=>{
136
138
  });
137
139
  await Promise.all(promises);
138
140
  };
139
- const writePartialsIndexDir = async (indexDirCtx, remotePartials)=>{
141
+ const writePartialsIndexDir = async (indexDirCtx, remotePartials, options)=>{
140
142
  const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
141
143
  try {
142
144
  // If the index directory already exists, back it up in the temp sandbox
@@ -154,7 +156,7 @@ const writePartialsIndexDir = async (indexDirCtx, remotePartials)=>{
154
156
  abspath: partialDirPath,
155
157
  exists: indexDirCtx.exists ? await (0, _helpers.isPartialDir)(partialDirPath) : false
156
158
  };
157
- return writePartialDirFromData(partialDirCtx, partial);
159
+ return writePartialDirFromData(partialDirCtx, partial, options);
158
160
  });
159
161
  await Promise.all(writePartialDirPromises);
160
162
  } catch (error) {
@@ -15,7 +15,7 @@ const REMOVED_READONLY_FIELDS = [
15
15
  "sha",
16
16
  "updated_at"
17
17
  ];
18
- const prepareResourceJson = (resource)=>{
18
+ const prepareResourceJson = (resource, $schema)=>{
19
19
  var _resource___annotation;
20
20
  const readonlyFields = ((_resource___annotation = resource.__annotation) === null || _resource___annotation === void 0 ? void 0 : _resource___annotation.readonly_fields) || [];
21
21
  const [readonly, remainder] = (0, _objectisomorphic.split)(resource, readonlyFields);
@@ -25,6 +25,12 @@ const prepareResourceJson = (resource)=>{
25
25
  ...remainder,
26
26
  __readonly: filteredReadonlyFields
27
27
  };
28
+ // Append the $schema property to the resource JSON if it is provided.
29
+ if ($schema) {
30
+ Object.assign(resourceJson, {
31
+ $schema
32
+ });
33
+ }
28
34
  // Strip out all schema annotations, so not to expose them to end users.
29
35
  return (0, _objectisomorphic.omitDeep)(resourceJson, [
30
36
  "__annotation"
@@ -250,8 +250,9 @@ const recursivelyBuildWorkflowDirBundle = (bundle, steps, localWorkflowStepsByRe
250
250
  }
251
251
  }
252
252
  };
253
- const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow = {})=>{
253
+ const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow, $schema)=>{
254
254
  const bundle = {};
255
+ localWorkflow = localWorkflow || {};
255
256
  const mutWorkflow = (0, _lodash.cloneDeep)(remoteWorkflow);
256
257
  const localWorkflowStepsByRef = keyLocalWorkflowStepsByRef(localWorkflow.steps);
257
258
  // Recursively traverse the workflow step tree, mutating it and the bundle
@@ -260,5 +261,5 @@ const buildWorkflowDirBundle = (remoteWorkflow, localWorkflow = {})=>{
260
261
  // Then, prepare the workflow data to be written into a workflow json file.
261
262
  return (0, _lodash.set)(bundle, [
262
263
  WORKFLOW_JSON
263
- ], (0, _helpersisomorphic.prepareResourceJson)(mutWorkflow));
264
+ ], (0, _helpersisomorphic.prepareResourceJson)(mutWorkflow, $schema));
264
265
  };
@@ -71,13 +71,15 @@ function _interop_require_wildcard(obj, nodeInterop) {
71
71
  }
72
72
  return newObj;
73
73
  }
74
- const writeWorkflowDirFromData = async (workflowDirCtx, remoteWorkflow)=>{
74
+ const WORKFLOW_SCHEMA = "https://schemas.knock.app/cli/workflow.json";
75
+ const writeWorkflowDirFromData = async (workflowDirCtx, remoteWorkflow, options)=>{
76
+ const { withSchema = false } = options || {};
75
77
  // If the workflow directory exists on the file system (i.e. previously
76
78
  // pulled before), then read the workflow file to use as a reference.
77
79
  const [localWorkflow] = workflowDirCtx.exists ? await (0, _reader.readWorkflowDir)(workflowDirCtx, {
78
80
  withExtractedFiles: true
79
81
  }) : [];
80
- const bundle = (0, _processorisomorphic.buildWorkflowDirBundle)(remoteWorkflow, localWorkflow);
82
+ const bundle = (0, _processorisomorphic.buildWorkflowDirBundle)(remoteWorkflow, localWorkflow, withSchema ? WORKFLOW_SCHEMA : undefined);
81
83
  return writeWorkflowDirFromBundle(workflowDirCtx, bundle);
82
84
  };
83
85
  const writeWorkflowDirFromBundle = async (workflowDirCtx, workflowDirBundle)=>{
@@ -132,7 +134,7 @@ const writeWorkflowDirFromBundle = async (workflowDirCtx, workflowDirBundle)=>{
132
134
  });
133
135
  await Promise.all(promises);
134
136
  };
135
- const writeWorkflowsIndexDir = async (indexDirCtx, remoteWorkflows)=>{
137
+ const writeWorkflowsIndexDir = async (indexDirCtx, remoteWorkflows, options)=>{
136
138
  const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
137
139
  try {
138
140
  // If the index directory already exists, back it up in the temp sandbox
@@ -150,7 +152,7 @@ const writeWorkflowsIndexDir = async (indexDirCtx, remoteWorkflows)=>{
150
152
  abspath: workflowDirPath,
151
153
  exists: indexDirCtx.exists ? await (0, _helpers.isWorkflowDir)(workflowDirPath) : false
152
154
  };
153
- return writeWorkflowDirFromData(workflowDirCtx, workflow);
155
+ return writeWorkflowDirFromData(workflowDirCtx, workflow, options);
154
156
  });
155
157
  await Promise.all(writeWorkflowDirPromises);
156
158
  } catch (error) {